@wordpress/components 32.6.0 → 33.0.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.
- package/CHANGELOG.md +25 -0
- package/build/autocomplete/get-autocomplete-match.cjs +11 -2
- package/build/autocomplete/get-autocomplete-match.cjs.map +2 -2
- package/build/autocomplete/index.cjs +42 -11
- package/build/autocomplete/index.cjs.map +2 -2
- package/build/external-link/index.cjs +1 -1
- package/build/external-link/index.cjs.map +2 -2
- package/build/form-token-field/index.cjs +22 -6
- package/build/form-token-field/index.cjs.map +3 -3
- package/build/form-token-field/token-input.cjs +1 -1
- package/build/form-token-field/token-input.cjs.map +2 -2
- package/build/menu/popover.cjs +7 -3
- package/build/menu/popover.cjs.map +2 -2
- package/build/menu/styles.cjs +39 -16
- package/build/menu/styles.cjs.map +2 -2
- package/build/navigable-container/container.cjs +72 -110
- package/build/navigable-container/container.cjs.map +2 -2
- package/build/utils/breakpoint.cjs.map +1 -1
- package/build/utils/font.cjs.map +1 -1
- package/build/visually-hidden/component.cjs +1 -0
- package/build/visually-hidden/component.cjs.map +2 -2
- package/build-module/autocomplete/get-autocomplete-match.mjs +11 -2
- package/build-module/autocomplete/get-autocomplete-match.mjs.map +2 -2
- package/build-module/autocomplete/index.mjs +42 -11
- package/build-module/autocomplete/index.mjs.map +2 -2
- package/build-module/external-link/index.mjs +1 -1
- package/build-module/external-link/index.mjs.map +2 -2
- package/build-module/form-token-field/index.mjs +22 -6
- package/build-module/form-token-field/index.mjs.map +2 -2
- package/build-module/form-token-field/token-input.mjs +1 -1
- package/build-module/form-token-field/token-input.mjs.map +2 -2
- package/build-module/menu/popover.mjs +7 -3
- package/build-module/menu/popover.mjs.map +2 -2
- package/build-module/menu/styles.mjs +37 -16
- package/build-module/menu/styles.mjs.map +2 -2
- package/build-module/navigable-container/container.mjs +73 -111
- package/build-module/navigable-container/container.mjs.map +2 -2
- package/build-module/utils/breakpoint.mjs.map +1 -1
- package/build-module/utils/font.mjs.map +1 -1
- package/build-module/visually-hidden/component.mjs +1 -0
- package/build-module/visually-hidden/component.mjs.map +2 -2
- package/build-style/style-rtl.css +26 -2
- package/build-style/style.css +26 -2
- package/build-types/autocomplete/get-autocomplete-match.d.ts +10 -1
- package/build-types/autocomplete/get-autocomplete-match.d.ts.map +1 -1
- package/build-types/autocomplete/index.d.ts.map +1 -1
- package/build-types/base-control/stories/index.story.d.ts.map +1 -1
- package/build-types/button/stories/index.story.d.ts.map +1 -1
- package/build-types/card/stories/index.story.d.ts +0 -6
- package/build-types/card/stories/index.story.d.ts.map +1 -1
- package/build-types/checkbox-control/stories/index.story.d.ts.map +1 -1
- package/build-types/color-indicator/stories/index.story.d.ts.map +1 -1
- package/build-types/color-palette/stories/index.story.d.ts.map +1 -1
- package/build-types/color-picker/stories/index.story.d.ts.map +1 -1
- package/build-types/combobox-control/stories/index.story.d.ts.map +1 -1
- package/build-types/composite/stories/index.story.d.ts.map +1 -1
- package/build-types/custom-select-control/stories/index.story.d.ts.map +1 -1
- package/build-types/disabled/stories/index.story.d.ts.map +1 -1
- package/build-types/drop-zone/stories/index.story.d.ts.map +1 -1
- package/build-types/dropdown/stories/index.story.d.ts.map +1 -1
- package/build-types/external-link/index.d.ts.map +1 -1
- package/build-types/external-link/stories/index.story.d.ts.map +1 -1
- package/build-types/form-file-upload/stories/index.story.d.ts.map +1 -1
- package/build-types/form-toggle/stories/index.story.d.ts.map +1 -1
- package/build-types/form-token-field/index.d.ts.map +1 -1
- package/build-types/form-token-field/stories/index.story.d.ts.map +1 -1
- package/build-types/form-token-field/token-input.d.ts.map +1 -1
- package/build-types/form-token-field/types.d.ts +16 -2
- package/build-types/form-token-field/types.d.ts.map +1 -1
- package/build-types/gradient-picker/stories/index.story.d.ts.map +1 -1
- package/build-types/icon/stories/index.story.d.ts.map +1 -1
- package/build-types/keyboard-shortcuts/stories/index.story.d.ts.map +1 -1
- package/build-types/menu/popover.d.ts.map +1 -1
- package/build-types/menu/styles.d.ts +16 -1
- package/build-types/menu/styles.d.ts.map +1 -1
- package/build-types/menu-group/stories/index.story.d.ts.map +1 -1
- package/build-types/menu-item/stories/index.story.d.ts.map +1 -1
- package/build-types/menu-items-choice/stories/index.story.d.ts.map +1 -1
- package/build-types/modal/stories/index.story.d.ts.map +1 -1
- package/build-types/navigable-container/container.d.ts +3 -8
- package/build-types/navigable-container/container.d.ts.map +1 -1
- package/build-types/navigable-container/types.d.ts +1 -5
- package/build-types/navigable-container/types.d.ts.map +1 -1
- package/build-types/navigation/stories/utils/more-examples.d.ts.map +1 -1
- package/build-types/navigator/stories/index.story.d.ts.map +1 -1
- package/build-types/notice/stories/index.story.d.ts.map +1 -1
- package/build-types/panel/stories/index.story.d.ts.map +1 -1
- package/build-types/popover/stories/index.story.d.ts.map +1 -1
- package/build-types/progress-bar/stories/index.story.d.ts.map +1 -1
- package/build-types/radio-control/stories/index.story.d.ts.map +1 -1
- package/build-types/range-control/stories/index.story.d.ts.map +1 -1
- package/build-types/resizable-box/stories/index.story.d.ts.map +1 -1
- package/build-types/sandbox/stories/index.story.d.ts.map +1 -1
- package/build-types/scroll-lock/stories/index.story.d.ts.map +1 -1
- package/build-types/search-control/stories/index.story.d.ts.map +1 -1
- package/build-types/select-control/stories/index.story.d.ts.map +1 -1
- package/build-types/shortcut/stories/index.story.d.ts.map +1 -1
- package/build-types/slot-fill/stories/index.story.d.ts.map +1 -1
- package/build-types/snackbar/stories/index.story.d.ts.map +1 -1
- package/build-types/spinner/stories/index.story.d.ts.map +1 -1
- package/build-types/text-control/stories/index.story.d.ts.map +1 -1
- package/build-types/text-highlight/stories/index.story.d.ts.map +1 -1
- package/build-types/textarea-control/stories/index.story.d.ts.map +1 -1
- package/build-types/toggle-control/stories/index.story.d.ts.map +1 -1
- package/build-types/tooltip/stories/index.story.d.ts.map +1 -1
- package/build-types/tree-select/stories/index.story.d.ts.map +1 -1
- package/build-types/utils/breakpoint.d.ts +2 -1
- package/build-types/utils/breakpoint.d.ts.map +1 -1
- package/build-types/utils/font.d.ts +3 -2
- package/build-types/utils/font.d.ts.map +1 -1
- package/build-types/visually-hidden/component.d.ts.map +1 -1
- package/build-types/visually-hidden/stories/index.story.d.ts +0 -6
- package/build-types/visually-hidden/stories/index.story.d.ts.map +1 -1
- package/package.json +21 -21
- package/src/autocomplete/get-autocomplete-match.ts +25 -4
- package/src/autocomplete/index.tsx +69 -21
- package/src/autocomplete/test/get-autocomplete-match.ts +97 -75
- package/src/base-control/stories/index.story.tsx +1 -0
- package/src/button/stories/index.story.tsx +1 -0
- package/src/button-group/style.scss +1 -2
- package/src/card/stories/index.story.tsx +2 -9
- package/src/checkbox-control/stories/index.story.tsx +1 -0
- package/src/circular-option-picker/style.scss +8 -6
- package/src/color-indicator/stories/index.story.tsx +1 -0
- package/src/color-palette/stories/index.story.tsx +1 -0
- package/src/color-picker/stories/index.story.tsx +1 -0
- package/src/combobox-control/stories/index.story.tsx +1 -0
- package/src/composite/stories/index.story.tsx +1 -0
- package/src/confirm-dialog/stories/index.story.tsx +1 -1
- package/src/custom-select-control/stories/index.story.tsx +1 -0
- package/src/disabled/stories/index.story.tsx +1 -0
- package/src/drop-zone/stories/index.story.tsx +1 -0
- package/src/dropdown/stories/index.story.tsx +1 -0
- package/src/external-link/index.tsx +1 -6
- package/src/external-link/stories/index.story.tsx +2 -1
- package/src/external-link/style.scss +30 -2
- package/src/form-file-upload/stories/index.story.tsx +1 -0
- package/src/form-toggle/stories/index.story.tsx +1 -0
- package/src/form-toggle/style.scss +3 -2
- package/src/form-token-field/README.md +2 -1
- package/src/form-token-field/index.tsx +39 -9
- package/src/form-token-field/stories/index.story.tsx +2 -0
- package/src/form-token-field/test/index.tsx +70 -10
- package/src/form-token-field/token-input.tsx +1 -6
- package/src/form-token-field/types.ts +16 -2
- package/src/gradient-picker/stories/index.story.tsx +1 -0
- package/src/icon/stories/index.story.tsx +1 -0
- package/src/input-control/stories/index.story.tsx +1 -1
- package/src/item-group/stories/index.story.tsx +1 -1
- package/src/keyboard-shortcuts/stories/index.story.tsx +1 -0
- package/src/menu/popover.tsx +15 -8
- package/src/menu/styles.ts +26 -16
- package/src/menu/test/index.tsx +24 -34
- package/src/menu-group/stories/index.story.tsx +1 -0
- package/src/menu-item/stories/index.story.tsx +1 -0
- package/src/menu-items-choice/stories/index.story.tsx +1 -0
- package/src/mobile/link-settings/index.native.js +1 -1
- package/src/modal/stories/index.story.tsx +1 -0
- package/src/navigable-container/container.tsx +120 -141
- package/src/navigable-container/test/navigable-menu.tsx +24 -0
- package/src/navigable-container/types.ts +1 -5
- package/src/navigation/stories/utils/more-examples.tsx +2 -1
- package/src/navigator/stories/index.story.tsx +1 -0
- package/src/notice/stories/index.story.tsx +1 -0
- package/src/notice/test/__snapshots__/index.tsx.snap +1 -0
- package/src/number-control/stories/index.story.tsx +1 -1
- package/src/panel/stories/index.story.tsx +1 -0
- package/src/popover/stories/index.story.tsx +1 -0
- package/src/progress-bar/stories/index.story.tsx +1 -0
- package/src/radio-control/stories/index.story.tsx +1 -0
- package/src/range-control/stories/index.story.tsx +1 -0
- package/src/resizable-box/stories/index.story.tsx +1 -0
- package/src/resizable-box/style.scss +4 -5
- package/src/sandbox/stories/index.story.tsx +1 -0
- package/src/scroll-lock/stories/index.story.tsx +1 -0
- package/src/search-control/stories/index.story.tsx +1 -0
- package/src/select-control/stories/index.story.tsx +1 -0
- package/src/shortcut/stories/index.story.tsx +1 -0
- package/src/slot-fill/stories/index.story.tsx +1 -0
- package/src/snackbar/stories/index.story.tsx +1 -0
- package/src/spinner/stories/index.story.tsx +1 -0
- package/src/text-control/stories/index.story.tsx +1 -0
- package/src/text-highlight/stories/index.story.tsx +1 -0
- package/src/textarea-control/stories/index.story.tsx +1 -0
- package/src/toggle-control/stories/index.story.tsx +1 -0
- package/src/toggle-group-control/stories/index.story.tsx +1 -1
- package/src/toolbar/toolbar-group/index.tsx +2 -2
- package/src/tooltip/stories/index.story.tsx +1 -0
- package/src/tooltip/test/index.tsx +3 -2
- package/src/tree-grid/stories/index.story.tsx +1 -1
- package/src/tree-select/stories/index.story.tsx +1 -0
- package/src/truncate/stories/index.story.tsx +1 -1
- package/src/unit-control/stories/index.story.tsx +1 -1
- package/src/utils/breakpoint.js +1 -1
- package/src/utils/font.js +1 -1
- package/src/visually-hidden/component.tsx +1 -0
- package/src/visually-hidden/stories/index.story.tsx +2 -8
- package/build/card/context.cjs +0 -36
- package/build/card/context.cjs.map +0 -7
- package/build-module/card/context.mjs +0 -10
- package/build-module/card/context.mjs.map +0 -7
- package/build-types/card/context.d.ts +0 -3
- package/build-types/card/context.d.ts.map +0 -1
- package/build-types/visually-hidden/test/index.d.ts +0 -2
- package/build-types/visually-hidden/test/index.d.ts.map +0 -1
- package/src/card/context.ts +0 -9
- package/src/visually-hidden/test/__snapshots__/index.tsx.snap +0 -12
- package/src/visually-hidden/test/index.tsx +0 -17
|
@@ -14,6 +14,7 @@ import MenuItem from '../../menu-item';
|
|
|
14
14
|
import { DropdownContentWrapper } from '../dropdown-content-wrapper';
|
|
15
15
|
|
|
16
16
|
const meta: Meta< typeof Dropdown > = {
|
|
17
|
+
tags: [ 'manifest' ],
|
|
17
18
|
title: 'Components/Overlays/Dropdown',
|
|
18
19
|
id: 'components-dropdown',
|
|
19
20
|
component: Dropdown,
|
|
@@ -26,12 +26,7 @@ function UnforwardedExternalLink(
|
|
|
26
26
|
const { href, children, className, rel = '', ...additionalProps } = props;
|
|
27
27
|
const optimizedRel = [
|
|
28
28
|
...new Set(
|
|
29
|
-
[
|
|
30
|
-
...rel.split( ' ' ),
|
|
31
|
-
'external',
|
|
32
|
-
'noreferrer',
|
|
33
|
-
'noopener',
|
|
34
|
-
].filter( Boolean )
|
|
29
|
+
[ ...rel.split( ' ' ), 'external', 'noopener' ].filter( Boolean )
|
|
35
30
|
),
|
|
36
31
|
].join( ' ' );
|
|
37
32
|
const classes = clsx( 'components-external-link', className );
|
|
@@ -21,8 +21,9 @@ const meta: Meta< typeof ExternalLink > = {
|
|
|
21
21
|
},
|
|
22
22
|
docs: { canvas: { sourceState: 'shown' } },
|
|
23
23
|
componentStatus: {
|
|
24
|
-
status: '
|
|
24
|
+
status: 'not-recommended',
|
|
25
25
|
whereUsed: 'global',
|
|
26
|
+
notes: 'Use `Link` from `@wordpress/ui` instead, with the `openInNewTab` prop set.',
|
|
26
27
|
},
|
|
27
28
|
},
|
|
28
29
|
};
|
|
@@ -1,12 +1,40 @@
|
|
|
1
1
|
.components-external-link {
|
|
2
|
+
color: var(--wpds-color-fg-interactive-brand);
|
|
2
3
|
text-decoration: none;
|
|
4
|
+
|
|
5
|
+
// Match the `outset-ring--focus` utility used by `Link` in `@wordpress/ui`.
|
|
6
|
+
@media not ( prefers-reduced-motion ) {
|
|
7
|
+
transition: outline 0.1s ease-out;
|
|
8
|
+
}
|
|
9
|
+
// Outline width must be kept at 0 even with a transparent color,
|
|
10
|
+
// or else the outline will be visible in forced-colors mode.
|
|
11
|
+
outline: 0 solid transparent;
|
|
12
|
+
outline-offset: 1px;
|
|
13
|
+
|
|
14
|
+
&:visited {
|
|
15
|
+
color: var(--wpds-color-fg-interactive-brand);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
&:hover,
|
|
19
|
+
&:active {
|
|
20
|
+
color: var(--wpds-color-fg-interactive-brand-active);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&:focus {
|
|
24
|
+
outline:
|
|
25
|
+
var(--wpds-border-width-focus) solid
|
|
26
|
+
var(--wpds-color-stroke-focus-brand);
|
|
27
|
+
}
|
|
3
28
|
}
|
|
4
29
|
|
|
5
30
|
.components-external-link__contents {
|
|
6
31
|
text-decoration: underline;
|
|
32
|
+
text-underline-offset: 0.2em;
|
|
33
|
+
text-decoration-thickness: from-font;
|
|
7
34
|
}
|
|
8
35
|
|
|
9
36
|
.components-external-link__icon {
|
|
10
|
-
|
|
11
|
-
|
|
37
|
+
display: inline-block;
|
|
38
|
+
margin-inline-start: var(--wpds-dimension-padding-xs);
|
|
39
|
+
font-weight: var(--wpds-typography-font-weight-regular);
|
|
12
40
|
}
|
|
@@ -14,6 +14,7 @@ import { upload as uploadIcon } from '@wordpress/icons';
|
|
|
14
14
|
import FormFileUpload from '..';
|
|
15
15
|
|
|
16
16
|
const meta: Meta< typeof FormFileUpload > = {
|
|
17
|
+
tags: [ 'manifest' ],
|
|
17
18
|
title: 'Components/Selection & Input/File Upload/FormFileUpload',
|
|
18
19
|
id: 'components-formfileupload',
|
|
19
20
|
component: FormFileUpload,
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
@use "@wordpress/base-styles/colors" as *;
|
|
3
3
|
@use "@wordpress/base-styles/mixins" as *;
|
|
4
4
|
@use "@wordpress/base-styles/variables" as *;
|
|
5
|
-
@use "@wordpress/base-styles/z-index" as *;
|
|
6
5
|
@use "../utils/theme-variables" as *;
|
|
7
6
|
|
|
8
7
|
$toggle-width: $grid-unit-40;
|
|
@@ -14,6 +13,7 @@ $transition-duration: 0.2s;
|
|
|
14
13
|
|
|
15
14
|
.components-form-toggle {
|
|
16
15
|
position: relative;
|
|
16
|
+
isolation: isolate;
|
|
17
17
|
display: inline-block;
|
|
18
18
|
height: $toggle-height;
|
|
19
19
|
|
|
@@ -151,7 +151,8 @@ $transition-duration: 0.2s;
|
|
|
151
151
|
opacity: 0;
|
|
152
152
|
margin: 0;
|
|
153
153
|
padding: 0;
|
|
154
|
-
|
|
154
|
+
// Sit above the visual track and thumb so the invisible input receives pointer events.
|
|
155
|
+
z-index: 1;
|
|
155
156
|
|
|
156
157
|
// This overrides a border style that is inherited from parent checkbox styles.
|
|
157
158
|
border: none;
|
|
@@ -51,6 +51,7 @@ The `value` property is handled in a manner similar to controlled form component
|
|
|
51
51
|
- `maxLength` - If passed, `TokenField` will disable ability to add new tokens once number of tokens is greater than or equal to `maxLength`.
|
|
52
52
|
- `disabled` - When true, tokens are not able to be added or removed.
|
|
53
53
|
- `placeholder` - If passed, the `TokenField` input will show a placeholder string if no value tokens are present.
|
|
54
|
+
- `help` - Additional description for the control. Only use for meaningful description or instructions for the control. An element containing the description will be programmatically associated to the `FormTokenField` via `aria-describedby`. Defaults to a how-to message (e.g. _Separate with commas or the Enter key._); pass an empty string to hide it.
|
|
54
55
|
- `messages` - Allows customizing the messages presented by screen readers in different occasions:
|
|
55
56
|
- `added` - The user added a new token.
|
|
56
57
|
- `removed` - The user removed an existing token.
|
|
@@ -58,7 +59,7 @@ The `value` property is handled in a manner similar to controlled form component
|
|
|
58
59
|
- `__experimentalInvalid` - The user tried to add a token that didn't pass the validation.
|
|
59
60
|
- `__experimentalRenderItem` - Custom renderer invoked for each option in the suggestion list. The render prop receives as its argument an object containing, under the `item` key, the single option's data (directly from the array of data passed to the `options` prop).
|
|
60
61
|
- `__experimentalExpandOnFocus` - If true, the suggestions list will be always expanded when the input field has the focus.
|
|
61
|
-
- `__experimentalShowHowTo` -
|
|
62
|
+
- `__experimentalShowHowTo` - **Deprecated.** Use the `help` prop instead. The `help` prop now defaults to the previous how-to text; if you were passing `__experimentalShowHowTo={ false }` to hide it, pass an empty string to `help` instead.
|
|
62
63
|
- `__experimentalValidateInput` - If passed, all introduced values will be validated before being added as tokens.
|
|
63
64
|
- `__experimentalAutoSelectFirstMatch` - If true, the select the first matching suggestion when the user presses the Enter key (or space when tokenizeOnSpace is true).
|
|
64
65
|
- `__next40pxDefaultSize` - Start opting into the larger default height that will become the default size in a future version.
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import clsx from 'clsx';
|
|
5
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
KeyboardEvent,
|
|
7
|
+
MouseEvent,
|
|
8
|
+
TouchEvent,
|
|
9
|
+
FocusEvent,
|
|
10
|
+
ReactNode,
|
|
11
|
+
} from 'react';
|
|
6
12
|
|
|
7
13
|
/**
|
|
8
14
|
* WordPress dependencies
|
|
@@ -12,6 +18,7 @@ import { __, _n, sprintf } from '@wordpress/i18n';
|
|
|
12
18
|
import { useDebounce, useInstanceId, usePrevious } from '@wordpress/compose';
|
|
13
19
|
import { speak } from '@wordpress/a11y';
|
|
14
20
|
import { isShallowEqual } from '@wordpress/is-shallow-equal';
|
|
21
|
+
import deprecated from '@wordpress/deprecated';
|
|
15
22
|
|
|
16
23
|
/**
|
|
17
24
|
* Internal dependencies
|
|
@@ -70,10 +77,11 @@ export function FormTokenField( props: FormTokenFieldProps ) {
|
|
|
70
77
|
__experimentalRenderItem,
|
|
71
78
|
__experimentalExpandOnFocus = false,
|
|
72
79
|
__experimentalValidateInput = () => true,
|
|
73
|
-
__experimentalShowHowTo
|
|
80
|
+
__experimentalShowHowTo,
|
|
74
81
|
__next40pxDefaultSize = false,
|
|
75
82
|
__experimentalAutoSelectFirstMatch = false,
|
|
76
83
|
tokenizeOnBlur = false,
|
|
84
|
+
help,
|
|
77
85
|
} = useDeprecated36pxDefaultSizeProp< FormTokenFieldProps >( props );
|
|
78
86
|
|
|
79
87
|
maybeWarnDeprecated36pxSize( {
|
|
@@ -82,6 +90,27 @@ export function FormTokenField( props: FormTokenFieldProps ) {
|
|
|
82
90
|
__next40pxDefaultSize,
|
|
83
91
|
} );
|
|
84
92
|
|
|
93
|
+
const defaultHelp = tokenizeOnSpace
|
|
94
|
+
? __( 'Separate with commas, spaces, or the Enter key.' )
|
|
95
|
+
: __( 'Separate with commas or the Enter key.' );
|
|
96
|
+
|
|
97
|
+
let computedHelp: ReactNode = help !== undefined ? help : defaultHelp;
|
|
98
|
+
|
|
99
|
+
if ( typeof __experimentalShowHowTo === 'boolean' ) {
|
|
100
|
+
deprecated(
|
|
101
|
+
'`__experimentalShowHowTo` prop in wp.components.FormTokenField',
|
|
102
|
+
{
|
|
103
|
+
since: '7.1',
|
|
104
|
+
alternative: '`help` prop',
|
|
105
|
+
hint: 'The `help` prop now defaults to the previous how-to text. Pass an empty string to hide it.',
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
if ( __experimentalShowHowTo === false && help === undefined ) {
|
|
110
|
+
computedHelp = '';
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
85
114
|
const instanceId = useInstanceId( FormTokenField );
|
|
86
115
|
|
|
87
116
|
// We reset to these initial values again in the onBlur
|
|
@@ -655,6 +684,10 @@ export function FormTokenField( props: FormTokenFieldProps ) {
|
|
|
655
684
|
}
|
|
656
685
|
|
|
657
686
|
function renderInput() {
|
|
687
|
+
const describedById = computedHelp
|
|
688
|
+
? `components-form-token-input-${ instanceId }__help`
|
|
689
|
+
: undefined;
|
|
690
|
+
|
|
658
691
|
const inputProps = {
|
|
659
692
|
instanceId,
|
|
660
693
|
autoCapitalize,
|
|
@@ -665,6 +698,7 @@ export function FormTokenField( props: FormTokenFieldProps ) {
|
|
|
665
698
|
onBlur,
|
|
666
699
|
isExpanded,
|
|
667
700
|
selectedSuggestionIndex,
|
|
701
|
+
'aria-describedby': describedById,
|
|
668
702
|
};
|
|
669
703
|
|
|
670
704
|
return (
|
|
@@ -749,16 +783,12 @@ export function FormTokenField( props: FormTokenFieldProps ) {
|
|
|
749
783
|
/>
|
|
750
784
|
) }
|
|
751
785
|
</div>
|
|
752
|
-
{
|
|
786
|
+
{ computedHelp && (
|
|
753
787
|
<StyledHelp
|
|
754
|
-
id={ `components-form-token-
|
|
788
|
+
id={ `components-form-token-input-${ instanceId }__help` }
|
|
755
789
|
className="components-form-token-field__help"
|
|
756
790
|
>
|
|
757
|
-
{
|
|
758
|
-
? __(
|
|
759
|
-
'Separate with commas, spaces, or the Enter key.'
|
|
760
|
-
)
|
|
761
|
-
: __( 'Separate with commas or the Enter key.' ) }
|
|
791
|
+
{ computedHelp }
|
|
762
792
|
</StyledHelp>
|
|
763
793
|
) }
|
|
764
794
|
</div>
|
|
@@ -14,6 +14,7 @@ import { useState } from '@wordpress/element';
|
|
|
14
14
|
import FormTokenField from '../';
|
|
15
15
|
|
|
16
16
|
const meta: Meta< typeof FormTokenField > = {
|
|
17
|
+
tags: [ 'manifest' ],
|
|
17
18
|
component: FormTokenField,
|
|
18
19
|
title: 'Components/Selection & Input/Common/FormTokenField',
|
|
19
20
|
id: 'components-formtokenfield',
|
|
@@ -24,6 +25,7 @@ const meta: Meta< typeof FormTokenField > = {
|
|
|
24
25
|
__experimentalValidateInput: {
|
|
25
26
|
control: false,
|
|
26
27
|
},
|
|
28
|
+
help: { control: 'text' },
|
|
27
29
|
},
|
|
28
30
|
parameters: {
|
|
29
31
|
controls: {
|
|
@@ -17,6 +17,7 @@ import type { ComponentProps } from 'react';
|
|
|
17
17
|
* WordPress dependencies
|
|
18
18
|
*/
|
|
19
19
|
import { useState } from '@wordpress/element';
|
|
20
|
+
import { logged } from '@wordpress/deprecated';
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* Internal dependencies
|
|
@@ -122,6 +123,14 @@ function unescapeAndFormatSpaces( str: string ) {
|
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
describe( 'FormTokenField', () => {
|
|
126
|
+
afterEach( () => {
|
|
127
|
+
// `@wordpress/deprecated` caches each warning message after the first
|
|
128
|
+
// log; reset it so multiple tests can assert the same deprecation.
|
|
129
|
+
for ( const key in logged ) {
|
|
130
|
+
delete logged[ key ];
|
|
131
|
+
}
|
|
132
|
+
} );
|
|
133
|
+
|
|
125
134
|
describe( 'basic usage', () => {
|
|
126
135
|
it( "should add tokens with the input's value when pressing the enter key", async () => {
|
|
127
136
|
const user = userEvent.setup();
|
|
@@ -582,18 +591,17 @@ describe( 'FormTokenField', () => {
|
|
|
582
591
|
);
|
|
583
592
|
} );
|
|
584
593
|
|
|
585
|
-
it( 'should show
|
|
594
|
+
it( 'should show the default how-to text via the `help` prop by default', () => {
|
|
586
595
|
const instructionsTokenizeSpace =
|
|
587
596
|
'Separate with commas, spaces, or the Enter key.';
|
|
588
597
|
const instructionsDefault =
|
|
589
598
|
'Separate with commas or the Enter key.';
|
|
590
599
|
|
|
591
|
-
// The __experimentalShowHowTo prop is `true` by default
|
|
592
600
|
const { rerender } = render( <FormTokenFieldWithState /> );
|
|
593
601
|
|
|
594
602
|
expect( screen.getByText( instructionsDefault ) ).toBeVisible();
|
|
595
603
|
|
|
596
|
-
// The
|
|
604
|
+
// The default how-to text is used to aria-describedby the input.
|
|
597
605
|
expect(
|
|
598
606
|
screen.getByRole( 'combobox' )
|
|
599
607
|
).toHaveAccessibleDescription( instructionsDefault );
|
|
@@ -604,27 +612,79 @@ describe( 'FormTokenField', () => {
|
|
|
604
612
|
screen.getByText( instructionsTokenizeSpace )
|
|
605
613
|
).toBeVisible();
|
|
606
614
|
|
|
607
|
-
// The "show how to" text is used to aria-describedby the input
|
|
608
615
|
expect(
|
|
609
616
|
screen.getByRole( 'combobox' )
|
|
610
617
|
).toHaveAccessibleDescription( instructionsTokenizeSpace );
|
|
618
|
+
} );
|
|
611
619
|
|
|
612
|
-
|
|
620
|
+
it( 'should allow hiding the help text by passing an empty string', () => {
|
|
621
|
+
render( <FormTokenFieldWithState help="" /> );
|
|
622
|
+
|
|
623
|
+
expect(
|
|
624
|
+
screen.queryByText( 'Separate with commas or the Enter key.' )
|
|
625
|
+
).not.toBeInTheDocument();
|
|
626
|
+
expect(
|
|
627
|
+
screen.getByRole( 'combobox' )
|
|
628
|
+
).not.toHaveAccessibleDescription();
|
|
629
|
+
} );
|
|
630
|
+
|
|
631
|
+
it( 'should associate the `help` text with the input accessibly', () => {
|
|
632
|
+
render( <FormTokenFieldWithState help="Help text" /> );
|
|
633
|
+
expect(
|
|
634
|
+
screen.getByRole( 'combobox' )
|
|
635
|
+
).toHaveAccessibleDescription( 'Help text' );
|
|
636
|
+
// The default how-to text should no longer be rendered.
|
|
637
|
+
expect(
|
|
638
|
+
screen.queryByText( 'Separate with commas or the Enter key.' )
|
|
639
|
+
).not.toBeInTheDocument();
|
|
640
|
+
} );
|
|
641
|
+
|
|
642
|
+
it( 'should warn and hide the default text when `__experimentalShowHowTo` is `false`', () => {
|
|
643
|
+
render(
|
|
644
|
+
<FormTokenFieldWithState __experimentalShowHowTo={ false } />
|
|
645
|
+
);
|
|
646
|
+
|
|
647
|
+
expect( console ).toHaveWarnedWith(
|
|
648
|
+
'`__experimentalShowHowTo` prop in wp.components.FormTokenField is deprecated since version 7.1. Please use `help` prop instead. Note: The `help` prop now defaults to the previous how-to text. Pass an empty string to hide it.'
|
|
649
|
+
);
|
|
650
|
+
|
|
651
|
+
expect(
|
|
652
|
+
screen.queryByText( 'Separate with commas or the Enter key.' )
|
|
653
|
+
).not.toBeInTheDocument();
|
|
654
|
+
expect(
|
|
655
|
+
screen.getByRole( 'combobox' )
|
|
656
|
+
).not.toHaveAccessibleDescription();
|
|
657
|
+
} );
|
|
658
|
+
|
|
659
|
+
it( 'should warn and prefer `help` over `__experimentalShowHowTo` when both are provided', () => {
|
|
660
|
+
const { rerender } = render(
|
|
613
661
|
<FormTokenFieldWithState
|
|
614
|
-
tokenizeOnSpace
|
|
615
662
|
__experimentalShowHowTo={ false }
|
|
663
|
+
help="Help text"
|
|
616
664
|
/>
|
|
617
665
|
);
|
|
618
666
|
|
|
667
|
+
expect( console ).toHaveWarned();
|
|
619
668
|
expect(
|
|
620
|
-
screen.
|
|
621
|
-
).
|
|
669
|
+
screen.getByRole( 'combobox' )
|
|
670
|
+
).toHaveAccessibleDescription( 'Help text' );
|
|
622
671
|
expect(
|
|
623
|
-
screen.queryByText(
|
|
672
|
+
screen.queryByText( 'Separate with commas or the Enter key.' )
|
|
624
673
|
).not.toBeInTheDocument();
|
|
674
|
+
|
|
675
|
+
rerender(
|
|
676
|
+
<FormTokenFieldWithState
|
|
677
|
+
__experimentalShowHowTo
|
|
678
|
+
help="Help text"
|
|
679
|
+
/>
|
|
680
|
+
);
|
|
681
|
+
|
|
625
682
|
expect(
|
|
626
683
|
screen.getByRole( 'combobox' )
|
|
627
|
-
).
|
|
684
|
+
).toHaveAccessibleDescription( 'Help text' );
|
|
685
|
+
expect(
|
|
686
|
+
screen.queryByText( 'Separate with commas or the Enter key.' )
|
|
687
|
+
).not.toBeInTheDocument();
|
|
628
688
|
} );
|
|
629
689
|
|
|
630
690
|
it( "should use the value of the `placeholder` prop as the input's placeholder only when there are no tokens", async () => {
|
|
@@ -87,12 +87,7 @@ export function UnForwardedTokenInput(
|
|
|
87
87
|
? `components-form-token-suggestions-${ instanceId }-${ selectedSuggestionIndex }`
|
|
88
88
|
: undefined
|
|
89
89
|
}
|
|
90
|
-
aria-describedby={
|
|
91
|
-
`components-form-token-suggestions-howto-${ instanceId }`,
|
|
92
|
-
ariaDescribedBy,
|
|
93
|
-
]
|
|
94
|
-
.filter( Boolean )
|
|
95
|
-
.join( ' ' ) }
|
|
90
|
+
aria-describedby={ ariaDescribedBy }
|
|
96
91
|
/>
|
|
97
92
|
);
|
|
98
93
|
}
|
|
@@ -147,9 +147,12 @@ export interface FormTokenFieldProps
|
|
|
147
147
|
*/
|
|
148
148
|
__experimentalValidateInput?: ( token: string ) => boolean;
|
|
149
149
|
/**
|
|
150
|
-
*
|
|
150
|
+
* Use the `help` prop instead. The `help` prop now defaults to the previous
|
|
151
|
+
* how-to text; if you were passing `__experimentalShowHowTo={ false }` to
|
|
152
|
+
* hide it, pass an empty string to `help` instead.
|
|
151
153
|
*
|
|
152
|
-
* @
|
|
154
|
+
* @deprecated Use the `help` prop instead.
|
|
155
|
+
* @ignore
|
|
153
156
|
*/
|
|
154
157
|
__experimentalShowHowTo?: boolean;
|
|
155
158
|
/**
|
|
@@ -193,6 +196,17 @@ export interface FormTokenFieldProps
|
|
|
193
196
|
* @default false
|
|
194
197
|
*/
|
|
195
198
|
tokenizeOnBlur?: boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Additional description for the control.
|
|
201
|
+
*
|
|
202
|
+
* Only use for meaningful description or instructions for the control. An
|
|
203
|
+
* element containing the description will be programmatically associated to
|
|
204
|
+
* the `FormTokenField` via `aria-describedby`.
|
|
205
|
+
*
|
|
206
|
+
* Defaults to a how-to message (e.g. _Separate with commas or the Enter key._);
|
|
207
|
+
* pass an empty string to hide it.
|
|
208
|
+
*/
|
|
209
|
+
help?: ReactNode;
|
|
196
210
|
}
|
|
197
211
|
|
|
198
212
|
/**
|
|
@@ -15,6 +15,7 @@ import { useState } from '@wordpress/element';
|
|
|
15
15
|
import GradientPicker from '..';
|
|
16
16
|
|
|
17
17
|
const meta: Meta< typeof GradientPicker > = {
|
|
18
|
+
tags: [ 'manifest' ],
|
|
18
19
|
title: 'Components/Selection & Input/Color/GradientPicker',
|
|
19
20
|
id: 'components-gradientpicker',
|
|
20
21
|
component: GradientPicker,
|
|
@@ -31,7 +31,7 @@ const meta: Meta< typeof InputControl > = {
|
|
|
31
31
|
type: { control: { type: 'text' } },
|
|
32
32
|
value: { control: { disable: true } },
|
|
33
33
|
},
|
|
34
|
-
tags: [ 'status-experimental' ],
|
|
34
|
+
tags: [ 'status-experimental', 'manifest' ],
|
|
35
35
|
args: {
|
|
36
36
|
onChange: fn(),
|
|
37
37
|
onValidate: fn(),
|
|
@@ -19,7 +19,7 @@ const meta: Meta< typeof ItemGroup > = {
|
|
|
19
19
|
as: { control: false },
|
|
20
20
|
children: { control: false },
|
|
21
21
|
},
|
|
22
|
-
tags: [ 'status-experimental' ],
|
|
22
|
+
tags: [ 'status-experimental', 'manifest' ],
|
|
23
23
|
parameters: {
|
|
24
24
|
controls: { expanded: true },
|
|
25
25
|
docs: { canvas: { sourceState: 'shown' } },
|
|
@@ -9,6 +9,7 @@ import type { Meta, StoryFn } from '@storybook/react-vite';
|
|
|
9
9
|
import KeyboardShortcuts from '..';
|
|
10
10
|
|
|
11
11
|
const meta: Meta< typeof KeyboardShortcuts > = {
|
|
12
|
+
tags: [ 'manifest' ],
|
|
12
13
|
component: KeyboardShortcuts,
|
|
13
14
|
title: 'Components/Utilities/KeyboardShortcuts',
|
|
14
15
|
id: 'components-keyboardshortcuts',
|
package/src/menu/popover.tsx
CHANGED
|
@@ -24,10 +24,7 @@ import { Context } from './context';
|
|
|
24
24
|
export const Popover = forwardRef<
|
|
25
25
|
HTMLDivElement,
|
|
26
26
|
WordPressComponentProps< PopoverProps, 'div', false >
|
|
27
|
-
>( function Popover(
|
|
28
|
-
{ gutter, children, shift, modal = true, ...otherProps },
|
|
29
|
-
ref
|
|
30
|
-
) {
|
|
27
|
+
>( function Popover( { gutter, shift, modal = true, ...otherProps }, ref ) {
|
|
31
28
|
const menuContext = useContext( Context );
|
|
32
29
|
|
|
33
30
|
// Extract the side from the applied placement — useful for animations.
|
|
@@ -70,6 +67,18 @@ export const Popover = forwardRef<
|
|
|
70
67
|
);
|
|
71
68
|
}
|
|
72
69
|
|
|
70
|
+
const renderMenu = useCallback(
|
|
71
|
+
( htmlProps: React.ComponentPropsWithRef< 'div' > ) => (
|
|
72
|
+
<Styled.MenuMotionRoot>
|
|
73
|
+
<Styled.MenuSurface
|
|
74
|
+
{ ...htmlProps }
|
|
75
|
+
variant={ menuContext.variant }
|
|
76
|
+
/>
|
|
77
|
+
</Styled.MenuMotionRoot>
|
|
78
|
+
),
|
|
79
|
+
[ menuContext.variant ]
|
|
80
|
+
);
|
|
81
|
+
|
|
73
82
|
return (
|
|
74
83
|
<Styled.Menu
|
|
75
84
|
{ ...otherProps }
|
|
@@ -88,9 +97,7 @@ export const Popover = forwardRef<
|
|
|
88
97
|
wrapperProps={ wrapperProps }
|
|
89
98
|
hideOnEscape={ hideOnEscape }
|
|
90
99
|
unmountOnHide
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
{ children }
|
|
94
|
-
</Styled.Menu>
|
|
100
|
+
render={ renderMenu }
|
|
101
|
+
/>
|
|
95
102
|
);
|
|
96
103
|
} );
|
package/src/menu/styles.ts
CHANGED
|
@@ -32,12 +32,17 @@ const TOOLBAR_VARIANT_BOX_SHADOW = `0 0 0 ${ CONFIG.borderWidth } ${ TOOLBAR_VAR
|
|
|
32
32
|
|
|
33
33
|
const GRID_TEMPLATE_COLS = 'minmax( 0, max-content ) 1fr';
|
|
34
34
|
|
|
35
|
-
export const Menu = styled( Ariakit.Menu )
|
|
35
|
+
export const Menu = styled( Ariakit.Menu )`
|
|
36
36
|
position: relative;
|
|
37
37
|
/* Same as popover component */
|
|
38
38
|
/* TODO: is there a way to read the sass variable? */
|
|
39
39
|
z-index: 1000000;
|
|
40
40
|
|
|
41
|
+
/* Only visible in Windows High Contrast mode */
|
|
42
|
+
outline: 2px solid transparent !important;
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
export const MenuSurface = styled.div< Pick< ContextProps, 'variant' > >`
|
|
41
46
|
display: grid;
|
|
42
47
|
grid-template-columns: ${ GRID_TEMPLATE_COLS };
|
|
43
48
|
grid-template-rows: auto;
|
|
@@ -59,11 +64,16 @@ export const Menu = styled( Ariakit.Menu )< Pick< ContextProps, 'variant' > >`
|
|
|
59
64
|
? TOOLBAR_VARIANT_BOX_SHADOW
|
|
60
65
|
: DEFAULT_BOX_SHADOW };
|
|
61
66
|
` }
|
|
67
|
+
`;
|
|
62
68
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Outer wrapper for menu motion. `Menu.Popover` uses Ariakit’s `render` prop so
|
|
71
|
+
* this element wraps the inner surface that receives all merged menu props
|
|
72
|
+
* (ref, role, `data-*`, children). Transitions mirror the pre-refactor `Menu`
|
|
73
|
+
* styles from `trunk`, driven by `data-enter` / `data-side` on the inner
|
|
74
|
+
* surface via `:has(> …)`.
|
|
75
|
+
*/
|
|
76
|
+
export const MenuMotionRoot = styled.div`
|
|
67
77
|
@media not ( prefers-reduced-motion ) {
|
|
68
78
|
transition-property: transform, opacity;
|
|
69
79
|
transition-duration: ${ DROPDOWN_MOTION_CSS.SLIDE_DURATION },
|
|
@@ -72,40 +82,40 @@ export const Menu = styled( Ariakit.Menu )< Pick< ContextProps, 'variant' > >`
|
|
|
72
82
|
${ DROPDOWN_MOTION_CSS.FADE_EASING };
|
|
73
83
|
will-change: transform, opacity;
|
|
74
84
|
|
|
75
|
-
&:not( [data-submenu] ) {
|
|
85
|
+
&:not( :has( > ${ MenuSurface }[data-submenu] ) ) {
|
|
76
86
|
/* Regardless of the side, fade in and out. */
|
|
77
87
|
opacity: 0;
|
|
78
|
-
|
|
88
|
+
&:has( > ${ MenuSurface }[data-enter] ) {
|
|
79
89
|
opacity: 1;
|
|
80
90
|
}
|
|
81
91
|
|
|
82
92
|
/* Slide in the direction the menu is opening. */
|
|
83
|
-
|
|
93
|
+
&:has( > ${ MenuSurface }[data-side='bottom'] ) {
|
|
84
94
|
transform: translateY(
|
|
85
95
|
-${ DROPDOWN_MOTION_CSS.SLIDE_DISTANCE }
|
|
86
96
|
);
|
|
87
97
|
}
|
|
88
|
-
|
|
98
|
+
&:has( > ${ MenuSurface }[data-side='top'] ) {
|
|
89
99
|
transform: translateY(
|
|
90
100
|
${ DROPDOWN_MOTION_CSS.SLIDE_DISTANCE }
|
|
91
101
|
);
|
|
92
102
|
}
|
|
93
|
-
|
|
103
|
+
&:has( > ${ MenuSurface }[data-side='left'] ) {
|
|
94
104
|
transform: translateX(
|
|
95
105
|
${ DROPDOWN_MOTION_CSS.SLIDE_DISTANCE }
|
|
96
106
|
);
|
|
97
107
|
}
|
|
98
|
-
|
|
108
|
+
&:has( > ${ MenuSurface }[data-side='right'] ) {
|
|
99
109
|
transform: translateX(
|
|
100
110
|
-${ DROPDOWN_MOTION_CSS.SLIDE_DISTANCE }
|
|
101
111
|
);
|
|
102
112
|
}
|
|
103
|
-
|
|
104
|
-
|
|
113
|
+
&:has( > ${ MenuSurface }[data-enter][data-side='bottom'] ),
|
|
114
|
+
&:has( > ${ MenuSurface }[data-enter][data-side='top'] ) {
|
|
105
115
|
transform: translateY( 0 );
|
|
106
116
|
}
|
|
107
|
-
|
|
108
|
-
|
|
117
|
+
&:has( > ${ MenuSurface }[data-enter][data-side='left'] ),
|
|
118
|
+
&:has( > ${ MenuSurface }[data-enter][data-side='right'] ) {
|
|
109
119
|
transform: translateX( 0 );
|
|
110
120
|
}
|
|
111
121
|
}
|
|
@@ -114,6 +124,7 @@ export const Menu = styled( Ariakit.Menu )< Pick< ContextProps, 'variant' > >`
|
|
|
114
124
|
|
|
115
125
|
const baseItem = css`
|
|
116
126
|
all: unset;
|
|
127
|
+
cursor: pointer;
|
|
117
128
|
|
|
118
129
|
position: relative;
|
|
119
130
|
min-height: ${ space( 8 ) };
|
|
@@ -157,7 +168,6 @@ const baseItem = css`
|
|
|
157
168
|
|
|
158
169
|
&[aria-disabled='true'] {
|
|
159
170
|
color: ${ COLORS.ui.textDisabled };
|
|
160
|
-
cursor: not-allowed;
|
|
161
171
|
}
|
|
162
172
|
|
|
163
173
|
/* Active item (including hover) */
|