newspack-components 4.9.2 → 4.10.0-alpha.1

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 (103) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/DEVELOPMENT.md +13 -14
  3. package/dist/cjs/_mixins.scss +0 -2
  4. package/dist/cjs/card/core-card.js +6 -3
  5. package/dist/cjs/card/core-card.test.js +76 -5
  6. package/dist/cjs/card/style-core.scss +12 -3
  7. package/dist/cjs/card/style.scss +4 -7
  8. package/dist/cjs/card-feature/index.js +2 -1
  9. package/dist/cjs/card-feature/index.test.js +13 -0
  10. package/dist/cjs/card-feature/style.scss +5 -0
  11. package/dist/cjs/color-picker/index.js +26 -15
  12. package/dist/cjs/color-picker/index.test.js +47 -0
  13. package/dist/cjs/color-picker/style.scss +13 -10
  14. package/dist/cjs/debug-badge/style.scss +1 -1
  15. package/dist/cjs/divider/index.js +2 -2
  16. package/dist/cjs/divider/style.scss +7 -5
  17. package/dist/cjs/grid/style.scss +4 -16
  18. package/dist/cjs/image-upload/index.js +9 -3
  19. package/dist/cjs/image-upload/style.scss +3 -0
  20. package/dist/cjs/index.js +0 -7
  21. package/dist/cjs/info-button/style.scss +1 -1
  22. package/dist/cjs/modal/style.scss +7 -8
  23. package/dist/cjs/page/style.scss +2 -4
  24. package/dist/cjs/plugin-settings/style.scss +1 -1
  25. package/dist/cjs/section-header/index.js +5 -2
  26. package/dist/cjs/section-header/style.scss +3 -3
  27. package/dist/cjs/settings/style.scss +1 -1
  28. package/dist/cjs/style-card/index.js +5 -6
  29. package/dist/cjs/style-card/style.scss +6 -10
  30. package/dist/cjs/style.scss +3 -2
  31. package/dist/cjs/tabbed-navigation/style.scss +0 -1
  32. package/dist/cjs/with-wizard-screen/style.scss +3 -2
  33. package/dist/cjs/wizard/index.js +2 -0
  34. package/dist/esm/_mixins.scss +0 -2
  35. package/dist/esm/card/core-card.js +6 -3
  36. package/dist/esm/card/core-card.test.js +76 -1
  37. package/dist/esm/card/style-core.scss +12 -3
  38. package/dist/esm/card/style.scss +4 -7
  39. package/dist/esm/card-feature/index.js +2 -1
  40. package/dist/esm/card-feature/index.test.js +13 -0
  41. package/dist/esm/card-feature/style.scss +5 -0
  42. package/dist/esm/color-picker/index.js +25 -8
  43. package/dist/esm/color-picker/index.test.js +47 -0
  44. package/dist/esm/color-picker/style.scss +13 -10
  45. package/dist/esm/debug-badge/style.scss +1 -1
  46. package/dist/esm/divider/index.js +2 -2
  47. package/dist/esm/divider/style.scss +7 -5
  48. package/dist/esm/grid/style.scss +4 -16
  49. package/dist/esm/image-upload/index.js +9 -3
  50. package/dist/esm/image-upload/style.scss +3 -0
  51. package/dist/esm/index.js +0 -1
  52. package/dist/esm/info-button/style.scss +1 -1
  53. package/dist/esm/modal/style.scss +7 -8
  54. package/dist/esm/page/style.scss +2 -4
  55. package/dist/esm/plugin-settings/style.scss +1 -1
  56. package/dist/esm/section-header/index.js +5 -2
  57. package/dist/esm/section-header/style.scss +3 -3
  58. package/dist/esm/settings/style.scss +1 -1
  59. package/dist/esm/style-card/index.js +6 -7
  60. package/dist/esm/style-card/style.scss +6 -10
  61. package/dist/esm/style.scss +3 -2
  62. package/dist/esm/tabbed-navigation/style.scss +0 -1
  63. package/dist/esm/with-wizard-screen/style.scss +3 -2
  64. package/dist/esm/wizard/index.js +2 -0
  65. package/package.json +7 -7
  66. package/src/_mixins.scss +0 -2
  67. package/src/card/core-card.js +5 -1
  68. package/src/card/core-card.test.js +28 -1
  69. package/src/card/style-core.scss +12 -3
  70. package/src/card/style.scss +4 -7
  71. package/src/card-feature/index.test.js +7 -0
  72. package/src/card-feature/index.tsx +1 -0
  73. package/src/card-feature/style.scss +5 -0
  74. package/src/color-picker/index.js +20 -6
  75. package/src/color-picker/index.test.js +25 -0
  76. package/src/color-picker/style.scss +13 -10
  77. package/src/debug-badge/style.scss +1 -1
  78. package/src/divider/README.md +2 -2
  79. package/src/divider/index.js +1 -1
  80. package/src/divider/style.scss +7 -5
  81. package/src/grid/style.scss +4 -16
  82. package/src/image-upload/index.js +7 -3
  83. package/src/image-upload/style.scss +3 -0
  84. package/src/index.js +0 -1
  85. package/src/info-button/style.scss +1 -1
  86. package/src/modal/style.scss +7 -8
  87. package/src/page/style.scss +2 -4
  88. package/src/plugin-settings/style.scss +1 -1
  89. package/src/section-header/index.js +4 -1
  90. package/src/section-header/style.scss +3 -3
  91. package/src/settings/style.scss +1 -1
  92. package/src/style-card/index.js +5 -6
  93. package/src/style-card/style.scss +6 -10
  94. package/src/style.scss +3 -2
  95. package/src/tabbed-navigation/style.scss +0 -1
  96. package/src/with-wizard-screen/style.scss +3 -2
  97. package/src/wizard/index.js +2 -0
  98. package/dist/cjs/box-contrast/index.js +0 -53
  99. package/dist/cjs/utils/color.js +0 -35
  100. package/dist/esm/box-contrast/index.js +0 -48
  101. package/dist/esm/utils/color.js +0 -29
  102. package/src/box-contrast/index.tsx +0 -44
  103. package/src/utils/color.ts +0 -32
@@ -54,7 +54,6 @@
54
54
 
55
55
  &[data-disabled],
56
56
  &[aria-disabled="true"] {
57
- /* stylelint-disable-next-line plugin-wpds/no-unknown-ds-tokens -- the plugin's token list lags the prebuilt design-tokens.css names. */
58
57
  color: var( --wpds-color-foreground-interactive-neutral-disabled, #{wp-colors.$gray-600} );
59
58
  pointer-events: none;
60
59
  }
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  @use "~@wordpress/base-styles/colors" as wp-colors;
6
+ @use "~@wordpress/base-styles/variables" as wp-vars;
6
7
  @use "../../../colors/colors.module" as np-colors;
7
8
 
8
9
  .newspack-wizard {
@@ -94,10 +95,10 @@
94
95
  background: wp-colors.$gray-300;
95
96
  border: 0;
96
97
  height: 1px;
97
- margin: 32px 0;
98
+ margin: wp-vars.$grid-unit-40 0;
98
99
 
99
100
  @media screen and ( min-width: 744px ) {
100
- margin: 64px 0;
101
+ margin: wp-vars.$grid-unit-60 0;
101
102
  }
102
103
  }
103
104
  &:not(.newspack-wizard__content--full-width) {
@@ -405,6 +405,7 @@ var Wizard = function Wizard(_ref2, ref) {
405
405
  var headerActions = (actions === null || actions === void 0 ? void 0 : actions.length) > 0 ? /*#__PURE__*/_jsxs(_Fragment, {
406
406
  children: [mainActions.map(function (action, index) {
407
407
  return /*#__PURE__*/_jsx(Button, {
408
+ "aria-label": action.ariaLabel,
408
409
  className: "newspack-wizard__actions__main",
409
410
  href: action.href,
410
411
  icon: resolveIcon(action.icon),
@@ -435,6 +436,7 @@ var Wizard = function Wizard(_ref2, ref) {
435
436
  return /*#__PURE__*/_jsx(MenuGroup, {
436
437
  children: group.map(function (action, index) {
437
438
  return /*#__PURE__*/_jsx(MenuItem, {
439
+ "aria-label": action.ariaLabel,
438
440
  className: action.type === 'primary' || action.type === 'secondary' ? 'newspack-wizard__actions__more__main' : 'newspack-wizard__actions__more__more',
439
441
  icon: action.icon,
440
442
  href: action.href,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newspack-components",
3
- "version": "4.9.2",
3
+ "version": "4.10.0-alpha.1",
4
4
  "description": "Newspack design system components",
5
5
  "author": "Automattic",
6
6
  "license": "GPL-2.0-or-later",
@@ -23,14 +23,14 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@wordpress/admin-ui": "2.4.0",
27
- "@wordpress/style-runtime": "^0.5.0",
28
- "@wordpress/theme": "^0.16.0",
29
- "@wordpress/ui": "^0.16.0",
26
+ "@wordpress/admin-ui": "2.11.0",
27
+ "@wordpress/style-runtime": "^0.12.0",
28
+ "@wordpress/theme": "^2.2.0",
29
+ "@wordpress/ui": "^0.23.0",
30
30
  "classnames": "^2.3.1",
31
31
  "lodash": "^4.17.21",
32
32
  "moment-range": "^3.1.1",
33
- "newspack-icons": "1.1.3",
33
+ "newspack-icons": "1.2.0-alpha.1",
34
34
  "qs": "^6.15.2",
35
35
  "react-router-dom": "^5.3.4",
36
36
  "@babel/runtime": "^7.29.7",
@@ -58,7 +58,7 @@
58
58
  "@babel/preset-env": "^7.29.7",
59
59
  "@babel/preset-react": "^7.29.7",
60
60
  "@babel/preset-typescript": "^7.29.7",
61
- "newspack-scripts": "5.11.0",
61
+ "newspack-scripts": "5.12.0-alpha.1",
62
62
  "recursive-copy": "^2.0.0"
63
63
  },
64
64
  "babel": {
package/src/_mixins.scss CHANGED
@@ -3,11 +3,9 @@
3
3
  @use "~@wordpress/base-styles/variables" as wp-vars;
4
4
 
5
5
  @mixin text-muted {
6
- /* stylelint-disable-next-line plugin-wpds/no-unknown-ds-tokens -- the plugin's token list lags the prebuilt design-tokens.css names. */
7
6
  color: var( --wpds-color-foreground-content-neutral-weak, #{wp-colors.$gray-700} );
8
7
  }
9
8
 
10
9
  @mixin wpds-focus-ring {
11
- /* stylelint-disable-next-line plugin-wpds/no-unknown-ds-tokens -- the plugin's token list lags the prebuilt design-tokens.css names. */
12
10
  outline: var( --wpds-border-width-focus, var( --wp-admin-border-width-focus, #{wp-vars.$border-width-focus-fallback} ) ) solid var( --wpds-color-stroke-focus, var( --wp-admin-theme-color, #{colors.$primary-600} ) );
13
11
  }
@@ -22,6 +22,7 @@ import classNames from 'classnames';
22
22
 
23
23
  const CoreCard = ( {
24
24
  actions,
25
+ actionsLabel,
25
26
  actionType,
26
27
  as,
27
28
  buttonsCard,
@@ -80,6 +81,7 @@ const CoreCard = ( {
80
81
  disabled && 'newspack-card--core__is-disabled',
81
82
  children && 'newspack-card--core__has-children',
82
83
  noMargin && 'newspack-card--core__no-margin',
84
+ ( noBorder || otherProps.isBorderless ) && 'newspack-card--core__no-border',
83
85
  hasGreyHeader && 'newspack-card--core__has-grey-header'
84
86
  );
85
87
  let sizeProps = isSmall ? 'small' : size;
@@ -169,7 +171,7 @@ const CoreCard = ( {
169
171
  />
170
172
  ) }
171
173
  { actions?.length > 0 && (
172
- <DropdownMenu icon={ moreVertical } label={ __( 'More', 'newspack-plugin' ) }>
174
+ <DropdownMenu icon={ moreVertical } label={ actionsLabel || __( 'More actions', 'newspack-plugin' ) }>
173
175
  { () =>
174
176
  actions.map( ( action, index ) => {
175
177
  // Actions can be an array of sub-actions, which are rendered within a MenuGroup.
@@ -183,6 +185,7 @@ const CoreCard = ( {
183
185
  icon={ subAction.icon }
184
186
  onClick={ subAction.action }
185
187
  href={ subAction.href }
188
+ aria-label={ subAction.ariaLabel }
186
189
  disabled={ subAction.disabled || false }
187
190
  isDestructive={ subAction.destructive || false }
188
191
  >
@@ -199,6 +202,7 @@ const CoreCard = ( {
199
202
  icon={ action.icon }
200
203
  onClick={ action.action }
201
204
  href={ action.href }
205
+ aria-label={ action.ariaLabel }
202
206
  disabled={ action.disabled || false }
203
207
  isDestructive={ action.destructive || false }
204
208
  >
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies.
3
3
  */
4
- import { render } from '@testing-library/react';
4
+ import { fireEvent, render, screen } from '@testing-library/react';
5
5
 
6
6
  /**
7
7
  * Internal dependencies.
@@ -35,6 +35,22 @@ describe( 'CoreCard', () => {
35
35
  expect( getHeader( container ).tagName ).not.toBe( 'BUTTON' );
36
36
  } );
37
37
 
38
+ it( 'names the actions menu "More actions" by default', () => {
39
+ render( <CoreCard header="Settings" actions={ [ { label: 'Delete', action: () => {} } ] } /> );
40
+ expect( screen.getByRole( 'button', { name: 'More actions' } ) ).toBeInTheDocument();
41
+ } );
42
+
43
+ it( 'names the actions menu with actionsLabel when supplied', () => {
44
+ render( <CoreCard header="Settings" actions={ [ { label: 'Delete', action: () => {} } ] } actionsLabel="Settings actions" /> );
45
+ expect( screen.getByRole( 'button', { name: 'Settings actions' } ) ).toBeInTheDocument();
46
+ } );
47
+
48
+ it( 'gives a menu item its ariaLabel as the accessible name', async () => {
49
+ render( <CoreCard header="Settings" actions={ [ { label: 'Delete', ariaLabel: 'Delete: Settings', action: () => {} } ] } /> );
50
+ fireEvent.click( screen.getByRole( 'button', { name: 'More actions' } ) );
51
+ expect( await screen.findByRole( 'menuitem', { name: 'Delete: Settings' } ) ).toBeInTheDocument();
52
+ } );
53
+
38
54
  it( 'renders the header as a non-button when it is also draggable', () => {
39
55
  const { container } = render( <CoreCard header="Settings" isDraggable onHeaderClick={ () => {} } /> );
40
56
  expect( getHeader( container ).tagName ).not.toBe( 'BUTTON' );
@@ -58,4 +74,15 @@ describe( 'CoreCard', () => {
58
74
  const { container: vertical } = render( <CoreCard header="Settings" isVertical /> );
59
75
  expect( vertical.querySelector( '.newspack-card--core__is-vertical' ) ).not.toBeNull();
60
76
  } );
77
+
78
+ it( 'marks the card borderless only when noBorder or isBorderless is passed', () => {
79
+ const { container: plain } = render( <CoreCard header="Settings" /> );
80
+ expect( plain.querySelector( '.newspack-card--core__no-border' ) ).toBeNull();
81
+
82
+ const { container: borderless } = render( <CoreCard header="Settings" noBorder /> );
83
+ expect( borderless.querySelector( '.newspack-card--core__no-border' ) ).not.toBeNull();
84
+
85
+ const { container: coreBorderless } = render( <CoreCard header="Settings" isBorderless /> );
86
+ expect( coreBorderless.querySelector( '.newspack-card--core__no-border' ) ).not.toBeNull();
87
+ } );
61
88
  } );
@@ -5,6 +5,15 @@
5
5
  @use "~@wordpress/base-styles/colors" as wp-colors;
6
6
  @use "~@wordpress/base-styles/variables" as wp-vars;
7
7
 
8
+ .newspack-card--core.components-card:where(:not(.newspack-card--core__no-border)) {
9
+ box-shadow: 0 0 0 1px var( --wpds-color-stroke-surface-neutral, #{wp-colors.$gray-300} );
10
+ }
11
+
12
+ .newspack-card--core .newspack-card--core__header.components-card__header,
13
+ .newspack-card--core .components-card__footer {
14
+ border-color: var( --wpds-color-stroke-surface-neutral, #{wp-colors.$gray-300} );
15
+ }
16
+
8
17
  .newspack-card--core,
9
18
  .newspack-wizard .newspack-card--core {
10
19
  background: wp-colors.$white;
@@ -107,10 +116,10 @@
107
116
  }
108
117
  > .components-dropdown-menu {
109
118
  aspect-ratio: 1;
110
- border-left: 1px solid wp-colors.$gray-200;
119
+ border-left: 1px solid var( --wpds-color-stroke-surface-neutral, #{wp-colors.$gray-300} );
111
120
  display: grid;
112
121
  height: 100%;
113
- max-width: 50px;
122
+ max-width: 70px;
114
123
  padding: 4px;
115
124
  place-items: center;
116
125
  position: absolute;
@@ -127,7 +136,7 @@
127
136
  padding-left: 80px !important;
128
137
  .newspack-card--core__header__draggable-controls {
129
138
  align-items: center;
130
- border-right: 1px solid wp-colors.$gray-200;
139
+ border-right: 1px solid var( --wpds-color-stroke-surface-neutral, #{wp-colors.$gray-300} );
131
140
  display: flex;
132
141
  height: 100%;
133
142
  justify-content: space-between;
@@ -3,10 +3,11 @@
3
3
  */
4
4
 
5
5
  @use "~@wordpress/base-styles/colors" as wp-colors;
6
+ @use "~@wordpress/base-styles/variables" as wp-vars;
6
7
 
7
8
  .newspack-card {
8
9
  border-radius: 2px;
9
- border: 1px solid wp-colors.$gray-300;
10
+ border: 1px solid var( --wpds-color-stroke-surface-neutral, #{wp-colors.$gray-300} );
10
11
  color: wp-colors.$gray-900;
11
12
  margin: 32px 0;
12
13
  padding: 16px 48px;
@@ -101,10 +102,6 @@
101
102
 
102
103
  // Margin
103
104
 
104
- &.mt64 {
105
- margin-top: 64px;
106
- }
107
-
108
105
  &.mt16 {
109
106
  margin-top: 16px;
110
107
  }
@@ -128,10 +125,10 @@
128
125
  background: wp-colors.$gray-300;
129
126
  border: 0;
130
127
  height: 1px;
131
- margin: 32px 0;
128
+ margin: wp-vars.$grid-unit-40 0;
132
129
 
133
130
  @media screen and ( min-width: 744px ) {
134
- margin: 64px 0;
131
+ margin: wp-vars.$grid-unit-60 0;
135
132
  }
136
133
  }
137
134
 
@@ -307,4 +307,11 @@ describe( 'CardFeature', () => {
307
307
  rerender( <CardFeature title="Content gifting" enabled requirements="Requires metering" /> );
308
308
  expect( container.querySelector( '.newspack-card-feature--muted' ) ).toBeInTheDocument();
309
309
  } );
310
+
311
+ it( 'marks the card as not enabled only when enabled is false', () => {
312
+ const { container, rerender } = render( <CardFeature title="Content gifting" /> );
313
+ expect( container.querySelector( '.newspack-card-feature--not-enabled' ) ).toBeInTheDocument();
314
+ rerender( <CardFeature title="Content gifting" enabled /> );
315
+ expect( container.querySelector( '.newspack-card-feature--not-enabled' ) ).toBeNull();
316
+ } );
310
317
  } );
@@ -110,6 +110,7 @@ const CardFeature = ( {
110
110
  const isMuted = !! requirements;
111
111
  const classes = classnames( 'newspack-card-feature', className, {
112
112
  'newspack-card-feature--muted': isMuted,
113
+ 'newspack-card-feature--not-enabled': ! enabled,
113
114
  } );
114
115
 
115
116
  let badge: { label: string; intent: BadgeIntent } | undefined;
@@ -2,6 +2,7 @@
2
2
  * CardFeature
3
3
  */
4
4
 
5
+ @use "~@wordpress/base-styles/colors" as wp-colors;
5
6
  @use "~@wordpress/base-styles/mixins" as wp-mixins;
6
7
  @use "~@wordpress/base-styles/variables" as wp-vars;
7
8
  @use "../mixins" as np-mixins;
@@ -9,6 +10,10 @@
9
10
  .newspack-card-feature {
10
11
  height: 100%;
11
12
 
13
+ &.newspack-card-feature--not-enabled {
14
+ border-color: var( --wpds-color-stroke-surface-neutral-weak, #{wp-colors.$gray-100} );
15
+ }
16
+
12
17
  &__actions {
13
18
  margin-top: auto;
14
19
 
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { BaseControl, ColorPicker as ColorPickerComponent } from '@wordpress/components';
5
5
  import { useInstanceId } from '@wordpress/compose';
6
- import { useState, useRef } from '@wordpress/element';
6
+ import { useState, useRef, useEffect } from '@wordpress/element';
7
7
 
8
8
  /**
9
9
  * External dependencies.
@@ -31,26 +31,40 @@ const { InteractiveDiv } = utils;
31
31
  * @param {string} [props.color] - Default color.
32
32
  * @param {Function} props.onChange - Function to call when the color changes.
33
33
  * @param {string} [props.className] - Additional class name.
34
+ * @param {boolean} [props.disabled] - Whether the color is shown but cannot be changed.
34
35
  * @return {JSX.Element} ColorPicker component.
35
36
  */
36
- const ColorPicker = ( { label, help, color = '#ffffff', onChange, className } ) => {
37
+ const ColorPicker = ( { label, help, color = '#ffffff', onChange, className, disabled = false } ) => {
37
38
  const [ isExpanded, setIsExpanded ] = useState( false );
38
- const ref = useRef();
39
+ const ref = useRef( undefined );
39
40
  const id = useInstanceId( ColorPicker, 'newspack-color-picker' );
40
41
  const labelId = `${ id }-label`;
41
42
  const colordColor = colord( color );
42
43
  hooks.useOnClickOutside( ref, () => setIsExpanded( false ) );
44
+ useEffect( () => {
45
+ if ( disabled ) {
46
+ setIsExpanded( false );
47
+ }
48
+ }, [ disabled ] );
43
49
  return (
44
- <BaseControl id={ id } className={ classnames( 'newspack-color-picker', className ) } help={ help } __nextHasNoMarginBottom>
50
+ <BaseControl
51
+ id={ id }
52
+ className={ classnames( 'newspack-color-picker', { 'is-disabled': disabled }, className ) }
53
+ help={ help }
54
+ __nextHasNoMarginBottom
55
+ >
45
56
  <BaseControl.VisualLabel id={ labelId }>{ label }</BaseControl.VisualLabel>
46
57
  <InteractiveDiv
47
58
  id={ id }
48
59
  aria-labelledby={ labelId }
49
60
  aria-describedby={ help ? `${ id }__help` : undefined }
50
61
  aria-expanded={ isExpanded }
62
+ aria-disabled={ disabled || undefined }
63
+ tabIndex={ disabled ? -1 : 0 }
51
64
  className={ 'newspack-color-picker__expander' }
52
- onClick={ () => setIsExpanded( ! isExpanded ) }
65
+ onClick={ () => ! disabled && setIsExpanded( ! isExpanded ) }
53
66
  style={ {
67
+ ...( disabled && { cursor: 'default' } ),
54
68
  backgroundColor: color,
55
69
  color: colordColor.contrast() > colordColor.contrast( '#000000' ) ? '#ffffff' : '#000000',
56
70
  } }
@@ -59,7 +73,7 @@ const ColorPicker = ( { label, help, color = '#ffffff', onChange, className } )
59
73
  </InteractiveDiv>
60
74
 
61
75
  <div className="newspack-color-picker__main" ref={ ref }>
62
- { isExpanded && <ColorPickerComponent color={ color } onChange={ onChange } enableAlpha={ false } /> }
76
+ { isExpanded && ! disabled && <ColorPickerComponent color={ color } onChange={ onChange } enableAlpha={ false } /> }
63
77
  </div>
64
78
  </BaseControl>
65
79
  );
@@ -49,4 +49,29 @@ describe( 'ColorPicker', () => {
49
49
  const { getByRole } = render( <ColorPicker label="Background color" onChange={ () => {} } /> );
50
50
  expect( getByRole( 'button' ) ).not.toHaveAttribute( 'aria-describedby' );
51
51
  } );
52
+
53
+ describe( 'when disabled', () => {
54
+ it( 'should not open on click', () => {
55
+ const { getByRole } = render( <ColorPicker label="Background color" disabled onChange={ () => {} } /> );
56
+ const expander = getByRole( 'button' );
57
+ fireEvent.click( expander );
58
+ expect( expander ).toHaveAttribute( 'aria-expanded', 'false' );
59
+ expect( expander ).toHaveAttribute( 'aria-disabled', 'true' );
60
+ } );
61
+
62
+ it( 'should not open on Enter', () => {
63
+ const { getByRole } = render( <ColorPicker label="Background color" disabled onChange={ () => {} } /> );
64
+ const expander = getByRole( 'button' );
65
+ fireEvent.keyDown( expander, { key: 'Enter', keyCode: 13 } );
66
+ expect( expander ).toHaveAttribute( 'aria-expanded', 'false' );
67
+ } );
68
+
69
+ it( 'should stay closed once re-enabled if it was open when disabled', () => {
70
+ const { getByRole, rerender } = render( <ColorPicker label="Background color" onChange={ () => {} } /> );
71
+ fireEvent.click( getByRole( 'button' ) );
72
+ rerender( <ColorPicker label="Background color" disabled onChange={ () => {} } /> );
73
+ rerender( <ColorPicker label="Background color" onChange={ () => {} } /> );
74
+ expect( getByRole( 'button' ) ).toHaveAttribute( 'aria-expanded', 'false' );
75
+ } );
76
+ } );
52
77
  } );
@@ -8,25 +8,28 @@
8
8
  .newspack-color-picker {
9
9
  position: relative;
10
10
  &__expander {
11
- box-shadow: inset 0 0 0 1px rgba(wp-colors.$black, 0.54);
12
- border-radius: wp-vars.$radius-small;
13
- height: wp-vars.$grid-unit-80;
14
- padding: wp-vars.$grid-unit-10;
15
- text-align: right;
11
+ box-shadow: inset 0 0 0 var(--wpds-border-width-xs, #{wp-vars.$border-width}) rgba(wp-colors.$black, 0.54);
12
+ border-radius: var(--wpds-border-radius-sm, #{wp-vars.$radius-small});
13
+ height: var(--wpds-dimension-size-lg, #{wp-vars.$grid-unit-50});
14
+ line-height: calc(var(--wpds-dimension-size-lg, #{wp-vars.$grid-unit-50}) - var(--wpds-dimension-padding-md, #{wp-vars.$grid-unit-15}));
15
+ padding: calc(var(--wpds-dimension-padding-md, #{wp-vars.$grid-unit-15}) / 2) var(--wpds-dimension-padding-md, #{wp-vars.$grid-unit-15});
16
16
  text-transform: uppercase;
17
17
 
18
18
  &:focus-visible {
19
- box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
20
- border-color: wp-colors.$white;
19
+ box-shadow: 0 0 0 var(--wpds-border-width-focus, #{wp-vars.$border-width-focus-fallback}) var(--wpds-color-stroke-focus, var(--wp-admin-theme-color));
21
20
  }
22
21
  }
23
22
 
23
+ &.is-disabled &__expander {
24
+ opacity: 0.5;
25
+ }
26
+
24
27
  &__main {
25
- background: wp-colors.$white;
28
+ background: var(--wpds-color-background-surface-neutral-strong, #{wp-colors.$white});
26
29
  box-shadow: wp-vars.$elevation-small;
27
- margin: wp-vars.$grid-unit-10 0 0;
30
+ margin: var(--wpds-dimension-gap-sm, #{wp-vars.$grid-unit-10}) 0 0;
28
31
  position: absolute;
29
- z-index: 2;
32
+ z-index: 3;
30
33
 
31
34
  &:empty {
32
35
  display: none;
@@ -10,7 +10,7 @@
10
10
  background: np-colors.$primary-600;
11
11
  border-radius: wp-vars.$radius-round;
12
12
  bottom: 0;
13
- box-shadow: var(--wpds-elevation-sm, #{wp-vars.$elevation-small});
13
+ box-shadow: wp-vars.$elevation-small;
14
14
  display: grid;
15
15
  height: wp-vars.$button-size;
16
16
  margin: 0 wp-vars.$grid-unit-30 wp-vars.$grid-unit-30;
@@ -8,8 +8,8 @@ Horizontal rule component with alignment, variant, and margin options.
8
8
  |------|------|---------|-------------|
9
9
  | `alignment` | `'full-width'` \| `'none'` | `'none'` | `full-width` breaks out of the container to span the viewport; `none` stays within the container. |
10
10
  | `className` | `string` | — | Additional CSS class. |
11
- | `marginBottom` | `number` \| `string` | `64` | Bottom margin (e.g. `64` or `"2rem"`). Capped at 32px on viewports &lt; 783px. |
12
- | `marginTop` | `number` \| `string` | `64` | Top margin (e.g. `64` or `"2rem"`). Capped at 32px on viewports &lt; 783px. |
11
+ | `marginBottom` | `number` \| `string` | `48` | Bottom margin (e.g. `48` or `"2rem"`). Capped at 32px on viewports &lt; 782px. |
12
+ | `marginTop` | `number` \| `string` | `48` | Top margin (e.g. `48` or `"2rem"`). Capped at 32px on viewports &lt; 782px. |
13
13
  | `variant` | `'default'` \| `'primary'` \| `'secondary'` \| `'tertiary'` | `'default'` | Line color: `default` uses `$gray-300`; `primary` uses the admin theme color (`--wp-admin-theme-color`); `secondary` uses `$gray-200`; `tertiary` uses `$gray-100`. |
14
14
 
15
15
  ## Usage
@@ -25,7 +25,7 @@ import classNames from 'classnames';
25
25
  * }} props - Component props: the documented options plus any `hr` attribute.
26
26
  * @return {JSX.Element} Divider component.
27
27
  */
28
- const Divider = ( { alignment = 'none', className = undefined, marginBottom = 64, marginTop = 64, variant = 'default', ...otherProps } ) => {
28
+ const Divider = ( { alignment = 'none', className = undefined, marginBottom = 48, marginTop = 48, variant = 'default', ...otherProps } ) => {
29
29
  const classes = classNames(
30
30
  'newspack-divider',
31
31
  className,
@@ -3,21 +3,23 @@
3
3
  */
4
4
 
5
5
  @use "~@wordpress/base-styles/colors" as wp-colors;
6
+ @use "~@wordpress/base-styles/mixins" as wp-mixins;
7
+ @use "~@wordpress/base-styles/variables" as wp-vars;
6
8
 
7
9
  .newspack-divider {
8
10
  background: transparent;
9
11
  border: 0;
10
12
  display: block;
11
13
  height: 1px;
12
- margin-bottom: min(32px, var(--divider-margin-bottom, 64px));
14
+ margin-bottom: min(#{wp-vars.$grid-unit-40}, var(--divider-margin-bottom, #{wp-vars.$grid-unit-60}));
13
15
  margin-left: 0;
14
16
  margin-right: 0;
15
- margin-top: min(32px, var(--divider-margin-top, 64px));
17
+ margin-top: min(#{wp-vars.$grid-unit-40}, var(--divider-margin-top, #{wp-vars.$grid-unit-60}));
16
18
  padding: 0;
17
19
 
18
- @media screen and (min-width: 783px) {
19
- margin-bottom: var(--divider-margin-bottom, 64px);
20
- margin-top: var(--divider-margin-top, 64px);
20
+ @include wp-mixins.break-medium {
21
+ margin-bottom: var(--divider-margin-bottom, #{wp-vars.$grid-unit-60});
22
+ margin-top: var(--divider-margin-top, #{wp-vars.$grid-unit-60});
21
23
  }
22
24
 
23
25
  // Alignment
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  @use "~@wordpress/base-styles/colors" as wp-colors;
6
+ @use "~@wordpress/base-styles/variables" as wp-vars;
6
7
 
7
8
  .newspack-grid {
8
9
  display: grid;
@@ -41,9 +42,9 @@
41
42
  grid-gap: 32px;
42
43
  }
43
44
 
44
- // Gutter 64
45
- &__gutter-64 {
46
- grid-gap: 64px;
45
+ // Gutter 48
46
+ &__gutter-48 {
47
+ grid-gap: wp-vars.$grid-unit-60;
47
48
  }
48
49
 
49
50
  // Row Gap 0
@@ -143,16 +144,6 @@
143
144
  &__columns-12 {
144
145
  grid-template-columns: repeat(12, 1fr);
145
146
  }
146
-
147
- // Gutter 48
148
- &__gutter-48 {
149
- grid-gap: 48px;
150
- }
151
-
152
- // Gutter 64
153
- &__gutter-64 {
154
- grid-gap: 64px;
155
- }
156
147
  }
157
148
 
158
149
  // Children
@@ -194,9 +185,6 @@
194
185
  &.newspack-grid__gutter-32 > * {
195
186
  padding: 32px;
196
187
  }
197
- &.newspack-grid__gutter-64 > * {
198
- padding: 64px;
199
- }
200
188
  }
201
189
 
202
190
  .components-base-control {
@@ -73,19 +73,23 @@ class ImageUpload extends Component {
73
73
  * Render.
74
74
  */
75
75
  render = () => {
76
- const { buttonLabel, className, disabled, help, image, isCovering, label, onChange, style = {} } = this.props;
76
+ const { buttonLabel, className, disabled, help, image, imageStyle, isCovering, label, onChange, style = {}, withMargin = true } = this.props;
77
77
  const classes = classnames(
78
78
  'newspack-image-upload__image',
79
79
  { 'newspack-image-upload__image--has-image': image },
80
80
  { 'newspack-image-upload__image--covering': isCovering }
81
81
  );
82
82
  return (
83
- <BaseControl __nextHasNoMarginBottom className={ classnames( 'newspack-image-upload', className ) } help={ help }>
83
+ <BaseControl
84
+ __nextHasNoMarginBottom
85
+ className={ classnames( 'newspack-image-upload', { 'newspack-image-upload--no-margin': ! withMargin }, className ) }
86
+ help={ help }
87
+ >
84
88
  { label && <BaseControl.VisualLabel>{ label }</BaseControl.VisualLabel> }
85
89
  <div className={ classes } style={ style }>
86
90
  { image?.url ? (
87
91
  <>
88
- <img data-testid="image-upload" src={ image.url } alt={ __( 'Image preview', 'newspack-plugin' ) } />
92
+ <img data-testid="image-upload" src={ image.url } alt={ __( 'Image preview', 'newspack-plugin' ) } style={ imageStyle } />
89
93
  <div className="newspack-image-upload__controls">
90
94
  <Button disabled={ disabled } onClick={ this.openModal } variant="tertiary">
91
95
  { __( 'Replace', 'newspack-plugin' ) }
@@ -7,6 +7,9 @@
7
7
 
8
8
  .newspack-image-upload {
9
9
  margin: wp-vars.$grid-unit-40 0;
10
+ &--no-margin {
11
+ margin: 0;
12
+ }
10
13
  &__image {
11
14
  align-items: center;
12
15
  background-position: center;
package/src/index.js CHANGED
@@ -4,7 +4,6 @@ export { default as AutocompleteWithSuggestions } from './autocomplete-with-sugg
4
4
  export { default as AutocompleteWithLatestPosts } from './autocomplete-with-latest-posts';
5
5
  export { default as Breadcrumbs } from './breadcrumbs';
6
6
  export { default as Button } from './button';
7
- export { default as BoxContrast } from './box-contrast';
8
7
  export { default as Card } from './card';
9
8
  export { default as CardFeature } from './card-feature';
10
9
  export { default as CardForm } from './card-form';
@@ -39,7 +39,7 @@
39
39
  .newspack-info-button__popup {
40
40
  background-color: wp-colors.$gray-900;
41
41
  border-radius: var(--wpds-border-radius-md, #{wp-vars.$radius-medium});
42
- box-shadow: var(--wpds-elevation-sm, #{wp-vars.$elevation-small});
42
+ box-shadow: wp-vars.$elevation-small;
43
43
  color: wp-colors.$white;
44
44
  outline: 0;
45
45
  padding: var(--wpds-dimension-padding-xs, #{wp-vars.$grid-unit-05}) var(--wpds-dimension-padding-sm, #{wp-vars.$grid-unit-10});
@@ -83,15 +83,14 @@
83
83
  }
84
84
  }
85
85
 
86
- .components-modal__content {
87
- > * {
88
- &:first-child {
89
- margin-top: 0;
90
- }
86
+ .components-modal__children-container {
87
+ > :first-child,
88
+ > .screen-reader-text:first-child + * {
89
+ margin-top: 0;
90
+ }
91
91
 
92
- &:last-child {
93
- margin-bottom: 0;
94
- }
92
+ > :last-child {
93
+ margin-bottom: 0;
95
94
  }
96
95
  }
97
96
  }
@@ -9,10 +9,10 @@
9
9
  // postcss-import cannot resolve exports maps, and resolving the public
10
10
  // specifier through sass/webpack leaks a bogus `wp-theme/design-tokens.css`
11
11
  // script dependency into consumers' asset manifests, which silently blocks
12
- // their enqueues. If upstream moves `src/prebuilt/`, this fails loudly at
12
+ // their enqueues. If upstream moves `prebuilt/`, this fails loudly at
13
13
  // build time.
14
14
  /* stylelint-disable-next-line no-invalid-position-at-import-rule -- sass @use must precede the CSS @import; postcss-import inlines it at build time. */
15
- @import "@wordpress/theme/src/prebuilt/css/design-tokens.css";
15
+ @import "@wordpress/theme/prebuilt/css/design-tokens.css";
16
16
 
17
17
  // Newspack brand mapping: the wpds brand color tokens ship in WordPress
18
18
  // blue; remap them onto the Newspack primary scale so every design-system
@@ -51,7 +51,6 @@
51
51
  }
52
52
 
53
53
  .newspack-page__header {
54
- /* stylelint-disable-next-line plugin-wpds/no-unknown-ds-tokens -- the plugin's token list lags the prebuilt design-tokens.css names. */
55
54
  background: var(--wpds-color-background-surface-neutral-strong);
56
55
  border-block-end: var(--wpds-border-width-xs) solid var(--wpds-color-stroke-surface-neutral-weak);
57
56
  padding: var(--wpds-dimension-padding-lg) var(--wpds-dimension-padding-2xl);
@@ -62,7 +61,6 @@
62
61
  }
63
62
 
64
63
  .newspack-page__header-subtitle {
65
- /* stylelint-disable-next-line plugin-wpds/no-unknown-ds-tokens -- the plugin's token list lags the prebuilt design-tokens.css names. */
66
64
  color: var(--wpds-color-foreground-content-neutral-weak);
67
65
  padding-block-end: var(--wpds-dimension-padding-xs);
68
66
  }