Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grid Visualizer - improve styles #64321

Open
wants to merge 25 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b74481f
Add support to root block list in `useBlockRefs`
talldan Aug 7, 2024
995d04d
Add basic underlay component
talldan Aug 7, 2024
c260c5f
Only render GridVisualizer above GridBlock and no longer on LayoutChi…
talldan Aug 7, 2024
e3ad0c3
Remove outdated comment
talldan Aug 7, 2024
210b233
Move padding to underlay to ensure it refreshes
talldan Aug 7, 2024
5f98335
Handle block moving
talldan Aug 7, 2024
ebcd385
Add a background for cells
talldan Aug 7, 2024
9e3b9ae
Use BlockPopoverCover with inline prop
talldan Aug 8, 2024
6c3b96a
Allow margin reset on inline popover via inline styles
talldan Aug 8, 2024
ca816ec
Override popover default z index
talldan Aug 8, 2024
6d078c6
Render two "grid visualizers", one under the block and one over-the o…
talldan Aug 8, 2024
8ff3a22
Revert change to root block list
talldan Aug 8, 2024
03c068e
Update grid styles
talldan Aug 9, 2024
628ffb1
Update appender styles
talldan Aug 9, 2024
1e4c9e7
Hide drop zone until active
talldan Aug 9, 2024
4386508
Improve highlight style
talldan Aug 9, 2024
37c4203
Refactor into separate GridPopunder / GridPopover components
talldan Aug 9, 2024
497eb0f
Fix resizer bounds
talldan Aug 9, 2024
3b4e9ae
Try for a smaller diff
talldan Aug 9, 2024
98cb5de
Rename GridVisualizerGrid, move occupiedRects
noisysocks Aug 12, 2024
ed7e1ed
Update grid css
talldan Aug 13, 2024
6139488
Move GridResizerBoundsContext.Provider rendering to `GridTools` and m…
talldan Aug 13, 2024
e1343e7
Use scss variables
talldan Aug 13, 2024
4620f5e
Rename popover prop to `style` instead of `contentStyle`
talldan Aug 13, 2024
f73ca9f
Fix: Resizer bounds not working for auto grids
talldan Aug 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
239 changes: 149 additions & 90 deletions packages/block-editor/src/components/grid/grid-visualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ const GridVisualizerGrid = forwardRef(
const [ gridInfo, setGridInfo ] = useState( () =>
getGridInfo( gridElement )
);
const [ isDroppingAllowed, setIsDroppingAllowed ] = useState( false );

useEffect( () => {
const observers = [];
Expand All @@ -68,60 +67,59 @@ const GridVisualizerGrid = forwardRef(
};
}, [ gridElement ] );

useEffect( () => {
function onGlobalDrag() {
setIsDroppingAllowed( true );
}
function onGlobalDragEnd() {
setIsDroppingAllowed( false );
}
document.addEventListener( 'drag', onGlobalDrag );
document.addEventListener( 'dragend', onGlobalDragEnd );
return () => {
document.removeEventListener( 'drag', onGlobalDrag );
document.removeEventListener( 'dragend', onGlobalDragEnd );
};
}, [] );

return (
<BlockPopoverCover
className={ clsx( 'block-editor-grid-visualizer', {
'is-dropping-allowed': isDroppingAllowed,
} ) }
clientId={ gridClientId }
__unstablePopoverSlot="__unstable-block-tools-after"
>
<div
ref={ ref }
className="block-editor-grid-visualizer__grid"
style={ gridInfo.style }
>
{ isManualGrid ? (
<ManualGridVisualizer
gridClientId={ gridClientId }
gridInfo={ gridInfo }
/>
) : (
Array.from( { length: gridInfo.numItems }, ( _, i ) => (
<GridVisualizerCell
key={ i }
color={ gridInfo.currentColor }
/>
) )
) }
</div>
</BlockPopoverCover>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has all moved into GridPopover

<>
<GridPopunder
gridClientId={ gridClientId }
gridInfo={ gridInfo }
isManualGrid={ isManualGrid }
/>
{ isManualGrid && (
<GridPopover
ref={ ref }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a bug here caused by ref only being passed/set when isManualGrid is true. It means that you're able to resize a grid item beyond the bounds of the grid block when it's in auto mode.

Kapture.2024-08-12.at.15.42.13.mp4

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed in f73ca9f. The annoying aspect is that it means some parts of GridPopover always have to be rendered even when there's not much going on, but I think it's necessary. I tried to optimize it by moving the items into a separate component.

To properly finish #64162, the auto grid will also need a single appender in the next available cell, so something like this will be needed anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To properly finish #64162, the auto grid will also need a single appender in the next available cell, so something like this will be needed anyway.

I think we can ignore that tbh. It's better imo to have it consistent across container blocks.

gridClientId={ gridClientId }
gridInfo={ gridInfo }
/>
) }
</>
);
}
);

function ManualGridVisualizer( { gridClientId, gridInfo } ) {
/**
* A popover component that renders in a slot over the grid block.
*
* This provides interactive elements of the grid visualization —
* block inserters and drop zones.
*
* @param {Object} props
* @param {string} props.gridClientId
* @param {Object} props.gridInfo
*/
const GridPopover = forwardRef( ( { gridClientId, gridInfo }, ref ) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ManualGridVisualizer is now renamed to GridPopover, and it now encompasses all the interactive aspects of the grid visualizer. It renders it's own popover over the grid.

const [ isDroppingAllowed, setIsDroppingAllowed ] = useState( false );
const [ highlightedRect, setHighlightedRect ] = useState( null );

const gridItems = useSelect(
( select ) => select( blockEditorStore ).getBlocks( gridClientId ),
[ gridClientId ]
);

useEffect( () => {
function onGlobalDrag() {
setIsDroppingAllowed( true );
}
function onGlobalDragEnd() {
setIsDroppingAllowed( false );
}
document.addEventListener( 'drag', onGlobalDrag );
document.addEventListener( 'dragend', onGlobalDragEnd );
return () => {
document.removeEventListener( 'drag', onGlobalDrag );
document.removeEventListener( 'dragend', onGlobalDragEnd );
};
}, [] );

const occupiedRects = useMemo( () => {
const rects = [];
for ( const block of gridItems ) {
Expand All @@ -146,56 +144,117 @@ function ManualGridVisualizer( { gridClientId, gridInfo } ) {
return rects;
}, [ gridItems ] );

return range( 1, gridInfo.numRows ).map( ( row ) =>
range( 1, gridInfo.numColumns ).map( ( column ) => {
const isCellOccupied = occupiedRects.some( ( rect ) =>
rect.contains( column, row )
);
const isHighlighted =
highlightedRect?.contains( column, row ) ?? false;
return (
<GridVisualizerCell
key={ `${ row }-${ column }` }
color={ gridInfo.currentColor }
className={ isHighlighted && 'is-highlighted' }
>
{ isCellOccupied ? (
<GridVisualizerDropZone
column={ column }
row={ row }
gridClientId={ gridClientId }
gridInfo={ gridInfo }
setHighlightedRect={ setHighlightedRect }
/>
) : (
<GridVisualizerAppender
column={ column }
row={ row }
gridClientId={ gridClientId }
gridInfo={ gridInfo }
setHighlightedRect={ setHighlightedRect }
/>
) }
</GridVisualizerCell>
);
} )
return (
<BlockPopoverCover
__unstablePopoverSlot="__unstable-block-tools-after"
className={ clsx( 'block-editor-grid-visualizer', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class names in this file have come out of sync with the component names. It used to be that GridVisualizer rendered an element with className = 'block-editor-grid-visualizer' and so on. Should we update them?

Also, is it bad that both BlockPopover and BlockPopunder render an element with the same classname?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I've pushed a commit that updates these. GridPopunder doesn't need classnames it relies on the inline css, so removing those solves the duplication. I changed the GridPopover classnames to block-editor-grid-visualizer-popover to match the components.

Also removed another unused classname.

It's not perfect, but I think good enough right now.

'is-dropping-allowed': isDroppingAllowed,
} ) }
clientId={ gridClientId }
>
<div
ref={ ref }
className="block-editor-grid-visualizer__grid"
style={ gridInfo.style }
>
{ range( 1, gridInfo.numRows ).map( ( row ) =>
range( 1, gridInfo.numColumns ).map( ( column ) => {
const isCellOccupied = occupiedRects.some( ( rect ) =>
rect.contains( column, row )
);
const isHighlighted =
highlightedRect?.contains( column, row ) ?? false;

return (
<div
key={ `${ row }-${ column }` }
className={ clsx(
'block-editor-grid-visualizer__cell',
{
'is-highlighted': isHighlighted,
}
) }
>
{ isCellOccupied ? (
<GridVisualizerDropZone
column={ column }
row={ row }
gridClientId={ gridClientId }
gridInfo={ gridInfo }
setHighlightedRect={
setHighlightedRect
}
/>
) : (
<GridVisualizerAppender
column={ column }
row={ row }
gridClientId={ gridClientId }
gridInfo={ gridInfo }
setHighlightedRect={
setHighlightedRect
}
/>
) }
</div>
);
} )
) }
</div>
</BlockPopoverCover>
);
}
} );

function GridVisualizerCell( { color, children, className } ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to get rid of GridVisualizerCell as it wasn't doing very much, especially in GridPopover where it's just a <div>.

In GridPopunder it's a <div> with a some styles, so I think it still doesn't need its own component.

return (
<div
className={ clsx(
'block-editor-grid-visualizer__cell',
className
) }
style={ {
boxShadow: `inset 0 0 0 1px color-mix(in srgb, ${ color } 20%, #0000)`,
/**
* A popover component that renders inline under the grid block.
*
* This provides non-interactive elements of the grid visualization and
* renders under the block so that the background colors are not atop
* the block content.
*
* @param {Object} props
* @param {string} props.gridClientId
* @param {Object} props.gridInfo
* @param {boolean} props.isManualGrid
*/
function GridPopunder( { gridClientId, gridInfo, isManualGrid } ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GridPopunder (not sure if the name is too twee) now renders the blue cells in the background. It's pretty similar to the auto mode cells in trunk in terms of code.

const color = gridInfo.currentColor;
const cellStyle = isManualGrid
? {
backgroundColor: `rgba(var(--wp-admin-theme-color--rgb), 0.2)`,
border: `1px dashed rgb(var(--wp-admin-theme-color--rgb))`,
borderRadius: '2px',
color,
} }
opacity: 0.2,
}
: {
border: `1px dashed ${ color }`,
borderRadius: '2px',
color,
opacity: 0.2,
};

return (
<BlockPopoverCover
inline
className="block-editor-grid-visualizer"
clientId={ gridClientId }
// Override layout margin and popover's zIndex.
contentStyle={ { margin: 0, zIndex: 0 } }
>
{ children }
</div>
<div
className="block-editor-grid-visualizer__grid"
style={ gridInfo.style }
>
{ Array.from( { length: gridInfo.numItems }, ( _, i ) => (
<div
key={ i }
className="block-editor-grid-visualizer__cell"
style={ cellStyle }
></div>
) ) }
</div>
</BlockPopoverCover>
);
}

Expand Down
19 changes: 12 additions & 7 deletions packages/block-editor/src/components/grid/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@
}
}

.block-editor-grid-visualizer__grid {
display: grid;
}

.block-editor-grid-visualizer__cell {
display: grid;
position: relative;
Expand All @@ -37,7 +33,7 @@
overflow: hidden;

.block-editor-grid-visualizer__appender {
box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 20%, #0000);
box-shadow: none;
color: inherit;
overflow: hidden;
height: 100%;
Expand All @@ -48,17 +44,26 @@

}

.block-editor-grid-visualizer__drop-zone {
opacity: 0;
}

&.is-highlighted {
.block-editor-inserter,
.block-editor-grid-visualizer__drop-zone {
background: var(--wp-admin-theme-color);
background: rgba(var(--wp-admin-theme-color--rgb), 0.25);
border: 1px solid var(--wp-admin-theme-color);
}
}

&:hover .block-editor-grid-visualizer__appender,
.block-editor-grid-visualizer__appender:focus {
opacity: 1;
background-color: color-mix(in srgb, currentColor 20%, #0000);
box-shadow: none;
background-color: rgba(var(--wp-admin-theme-color--rgb), 0.05);
border: 1px dashed;
border-radius: 2px;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we have a $border-radius var for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yep, that was lazy. Now updated.

color: var(--wp-admin-theme-color);
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/block-editor/src/components/grid/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ export function getGridInfo( gridElement ) {
gridTemplateColumns,
gridTemplateRows,
gap: getComputedCSS( gridElement, 'gap' ),
display: 'grid',
padding: getComputedCSS( gridElement, 'padding' ),
},
};
Expand Down
Loading
Loading