Skip to content

Commit

Permalink
add shadow ui controls in global styles
Browse files Browse the repository at this point in the history
  • Loading branch information
madhusudhand committed Dec 30, 2022
1 parent c14a77b commit 0883fb7
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 1 deletion.
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
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
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 @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<>
<ScreenHeader title={ __( 'Border' ) } />
<BlockPreviewPanel name={ name } />
{ hasBorderPanel && <BorderPanel name={ name } /> }
{ hasShadowPanel && <ShadowPanel name={ name } /> }
</>
);
}
Expand Down
175 changes: 175 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,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 (
<ToolsPanel label={ __( 'Shadow' ) } resetAll={ resetAll }>
<ToolsPanelItem
label={ __( 'Drop 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">
{ __( 'Drop shadow' ) }
</FlexItem>
</HStack>
</Button>
);
};
}

function ShadowPopoverContainer( { shadow, onShadowChange } ) {
const [ defaultShadows ] = useSetting( 'shadow.palette.default' );
const [ themeShadows ] = useSetting( 'shadow.palette.theme' );

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

function ShadowPresets( { label, presets, activeShadow, onSelect } ) {
return ! presets ? null : (
<div>
<BaseControl.VisualLabel as="legend">
{ label }
</BaseControl.VisualLabel>

<Grid columns={ 2 }>
{ presets.map( ( { name, shadow }, i ) => (
<ShadowIndicator
key={ i }
label={ name }
isActive={ shadow === activeShadow }
onSelect={ () =>
onSelect(
shadow === activeShadow ? undefined : shadow
)
}
/>
) ) }
</Grid>
</div>
);
}

function ShadowIndicator( { label, isActive, onSelect } ) {
return (
<Button
className={ classnames(
'edit-site-global-styles__shadow-indicator',
{ active: isActive }
) }
onClick={ onSelect }
>
{ label }
</Button>
);
}
33 changes: 33 additions & 0 deletions packages/edit-site/src/components/global-styles/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
7 changes: 7 additions & 0 deletions packages/edit-site/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', 'palette' ],
valueKey: 'shadow',
cssVarInfix: 'shadow',
classes: [],
},
{
path: [ 'typography', 'fontSizes' ],
valueFunc: ( preset, { typography: typographySettings } ) =>
Expand Down Expand Up @@ -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',
};
Expand Down

0 comments on commit 0883fb7

Please sign in to comment.