@wordpress/edit-site 4.8.0 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/add-new-template/add-custom-template-modal.js +185 -0
  3. package/build/components/add-new-template/add-custom-template-modal.js.map +1 -0
  4. package/build/components/add-new-template/new-template.js +79 -14
  5. package/build/components/add-new-template/new-template.js.map +1 -1
  6. package/build/components/add-new-template/utils.js +139 -0
  7. package/build/components/add-new-template/utils.js.map +1 -0
  8. package/build/components/global-styles/context-menu.js +6 -3
  9. package/build/components/global-styles/context-menu.js.map +1 -1
  10. package/build/components/global-styles/hooks.js +1 -1
  11. package/build/components/global-styles/hooks.js.map +1 -1
  12. package/build/components/global-styles/palette.js +2 -1
  13. package/build/components/global-styles/palette.js.map +1 -1
  14. package/build/components/global-styles/screen-block-list.js +4 -1
  15. package/build/components/global-styles/screen-block-list.js.map +1 -1
  16. package/build/components/global-styles/screen-button-color.js +80 -0
  17. package/build/components/global-styles/screen-button-color.js.map +1 -0
  18. package/build/components/global-styles/screen-colors.js +47 -7
  19. package/build/components/global-styles/screen-colors.js.map +1 -1
  20. package/build/components/global-styles/screen-root.js +4 -2
  21. package/build/components/global-styles/screen-root.js.map +1 -1
  22. package/build/components/global-styles/screen-typography-element.js +4 -0
  23. package/build/components/global-styles/screen-typography-element.js.map +1 -1
  24. package/build/components/global-styles/screen-typography.js +9 -1
  25. package/build/components/global-styles/screen-typography.js.map +1 -1
  26. package/build/components/global-styles/ui.js +11 -0
  27. package/build/components/global-styles/ui.js.map +1 -1
  28. package/build/components/global-styles/use-global-styles-output.js +40 -9
  29. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  30. package/build/components/global-styles/utils.js +3 -1
  31. package/build/components/global-styles/utils.js.map +1 -1
  32. package/build/components/header/index.js +28 -10
  33. package/build/components/header/index.js.map +1 -1
  34. package/build/components/header/more-menu/site-export.js +4 -1
  35. package/build/components/header/more-menu/site-export.js.map +1 -1
  36. package/build/components/header/undo-redo/redo.js +13 -4
  37. package/build/components/header/undo-redo/redo.js.map +1 -1
  38. package/build/components/header/undo-redo/undo.js +13 -4
  39. package/build/components/header/undo-redo/undo.js.map +1 -1
  40. package/build/components/keyboard-shortcut-help-modal/config.js +17 -0
  41. package/build/components/keyboard-shortcut-help-modal/config.js.map +1 -1
  42. package/build/components/sidebar/template-card/index.js +19 -7
  43. package/build/components/sidebar/template-card/index.js.map +1 -1
  44. package/build/components/sidebar/template-card/template-actions.js +64 -0
  45. package/build/components/sidebar/template-card/template-actions.js.map +1 -0
  46. package/build-module/components/add-new-template/add-custom-template-modal.js +170 -0
  47. package/build-module/components/add-new-template/add-custom-template-modal.js.map +1 -0
  48. package/build-module/components/add-new-template/new-template.js +79 -17
  49. package/build-module/components/add-new-template/new-template.js.map +1 -1
  50. package/build-module/components/add-new-template/utils.js +119 -0
  51. package/build-module/components/add-new-template/utils.js.map +1 -0
  52. package/build-module/components/global-styles/context-menu.js +6 -3
  53. package/build-module/components/global-styles/context-menu.js.map +1 -1
  54. package/build-module/components/global-styles/hooks.js +1 -1
  55. package/build-module/components/global-styles/hooks.js.map +1 -1
  56. package/build-module/components/global-styles/palette.js +2 -1
  57. package/build-module/components/global-styles/palette.js.map +1 -1
  58. package/build-module/components/global-styles/screen-block-list.js +4 -1
  59. package/build-module/components/global-styles/screen-block-list.js.map +1 -1
  60. package/build-module/components/global-styles/screen-button-color.js +67 -0
  61. package/build-module/components/global-styles/screen-button-color.js.map +1 -0
  62. package/build-module/components/global-styles/screen-colors.js +48 -8
  63. package/build-module/components/global-styles/screen-colors.js.map +1 -1
  64. package/build-module/components/global-styles/screen-root.js +4 -2
  65. package/build-module/components/global-styles/screen-root.js.map +1 -1
  66. package/build-module/components/global-styles/screen-typography-element.js +4 -0
  67. package/build-module/components/global-styles/screen-typography-element.js.map +1 -1
  68. package/build-module/components/global-styles/screen-typography.js +10 -2
  69. package/build-module/components/global-styles/screen-typography.js.map +1 -1
  70. package/build-module/components/global-styles/ui.js +10 -0
  71. package/build-module/components/global-styles/ui.js.map +1 -1
  72. package/build-module/components/global-styles/use-global-styles-output.js +39 -9
  73. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  74. package/build-module/components/global-styles/utils.js +3 -1
  75. package/build-module/components/global-styles/utils.js.map +1 -1
  76. package/build-module/components/header/index.js +29 -11
  77. package/build-module/components/header/index.js.map +1 -1
  78. package/build-module/components/header/more-menu/site-export.js +4 -1
  79. package/build-module/components/header/more-menu/site-export.js.map +1 -1
  80. package/build-module/components/header/undo-redo/redo.js +9 -3
  81. package/build-module/components/header/undo-redo/redo.js.map +1 -1
  82. package/build-module/components/header/undo-redo/undo.js +9 -3
  83. package/build-module/components/header/undo-redo/undo.js.map +1 -1
  84. package/build-module/components/keyboard-shortcut-help-modal/config.js +17 -0
  85. package/build-module/components/keyboard-shortcut-help-modal/config.js.map +1 -1
  86. package/build-module/components/sidebar/template-card/index.js +18 -7
  87. package/build-module/components/sidebar/template-card/index.js.map +1 -1
  88. package/build-module/components/sidebar/template-card/template-actions.js +49 -0
  89. package/build-module/components/sidebar/template-card/template-actions.js.map +1 -0
  90. package/build-style/style-rtl.css +167 -16
  91. package/build-style/style.css +167 -16
  92. package/package.json +29 -29
  93. package/src/components/add-new-template/add-custom-template-modal.js +231 -0
  94. package/src/components/add-new-template/new-template.js +124 -47
  95. package/src/components/add-new-template/style.scss +116 -0
  96. package/src/components/add-new-template/utils.js +125 -0
  97. package/src/components/global-styles/context-menu.js +3 -0
  98. package/src/components/global-styles/hooks.js +1 -0
  99. package/src/components/global-styles/palette.js +4 -1
  100. package/src/components/global-styles/screen-block-list.js +10 -1
  101. package/src/components/global-styles/screen-button-color.js +102 -0
  102. package/src/components/global-styles/screen-colors.js +49 -4
  103. package/src/components/global-styles/screen-root.js +8 -2
  104. package/src/components/global-styles/screen-typography-element.js +4 -0
  105. package/src/components/global-styles/screen-typography.js +17 -2
  106. package/src/components/global-styles/style.scss +10 -0
  107. package/src/components/global-styles/test/use-global-styles-output.js +82 -16
  108. package/src/components/global-styles/ui.js +13 -0
  109. package/src/components/global-styles/use-global-styles-output.js +43 -4
  110. package/src/components/global-styles/utils.js +3 -0
  111. package/src/components/header/index.js +36 -10
  112. package/src/components/header/more-menu/site-export.js +3 -0
  113. package/src/components/header/style.scss +53 -5
  114. package/src/components/header/undo-redo/redo.js +6 -1
  115. package/src/components/header/undo-redo/undo.js +6 -1
  116. package/src/components/keyboard-shortcut-help-modal/config.js +12 -0
  117. package/src/components/sidebar/template-card/index.js +15 -6
  118. package/src/components/sidebar/template-card/style.scss +49 -35
  119. package/src/components/sidebar/template-card/template-actions.js +43 -0
@@ -0,0 +1,125 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { get } from 'lodash';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { useSelect } from '@wordpress/data';
10
+ import { store as coreStore } from '@wordpress/core-data';
11
+ import { decodeEntities } from '@wordpress/html-entities';
12
+ import { useMemo } from '@wordpress/element';
13
+
14
+ export const usePostTypes = () => {
15
+ const postTypes = useSelect(
16
+ ( select ) => select( coreStore ).getPostTypes( { per_page: -1 } ),
17
+ []
18
+ );
19
+ return useMemo( () => {
20
+ const excludedPostTypes = [ 'attachment', 'page' ];
21
+ return postTypes?.filter(
22
+ ( { viewable, slug } ) =>
23
+ viewable && ! excludedPostTypes.includes( slug )
24
+ );
25
+ }, [ postTypes ] );
26
+ };
27
+
28
+ /**
29
+ * @typedef {Object} PostTypeEntitiesInfo
30
+ * @property {boolean} hasEntities If a postType has available entities.
31
+ * @property {number[]} existingPosts An array of the existing entities ids.
32
+ */
33
+
34
+ /**
35
+ * Helper hook that returns information about a post type having
36
+ * posts that we can create a specific template for.
37
+ *
38
+ * First we need to find the existing posts with an associated template,
39
+ * to query afterwards for any remaing post, by excluding them.
40
+ *
41
+ * @param {string[]} existingTemplates The existing templates.
42
+ * @return {Record<string,PostTypeEntitiesInfo>} An object with the postTypes as `keys` and PostTypeEntitiesInfo as values.
43
+ */
44
+ export const usePostTypesEntitiesInfo = ( existingTemplates ) => {
45
+ const postTypes = usePostTypes();
46
+ const slugsToExcludePerEntity = useMemo( () => {
47
+ return postTypes?.reduce( ( accumulator, _postType ) => {
48
+ const slugsWithTemplates = ( existingTemplates || [] ).reduce(
49
+ ( _accumulator, existingTemplate ) => {
50
+ const prefix = `single-${ _postType.slug }-`;
51
+ if ( existingTemplate.slug.startsWith( prefix ) ) {
52
+ _accumulator.push(
53
+ existingTemplate.slug.substring( prefix.length )
54
+ );
55
+ }
56
+ return _accumulator;
57
+ },
58
+ []
59
+ );
60
+ if ( slugsWithTemplates.length ) {
61
+ accumulator[ _postType.slug ] = slugsWithTemplates;
62
+ }
63
+ return accumulator;
64
+ }, {} );
65
+ }, [ postTypes, existingTemplates ] );
66
+ const postsToExcludePerEntity = useSelect(
67
+ ( select ) => {
68
+ if ( ! slugsToExcludePerEntity ) {
69
+ return;
70
+ }
71
+ const postsToExclude = Object.entries(
72
+ slugsToExcludePerEntity
73
+ ).reduce( ( accumulator, [ slug, slugsWithTemplates ] ) => {
74
+ const postsWithTemplates = select( coreStore ).getEntityRecords(
75
+ 'postType',
76
+ slug,
77
+ {
78
+ _fields: 'id',
79
+ context: 'view',
80
+ slug: slugsWithTemplates,
81
+ }
82
+ );
83
+ if ( postsWithTemplates?.length ) {
84
+ accumulator[ slug ] = postsWithTemplates;
85
+ }
86
+ return accumulator;
87
+ }, {} );
88
+ return postsToExclude;
89
+ },
90
+ [ slugsToExcludePerEntity ]
91
+ );
92
+ const entitiesInfo = useSelect(
93
+ ( select ) => {
94
+ return postTypes?.reduce( ( accumulator, { slug } ) => {
95
+ const existingPosts =
96
+ postsToExcludePerEntity?.[ slug ]?.map(
97
+ ( { id } ) => id
98
+ ) || [];
99
+ accumulator[ slug ] = {
100
+ hasEntities: !! select( coreStore ).getEntityRecords(
101
+ 'postType',
102
+ slug,
103
+ {
104
+ per_page: 1,
105
+ _fields: 'id',
106
+ context: 'view',
107
+ exclude: existingPosts,
108
+ }
109
+ )?.length,
110
+ existingPosts,
111
+ };
112
+ return accumulator;
113
+ }, {} );
114
+ },
115
+ [ postTypes, postsToExcludePerEntity ]
116
+ );
117
+ return entitiesInfo;
118
+ };
119
+
120
+ export const mapToIHasNameAndId = ( entities, path ) => {
121
+ return ( entities || [] ).map( ( entity ) => ( {
122
+ ...entity,
123
+ name: decodeEntities( get( entity, path ) ),
124
+ } ) );
125
+ };
@@ -27,6 +27,7 @@ function ContextMenu( { name, parentMenu = '' } ) {
27
27
  <NavigationButtonAsItem
28
28
  icon={ typography }
29
29
  path={ parentMenu + '/typography' }
30
+ aria-label={ __( 'Typography styles' ) }
30
31
  >
31
32
  { __( 'Typography' ) }
32
33
  </NavigationButtonAsItem>
@@ -35,6 +36,7 @@ function ContextMenu( { name, parentMenu = '' } ) {
35
36
  <NavigationButtonAsItem
36
37
  icon={ color }
37
38
  path={ parentMenu + '/colors' }
39
+ aria-label={ __( 'Colors styles' ) }
38
40
  >
39
41
  { __( 'Colors' ) }
40
42
  </NavigationButtonAsItem>
@@ -43,6 +45,7 @@ function ContextMenu( { name, parentMenu = '' } ) {
43
45
  <NavigationButtonAsItem
44
46
  icon={ layout }
45
47
  path={ parentMenu + '/layout' }
48
+ aria-label={ __( 'Layout styles' ) }
46
49
  >
47
50
  { __( 'Layout' ) }
48
51
  </NavigationButtonAsItem>
@@ -159,6 +159,7 @@ const ROOT_BLOCK_SUPPORTS = [
159
159
  'backgroundColor',
160
160
  'color',
161
161
  'linkColor',
162
+ 'buttonColor',
162
163
  'fontFamily',
163
164
  'fontSize',
164
165
  'fontStyle',
@@ -58,7 +58,10 @@ function Palette( { name } ) {
58
58
  <VStack spacing={ 3 }>
59
59
  <Subtitle>{ __( 'Palette' ) }</Subtitle>
60
60
  <ItemGroup isBordered isSeparated>
61
- <NavigationButtonAsItem path={ screenPath }>
61
+ <NavigationButtonAsItem
62
+ path={ screenPath }
63
+ aria-label={ __( 'Color palettes' ) }
64
+ >
62
65
  <HStack
63
66
  direction={
64
67
  colors.length === 0 ? 'row-reverse' : 'row'
@@ -60,8 +60,17 @@ function BlockMenuItem( { block } ) {
60
60
  return null;
61
61
  }
62
62
 
63
+ const navigationButtonLabel = sprintf(
64
+ // translators: %s: is the name of a block e.g., 'Image' or 'Table'.
65
+ __( '%s block styles' ),
66
+ block.title
67
+ );
68
+
63
69
  return (
64
- <NavigationButtonAsItem path={ '/blocks/' + block.name }>
70
+ <NavigationButtonAsItem
71
+ path={ '/blocks/' + block.name }
72
+ aria-label={ navigationButtonLabel }
73
+ >
65
74
  <HStack justify="flex-start">
66
75
  <BlockIcon icon={ block.icon } />
67
76
  <FlexItem>{ block.title }</FlexItem>
@@ -0,0 +1,102 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { __ } from '@wordpress/i18n';
5
+ import { __experimentalColorGradientControl as ColorGradientControl } from '@wordpress/block-editor';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import ScreenHeader from './header';
11
+ import {
12
+ getSupportedGlobalStylesPanels,
13
+ useSetting,
14
+ useStyle,
15
+ useColorsPerOrigin,
16
+ } from './hooks';
17
+
18
+ function ScreenButtonColor( { name } ) {
19
+ const supports = getSupportedGlobalStylesPanels( name );
20
+ const [ solids ] = useSetting( 'color.palette', name );
21
+ const [ areCustomSolidsEnabled ] = useSetting( 'color.custom', name );
22
+
23
+ const colorsPerOrigin = useColorsPerOrigin( name );
24
+
25
+ const [ isBackgroundEnabled ] = useSetting( 'color.background', name );
26
+
27
+ const hasButtonColor =
28
+ supports.includes( 'buttonColor' ) &&
29
+ isBackgroundEnabled &&
30
+ ( solids.length > 0 || areCustomSolidsEnabled );
31
+
32
+ const [ buttonTextColor, setButtonTextColor ] = useStyle(
33
+ 'elements.button.color.text',
34
+ name
35
+ );
36
+ const [ userButtonTextColor ] = useStyle(
37
+ 'elements.button.color.text',
38
+ name,
39
+ 'user'
40
+ );
41
+
42
+ const [ buttonBgColor, setButtonBgColor ] = useStyle(
43
+ 'elements.button.color.background',
44
+ name
45
+ );
46
+ const [ userButtonBgColor ] = useStyle(
47
+ 'elements.button.color.background',
48
+ name,
49
+ 'user'
50
+ );
51
+
52
+ if ( ! hasButtonColor ) {
53
+ return null;
54
+ }
55
+
56
+ return (
57
+ <>
58
+ <ScreenHeader
59
+ title={ __( 'Buttons' ) }
60
+ description={ __(
61
+ 'Set the default colors used for buttons across the site.'
62
+ ) }
63
+ />
64
+
65
+ <h4 className="edit-site-global-styles-section-title">
66
+ { __( 'Text color' ) }
67
+ </h4>
68
+
69
+ <ColorGradientControl
70
+ className="edit-site-screen-button-color__control"
71
+ colors={ colorsPerOrigin }
72
+ disableCustomColors={ ! areCustomSolidsEnabled }
73
+ __experimentalHasMultipleOrigins
74
+ showTitle={ false }
75
+ enableAlpha
76
+ __experimentalIsRenderedInSidebar
77
+ colorValue={ buttonTextColor }
78
+ onColorChange={ setButtonTextColor }
79
+ clearable={ buttonTextColor === userButtonTextColor }
80
+ />
81
+
82
+ <h4 className="edit-site-global-styles-section-title">
83
+ { __( 'Background color' ) }
84
+ </h4>
85
+
86
+ <ColorGradientControl
87
+ className="edit-site-screen-button-color__control"
88
+ colors={ colorsPerOrigin }
89
+ disableCustomColors={ ! areCustomSolidsEnabled }
90
+ __experimentalHasMultipleOrigins
91
+ showTitle={ false }
92
+ enableAlpha
93
+ __experimentalIsRenderedInSidebar
94
+ colorValue={ buttonBgColor }
95
+ onColorChange={ setButtonBgColor }
96
+ clearable={ buttonBgColor === userButtonBgColor }
97
+ />
98
+ </>
99
+ );
100
+ }
101
+
102
+ export default ScreenButtonColor;
@@ -6,6 +6,7 @@ import {
6
6
  __experimentalItemGroup as ItemGroup,
7
7
  __experimentalHStack as HStack,
8
8
  __experimentalVStack as VStack,
9
+ __experimentalZStack as ZStack,
9
10
  FlexItem,
10
11
  ColorIndicator,
11
12
  } from '@wordpress/components';
@@ -33,11 +34,15 @@ function BackgroundColorItem( { name, parentMenu } ) {
33
34
  }
34
35
 
35
36
  return (
36
- <NavigationButtonAsItem path={ parentMenu + '/colors/background' }>
37
+ <NavigationButtonAsItem
38
+ path={ parentMenu + '/colors/background' }
39
+ aria-label={ __( 'Colors background styles' ) }
40
+ >
37
41
  <HStack justify="flex-start">
38
42
  <ColorIndicatorWrapper expanded={ false }>
39
43
  <ColorIndicator
40
44
  colorValue={ gradientValue ?? backgroundColor }
45
+ data-testid="background-color-indicator"
41
46
  />
42
47
  </ColorIndicatorWrapper>
43
48
  <FlexItem>{ __( 'Background' ) }</FlexItem>
@@ -56,10 +61,16 @@ function TextColorItem( { name, parentMenu } ) {
56
61
  }
57
62
 
58
63
  return (
59
- <NavigationButtonAsItem path={ parentMenu + '/colors/text' }>
64
+ <NavigationButtonAsItem
65
+ path={ parentMenu + '/colors/text' }
66
+ aria-label={ __( 'Colors text styles' ) }
67
+ >
60
68
  <HStack justify="flex-start">
61
69
  <ColorIndicatorWrapper expanded={ false }>
62
- <ColorIndicator colorValue={ color } />
70
+ <ColorIndicator
71
+ colorValue={ color }
72
+ data-testid="text-color-indicator"
73
+ />
63
74
  </ColorIndicatorWrapper>
64
75
  <FlexItem>{ __( 'Text' ) }</FlexItem>
65
76
  </HStack>
@@ -77,7 +88,10 @@ function LinkColorItem( { name, parentMenu } ) {
77
88
  }
78
89
 
79
90
  return (
80
- <NavigationButtonAsItem path={ parentMenu + '/colors/link' }>
91
+ <NavigationButtonAsItem
92
+ path={ parentMenu + '/colors/link' }
93
+ aria-label={ __( 'Colors link styles' ) }
94
+ >
81
95
  <HStack justify="flex-start">
82
96
  <ColorIndicatorWrapper expanded={ false }>
83
97
  <ColorIndicator colorValue={ color } />
@@ -88,6 +102,33 @@ function LinkColorItem( { name, parentMenu } ) {
88
102
  );
89
103
  }
90
104
 
105
+ function ButtonColorItem( { name, parentMenu } ) {
106
+ const supports = getSupportedGlobalStylesPanels( name );
107
+ const hasSupport = supports.includes( 'buttonColor' );
108
+ const [ color ] = useStyle( 'elements.button.color.text', name );
109
+ const [ bgColor ] = useStyle( 'elements.button.color.background', name );
110
+
111
+ if ( ! hasSupport ) {
112
+ return null;
113
+ }
114
+
115
+ return (
116
+ <NavigationButtonAsItem path={ parentMenu + '/colors/button' }>
117
+ <HStack justify="flex-start">
118
+ <ZStack isLayered={ false } offset={ -8 }>
119
+ <ColorIndicatorWrapper expanded={ false }>
120
+ <ColorIndicator colorValue={ bgColor } />
121
+ </ColorIndicatorWrapper>
122
+ <ColorIndicatorWrapper expanded={ false }>
123
+ <ColorIndicator colorValue={ color } />
124
+ </ColorIndicatorWrapper>
125
+ </ZStack>
126
+ <FlexItem>{ __( 'Buttons' ) }</FlexItem>
127
+ </HStack>
128
+ </NavigationButtonAsItem>
129
+ );
130
+ }
131
+
91
132
  function ScreenColors( { name } ) {
92
133
  const parentMenu = name === undefined ? '' : '/blocks/' + name;
93
134
 
@@ -119,6 +160,10 @@ function ScreenColors( { name } ) {
119
160
  name={ name }
120
161
  parentMenu={ parentMenu }
121
162
  />
163
+ <ButtonColorItem
164
+ name={ name }
165
+ parentMenu={ parentMenu }
166
+ />
122
167
  </ItemGroup>
123
168
  </VStack>
124
169
  </VStack>
@@ -46,7 +46,10 @@ function ScreenRoot() {
46
46
  </Card>
47
47
  { !! variations?.length && (
48
48
  <ItemGroup>
49
- <NavigationButtonAsItem path="/variations">
49
+ <NavigationButtonAsItem
50
+ path="/variations"
51
+ aria-label={ __( 'Browse styles' ) }
52
+ >
50
53
  <HStack justify="space-between">
51
54
  <FlexItem>
52
55
  { __( 'Browse styles' ) }
@@ -82,7 +85,10 @@ function ScreenRoot() {
82
85
  ) }
83
86
  </Spacer>
84
87
  <ItemGroup>
85
- <NavigationButtonAsItem path="/blocks">
88
+ <NavigationButtonAsItem
89
+ path="/blocks"
90
+ aria-label={ __( 'Blocks styles' ) }
91
+ >
86
92
  <HStack justify="space-between">
87
93
  <FlexItem>{ __( 'Blocks' ) }</FlexItem>
88
94
  <IconWithCurrentColor
@@ -18,6 +18,10 @@ const elements = {
18
18
  description: __( 'Manage the fonts and typography used on the links.' ),
19
19
  title: __( 'Links' ),
20
20
  },
21
+ button: {
22
+ description: __( 'Manage the fonts and typography used on buttons.' ),
23
+ title: __( 'Buttons' ),
24
+ },
21
25
  };
22
26
 
23
27
  function ScreenTypographyElement( { name, element } ) {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { __ } from '@wordpress/i18n';
4
+ import { __, sprintf } from '@wordpress/i18n';
5
5
  import {
6
6
  __experimentalItemGroup as ItemGroup,
7
7
  __experimentalVStack as VStack,
@@ -43,8 +43,17 @@ function Item( { name, parentMenu, element, label } ) {
43
43
  return null;
44
44
  }
45
45
 
46
+ const navigationButtonLabel = sprintf(
47
+ // translators: %s: is a subset of Typography, e.g., 'text' or 'links'.
48
+ __( 'Typography %s styles' ),
49
+ label
50
+ );
51
+
46
52
  return (
47
- <NavigationButtonAsItem path={ parentMenu + '/typography/' + element }>
53
+ <NavigationButtonAsItem
54
+ path={ parentMenu + '/typography/' + element }
55
+ aria-label={ navigationButtonLabel }
56
+ >
48
57
  <HStack justify="flex-start">
49
58
  <FlexItem
50
59
  className="edit-site-global-styles-screen-typography__indicator"
@@ -95,6 +104,12 @@ function ScreenTypography( { name } ) {
95
104
  element="link"
96
105
  label={ __( 'Links' ) }
97
106
  />
107
+ <Item
108
+ name={ name }
109
+ parentMenu={ parentMenu }
110
+ element="button"
111
+ label={ __( 'Buttons' ) }
112
+ />
98
113
  </ItemGroup>
99
114
  </VStack>
100
115
  </div>
@@ -57,6 +57,15 @@
57
57
  font-size: 11px !important;
58
58
  }
59
59
 
60
+ .edit-site-global-styles-section-title {
61
+ color: $gray-800;
62
+ font-weight: 600;
63
+ line-height: 1.2;
64
+ padding: $grid-unit-20;
65
+ padding-bottom: 0;
66
+ margin: 0;
67
+ }
68
+
60
69
  .edit-site-screen-color-palette-toggle.edit-site-screen-color-palette-toggle {
61
70
  margin-right: $grid-unit-20;
62
71
  margin-left: $grid-unit-20;
@@ -68,6 +77,7 @@
68
77
 
69
78
  .edit-site-screen-text-color__control,
70
79
  .edit-site-screen-link-color__control,
80
+ .edit-site-screen-button-color__control,
71
81
  .edit-site-screen-background-color__control {
72
82
  padding: $grid-unit-20;
73
83
  }
@@ -40,6 +40,20 @@ describe( 'global styles renderer', () => {
40
40
  fontSize: '23px',
41
41
  },
42
42
  },
43
+ link: {
44
+ ':hover': {
45
+ color: {
46
+ background: 'green',
47
+ text: 'yellow',
48
+ },
49
+ },
50
+ ':focus': {
51
+ color: {
52
+ background: 'green',
53
+ text: 'yellow',
54
+ },
55
+ },
56
+ },
43
57
  },
44
58
  },
45
59
  },
@@ -49,6 +63,18 @@ describe( 'global styles renderer', () => {
49
63
  background: 'yellow',
50
64
  text: 'yellow',
51
65
  },
66
+ ':hover': {
67
+ color: {
68
+ background: 'hotpink',
69
+ text: 'black',
70
+ },
71
+ },
72
+ ':focus': {
73
+ color: {
74
+ background: 'hotpink',
75
+ text: 'black',
76
+ },
77
+ },
52
78
  },
53
79
  },
54
80
  },
@@ -58,6 +84,7 @@ describe( 'global styles renderer', () => {
58
84
  selector: '.my-heading1, .my-heading2',
59
85
  },
60
86
  };
87
+
61
88
  expect( getNodesWithStyles( tree, blockSelectors ) ).toEqual( [
62
89
  {
63
90
  styles: {
@@ -74,6 +101,18 @@ describe( 'global styles renderer', () => {
74
101
  background: 'yellow',
75
102
  text: 'yellow',
76
103
  },
104
+ ':hover': {
105
+ color: {
106
+ background: 'hotpink',
107
+ text: 'black',
108
+ },
109
+ },
110
+ ':focus': {
111
+ color: {
112
+ background: 'hotpink',
113
+ text: 'black',
114
+ },
115
+ },
77
116
  },
78
117
  selector: ELEMENTS.link,
79
118
  },
@@ -102,6 +141,23 @@ describe( 'global styles renderer', () => {
102
141
  },
103
142
  selector: '.my-heading1 h2, .my-heading2 h2',
104
143
  },
144
+ {
145
+ styles: {
146
+ ':hover': {
147
+ color: {
148
+ background: 'green',
149
+ text: 'yellow',
150
+ },
151
+ },
152
+ ':focus': {
153
+ color: {
154
+ background: 'green',
155
+ text: 'yellow',
156
+ },
157
+ },
158
+ },
159
+ selector: '.my-heading1 a, .my-heading2 a',
160
+ },
105
161
  ] );
106
162
  } );
107
163
  } );
@@ -318,6 +374,21 @@ describe( 'global styles renderer', () => {
318
374
  fontSize: '42px',
319
375
  },
320
376
  },
377
+ link: {
378
+ color: {
379
+ text: 'blue',
380
+ },
381
+ ':hover': {
382
+ color: {
383
+ text: 'orange',
384
+ },
385
+ },
386
+ ':focus': {
387
+ color: {
388
+ text: 'orange',
389
+ },
390
+ },
391
+ },
321
392
  },
322
393
  blocks: {
323
394
  'core/group': {
@@ -345,6 +416,16 @@ describe( 'global styles renderer', () => {
345
416
  color: {
346
417
  text: 'hotpink',
347
418
  },
419
+ ':hover': {
420
+ color: {
421
+ text: 'red',
422
+ },
423
+ },
424
+ ':focus': {
425
+ color: {
426
+ text: 'red',
427
+ },
428
+ },
348
429
  },
349
430
  },
350
431
  },
@@ -358,27 +439,12 @@ describe( 'global styles renderer', () => {
358
439
  },
359
440
  'core/heading': {
360
441
  selector: 'h1,h2,h3,h4,h5,h6',
361
- elements: {
362
- link:
363
- 'h1 ' +
364
- ELEMENTS.link +
365
- ',h2 ' +
366
- ELEMENTS.link +
367
- ',h3 ' +
368
- ELEMENTS.link +
369
- ',h4 ' +
370
- ELEMENTS.link +
371
- ',h5 ' +
372
- ELEMENTS.link +
373
- ',h6 ' +
374
- ELEMENTS.link,
375
- },
376
442
  },
377
443
  };
378
444
 
379
445
  expect( toStyles( tree, blockSelectors ) ).toEqual(
380
446
  'body {margin: 0;}' +
381
- 'body{background-color: red;margin: 10px;padding: 10px;}h1{font-size: 42px;}.wp-block-group{margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}h1,h2,h3,h4,h5,h6{color: orange;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: hotpink;}' +
447
+ 'body{background-color: red;margin: 10px;padding: 10px;}h1{font-size: 42px;}a{color: blue;}a:hover{color: orange;}a:focus{color: orange;}.wp-block-group{margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}h1,h2,h3,h4,h5,h6{color: orange;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: hotpink;}h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover{color: red;}h1 a:focus,h2 a:focus,h3 a:focus,h4 a:focus,h5 a:focus,h6 a:focus{color: red;}' +
382
448
  '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' +
383
449
  '.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}'
384
450
  );
@@ -20,6 +20,7 @@ import ScreenColorPalette from './screen-color-palette';
20
20
  import ScreenBackgroundColor from './screen-background-color';
21
21
  import ScreenTextColor from './screen-text-color';
22
22
  import ScreenLinkColor from './screen-link-color';
23
+ import ScreenButtonColor from './screen-button-color';
23
24
  import ScreenLayout from './screen-layout';
24
25
  import ScreenStyleVariations from './screen-style-variations';
25
26
 
@@ -58,6 +59,12 @@ function ContextScreens( { name } ) {
58
59
  <ScreenTypographyElement name={ name } element="link" />
59
60
  </GlobalStylesNavigationScreen>
60
61
 
62
+ <GlobalStylesNavigationScreen
63
+ path={ parentMenu + '/typography/button' }
64
+ >
65
+ <ScreenTypographyElement name={ name } element="button" />
66
+ </GlobalStylesNavigationScreen>
67
+
61
68
  <GlobalStylesNavigationScreen path={ parentMenu + '/colors' }>
62
69
  <ScreenColors name={ name } />
63
70
  </GlobalStylesNavigationScreen>
@@ -82,6 +89,12 @@ function ContextScreens( { name } ) {
82
89
  <ScreenLinkColor name={ name } />
83
90
  </GlobalStylesNavigationScreen>
84
91
 
92
+ <GlobalStylesNavigationScreen
93
+ path={ parentMenu + '/colors/button' }
94
+ >
95
+ <ScreenButtonColor name={ name } />
96
+ </GlobalStylesNavigationScreen>
97
+
85
98
  <GlobalStylesNavigationScreen path={ parentMenu + '/layout' }>
86
99
  <ScreenLayout name={ name } />
87
100
  </GlobalStylesNavigationScreen>