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

Add color and typography presets to Global Styles #56622

Merged
merged 48 commits into from Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
3366eca
Add colors and typography to the styles tab
scruffian Nov 29, 2023
9532adf
refactor
scruffian Nov 29, 2023
ddf005d
refactor
scruffian Nov 29, 2023
f075c7f
Add font family names
scruffian Nov 29, 2023
92167fd
add heading and body previews
scruffian Nov 30, 2023
379f62d
use palettes
scruffian Nov 30, 2023
c62be75
make typograpgy a grid
scruffian Nov 30, 2023
1a3dd8a
make the styles look nicer
scruffian Nov 30, 2023
5f50937
move component to its own file
scruffian Dec 6, 2023
de565ad
move color and type variations to different locations in the UI
scruffian Dec 6, 2023
db8fc25
revert
scruffian Dec 6, 2023
76f9a9b
revert
scruffian Dec 6, 2023
8663e68
revert
scruffian Dec 6, 2023
e2c18ec
revert
scruffian Dec 6, 2023
32723f1
code dedupe
scruffian Dec 6, 2023
baab507
Add typesets
scruffian Dec 6, 2023
d8ec720
reorg typogrpahy
scruffian Dec 7, 2023
0e94cbe
tidy up
scruffian Dec 7, 2023
e6d2392
tidy up code
scruffian Dec 7, 2023
dcf7f89
restyle color palettes
scruffian Dec 7, 2023
e8033c5
restyle color palettes
scruffian Dec 7, 2023
b4b0f80
remove typesets
scruffian Dec 7, 2023
f156dd5
add padding back
scruffian Dec 7, 2023
00726ba
refactor
scruffian Dec 7, 2023
f401473
Show theme_name + style where there is no typography font family info.
ramonjd Feb 5, 2024
c0be163
Consolidating logic into a hook phase 1
ramonjd Feb 6, 2024
1e15d41
2022 borks getFamilyPreviewStyle because `face.fontStyle` doesn't exist
ramonjd Feb 6, 2024
a23a6ca
comments
ramonjd Feb 6, 2024
13bea45
Filtering results
ramonjd Feb 8, 2024
63b85db
Create new convenience hook `useCurrentMergeThemeStyleVariationsWithU…
ramonjd Feb 14, 2024
c17157a
add a todo
ramonjd Feb 16, 2024
3af2f95
A bit of clean up. Remove comments, adjust margins.
ramonjd Feb 19, 2024
f12bb72
move variation to a new component
scruffian Feb 23, 2024
da353ae
make variation a composible component
scruffian Feb 23, 2024
88c8a3f
use the variation component for typography
scruffian Feb 24, 2024
993a98e
Update typography preview
scruffian Feb 24, 2024
ecffb64
Add animation
scruffian Feb 24, 2024
9493d20
move variation to a component
scruffian Feb 24, 2024
d368393
move preset to the higher level
scruffian Feb 24, 2024
7bea0bf
Remove unneeded CSS
scruffian Feb 24, 2024
6fbd619
updawte the design
scruffian Feb 24, 2024
949f199
remove unsed css
scruffian Feb 24, 2024
993c4af
Ensuring the cursor for the color previews is a pointer, which is the…
ramonjd Feb 26, 2024
e4eedf0
Reinstate removing property from user config before merging with vari…
ramonjd Feb 26, 2024
c642d19
i18n for letters
ramonjd Feb 27, 2024
e51b44f
Refactor unique font calculation
ramonjd Feb 27, 2024
b23d64c
move color and type variations higher
scruffian Feb 27, 2024
f7b735e
Use same box shadow as ColorIndicator so that there's a border around…
ramonjd Feb 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -13,6 +13,8 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';
import ColorVariations from './variations-color';
import { useCurrentMergeThemeStyleVariationsWithUserConfig } from '../../hooks/use-theme-style-variations/use-theme-style-variations-by-property';

const { useGlobalSetting } = unlock( blockEditorPrivateApis );
const mobilePopoverProps = { placement: 'bottom-start', offset: 8 };
Expand Down Expand Up @@ -45,7 +47,12 @@ export default function ColorPalettePanel( { name } ) {
'color.defaultPalette',
name
);

const colorVariations = useCurrentMergeThemeStyleVariationsWithUserConfig( {
property: 'color',
filter: ( variation ) =>
variation?.settings?.color &&
Object.keys( variation?.settings?.color ).length,
} );
const isMobileViewport = useViewportMatch( 'small', '<' );
const popoverProps = isMobileViewport ? mobilePopoverProps : undefined;

Expand Down Expand Up @@ -78,6 +85,9 @@ export default function ColorPalettePanel( { name } ) {
popoverProps={ popoverProps }
/>
) }
{ !! colorVariations.length && (
<ColorVariations variations={ colorVariations } />
) }
<PaletteEdit
colors={ customColors }
onChange={ setCustomColors }
Expand Down
Expand Up @@ -117,7 +117,8 @@ export function getFamilyPreviewStyle( family ) {
if ( family.fontFace ) {
//get all the font faces with normal style
const normalFaces = family.fontFace.filter(
( face ) => face.fontStyle.toLowerCase() === 'normal'
( face ) =>
face?.fontStyle && face.fontStyle.toLowerCase() === 'normal'
ramonjd marked this conversation as resolved.
Show resolved Hide resolved
);
if ( normalFaces.length > 0 ) {
style.fontStyle = 'normal';
Expand Down
216 changes: 216 additions & 0 deletions packages/edit-site/src/components/global-styles/preview-colors.js
@@ -0,0 +1,216 @@
/**
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a duplicate of the preview component

* WordPress dependencies
*/
import {
__unstableIframe as Iframe,
__unstableEditorStyles as EditorStyles,
privateApis as blockEditorPrivateApis,
} from '@wordpress/block-editor';
import {
__unstableMotion as motion,
__experimentalHStack as HStack,
} from '@wordpress/components';
import {
useThrottle,
useReducedMotion,
useResizeObserver,
} from '@wordpress/compose';
import { useLayoutEffect, useState, useMemo } from '@wordpress/element';

/**
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';
import { useStylesPreviewColors } from './hooks';

const { useGlobalStyle, useGlobalStylesOutput } = unlock(
blockEditorPrivateApis
);

const firstFrame = {
start: {
scale: 1,
opacity: 1,
},
hover: {
scale: 0,
opacity: 0,
},
};

const normalizedWidth = 248;
const normalizedHeight = 152;

const normalizedColorSwatchSize = 66;

// Throttle options for useThrottle. Must be defined outside of the component,
// so that the object reference is the same on each render.
const THROTTLE_OPTIONS = {
leading: true,
trailing: true,
};

const StylesPreviewColors = ( { label, isFocused, withHoverView } ) => {
const [ backgroundColor = 'white' ] = useGlobalStyle( 'color.background' );
const [ gradientValue ] = useGlobalStyle( 'color.gradient' );
const [ styles ] = useGlobalStylesOutput();
const disableMotion = useReducedMotion();
const [ isHovered, setIsHovered ] = useState( false );
const [ containerResizeListener, { width } ] = useResizeObserver();
const [ throttledWidth, setThrottledWidthState ] = useState( width );
const [ ratioState, setRatioState ] = useState();

const setThrottledWidth = useThrottle(
setThrottledWidthState,
250,
THROTTLE_OPTIONS
);

// Must use useLayoutEffect to avoid a flash of the iframe at the wrong
// size before the width is set.
useLayoutEffect( () => {
if ( width ) {
setThrottledWidth( width );
}
}, [ width, setThrottledWidth ] );

// Must use useLayoutEffect to avoid a flash of the iframe at the wrong
// size before the width is set.
useLayoutEffect( () => {
const newRatio = throttledWidth ? throttledWidth / normalizedWidth : 1;
const ratioDiff = newRatio - ( ratioState || 0 );

// Only update the ratio state if the difference is big enough
// or if the ratio state is not yet set. This is to avoid an
// endless loop of updates at particular viewport heights when the
// presence of a scrollbar causes the width to change slightly.
const isRatioDiffBigEnough = Math.abs( ratioDiff ) > 0.1;

if ( isRatioDiffBigEnough || ! ratioState ) {
setRatioState( newRatio );
}
}, [ throttledWidth, ratioState ] );

// Set a fallbackRatio to use before the throttled ratio has been set.
const fallbackRatio = width ? width / normalizedWidth : 1;
/*
* Use the throttled ratio if it has been calculated, otherwise
* use the fallback ratio. The throttled ratio is used to avoid
* an endless loop of updates at particular viewport heights.
* See: https://github.com/WordPress/gutenberg/issues/55112
*/
const ratio = ratioState ? ratioState : fallbackRatio;

const { highlightedColors } = useStylesPreviewColors();
Copy link
Member

Choose a reason for hiding this comment

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

While testing I noticed an issue with some themes that had only 2 palette colors, e.g., Freddie.

If those colors match heading or background colors, they're being filtered out:

const highlightedColors = paletteColors
.filter(
// we exclude these two colors because they are already visible in the preview.
( { color } ) => color !== backgroundColor && color !== headingColor

The result is that, although there's a variation, the colors are empty:

Screenshot 2024-02-28 at 12 08 24 pm

CanvasLoader already gets around it this way:

const [ fallbackIndicatorColor ] = useGlobalStyle( 'color.text' );
const [ backgroundColor ] = useGlobalStyle( 'color.background' );
const { highlightedColors } = useStylesPreviewColors();
const indicatorColor =
highlightedColors[ 0 ]?.color ?? fallbackIndicatorColor;

Not sure what's appropriate in <StylesPreviewColors />

Maybe something like:

	const { paletteColors, highlightedColors } = useStylesPreviewColors();

	const previewColors = highlightedColors.length
		? highlightedColors
		: paletteColors.slice( 0, 2 );

Copy link
Member

Choose a reason for hiding this comment

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

Update: this is already an "feature" of trunk, in that style variation previews won't show them either.

I think it just looks strange in the preset previews. Maybe good for an immediate follow up.

To replicate the above issue, here's a style variation example. The palette colors are the same as the background and text colors so the variation will show nothing.

{
	"version": 2,
	"settings": {
	"color": {
		"palette": [
			{
				"color": "#000000",
				"name": "Base",
				"slug": "base"
			},
			{
				"color": "#ffffff",
				"name": "Contrast",
				"slug": "contrast"
			}
		]
	}
	},
	"styles": {
		"color": {
			"text": "#000000",
			"background": "var(--wp--preset--color--contrast)"
		}
	}
}


/*
* Reset leaked styles from WP common.css and remove main content layout padding and border.
* Add pointer cursor to the body to indicate the iframe is interactive,
* similar to Typography variation previews.
*/
const editorStyles = useMemo( () => {
if ( styles ) {
return [
...styles,
{
css: 'html{overflow:hidden}body{min-width: 0;padding: 0;border: none;cursor: pointer;}',
isGlobalStyles: true,
},
];
}

return styles;
}, [ styles ] );
const isReady = !! width;

return (
<>
<div style={ { position: 'relative' } }>
{ containerResizeListener }
</div>
{ isReady && (
<Iframe
className="edit-site-global-styles-preview__iframe"
style={ {
width: '100%',
height: normalizedHeight * ratio,
} }
onMouseEnter={ () => setIsHovered( true ) }
onMouseLeave={ () => setIsHovered( false ) }
tabIndex={ -1 }
>
<EditorStyles styles={ editorStyles } />
<motion.div
style={ {
Copy link
Member

Choose a reason for hiding this comment

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

Is this animation block necessary any more for these specific previews?

2024-02-26.12.42.40.mp4

If not, wondering if we can remove it entirely. I was going to, but just wanted to make sure it's doing something that's not obvious.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, didn't see the transition as the panel opens, as with Typography

https://github.com/WordPress/gutenberg/pull/56622/files#r1503522214

A lot of code though for how much value?

height: normalizedHeight * ratio,
width: '100%',
background: gradientValue ?? backgroundColor,
cursor: withHoverView ? 'pointer' : undefined,
} }
initial="start"
animate={
( isHovered || isFocused ) &&
Copy link
Member

Choose a reason for hiding this comment

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

If we don't require motion, then I think the isFocused prop is also unnecessary (?)

! disableMotion &&
label
? 'hover'
: 'start'
}
>
<motion.div
variants={ firstFrame }
style={ {
height: '100%',
overflow: 'hidden',
} }
>
<HStack
spacing={ 10 * ratio }
justify="center"
style={ {
height: '100%',
overflow: 'hidden',
} }
>
{ highlightedColors.map(
( { slug, color }, index ) => (
<motion.div
key={ slug }
style={ {
boxShadow:
'inset 0 0 0 1px #0003',
Copy link
Member

Choose a reason for hiding this comment

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

I added this to ensure the colors have a border like the ColorIndicator component.

In some themes, the background color matches the highlights, or are close in contrast:

Before

Screenshot 2024-02-28 at 12 11 30 pm

After

Screenshot 2024-02-28 at 12 11 02 pm

Copy link
Member

@richtabor richtabor Feb 28, 2024

Choose a reason for hiding this comment

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

I added this to ensure the colors have a border like the ColorIndicator component.

I don't think this is necessary, as I want to update these colors to be more representative of the style by using the text and button colors for the indicators. I will open another issue on that (to do as a follow-up).

height:
normalizedColorSwatchSize *
ratio,
width:
normalizedColorSwatchSize *
ratio,
background: color,
borderRadius:
( normalizedColorSwatchSize *
ratio ) /
2,
} }
animate={ {
scale: 1,
opacity: 1,
} }
initial={ {
scale: 0.1,
opacity: 0,
} }
transition={ {
delay: index === 1 ? 0.2 : 0.1,
} }
/>
)
) }
</HStack>
</motion.div>
</motion.div>
</Iframe>
) }
</>
);
};

export default StylesPreviewColors;
14 changes: 13 additions & 1 deletion packages/edit-site/src/components/global-styles/screen-colors.js
Expand Up @@ -11,6 +11,8 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
import ScreenHeader from './header';
import Palette from './palette';
import { unlock } from '../../lock-unlock';
import ColorVariations from './variations-color';
import { useCurrentMergeThemeStyleVariationsWithUserConfig } from '../../hooks/use-theme-style-variations/use-theme-style-variations-by-property';

const {
useGlobalStyle,
Expand All @@ -29,6 +31,12 @@ function ScreenColors() {
const [ rawSettings ] = useGlobalSetting( '' );
const settings = useSettingsForBlockElement( rawSettings );

const colorVariations = useCurrentMergeThemeStyleVariationsWithUserConfig( {
property: 'color',
ramonjd marked this conversation as resolved.
Show resolved Hide resolved
filter: ( variation ) =>
variation?.settings?.color &&
Object.keys( variation?.settings?.color ).length,
} );
return (
<>
<ScreenHeader
Expand All @@ -38,7 +46,11 @@ function ScreenColors() {
) }
/>
<div className="edit-site-global-styles-screen-colors">
<VStack spacing={ 10 }>
<VStack spacing={ 3 }>
{ !! colorVariations.length && (
<ColorVariations variations={ colorVariations } />
) }

<Palette />

<StylesColorPanel
Expand Down
Expand Up @@ -10,15 +10,25 @@ import { useSelect } from '@wordpress/data';
* Internal dependencies
*/
import TypographyElements from './typography-elements';
import TypographyVariations from './variations-typography';
import FontFamilies from './font-families';
import ScreenHeader from './header';
import { useCurrentMergeThemeStyleVariationsWithUserConfig } from '../../hooks/use-theme-style-variations/use-theme-style-variations-by-property';

function ScreenTypography() {
const fontLibraryEnabled = useSelect(
( select ) =>
select( editorStore ).getEditorSettings().fontLibraryEnabled,
[]
);
const typographyVariations =
useCurrentMergeThemeStyleVariationsWithUserConfig( {
property: 'typography',
filter: ( variation ) =>
variation?.settings?.typography?.fontFamilies &&
Object.keys( variation?.settings?.typography?.fontFamilies )
.length,
} );

return (
<>
Expand All @@ -30,7 +40,14 @@ function ScreenTypography() {
/>
<div className="edit-site-global-styles-screen-typography">
<VStack spacing={ 6 }>
{ fontLibraryEnabled && <FontFamilies /> }
{ !! typographyVariations.length && (
<TypographyVariations />
) }
{ ! window.__experimentalDisableFontLibrary && (
<VStack spacing={ 3 }>
{ fontLibraryEnabled && <FontFamilies /> }
</VStack>
) }
<TypographyElements />
</VStack>
</div>
Expand Down