@wordpress/edit-site 4.15.0 → 4.16.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 (51) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/block-editor/resizable-editor.js +11 -35
  3. package/build/components/block-editor/resizable-editor.js.map +1 -1
  4. package/build/components/global-styles/palette.js +2 -2
  5. package/build/components/global-styles/palette.js.map +1 -1
  6. package/build/components/global-styles/preview.js +2 -2
  7. package/build/components/global-styles/preview.js.map +1 -1
  8. package/build/components/global-styles/screen-typography-element.js +49 -2
  9. package/build/components/global-styles/screen-typography-element.js.map +1 -1
  10. package/build/components/global-styles/typography-panel.js +128 -81
  11. package/build/components/global-styles/typography-panel.js.map +1 -1
  12. package/build/components/global-styles/typography-preview.js +54 -0
  13. package/build/components/global-styles/typography-preview.js.map +1 -0
  14. package/build/components/global-styles/use-global-styles-output.js +7 -7
  15. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  16. package/build/components/main-dashboard-button/index.js +2 -2
  17. package/build/components/main-dashboard-button/index.js.map +1 -1
  18. package/build/index.js +20 -1
  19. package/build/index.js.map +1 -1
  20. package/build-module/components/block-editor/resizable-editor.js +10 -34
  21. package/build-module/components/block-editor/resizable-editor.js.map +1 -1
  22. package/build-module/components/global-styles/palette.js +2 -2
  23. package/build-module/components/global-styles/palette.js.map +1 -1
  24. package/build-module/components/global-styles/preview.js +2 -2
  25. package/build-module/components/global-styles/preview.js.map +1 -1
  26. package/build-module/components/global-styles/screen-typography-element.js +48 -2
  27. package/build-module/components/global-styles/screen-typography-element.js.map +1 -1
  28. package/build-module/components/global-styles/typography-panel.js +129 -83
  29. package/build-module/components/global-styles/typography-panel.js.map +1 -1
  30. package/build-module/components/global-styles/typography-preview.js +46 -0
  31. package/build-module/components/global-styles/typography-preview.js.map +1 -0
  32. package/build-module/components/global-styles/use-global-styles-output.js +7 -7
  33. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  34. package/build-module/components/main-dashboard-button/index.js +3 -3
  35. package/build-module/components/main-dashboard-button/index.js.map +1 -1
  36. package/build-module/index.js +19 -1
  37. package/build-module/index.js.map +1 -1
  38. package/build-style/style-rtl.css +4 -4
  39. package/build-style/style.css +4 -4
  40. package/package.json +29 -29
  41. package/src/components/block-editor/resizable-editor.js +8 -37
  42. package/src/components/global-styles/palette.js +9 -5
  43. package/src/components/global-styles/preview.js +2 -2
  44. package/src/components/global-styles/screen-typography-element.js +65 -1
  45. package/src/components/global-styles/style.scss +3 -3
  46. package/src/components/global-styles/typography-panel.js +192 -150
  47. package/src/components/global-styles/typography-preview.js +49 -0
  48. package/src/components/global-styles/use-global-styles-output.js +15 -9
  49. package/src/components/main-dashboard-button/index.js +3 -3
  50. package/src/components/sidebar/style.scss +1 -1
  51. package/src/index.js +21 -0
@@ -57,38 +57,14 @@ function ResizableEditor( { enableResizing, settings, children, ...props } ) {
57
57
 
58
58
  useEffect(
59
59
  function autoResizeIframeHeight() {
60
- const iframe = iframeRef.current;
61
-
62
- if ( ! iframe || ! enableResizing ) {
60
+ if ( ! iframeRef.current || ! enableResizing ) {
63
61
  return;
64
62
  }
65
63
 
66
- let timeoutId = null;
67
-
68
- function resizeHeight() {
69
- if ( ! timeoutId ) {
70
- // Throttle the updates on timeout. This code previously
71
- // used `requestAnimationFrame`, but that seems to not
72
- // always work before an iframe is ready.
73
- timeoutId = iframe.contentWindow.setTimeout( () => {
74
- const { readyState } = iframe.contentDocument;
75
-
76
- // Continue deferring the timeout until the document is ready.
77
- // Only then will it have a height.
78
- if (
79
- readyState !== 'interactive' &&
80
- readyState !== 'complete'
81
- ) {
82
- resizeHeight();
83
- return;
84
- }
85
-
86
- setHeight( iframe.contentDocument.body.scrollHeight );
87
- timeoutId = null;
88
-
89
- // 30 frames per second.
90
- }, 1000 / 30 );
91
- }
64
+ const iframe = iframeRef.current;
65
+
66
+ function setFrameHeight() {
67
+ setHeight( iframe.contentDocument.body.scrollHeight );
92
68
  }
93
69
 
94
70
  let resizeObserver;
@@ -97,28 +73,23 @@ function ResizableEditor( { enableResizing, settings, children, ...props } ) {
97
73
  resizeObserver?.disconnect();
98
74
 
99
75
  resizeObserver = new iframe.contentWindow.ResizeObserver(
100
- resizeHeight
76
+ setFrameHeight
101
77
  );
102
78
 
103
79
  // Observe the body, since the `html` element seems to always
104
80
  // have a height of `100%`.
105
81
  resizeObserver.observe( iframe.contentDocument.body );
106
-
107
- resizeHeight();
82
+ setFrameHeight();
108
83
  }
109
84
 
110
- // This is only required in Firefox for some unknown reasons.
111
85
  iframe.addEventListener( 'load', registerObserver );
112
- // This is required in Chrome and Safari.
113
- registerObserver();
114
86
 
115
87
  return () => {
116
- iframe.contentWindow?.clearTimeout( timeoutId );
117
88
  resizeObserver?.disconnect();
118
89
  iframe.removeEventListener( 'load', registerObserver );
119
90
  };
120
91
  },
121
- [ enableResizing ]
92
+ [ enableResizing, iframeRef.current ]
122
93
  );
123
94
 
124
95
  const resizeWidthBy = useCallback( ( deltaPixels ) => {
@@ -68,11 +68,15 @@ function Palette( { name } ) {
68
68
  }
69
69
  >
70
70
  <ZStack isLayered={ false } offset={ -8 }>
71
- { colors.slice( 0, 5 ).map( ( { color } ) => (
72
- <ColorIndicatorWrapper key={ color }>
73
- <ColorIndicator colorValue={ color } />
74
- </ColorIndicatorWrapper>
75
- ) ) }
71
+ { colors
72
+ .slice( 0, 5 )
73
+ .map( ( { color }, index ) => (
74
+ <ColorIndicatorWrapper
75
+ key={ `${ color }-${ index }` }
76
+ >
77
+ <ColorIndicator colorValue={ color } />
78
+ </ColorIndicatorWrapper>
79
+ ) ) }
76
80
  </ZStack>
77
81
  <FlexItem>{ paletteButtonText }</FlexItem>
78
82
  </HStack>
@@ -79,13 +79,13 @@ const StylesPreview = ( { label, isFocused } ) => {
79
79
  )
80
80
  .slice( 0, 2 );
81
81
 
82
- // Reset leaked styles from WP common.css and remove main content layout padding.
82
+ // Reset leaked styles from WP common.css and remove main content layout padding and border.
83
83
  const editorStyles = useMemo( () => {
84
84
  if ( styles ) {
85
85
  return [
86
86
  ...styles,
87
87
  {
88
- css: 'body{min-width: 0;padding: 0;}',
88
+ css: 'body{min-width: 0;padding: 0;border: none;}',
89
89
  isGlobalStyles: true,
90
90
  },
91
91
  ];
@@ -2,12 +2,19 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
+ import {
6
+ __experimentalToggleGroupControl as ToggleGroupControl,
7
+ __experimentalToggleGroupControlOption as ToggleGroupControlOption,
8
+ __experimentalSpacer as Spacer,
9
+ } from '@wordpress/components';
10
+ import { useState } from '@wordpress/element';
5
11
 
6
12
  /**
7
13
  * Internal dependencies
8
14
  */
9
15
  import TypographyPanel from './typography-panel';
10
16
  import ScreenHeader from './header';
17
+ import TypographyPreview from './typography-preview';
11
18
 
12
19
  const elements = {
13
20
  text: {
@@ -29,13 +36,70 @@ const elements = {
29
36
  };
30
37
 
31
38
  function ScreenTypographyElement( { name, element } ) {
39
+ const [ headingLevel, setHeadingLevel ] = useState( 'heading' );
40
+
32
41
  return (
33
42
  <>
34
43
  <ScreenHeader
35
44
  title={ elements[ element ].title }
36
45
  description={ elements[ element ].description }
37
46
  />
38
- <TypographyPanel name={ name } element={ element } />
47
+ <Spacer marginX={ 4 }>
48
+ <TypographyPreview
49
+ name={ name }
50
+ element={ element }
51
+ headingLevel={ headingLevel }
52
+ />
53
+ </Spacer>
54
+ { element === 'heading' && (
55
+ <Spacer marginX={ 4 } marginBottom="1em">
56
+ <ToggleGroupControl
57
+ label={ __( 'Select heading level' ) }
58
+ hideLabelFromVision
59
+ value={ headingLevel }
60
+ onChange={ setHeadingLevel }
61
+ isBlock
62
+ size="__unstable-large"
63
+ __nextHasNoMarginBottom
64
+ >
65
+ <ToggleGroupControlOption
66
+ value="heading"
67
+ /* translators: 'All' refers to selecting all heading levels
68
+ and applying the same style to h1-h6. */
69
+ label={ __( 'All' ) }
70
+ />
71
+ <ToggleGroupControlOption
72
+ value="h1"
73
+ label={ __( 'H1' ) }
74
+ />
75
+ <ToggleGroupControlOption
76
+ value="h2"
77
+ label={ __( 'H2' ) }
78
+ />
79
+ <ToggleGroupControlOption
80
+ value="h3"
81
+ label={ __( 'H3' ) }
82
+ />
83
+ <ToggleGroupControlOption
84
+ value="h4"
85
+ label={ __( 'H4' ) }
86
+ />
87
+ <ToggleGroupControlOption
88
+ value="h5"
89
+ label={ __( 'H5' ) }
90
+ />
91
+ <ToggleGroupControlOption
92
+ value="h6"
93
+ label={ __( 'H6' ) }
94
+ />
95
+ </ToggleGroupControl>
96
+ </Spacer>
97
+ ) }
98
+ <TypographyPanel
99
+ name={ name }
100
+ element={ element }
101
+ headingLevel={ headingLevel }
102
+ />
39
103
  </>
40
104
  );
41
105
  }
@@ -11,7 +11,7 @@
11
11
  display: block;
12
12
  }
13
13
 
14
- .edit-site-typography-panel__preview {
14
+ .edit-site-typography-preview {
15
15
  display: flex;
16
16
  align-items: center;
17
17
  justify-content: center;
@@ -46,7 +46,7 @@
46
46
 
47
47
  .component-color-indicator {
48
48
  // Show a diagonal line (crossed out) for empty swatches.
49
- background: linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%);
49
+ background: $white linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%);
50
50
  flex-shrink: 0;
51
51
  }
52
52
  }
@@ -97,7 +97,7 @@
97
97
  }
98
98
 
99
99
  &:focus .edit-site-global-styles-variations_item-preview {
100
- border: var(--wp-admin-theme-color) $border-width solid;
100
+ border: var(--wp-admin-theme-color) var(--wp-admin-border-width-focus) solid;
101
101
  }
102
102
  }
103
103
 
@@ -9,25 +9,25 @@ import {
9
9
  __experimentalTextTransformControl as TextTransformControl,
10
10
  } from '@wordpress/block-editor';
11
11
  import {
12
- PanelBody,
13
12
  FontSizePicker,
14
- __experimentalToggleGroupControl as ToggleGroupControl,
15
- __experimentalToggleGroupControlOption as ToggleGroupControlOption,
16
- __experimentalGrid as Grid,
13
+ __experimentalToolsPanel as ToolsPanel,
14
+ __experimentalToolsPanelItem as ToolsPanelItem,
17
15
  } from '@wordpress/components';
18
16
  import { __ } from '@wordpress/i18n';
19
- import { useState } from '@wordpress/element';
17
+
20
18
  /**
21
19
  * Internal dependencies
22
20
  */
23
21
  import { getSupportedGlobalStylesPanels, useSetting, useStyle } from './hooks';
24
22
 
25
23
  export function useHasTypographyPanel( name ) {
24
+ const hasFontFamily = useHasFontFamilyControl( name );
26
25
  const hasLineHeight = useHasLineHeightControl( name );
27
26
  const hasFontAppearance = useHasAppearanceControl( name );
28
27
  const hasLetterSpacing = useHasLetterSpacingControl( name );
29
28
  const supports = getSupportedGlobalStylesPanels( name );
30
29
  return (
30
+ hasFontFamily ||
31
31
  hasLineHeight ||
32
32
  hasFontAppearance ||
33
33
  hasLetterSpacing ||
@@ -35,6 +35,12 @@ export function useHasTypographyPanel( name ) {
35
35
  );
36
36
  }
37
37
 
38
+ function useHasFontFamilyControl( name ) {
39
+ const supports = getSupportedGlobalStylesPanels( name );
40
+ const [ fontFamilies ] = useSetting( 'typography.fontFamilies', name );
41
+ return supports.includes( 'fontFamily' ) && !! fontFamilies?.length;
42
+ }
43
+
38
44
  function useHasLineHeightControl( name ) {
39
45
  const supports = getSupportedGlobalStylesPanels( name );
40
46
  return (
@@ -54,6 +60,23 @@ function useHasAppearanceControl( name ) {
54
60
  return hasFontStyles || hasFontWeights;
55
61
  }
56
62
 
63
+ function useAppearanceControlLabel( name ) {
64
+ const supports = getSupportedGlobalStylesPanels( name );
65
+ const hasFontStyles =
66
+ useSetting( 'typography.fontStyle', name )[ 0 ] &&
67
+ supports.includes( 'fontStyle' );
68
+ const hasFontWeights =
69
+ useSetting( 'typography.fontWeight', name )[ 0 ] &&
70
+ supports.includes( 'fontWeight' );
71
+ if ( ! hasFontStyles ) {
72
+ return __( 'Font weight' );
73
+ }
74
+ if ( ! hasFontWeights ) {
75
+ return __( 'Font style' );
76
+ }
77
+ return __( 'Appearance' );
78
+ }
79
+
57
80
  function useHasLetterSpacingControl( name, element ) {
58
81
  const setting = useSetting( 'typography.letterSpacing', name )[ 0 ];
59
82
  if ( ! setting ) {
@@ -78,12 +101,53 @@ function useHasTextTransformControl( name, element ) {
78
101
  return supports.includes( 'textTransform' );
79
102
  }
80
103
 
81
- export default function TypographyPanel( { name, element } ) {
82
- const [ selectedLevel, setCurrentTab ] = useState( 'heading' );
104
+ function useStyleWithReset( path, blockName ) {
105
+ const [ style, setStyle ] = useStyle( path, blockName );
106
+ const [ userStyle ] = useStyle( path, blockName, 'user' );
107
+ const hasStyle = () => !! userStyle;
108
+ const resetStyle = () => setStyle( undefined );
109
+ return [ style, setStyle, hasStyle, resetStyle ];
110
+ }
111
+
112
+ function useFontAppearance( prefix, name ) {
113
+ const [ fontStyle, setFontStyle ] = useStyle(
114
+ prefix + 'typography.fontStyle',
115
+ name
116
+ );
117
+ const [ userFontStyle ] = useStyle(
118
+ prefix + 'typography.fontStyle',
119
+ name,
120
+ 'user'
121
+ );
122
+ const [ fontWeight, setFontWeight ] = useStyle(
123
+ prefix + 'typography.fontWeight',
124
+ name
125
+ );
126
+ const [ userFontWeight ] = useStyle(
127
+ prefix + 'typography.fontWeight',
128
+ name,
129
+ 'user'
130
+ );
131
+ const hasFontAppearance = () => !! userFontStyle || !! userFontWeight;
132
+ const resetFontAppearance = () => {
133
+ setFontStyle( undefined );
134
+ setFontWeight( undefined );
135
+ };
136
+ return {
137
+ fontStyle,
138
+ setFontStyle,
139
+ fontWeight,
140
+ setFontWeight,
141
+ hasFontAppearance,
142
+ resetFontAppearance,
143
+ };
144
+ }
145
+
146
+ export default function TypographyPanel( { name, element, headingLevel } ) {
83
147
  const supports = getSupportedGlobalStylesPanels( name );
84
148
  let prefix = '';
85
149
  if ( element === 'heading' ) {
86
- prefix = `elements.${ selectedLevel }.`;
150
+ prefix = `elements.${ headingLevel }.`;
87
151
  } else if ( element && element !== 'text' ) {
88
152
  prefix = `elements.${ element }.`;
89
153
  }
@@ -99,142 +163,99 @@ export default function TypographyPanel( { name, element } ) {
99
163
  const hasFontWeights =
100
164
  useSetting( 'typography.fontWeight', name )[ 0 ] &&
101
165
  supports.includes( 'fontWeight' );
166
+ const hasFontFamilyEnabled = useHasFontFamilyControl( name );
102
167
  const hasLineHeightEnabled = useHasLineHeightControl( name );
103
168
  const hasAppearanceControl = useHasAppearanceControl( name );
169
+ const appearanceControlLabel = useAppearanceControlLabel( name );
104
170
  const hasLetterSpacingControl = useHasLetterSpacingControl( name, element );
105
171
  const hasTextTransformControl = useHasTextTransformControl( name, element );
106
172
 
107
173
  /* Disable font size controls when the option to style all headings is selected. */
108
174
  let hasFontSizeEnabled = supports.includes( 'fontSize' );
109
- if ( element === 'heading' && selectedLevel === 'heading' ) {
175
+ if ( element === 'heading' && headingLevel === 'heading' ) {
110
176
  hasFontSizeEnabled = false;
111
177
  }
112
178
 
113
- const [ fontFamily, setFontFamily ] = useStyle(
114
- prefix + 'typography.fontFamily',
115
- name
116
- );
117
- const [ fontSize, setFontSize ] = useStyle(
118
- prefix + 'typography.fontSize',
119
- name
120
- );
179
+ const [ fontFamily, setFontFamily, hasFontFamily, resetFontFamily ] =
180
+ useStyleWithReset( prefix + 'typography.fontFamily', name );
181
+ const [ fontSize, setFontSize, hasFontSize, resetFontSize ] =
182
+ useStyleWithReset( prefix + 'typography.fontSize', name );
183
+ const {
184
+ fontStyle,
185
+ setFontStyle,
186
+ fontWeight,
187
+ setFontWeight,
188
+ hasFontAppearance,
189
+ resetFontAppearance,
190
+ } = useFontAppearance( prefix, name );
191
+ const [ lineHeight, setLineHeight, hasLineHeight, resetLineHeight ] =
192
+ useStyleWithReset( prefix + 'typography.lineHeight', name );
193
+ const [
194
+ letterSpacing,
195
+ setLetterSpacing,
196
+ hasLetterSpacing,
197
+ resetLetterSpacing,
198
+ ] = useStyleWithReset( prefix + 'typography.letterSpacing', name );
199
+ const [
200
+ textTransform,
201
+ setTextTransform,
202
+ hasTextTransform,
203
+ resetTextTransform,
204
+ ] = useStyleWithReset( prefix + 'typography.textTransform', name );
121
205
 
122
- const [ fontStyle, setFontStyle ] = useStyle(
123
- prefix + 'typography.fontStyle',
124
- name
125
- );
126
- const [ fontWeight, setFontWeight ] = useStyle(
127
- prefix + 'typography.fontWeight',
128
- name
129
- );
130
- const [ lineHeight, setLineHeight ] = useStyle(
131
- prefix + 'typography.lineHeight',
132
- name
133
- );
134
- const [ letterSpacing, setLetterSpacing ] = useStyle(
135
- prefix + 'typography.letterSpacing',
136
- name
137
- );
138
- const [ textTransform, setTextTransform ] = useStyle(
139
- prefix + 'typography.textTransform',
140
- name
141
- );
142
- const [ backgroundColor ] = useStyle( prefix + 'color.background', name );
143
- const [ gradientValue ] = useStyle( prefix + 'color.gradient', name );
144
- const [ color ] = useStyle( prefix + 'color.text', name );
145
- const extraStyles =
146
- element === 'link'
147
- ? {
148
- textDecoration: 'underline',
149
- }
150
- : {};
206
+ const resetAll = () => {
207
+ resetFontFamily();
208
+ resetFontSize();
209
+ resetFontAppearance();
210
+ resetLineHeight();
211
+ resetLetterSpacing();
212
+ resetTextTransform();
213
+ };
151
214
 
152
215
  return (
153
- <PanelBody className="edit-site-typography-panel" initialOpen={ true }>
154
- <div
155
- className="edit-site-typography-panel__preview"
156
- style={ {
157
- fontFamily: fontFamily ?? 'serif',
158
- background: gradientValue ?? backgroundColor,
159
- color,
160
- fontSize,
161
- fontStyle,
162
- fontWeight,
163
- letterSpacing,
164
- ...extraStyles,
165
- } }
166
- >
167
- Aa
168
- </div>
169
- <Grid columns={ 2 } rowGap={ 16 } columnGap={ 8 }>
170
- { element === 'heading' && (
171
- <div className="edit-site-typography-panel__full-width-control">
172
- <ToggleGroupControl
173
- label={ __( 'Select heading level' ) }
174
- hideLabelFromVision
175
- value={ selectedLevel }
176
- onChange={ setCurrentTab }
177
- isBlock
178
- size="__unstable-large"
179
- __nextHasNoMarginBottom
180
- >
181
- <ToggleGroupControlOption
182
- value="heading"
183
- /* translators: 'All' refers to selecting all heading levels
184
- and applying the same style to h1-h6. */
185
- label={ __( 'All' ) }
186
- />
187
- <ToggleGroupControlOption
188
- value="h1"
189
- label={ __( 'H1' ) }
190
- />
191
- <ToggleGroupControlOption
192
- value="h2"
193
- label={ __( 'H2' ) }
194
- />
195
- <ToggleGroupControlOption
196
- value="h3"
197
- label={ __( 'H3' ) }
198
- />
199
- <ToggleGroupControlOption
200
- value="h4"
201
- label={ __( 'H4' ) }
202
- />
203
- <ToggleGroupControlOption
204
- value="h5"
205
- label={ __( 'H5' ) }
206
- />
207
- <ToggleGroupControlOption
208
- value="h6"
209
- label={ __( 'H6' ) }
210
- />
211
- </ToggleGroupControl>
212
- </div>
213
- ) }
214
- { supports.includes( 'fontFamily' ) && (
215
- <div className="edit-site-typography-panel__full-width-control">
216
- <FontFamilyControl
217
- fontFamilies={ fontFamilies }
218
- value={ fontFamily }
219
- onChange={ setFontFamily }
220
- size="__unstable-large"
221
- __nextHasNoMarginBottom
222
- />
223
- </div>
224
- ) }
225
- { hasFontSizeEnabled && (
226
- <div className="edit-site-typography-panel__full-width-control">
227
- <FontSizePicker
228
- value={ fontSize }
229
- onChange={ setFontSize }
230
- fontSizes={ fontSizes }
231
- disableCustomFontSizes={ disableCustomFontSizes }
232
- size="__unstable-large"
233
- __nextHasNoMarginBottom
234
- />
235
- </div>
236
- ) }
237
- { hasAppearanceControl && (
216
+ <ToolsPanel label={ __( 'Typography' ) } resetAll={ resetAll }>
217
+ { hasFontFamilyEnabled && (
218
+ <ToolsPanelItem
219
+ label={ __( 'Font family' ) }
220
+ hasValue={ hasFontFamily }
221
+ onDeselect={ resetFontFamily }
222
+ isShownByDefault
223
+ >
224
+ <FontFamilyControl
225
+ fontFamilies={ fontFamilies }
226
+ value={ fontFamily }
227
+ onChange={ setFontFamily }
228
+ size="__unstable-large"
229
+ __nextHasNoMarginBottom
230
+ />
231
+ </ToolsPanelItem>
232
+ ) }
233
+ { hasFontSizeEnabled && (
234
+ <ToolsPanelItem
235
+ label={ __( 'Font size' ) }
236
+ hasValue={ hasFontSize }
237
+ onDeselect={ resetFontSize }
238
+ isShownByDefault
239
+ >
240
+ <FontSizePicker
241
+ value={ fontSize }
242
+ onChange={ setFontSize }
243
+ fontSizes={ fontSizes }
244
+ disableCustomFontSizes={ disableCustomFontSizes }
245
+ withReset={ false }
246
+ size="__unstable-large"
247
+ __nextHasNoMarginBottom
248
+ />
249
+ </ToolsPanelItem>
250
+ ) }
251
+ { hasAppearanceControl && (
252
+ <ToolsPanelItem
253
+ className="single-column"
254
+ label={ appearanceControlLabel }
255
+ hasValue={ hasFontAppearance }
256
+ onDeselect={ resetFontAppearance }
257
+ isShownByDefault
258
+ >
238
259
  <FontAppearanceControl
239
260
  value={ {
240
261
  fontStyle,
@@ -252,8 +273,16 @@ export default function TypographyPanel( { name, element } ) {
252
273
  size="__unstable-large"
253
274
  __nextHasNoMarginBottom
254
275
  />
255
- ) }
256
- { hasLineHeightEnabled && (
276
+ </ToolsPanelItem>
277
+ ) }
278
+ { hasLineHeightEnabled && (
279
+ <ToolsPanelItem
280
+ className="single-column"
281
+ label={ __( 'Line height' ) }
282
+ hasValue={ hasLineHeight }
283
+ onDeselect={ resetLineHeight }
284
+ isShownByDefault
285
+ >
257
286
  <LineHeightControl
258
287
  __nextHasNoMarginBottom
259
288
  __unstableInputWidth="auto"
@@ -261,28 +290,41 @@ export default function TypographyPanel( { name, element } ) {
261
290
  onChange={ setLineHeight }
262
291
  size="__unstable-large"
263
292
  />
264
- ) }
265
- { hasLetterSpacingControl && (
293
+ </ToolsPanelItem>
294
+ ) }
295
+ { hasLetterSpacingControl && (
296
+ <ToolsPanelItem
297
+ className="single-column"
298
+ label={ __( 'Letter spacing' ) }
299
+ hasValue={ hasLetterSpacing }
300
+ onDeselect={ resetLetterSpacing }
301
+ isShownByDefault
302
+ >
266
303
  <LetterSpacingControl
267
304
  value={ letterSpacing }
268
305
  onChange={ setLetterSpacing }
269
306
  size="__unstable-large"
270
307
  __unstableInputWidth="auto"
271
308
  />
272
- ) }
273
- { hasTextTransformControl && (
274
- <div className="edit-site-typography-panel__full-width-control">
275
- <TextTransformControl
276
- value={ textTransform }
277
- onChange={ setTextTransform }
278
- showNone
279
- isBlock
280
- size="__unstable-large"
281
- __nextHasNoMarginBottom
282
- />
283
- </div>
284
- ) }
285
- </Grid>
286
- </PanelBody>
309
+ </ToolsPanelItem>
310
+ ) }
311
+ { hasTextTransformControl && (
312
+ <ToolsPanelItem
313
+ label={ __( 'Letter case' ) }
314
+ hasValue={ hasTextTransform }
315
+ onDeselect={ resetTextTransform }
316
+ isShownByDefault
317
+ >
318
+ <TextTransformControl
319
+ value={ textTransform }
320
+ onChange={ setTextTransform }
321
+ showNone
322
+ isBlock
323
+ size="__unstable-large"
324
+ __nextHasNoMarginBottom
325
+ />
326
+ </ToolsPanelItem>
327
+ ) }
328
+ </ToolsPanel>
287
329
  );
288
330
  }