Skip to content

Commit

Permalink
Update BlockStyles control
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronrobertshaw committed Jan 3, 2024
1 parent f566747 commit c4ce9f8
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 102 deletions.
136 changes: 81 additions & 55 deletions packages/block-editor/src/components/block-styles/index.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,59 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { useState } from '@wordpress/element';
import { debounce, useViewportMatch } from '@wordpress/compose';
import {
Button,
__experimentalTruncate as Truncate,
ColorIndicator,
Flex,
FlexItem,
Popover,
privateApis as componentsPrivateApis,
__experimentalHStack as HStack,
__experimentalZStack as ZStack,
} from '@wordpress/components';
import { debounce, useViewportMatch } from '@wordpress/compose';
import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';
import BlockStylesPreviewPanel from './preview-panel';
import useStylesForBlocks from './use-styles-for-block';
import { getDefaultStyle } from './utils';

const noop = () => {};
const { CustomSelect, CustomSelectItem } = unlock( componentsPrivateApis );

const BlockStyleItem = ( { blockStyle } ) => {
const indicators = [
blockStyle.styles?.color?.background,
blockStyle.styles?.color?.text,
];

return (
<HStack justify="flex-start">
<ZStack isLayered={ false } offset={ -8 }>
{ indicators.map( ( indicator, index ) => (
<Flex key={ index } expanded={ false }>
<ColorIndicator colorValue={ indicator } />
</Flex>
) ) }
</ZStack>
<FlexItem title={ blockStyle.label }>{ blockStyle.label }</FlexItem>
</HStack>
);
};

// Block Styles component for the Settings Sidebar.
function BlockStyles( { clientId, onSwitch = noop, onHoverClassName = noop } ) {
const {
onSelect,
stylesToRender,
activeStyle,
genericPreviewBlock,
className: previewClassName,
} = useStylesForBlocks( {
clientId,
onSwitch,
} );
} = useStylesForBlocks( { clientId, onSwitch } );

const [ hoveredStyle, setHoveredStyle ] = useState( null );
const isMobileViewport = useViewportMatch( 'medium', '<' );

Expand All @@ -43,58 +63,64 @@ function BlockStyles( { clientId, onSwitch = noop, onHoverClassName = noop } ) {

const debouncedSetHoveredStyle = debounce( setHoveredStyle, 250 );

const onSelectStylePreview = ( style ) => {
onSelect( style );
const handleOnChange = ( style ) => {
onSelect( { name: style } );
onHoverClassName( null );
setHoveredStyle( null );
debouncedSetHoveredStyle.cancel();
};

const styleItemHandler = ( item ) => {
if ( hoveredStyle === item ) {
const hoverStyleHandler = ( style ) => {
if ( hoveredStyle === style ) {
debouncedSetHoveredStyle.cancel();
return;
}
debouncedSetHoveredStyle( item );
onHoverClassName( item?.name ?? null );

debouncedSetHoveredStyle( style );
onHoverClassName( style?.name ?? null );
};

const renderSelectedBlockStlye = ( currentStyle ) => {
const currentBlockStyle = stylesToRender.find(
( style ) => style.name === currentStyle
);

if ( ! currentBlockStyle ) {
return null;
}

return <BlockStyleItem blockStyle={ currentBlockStyle } />;
};

const defaultStyle = getDefaultStyle( stylesToRender );

return (
<div className="block-editor-block-styles">
<div className="block-editor-block-styles__variants">
{ stylesToRender.map( ( style ) => {
const buttonText = style.label || style.name;

return (
<Button
__next40pxDefaultSize
className={ classnames(
'block-editor-block-styles__item',
{
'is-active':
activeStyle.name === style.name,
}
) }
key={ style.name }
variant="secondary"
label={ buttonText }
onMouseEnter={ () => styleItemHandler( style ) }
onFocus={ () => styleItemHandler( style ) }
onMouseLeave={ () => styleItemHandler( null ) }
onBlur={ () => styleItemHandler( null ) }
onClick={ () => onSelectStylePreview( style ) }
aria-current={ activeStyle.name === style.name }
>
<Truncate
numberOfLines={ 1 }
className="block-editor-block-styles__item-text"
>
{ buttonText }
</Truncate>
</Button>
);
} ) }
</div>
<CustomSelect
className="block-editor-block-styles__button"
defaultValue={ defaultStyle?.name }
label={ __( 'Select a block style' ) }
onChange={ handleOnChange }
renderSelectedValue={ renderSelectedBlockStlye }
value={ activeStyle?.name }
hideLabelFromVision
popoverProps={ {
wrapperProps: { style: { zIndex: 1000000 } },
} }
>
{ stylesToRender.map( ( blockStyle, index ) => (
<CustomSelectItem
key={ index }
value={ blockStyle.name }
onMouseEnter={ () => hoverStyleHandler( blockStyle ) }
onMouseLeave={ () => hoverStyleHandler( null ) }
onFocus={ () => hoverStyleHandler( blockStyle ) }
onBlur={ () => hoverStyleHandler( null ) }
>
<BlockStyleItem blockStyle={ blockStyle } />
</CustomSelectItem>
) ) }
</CustomSelect>
{ hoveredStyle && ! isMobileViewport && (
<Popover
placement="left-start"
Expand All @@ -103,7 +129,7 @@ function BlockStyles( { clientId, onSwitch = noop, onHoverClassName = noop } ) {
>
<div
className="block-editor-block-styles__preview-panel"
onMouseLeave={ () => styleItemHandler( null ) }
onMouseLeave={ () => hoverStyleHandler( null ) }
>
<BlockStylesPreviewPanel
activeStyle={ activeStyle }
Expand Down
52 changes: 7 additions & 45 deletions packages/block-editor/src/components/block-styles/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,55 +17,17 @@
}
}

.block-editor-block-styles__variants {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: $grid-unit-10;

button.components-button.block-editor-block-styles__item {
color: $gray-900;
box-shadow: inset 0 0 0 $border-width $gray-300;
display: inline-block;
width: calc(50% - #{$grid-unit-05});

&:hover {
color: var(--wp-admin-theme-color);
box-shadow: inset 0 0 0 $border-width $gray-300;
}

&.is-active,
&.is-active:hover {
background-color: $gray-900;
box-shadow: none;
}

&.is-active .block-editor-block-styles__item-text,
&.is-active:hover .block-editor-block-styles__item-text {
color: $white;
}

&:focus,
&.is-active:focus {
@include block-toolbar-button-style__focus();
}
}

.block-editor-block-styles__item-text {
word-break: break-all;
// The Button component is white-space: nowrap, and that won't work with line-clamp.
white-space: normal;

// Without this, the ellipsis can sometimes be partially hidden by the Button padding.
text-align: start;
text-align-last: center;
}
}

// To prevent overflow in the preview container,
// ensure that block contents' margin and padding
// do not add to the block container's width.
.block-editor-block-styles__block-preview-container,
.block-editor-block-styles__block-preview-container * {
box-sizing: border-box !important;
}

.block-editor-block-styles__button {
/* Increased specificity required to overcome default button padding. */
&#{&} {
padding: 6px 12px;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,34 @@ function useGenericPreviewBlock( block, type ) {
*/
export default function useStylesForBlocks( { clientId, onSwitch } ) {
const selector = ( select ) => {
const { getBlock } = select( blockEditorStore );
const { getBlock, getSettings } = select( blockEditorStore );
const block = getBlock( clientId );

if ( ! block ) {
return {};
}

const blockType = getBlockType( block.name );
const { getBlockStyles } = select( blocksStore );
const styles = getBlockStyles( block.name );

// Add theme.json styles for each block style if available.
const variations =
getSettings().__experimentalStyles?.blocks?.[ block.name ]
?.variations ?? {};

if ( variations ) {
styles?.forEach( ( style, index ) => {
if ( variations[ style.name ] ) {
styles[ index ].styles = variations[ style.name ];
}
} );
}

return {
block,
blockType,
styles: getBlockStyles( block.name ),
styles,
className: block.attributes.className || '',
};
};
Expand Down

0 comments on commit c4ce9f8

Please sign in to comment.