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

Disable core shadow presets by default, let themes opt-in #58766

Merged
merged 4 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Settings related to shadows.

| Property | Type | Default | Props |
| --- | --- | --- |--- |
| defaultPresets | boolean | true | |
| defaultPresets | boolean | false | |
| presets | array | | name, shadow, slug |

---
Expand Down
1 change: 1 addition & 0 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@ public static function get_element_class_name( $element ) {
array( 'spacing', 'margin' ),
array( 'spacing', 'padding' ),
array( 'typography', 'lineHeight' ),
array( 'shadow', 'defaultPresets' ),
);

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@
"text": true
},
"shadow": {
"defaultPresets": true,
Copy link
Contributor

@ajlende ajlende Mar 14, 2024

Choose a reason for hiding this comment

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

@madhusudhand This is a breaking change for themes that have shadow presets with the same slug as the core presets as it changes the CSS output for the theme. It should have a theme.json version bump and migration to maintain backwards compatibility.

I've been discussing this in #58409 (comment) since I want to change the default for the font sizes presets as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

This change updates defaultPresets from true to false, and also it is controlled by appearanceTools setting.
Meaning that defaultPresets are off by default and when appearanceTools is set to true, they are enabled, which makes existing themes that are using default presets to work as before.

Also, I created #59893 to discuss on this idea of theme being able to add(override) a preset with same slug as core preset.

Copy link
Contributor

@ajlende ajlende Mar 18, 2024

Choose a reason for hiding this comment

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

Meaning that defaultPresets are off by default and when appearanceTools is set to true, they are enabled, which makes existing themes that are using default presets to work as before.

appearanceTools is also false by default, so it's still a problem for themes that haven't configured either.

Before this change, with a theme that has custom settings.shadow.presets defined with matching slugs to those in the defailt lib/theme.json and settings.shadow.defaultPresets and settings.appearanceTools both undefined, you'll end up with different CSS that gets output to the page.

In the first case the default styles will be output and in the second case, the theme styles will be output.

Here's an example of what I'm talking about.

// Relevant parts of theme.json
{
  "settings": {
    // `appearanceTools` is not set
    "shadow": {
      // `defaultPresets` is not set
      "presets": [
        {
          "name": "Natural",
          "slug": "natural",
          "shadow": "2px 2px 3px #000"
        }
      ]
    }
  }
}
/* Generated CSS before */
--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);
/* Generated CSS after */
--wp--preset--shadow--natural: 2px 2px 3px #000;

It's because to the settings.shadow.defaultPresets being used as the value for prevent_override in PRESETS_METADATA in WP_Theme_JSON. The setting defines the behavior of matching slugs in the default and theme origins for presets in theme.json.

'prevent_override' => array( 'shadow', 'defaultPresets' ),

// Filter out default slugs from theme presets when defaults should not be overridden.
if ( 'theme' === $origin && $prevent_override ) {
$slugs_node = static::get_default_slugs( $this->theme_json, $node['path'] );
$preset_global = _wp_array_get( $slugs_global, $preset_metadata['path'], array() );
$preset_node = _wp_array_get( $slugs_node, $preset_metadata['path'], array() );
$preset_slugs = array_merge_recursive( $preset_global, $preset_node );
$content = static::filter_slugs( $content, $preset_slugs );
}

I'm suggesting that we revert this for 6.5 (at least this line since it is the one causing the problems). Then we can use the theme.json version bump to opt-in to breaking changes like this.

I'm adding the theme.json version bump in #58409. So you'd just need to update the migration from that PR to make sure that existing themes are unaffected.

Hopefully that all makes sense. 😅

Copy link
Member Author

Choose a reason for hiding this comment

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

Thank for details @ajlende.
I see that it may break a shadow when the following conditions are met

  • appearanceTools: false
  • theme defined custom shadows
  • and they are defined with same slug as defaultPresets

Also, prior to 6.5 shadows are enabled for button block and in global styles only.
It seems to be very unlikely edge case and shouldn't have big impact on themes.

@annezazu @swissspidy @t-hamano what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also cc @fabiankaegy editor triage co-lead.

Copy link
Contributor

Choose a reason for hiding this comment

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

I decided it was best to create a dedicated issue where this can be discussed.

#59989

This is also useful as it can be placed in Triage on the WP 6.5 Editor board for review by Editor triage leads.

"defaultPresets": false,
"presets": [
{
"name": "Natural",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,7 @@ import { getValueFromVariable, TOOLSPANEL_DROPDOWNMENU_PROPS } from './utils';
import { overrideOrigins } from '../../store/get-block-settings';
import { setImmutably } from '../../utils/object';
import { getBorderPanelLabel } from '../../hooks/border';
import { ShadowPopover } from './shadow-panel-components';

function useHasShadowControl( settings ) {
return !! settings?.shadow;
}
import { ShadowPopover, useShadowPresets } from './shadow-panel-components';

export function useHasBorderPanel( settings ) {
const controls = [
Expand Down Expand Up @@ -56,6 +52,11 @@ function useHasBorderWidthControl( settings ) {
return settings?.border?.width;
}

function useHasShadowControl( settings ) {
const shadows = useShadowPresets( settings );
return !! settings?.shadow && shadows.length > 0;
}

function BorderToolsPanel( {
resetAllFilter,
onChange,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
Dropdown,
privateApis as componentsPrivateApis,
} from '@wordpress/components';
import { useMemo } from '@wordpress/element';
import { shadow as shadowIcon, Icon, check } from '@wordpress/icons';

/**
Expand All @@ -24,15 +25,16 @@ import classNames from 'classnames';
*/
import { unlock } from '../../lock-unlock';

export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) {
const defaultShadows = settings?.shadow?.presets?.default || [];
const themeShadows = settings?.shadow?.presets?.theme || [];
const defaultPresetsEnabled = settings?.shadow?.defaultPresets;
/**
* Shared reference to an empty array for cases where it is important to avoid
* returning a new array reference on every invocation.
*
* @type {Array}
*/
const EMPTY_ARRAY = [];

const shadows = [
...( defaultPresetsEnabled ? defaultShadows : [] ),
...themeShadows,
];
export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) {
const shadows = useShadowPresets( settings );

return (
<div className="block-editor-global-styles__shadow-popover-container">
Expand All @@ -43,6 +45,14 @@ export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) {
activeShadow={ shadow }
onSelect={ onShadowChange }
/>
<div className="block-editor-global-styles__clear-shadow">
<Button
variant="tertiary"
onClick={ () => onShadowChange( undefined ) }
>
{ __( 'Clear' ) }
</Button>
</div>
</VStack>
</div>
);
Expand All @@ -64,6 +74,7 @@ export function ShadowPresets( { presets, activeShadow, onSelect } ) {
key={ slug }
label={ name }
isActive={ shadow === activeShadow }
type={ slug === 'unset' ? 'unset' : 'preset' }
onSelect={ () =>
onSelect( shadow === activeShadow ? undefined : shadow )
}
Expand All @@ -74,7 +85,7 @@ export function ShadowPresets( { presets, activeShadow, onSelect } ) {
);
}

export function ShadowIndicator( { label, isActive, onSelect, shadow } ) {
export function ShadowIndicator( { type, label, isActive, onSelect, shadow } ) {
const { CompositeItemV2: CompositeItem } = unlock( componentsPrivateApis );
return (
<CompositeItem
Expand All @@ -89,7 +100,12 @@ export function ShadowIndicator( { label, isActive, onSelect, shadow } ) {
) }
render={
<Button
className="block-editor-global-styles__shadow-indicator"
className={ classNames(
'block-editor-global-styles__shadow-indicator',
{
unset: type === 'unset',
}
) }
onClick={ onSelect }
label={ label }
style={ { boxShadow: shadow } }
Expand Down Expand Up @@ -149,3 +165,30 @@ function renderShadowToggle() {
);
};
}

export function useShadowPresets( settings ) {
return useMemo( () => {
if ( ! settings?.shadow ) {
return EMPTY_ARRAY;
}

const defaultPresetsEnabled = settings?.shadow?.defaultPresets;
const { default: defaultShadows, theme: themeShadows } =
settings?.shadow?.presets ?? {};
const unsetShadow = {
name: __( 'Unset' ),
slug: 'unset',
shadow: 'none',
};

const shadowPresets = [
...( ( defaultPresetsEnabled && defaultShadows ) || EMPTY_ARRAY ),
...( themeShadows || EMPTY_ARRAY ),
];
if ( shadowPresets.length ) {
shadowPresets.unshift( unsetShadow );
}

return shadowPresets;
}, [ settings ] );
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
padding-bottom: $grid-unit-10;
}

.block-editor-global-styles__clear-shadow {
text-align: right;
}

.block-editor-global-styles-filters-panel__dropdown,
.block-editor-global-styles__shadow-dropdown {
display: block;
Expand Down Expand Up @@ -54,6 +58,10 @@
&:hover {
transform: scale(1.2);
}

&.unset {
background: linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%);
}
}

.block-editor-global-styles-advanced-panel__custom-css-input textarea {
Expand Down
6 changes: 6 additions & 0 deletions phpunit/class-wp-theme-json-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ public function test_get_settings_appearance_true_opts_in() {
'typography' => array(
'lineHeight' => true,
),
'shadow' => array(
'defaultPresets' => true,
),
'blocks' => array(
'core/paragraph' => array(
'typography' => array(
Expand Down Expand Up @@ -321,6 +324,9 @@ public function test_get_settings_appearance_true_opts_in() {
'typography' => array(
'lineHeight' => false,
),
'shadow' => array(
'defaultPresets' => true,
),
),
),
);
Expand Down
2 changes: 1 addition & 1 deletion schemas/json/theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
"defaultPresets": {
"description": "Allow users to choose shadows from the default shadow presets.",
"type": "boolean",
"default": true
"default": false
},
"presets": {
"description": "Shadow presets for the shadow picker.\nGenerates a single custom property (`--wp--preset--shadow--{slug}`) per preset value.",
Expand Down
Loading