Skip to content

Commit

Permalink
Shadow: Add shadow presets and UI tools in global styles (#46502)
Browse files Browse the repository at this point in the history
* add shadow ui controls in global styles

hide/show default shadows based on the setting from theme.json

add block style variations prefix

rename border menu to border & shadow

* update shadow presets

* Make the shadow panel use small buttons

* fix issues with global settings

* clip shadow outside 6px boundary

* update default shadow presets

* update variation path

* fix block variation styles for shadow

---------

Co-authored-by: Ben Dwyer <ben@escruffian.com>
  • Loading branch information
madhusudhand and Ben Dwyer authored Feb 1, 2023
1 parent 18e6dc3 commit d9da125
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 6 deletions.
2 changes: 1 addition & 1 deletion docs/reference-guides/core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Prompt visitors to take action with a button-style link. ([Source](https://githu

- **Name:** core/button
- **Category:** design
- **Supports:** anchor, color (background, gradients, text), spacing (padding), typography (fontSize, lineHeight), ~~alignWide~~, ~~align~~, ~~reusable~~
- **Supports:** anchor, color (background, gradients, text), shadow, spacing (padding), typography (fontSize, lineHeight), ~~alignWide~~, ~~align~~, ~~reusable~~
- **Attributes:** backgroundColor, gradient, linkTarget, placeholder, rel, text, textAlign, textColor, title, url, width

## Buttons
Expand Down
20 changes: 18 additions & 2 deletions lib/theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -187,16 +187,32 @@
"text": true
},
"shadow": {
"defaultPresets": true,
"presets": [
{
"name": "Natural",
"slug": "natural",
"shadow": "0 .2rem .3rem 0 rgba(0,0,0, 0.3), 0 .5rem .6rem 0 rgba(0,0,0, 0.4)"
"shadow": "6px 6px 9px rgba(0, 0, 0, 0.2)"
},
{
"name": "Deep",
"slug": "deep",
"shadow": "12px 12px 50px rgba(0, 0, 0, 0.4)"
},
{
"name": "Sharp",
"slug": "sharp",
"shadow": ".5rem .5rem 0 0 rgba(0,0,0, 0.4)"
"shadow": "6px 6px 0px rgba(0, 0, 0, 0.2)"
},
{
"name": "Outlined",
"slug": "outlined",
"shadow": "6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1)"
},
{
"name": "Crisp",
"slug": "crisp",
"shadow": "6px 6px 0px rgba(0, 0, 0, 1)"
}
]
},
Expand Down
7 changes: 7 additions & 0 deletions packages/block-editor/src/components/global-styles/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ export const PRESET_METADATA = [
valueFunc: ( { slug } ) => `url( '#wp-duotone-${ slug }' )`,
classes: [],
},
{
path: [ 'shadow', 'presets' ],
valueKey: 'shadow',
cssVarInfix: 'shadow',
classes: [],
},
{
path: [ 'typography', 'fontSizes' ],
valueFunc: ( preset, { typography: typographySettings } ) =>
Expand Down Expand Up @@ -127,6 +133,7 @@ export const STYLE_PATH_TO_CSS_VAR_INFIX = {
'elements.h6.typography.fontFamily': 'font-family',
'elements.h6.color.gradient': 'gradient',
'color.gradient': 'gradient',
shadow: 'shadow',
'typography.fontSize': 'font-size',
'typography.fontFamily': 'font-family',
};
Expand Down
1 change: 1 addition & 0 deletions packages/block-library/src/button/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
}
},
"reusable": false,
"shadow": true,
"spacing": {
"__experimentalSkipSerialization": true,
"padding": [ "horizontal", "vertical" ],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ function ContextMenu( { name, parentMenu = '' } ) {
<NavigationButtonAsItem
icon={ border }
path={ parentMenu + '/border' }
aria-label={ __( 'Border styles' ) }
aria-label={ __( 'Border & shadow styles' ) }
>
{ __( 'Border' ) }
{ __( 'Border & Shadow' ) }
</NavigationButtonAsItem>
) }
{ hasLayoutPanel && (
Expand Down
5 changes: 5 additions & 0 deletions packages/edit-site/src/components/global-styles/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ export function getSupportedGlobalStylesPanels( name ) {
supportKeys.push( 'blockGap' );
}

// check for shadow support
if ( blockType?.supports?.shadow ) {
supportKeys.push( 'shadow' );
}

Object.keys( STYLE_PROPERTY ).forEach( ( styleName ) => {
if ( ! STYLE_PROPERTY[ styleName ].support ) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,22 @@ import ScreenHeader from './header';
import BorderPanel, { useHasBorderPanel } from './border-panel';
import BlockPreviewPanel from './block-preview-panel';
import { getVariationClassName } from './utils';
import ShadowPanel, { useHasShadowControl } from './shadow-panel';

function ScreenBorder( { name, variation = '' } ) {
const hasBorderPanel = useHasBorderPanel( name );
const variationClassName = getVariationClassName( variation );
const hasShadowPanel = useHasShadowControl( name );
return (
<>
<ScreenHeader title={ __( 'Border' ) } />
<ScreenHeader title={ __( 'Border & Shadow' ) } />
<BlockPreviewPanel name={ name } variation={ variationClassName } />
{ hasBorderPanel && (
<BorderPanel name={ name } variation={ variation } />
) }
{ hasShadowPanel && (
<ShadowPanel name={ name } variation={ variation } />
) }
</>
);
}
Expand Down
174 changes: 174 additions & 0 deletions packages/edit-site/src/components/global-styles/shadow-panel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import {
__experimentalToolsPanel as ToolsPanel,
__experimentalToolsPanelItem as ToolsPanelItem,
__experimentalItemGroup as ItemGroup,
__experimentalHStack as HStack,
__experimentalVStack as VStack,
__experimentalGrid as Grid,
__experimentalHeading as Heading,
FlexItem,
Dropdown,
__experimentalDropdownContentWrapper as DropdownContentWrapper,
Button,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { shadow as shadowIcon, Icon, check } from '@wordpress/icons';
import { useCallback } from '@wordpress/element';
import { experiments as blockEditorExperiments } from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import { getSupportedGlobalStylesPanels } from './hooks';
import { IconWithCurrentColor } from './icon-with-current-color';
import { unlock } from '../../experiments';

const { useGlobalSetting, useGlobalStyle } = unlock( blockEditorExperiments );

export function useHasShadowControl( name ) {
const supports = getSupportedGlobalStylesPanels( name );
return supports.includes( 'shadow' );
}

export default function ShadowPanel( { name, variation = '' } ) {
const prefix = variation ? `variations.${ variation }.` : '';
const [ shadow, setShadow ] = useGlobalStyle( `${ prefix }shadow`, name );
const [ userShadow ] = useGlobalStyle( `${ prefix }shadow`, name, 'user' );
const hasShadow = () => !! userShadow;

const resetShadow = () => setShadow( undefined );
const resetAll = useCallback(
() => resetShadow( undefined ),
[ resetShadow ]
);

return (
<ToolsPanel label={ __( 'Shadow' ) } resetAll={ resetAll }>
<ToolsPanelItem
label={ __( 'Shadow' ) }
hasValue={ hasShadow }
onDeselect={ resetShadow }
isShownByDefault
>
<ItemGroup isBordered isSeparated>
<ShadowPopover
shadow={ shadow }
onShadowChange={ setShadow }
/>
</ItemGroup>
</ToolsPanelItem>
</ToolsPanel>
);
}

const ShadowPopover = ( { shadow, onShadowChange } ) => {
const popoverProps = {
placement: 'left-start',
offset: 36,
shift: true,
};

return (
<Dropdown
popoverProps={ popoverProps }
className="edit-site-global-styles__shadow-dropdown"
renderToggle={ renderShadowToggle() }
renderContent={ () => (
<DropdownContentWrapper paddingSize="medium">
<ShadowPopoverContainer
shadow={ shadow }
onShadowChange={ onShadowChange }
/>
</DropdownContentWrapper>
) }
/>
);
};

function renderShadowToggle() {
return ( { onToggle, isOpen } ) => {
const toggleProps = {
onClick: onToggle,
className: classnames( { 'is-open': isOpen } ),
'aria-expanded': isOpen,
};

return (
<Button { ...toggleProps }>
<HStack justify="flex-start">
<IconWithCurrentColor icon={ shadowIcon } size={ 24 } />
<FlexItem className="edit-site-global-styles__shadow-label">
{ __( 'Shadow' ) }
</FlexItem>
</HStack>
</Button>
);
};
}

function ShadowPopoverContainer( { shadow, onShadowChange } ) {
const [ defaultShadows ] = useGlobalSetting( 'shadow.presets.default' );
const [ themeShadows ] = useGlobalSetting( 'shadow.presets.theme' );
const [ defaultPresetsEnabled ] = useGlobalSetting(
'shadow.defaultPresets'
);

const shadows = [
...( defaultPresetsEnabled ? defaultShadows : [] ),
...( themeShadows || [] ),
];

return (
<div className="edit-site-global-styles__shadow-panel">
<VStack spacing={ 4 }>
<Heading level={ 5 }>{ __( 'Shadows' ) }</Heading>
<ShadowPresets
presets={ shadows }
activeShadow={ shadow }
onSelect={ onShadowChange }
/>
</VStack>
</div>
);
}

function ShadowPresets( { presets, activeShadow, onSelect } ) {
return ! presets ? null : (
<Grid columns={ 6 } gap={ 0 } align="center" justify="center">
{ presets.map( ( { name, shadow }, i ) => (
<ShadowIndicator
key={ i }
label={ name }
isActive={ shadow === activeShadow }
onSelect={ () =>
onSelect( shadow === activeShadow ? undefined : shadow )
}
shadow={ shadow }
/>
) ) }
</Grid>
);
}

function ShadowIndicator( { label, isActive, onSelect, shadow } ) {
return (
<div className="edit-site-global-styles__shadow-indicator-wrapper">
<Button
className="edit-site-global-styles__shadow-indicator"
onClick={ onSelect }
aria-label={ label }
style={ { boxShadow: shadow } }
>
{ isActive && <Icon icon={ check } /> }
</Button>
</div>
);
}
39 changes: 39 additions & 0 deletions packages/edit-site/src/components/global-styles/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,42 @@ $block-preview-height: 150px;
display: flex;
flex-direction: column;
}

.edit-site-global-styles__shadow-panel {
width: 230px;
}

.edit-site-global-styles__shadow-dropdown {
display: block;
padding: 0;

> button {
width: 100%;
padding: $grid-unit-10;

&.is-open {
background-color: $gray-100;
}
}
}

// wrapper to clip the shadow beyond 6px
.edit-site-global-styles__shadow-indicator-wrapper {
padding: 6px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}

// These styles are similar to the color palette.
.edit-site-global-styles__shadow-indicator {
color: $gray-800;
border: $gray-200 $border-width solid;
border-radius: $radius-block-ui;
cursor: pointer;
padding: 0;

height: 24px;
width: 24px;
}

1 comment on commit d9da125

@github-actions
Copy link

Choose a reason for hiding this comment

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

Flaky tests detected in d9da125.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/4061767979
📝 Reported issues:

Please sign in to comment.