diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 25fe5746a04122..279bf2adc2e6e0 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -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 diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md index 7aa790dd977899..24b060605da718 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-living.md +++ b/docs/reference-guides/theme-json-reference/theme-json-living.md @@ -52,6 +52,16 @@ Settings related to borders. --- +### shadow + +Settings related to shadows. + +| Property | Type | Default | Props | +| --- | --- | --- |--- | +| palette | array | | name, shadow, slug | + +--- + ### color Settings related to colors. diff --git a/packages/block-library/src/button/block.json b/packages/block-library/src/button/block.json index f34437f74b573e..cc9921953abf66 100644 --- a/packages/block-library/src/button/block.json +++ b/packages/block-library/src/button/block.json @@ -83,6 +83,7 @@ } }, "reusable": false, + "shadow": true, "spacing": { "__experimentalSkipSerialization": true, "padding": [ "horizontal", "vertical" ], diff --git a/packages/edit-site/src/components/global-styles/hooks.js b/packages/edit-site/src/components/global-styles/hooks.js index c767f1a488cbfd..0c616ab7f50a95 100644 --- a/packages/edit-site/src/components/global-styles/hooks.js +++ b/packages/edit-site/src/components/global-styles/hooks.js @@ -211,6 +211,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; diff --git a/packages/edit-site/src/components/global-styles/screen-border.js b/packages/edit-site/src/components/global-styles/screen-border.js index d2d3707271dede..3449f57f987b79 100644 --- a/packages/edit-site/src/components/global-styles/screen-border.js +++ b/packages/edit-site/src/components/global-styles/screen-border.js @@ -9,15 +9,18 @@ import { __ } from '@wordpress/i18n'; import ScreenHeader from './header'; import BorderPanel, { useHasBorderPanel } from './border-panel'; import BlockPreviewPanel from './block-preview-panel'; +import ShadowPanel, { useHasShadowControl } from './shadow-panel'; function ScreenBorder( { name } ) { const hasBorderPanel = useHasBorderPanel( name ); + const hasShadowPanel = useHasShadowControl( name ); return ( <> { hasBorderPanel && } + { hasShadowPanel && } ); } diff --git a/packages/edit-site/src/components/global-styles/shadow-panel.js b/packages/edit-site/src/components/global-styles/shadow-panel.js new file mode 100644 index 00000000000000..106203dacd0935 --- /dev/null +++ b/packages/edit-site/src/components/global-styles/shadow-panel.js @@ -0,0 +1,175 @@ +/** + * 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, + BaseControl, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { shadow as shadowIcon } from '@wordpress/icons'; +import { useCallback } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { getSupportedGlobalStylesPanels, useStyle, useSetting } from './hooks'; +import { IconWithCurrentColor } from './icon-with-current-color'; + +export function useHasShadowControl( name ) { + const supports = getSupportedGlobalStylesPanels( name ); + return supports.includes( 'shadow' ); +} + +export default function ShadowPanel( { name } ) { + const [ shadow, setShadow ] = useStyle( 'shadow', name ); + const [ userShadow ] = useStyle( 'shadow', name, 'user' ); + const hasShadow = () => !! userShadow; + + const resetShadow = () => setShadow( undefined ); + const resetAll = useCallback( + () => resetShadow( undefined ), + [ resetShadow ] + ); + + return ( + + + + + + + + ); +} + +const ShadowPopover = ( { shadow, onShadowChange } ) => { + const popoverProps = { + placement: 'left-start', + offset: 36, + shift: true, + }; + + return ( + ( + + + + ) } + /> + ); +}; + +function renderShadowToggle() { + return ( { onToggle, isOpen } ) => { + const toggleProps = { + onClick: onToggle, + className: classnames( { 'is-open': isOpen } ), + 'aria-expanded': isOpen, + }; + + return ( + + ); + }; +} + +function ShadowPopoverContainer( { shadow, onShadowChange } ) { + const [ defaultShadows ] = useSetting( 'shadow.palette.default' ); + const [ themeShadows ] = useSetting( 'shadow.palette.theme' ); + + return ( +
+ + { __( 'Drop shadows' ) } + + + +
+ ); +} + +function ShadowPresets( { label, presets, activeShadow, onSelect } ) { + return ! presets ? null : ( +
+ + { label } + + + + { presets.map( ( { name, shadow }, i ) => ( + + onSelect( + shadow === activeShadow ? undefined : shadow + ) + } + /> + ) ) } + +
+ ); +} + +function ShadowIndicator( { label, isActive, onSelect } ) { + return ( + + ); +} diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index 5616a068b594c8..f427c247d5ef56 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -146,3 +146,36 @@ $block-preview-height: 150px; max-height: 200px; overflow-y: scroll; } + +.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; + } + } +} + +.edit-site-global-styles__shadow-indicator { + color: $gray-800; + border: $gray-200 $border-width solid; + border-radius: $radius-block-ui; + padding: $grid-unit-10; + cursor: pointer; + + &.active, + &.components-button:active { + color: $gray-100; + background-color: $gray-900; + border-color: $gray-900; + } +} diff --git a/packages/edit-site/src/components/global-styles/utils.js b/packages/edit-site/src/components/global-styles/utils.js index 14f3b868294172..4811d24c84e1ed 100644 --- a/packages/edit-site/src/components/global-styles/utils.js +++ b/packages/edit-site/src/components/global-styles/utils.js @@ -61,6 +61,12 @@ export const PRESET_METADATA = [ valueFunc: ( { slug } ) => `url( '#wp-duotone-${ slug }' )`, classes: [], }, + { + path: [ 'shadow', 'palette' ], + valueKey: 'shadow', + cssVarInfix: 'shadow', + classes: [], + }, { path: [ 'typography', 'fontSizes' ], valueFunc: ( preset, { typography: typographySettings } ) => @@ -96,6 +102,7 @@ export const STYLE_PATH_TO_CSS_VAR_INFIX = { 'elements.heading.backgroundColor': 'background-color', 'elements.heading.gradient': 'gradient', 'color.gradient': 'gradient', + shadow: 'shadow', 'typography.fontSize': 'font-size', 'typography.fontFamily': 'font-family', };