From 0fac00c68cc70bb69886aa019db681ff28dc4c21 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 27 Sep 2024 16:53:36 +1000 Subject: [PATCH 1/9] Style Book: Add color tab --- ...se-multiple-origin-colors-and-gradients.js | 6 + .../src/components/global-styles/ui.js | 15 ++ .../src/components/style-book/constants.ts | 49 +++++- .../src/components/style-book/examples.ts | 146 +++++++++++++++++- .../src/components/style-book/index.js | 138 ++++++++++++++--- .../components/style-book/test/categories.js | 5 - .../src/components/style-book/types.ts | 36 ++++- 7 files changed, 361 insertions(+), 34 deletions(-) diff --git a/packages/block-editor/src/components/colors-gradients/use-multiple-origin-colors-and-gradients.js b/packages/block-editor/src/components/colors-gradients/use-multiple-origin-colors-and-gradients.js index ee27960529ede3..1163492c322378 100644 --- a/packages/block-editor/src/components/colors-gradients/use-multiple-origin-colors-and-gradients.js +++ b/packages/block-editor/src/components/colors-gradients/use-multiple-origin-colors-and-gradients.js @@ -55,6 +55,7 @@ export default function useMultipleOriginColorsAndGradients() { 'Theme', 'Indicates this palette comes from the theme.' ), + slug: 'theme', colors: themeColors, } ); } @@ -68,6 +69,7 @@ export default function useMultipleOriginColorsAndGradients() { 'Default', 'Indicates this palette comes from WordPress.' ), + slug: 'default', colors: defaultColors, } ); } @@ -77,6 +79,7 @@ export default function useMultipleOriginColorsAndGradients() { 'Custom', 'Indicates this palette comes from the theme.' ), + slug: 'custom', colors: customColors, } ); } @@ -96,6 +99,7 @@ export default function useMultipleOriginColorsAndGradients() { 'Theme', 'Indicates this palette comes from the theme.' ), + slug: 'theme', gradients: themeGradients, } ); } @@ -109,6 +113,7 @@ export default function useMultipleOriginColorsAndGradients() { 'Default', 'Indicates this palette comes from WordPress.' ), + slug: 'default', gradients: defaultGradients, } ); } @@ -118,6 +123,7 @@ export default function useMultipleOriginColorsAndGradients() { 'Custom', 'Indicates this palette is created by the user.' ), + slug: 'custom', gradients: customGradients, } ); } diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index 6cd465e237100a..4c1b00b283b06f 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -45,6 +45,7 @@ import ScreenCSS from './screen-css'; import ScreenRevisions from './screen-revisions'; import { unlock } from '../../lock-unlock'; import { store as editSiteStore } from '../../store'; +import { STYLE_BOOK_COLOR_GROUPS } from '../style-book/constants'; const SLOT_FILL_NAME = 'GlobalStylesMenu'; const { useGlobalStylesReset } = unlock( blockEditorPrivateApis ); @@ -191,6 +192,20 @@ function GlobalStylesStyleBook() { ) } onSelect={ ( blockName ) => { + if ( blockName === 'duotones' ) { + return; + } + + if ( + STYLE_BOOK_COLOR_GROUPS.find( + ( group ) => group.slug === blockName + ) + ) { + // Go to color palettes Global Styles. + navigator.goTo( '/colors/palette' ); + return; + } + // Now go to the selected block. navigator.goTo( '/blocks/' + encodeURIComponent( blockName ) ); } } diff --git a/packages/edit-site/src/components/style-book/constants.ts b/packages/edit-site/src/components/style-book/constants.ts index fc06d8f1409f0d..96352844177617 100644 --- a/packages/edit-site/src/components/style-book/constants.ts +++ b/packages/edit-site/src/components/style-book/constants.ts @@ -6,7 +6,46 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import type { StyleBookCategory } from './types'; +import type { StyleBookCategory, StyleBookColorGroup } from './types'; + +export const STYLE_BOOK_COLOR_GROUPS: StyleBookColorGroup[] = [ + { + slug: 'theme-colors', + title: __( 'Theme Colors' ), + origin: 'theme', + type: 'colors', + }, + { + slug: 'custom-colors', + title: __( 'Custom Colors' ), + origin: 'custom', + type: 'colors', + }, + { + slug: 'custom-gradients', + title: __( 'Custom Gradients' ), + origin: 'custom', // User. + type: 'gradients', + }, + { + slug: 'duotones', + title: __( 'Duotones' ), + origin: 'theme', + type: 'duotones', + }, + { + slug: 'default-colors', + title: __( 'Default Colors' ), + origin: 'default', + type: 'colors', + }, + { + slug: 'default-gradients', + title: __( 'Default Gradients' ), + origin: 'default', + type: 'gradients', + }, +]; export const STYLE_BOOK_THEME_SUBCATEGORIES: Omit< StyleBookCategory, @@ -74,7 +113,7 @@ export const STYLE_BOOK_CATEGORIES: StyleBookCategory[] = [ { slug: 'colors', title: __( 'Colors' ), - blocks: [ 'custom/colors' ], + blocks: [], }, { slug: 'theme', @@ -111,7 +150,7 @@ export const STYLE_BOOK_IFRAME_STYLES = ` .is-root-container { display: flow-root; } - + body { position: relative; padding: 32px !important; @@ -149,7 +188,7 @@ export const STYLE_BOOK_IFRAME_STYLES = ` .edit-site-style-book__examples.is-wide .edit-site-style-book__example { flex-direction: row; } - + .edit-site-style-book__subcategory-title, .edit-site-style-book__example-title { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; @@ -160,7 +199,7 @@ export const STYLE_BOOK_IFRAME_STYLES = ` text-align: left; text-transform: uppercase; } - + .edit-site-style-book__subcategory-title { font-size: 16px; margin-bottom: 40px; diff --git a/packages/edit-site/src/components/style-book/examples.ts b/packages/edit-site/src/components/style-book/examples.ts index 80807b10374c68..c9be0666846670 100644 --- a/packages/edit-site/src/components/style-book/examples.ts +++ b/packages/edit-site/src/components/style-book/examples.ts @@ -12,21 +12,158 @@ import { /** * Internal dependencies */ -import type { BlockExample } from './types'; +import type { + Block, + BlockExample, + ColorItem, + ColorOrigin, + Duotone, + MultiOriginPalettes, +} from './types'; +import { STYLE_BOOK_COLOR_GROUPS } from './constants'; + +// Base CSS styles to be applied to color block examples. +const defaultColorExampleStyles = { + dimensions: { minHeight: '52px' }, + border: { + width: '1px', + style: 'solid', + color: '#ddd', // Match horizontal rule under sub title headings + }, +}; + +/** + * Creates an example block to demo a given color item for the Style Book. + * A color example could be for a simple color, gradient, or duotone filter. + * + * @param {ColorItem} color The color for display. + * @param {string} type Type of color e.g. color, gradient, or duotone. + * @return {Block|undefined} Example block. + */ +function getColorExample( color: ColorItem, type: string ): Block | undefined { + if ( type === 'colors' ) { + return createBlock( 'core/group', { + backgroundColor: color.slug, + style: defaultColorExampleStyles, + } ); + } + + if ( type === 'gradients' ) { + return createBlock( 'core/group', { + gradient: color.slug, + style: defaultColorExampleStyles, + } ); + } + + if ( type === 'duotones' ) { + return createBlock( + 'core/group', + { + layout: { + type: 'grid', + columnCount: 2, + minimumColumnWidth: null, + }, + style: { spacing: { blockGap: '8px' } }, + }, + [ + createBlock( 'core/image', { + sizeSlug: 'medium', + url: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg', + aspectRatio: '16/9', + scale: 'cover', + style: { + layout: { columnSpan: 2, rowSpan: 1 }, + color: { + duotone: `var:preset|duotone|${ color.slug }`, + }, + }, + } ), + createBlock( 'core/group', { + style: { + ...defaultColorExampleStyles, + color: { background: ( color as Duotone ).colors[ 0 ] }, + dimensions: { minHeight: '20px' }, + }, + } ), + createBlock( 'core/group', { + style: { + ...defaultColorExampleStyles, + color: { background: ( color as Duotone ).colors[ 1 ] }, + dimensions: { minHeight: '20px' }, + }, + } ), + ] + ); + } +} + +/** + * Returns examples color examples for each origin + * e.g. Core (Default), Theme, and User. + * + * @param {MultiOriginPalettes} colors Global Styles color palettes per origin. + * @return {BlockExample[]} An array of color block examples. + */ +function getColorExamples( colors: MultiOriginPalettes ): BlockExample[] { + if ( ! colors ) { + return []; + } + + const examples: BlockExample[] = []; + + STYLE_BOOK_COLOR_GROUPS.forEach( ( group ) => { + const palette = colors[ group.type ].find( + ( origin: ColorOrigin ) => origin.slug === group.origin + ); + + if ( palette?.[ group.type ] ) { + const example: BlockExample = { + name: group.slug, + title: group.title, + category: 'colors', + blocks: [ + createBlock( + 'core/group', + { + layout: { + type: 'grid', + columnCount: 2, + minimumColumnWidth: null, + }, + style: { + spacing: { + blockGap: { top: '8px', left: '16px' }, + }, + }, + }, + palette[ group.type ].map( ( color: ColorItem ) => + getColorExample( color, group.type ) + ) + ), + ], + }; + examples.push( example ); + } + } ); + + return examples; +} /** * Returns a list of examples for registered block types. * + * @param {MultiOriginPalettes} colors Global styles colors grouped by origin e.g. Core, Theme, and User. * @return {BlockExample[]} An array of block examples. */ -export function getExamples(): BlockExample[] { +export function getExamples( colors: MultiOriginPalettes ): BlockExample[] { const nonHeadingBlockExamples = getBlockTypes() .filter( ( blockType ) => { const { name, example, supports } = blockType; return ( name !== 'core/heading' && !! example && - supports.inserter !== false + supports?.inserter !== false ); } ) .map( ( blockType ) => ( { @@ -58,6 +195,7 @@ export function getExamples(): BlockExample[] { } ); } ), }; + const colorExamples = getColorExamples( colors ); - return [ headingsExample, ...nonHeadingBlockExamples ]; + return [ headingsExample, ...colorExamples, ...nonHeadingBlockExamples ]; } diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 42b6e3f4fc99b6..423d45b86834e4 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -11,18 +11,26 @@ import { Composite, privateApis as componentsPrivateApis, } from '@wordpress/components'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, _x, sprintf } from '@wordpress/i18n'; import { BlockList, privateApis as blockEditorPrivateApis, store as blockEditorStore, + useSettings, __unstableEditorStyles as EditorStyles, __unstableIframe as Iframe, + __experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients, } from '@wordpress/block-editor'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { useSelect } from '@wordpress/data'; import { useResizeObserver } from '@wordpress/compose'; -import { useMemo, useState, memo, useContext } from '@wordpress/element'; +import { + useMemo, + useState, + memo, + useContext, + useEffect, +} from '@wordpress/element'; import { ENTER, SPACE } from '@wordpress/keycodes'; /** @@ -51,6 +59,83 @@ function isObjectEmpty( object ) { return ! object || Object.keys( object ).length === 0; } +/** + * Retrieves colors, gradients, and duotone filters from Global Styles. + * The inclusion of default (Core) palettes is controlled by the relevant + * theme.json property e.g. defaultPalette, defaultGradients, defaultDuotone. + * + * @return {Object} Object containing properties for each type of palette. + */ +function useMultiOriginPalettes() { + const { colors, gradients } = useMultipleOriginColorsAndGradients(); + + // Add duotone filters to the palettes data. + // TODO: Might need to include `disableCustomDuotones` setting or whatever to match colors/gradients from useMultipleOriginColorsAndGradients. + const [ + shouldDisplayDefaultDuotones, + customDuotones, + themeDuotones, + defaultDuotones, + ] = useSettings( + 'color.defaultDuotone', + 'color.duotone.custom', + 'color.duotone.theme', + 'color.duotone.default' + ); + + const palettes = useMemo( () => { + const result = { colors, gradients, duotones: [] }; + + if ( themeDuotones && themeDuotones.length ) { + result.duotones.push( { + name: _x( + 'Theme', + 'Indicates this palette comes from the theme.' + ), + slug: 'theme', + duotones: themeDuotones, + } ); + } + + if ( + shouldDisplayDefaultDuotones && + defaultDuotones && + defaultDuotones.length + ) { + result.duotones.push( { + name: _x( + 'Default', + 'Indicates this palette comes from WordPress.' + ), + slug: 'default', + duotones: defaultDuotones, + } ); + } + if ( customDuotones && customDuotones.length ) { + result.duotones.push( { + name: _x( + 'Custom', + // TODO: Should the follow saying from the theme or user? It currently matches useMultipleOriginColorsAndGradients. + 'Indicates this palette comes from the theme.' + ), + slug: 'custom', + duotones: customDuotones, + } ); + } + + return result; + }, [ + colors, + gradients, + customDuotones, + themeDuotones, + defaultDuotones, + shouldDisplayDefaultDuotones, + ] ); + + return palettes; +} + function StyleBook( { enableResizing = true, isSelected, @@ -64,7 +149,8 @@ function StyleBook( { const [ resizeObserver, sizes ] = useResizeObserver(); const [ textColor ] = useGlobalStyle( 'color.text' ); const [ backgroundColor ] = useGlobalStyle( 'color.background' ); - const [ examples ] = useState( getExamples ); + const colors = useMultiOriginPalettes(); + const [ examples, setExamples ] = useState( () => getExamples( colors ) ); const tabs = useMemo( () => getTopLevelStyleBookCategories().filter( ( category ) => @@ -74,6 +160,12 @@ function StyleBook( { ), [ examples ] ); + + // Ensure color examples are kept in sync with Global Styles palette changes. + useEffect( () => { + setExamples( getExamples( colors ) ); + }, [ colors ] ); + const { base: baseConfig } = useContext( GlobalStylesContext ); const mergedConfig = useMemo( () => { @@ -217,7 +309,6 @@ const StyleBookBody = ( { tabIndex={ 0 } { ...( onClick ? buttonModeProps : {} ) } > - + ) ) } + + + + ); +}; + export default StyleBook; From 16429fbdf0f3be371db40925dcc6e513257a3e42 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 2 Oct 2024 11:54:57 +1000 Subject: [PATCH 3/9] Revert "Try rendering only style overrides and duotone svgs in each example" This reverts commit eb744676097f12438478abaf0b96bd26a095cac0. --- .../src/components/style-book/examples.ts | 3 +- .../src/components/style-book/index.js | 41 +------------------ 2 files changed, 3 insertions(+), 41 deletions(-) diff --git a/packages/edit-site/src/components/style-book/examples.ts b/packages/edit-site/src/components/style-book/examples.ts index 3f43d7364a612f..c9be0666846670 100644 --- a/packages/edit-site/src/components/style-book/examples.ts +++ b/packages/edit-site/src/components/style-book/examples.ts @@ -118,7 +118,6 @@ function getColorExamples( colors: MultiOriginPalettes ): BlockExample[] { ); if ( palette?.[ group.type ] ) { - const rowGap = group.type === 'duotones' ? '16px' : '8px'; const example: BlockExample = { name: group.slug, title: group.title, @@ -134,7 +133,7 @@ function getColorExamples( colors: MultiOriginPalettes ): BlockExample[] { }, style: { spacing: { - blockGap: { top: rowGap, left: '16px' }, + blockGap: { top: '8px', left: '16px' }, }, }, }, diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 798920a41ead27..423d45b86834e4 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -9,7 +9,6 @@ import clsx from 'clsx'; import { Disabled, Composite, - SVG, privateApis as componentsPrivateApis, } from '@wordpress/components'; import { __, _x, sprintf } from '@wordpress/i18n'; @@ -310,7 +309,6 @@ const StyleBookBody = ( { tabIndex={ 0 } { ...( onClick ? buttonModeProps : {} ) } > - - ) ) } - - - - ); -}; - export default StyleBook; From 700675d2c87a1e65cbbcb0a61a8824d5f9467664 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 2 Oct 2024 12:11:52 +1000 Subject: [PATCH 4/9] Simplify inclusion of block support styles in style book examples --- .../src/components/style-book/examples.ts | 3 +- .../src/components/style-book/index.js | 41 ++++++++----------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/packages/edit-site/src/components/style-book/examples.ts b/packages/edit-site/src/components/style-book/examples.ts index c9be0666846670..3f43d7364a612f 100644 --- a/packages/edit-site/src/components/style-book/examples.ts +++ b/packages/edit-site/src/components/style-book/examples.ts @@ -118,6 +118,7 @@ function getColorExamples( colors: MultiOriginPalettes ): BlockExample[] { ); if ( palette?.[ group.type ] ) { + const rowGap = group.type === 'duotones' ? '16px' : '8px'; const example: BlockExample = { name: group.slug, title: group.title, @@ -133,7 +134,7 @@ function getColorExamples( colors: MultiOriginPalettes ): BlockExample[] { }, style: { spacing: { - blockGap: { top: '8px', left: '16px' }, + blockGap: { top: rowGap, left: '16px' }, }, }, }, diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js index 423d45b86834e4..ac0a990758f5ad 100644 --- a/packages/edit-site/src/components/style-book/index.js +++ b/packages/edit-site/src/components/style-book/index.js @@ -309,6 +309,7 @@ const StyleBookBody = ( { tabIndex={ 0 } { ...( onClick ? buttonModeProps : {} ) } > +