@wordpress/ui 0.10.0 → 0.11.1-next.v.202604091042.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 +27 -0
- package/CONTRIBUTING.md +25 -0
- package/README.md +22 -2
- package/build/alert-dialog/context.cjs +6 -1
- package/build/alert-dialog/context.cjs.map +2 -2
- package/build/alert-dialog/popup.cjs +105 -33
- package/build/alert-dialog/popup.cjs.map +4 -4
- package/build/alert-dialog/root.cjs +106 -6
- package/build/alert-dialog/root.cjs.map +2 -2
- package/build/alert-dialog/trigger.cjs +4 -14
- package/build/alert-dialog/trigger.cjs.map +3 -3
- package/build/alert-dialog/types.cjs.map +1 -1
- package/build/button/button.cjs +16 -6
- package/build/button/button.cjs.map +3 -3
- package/build/card/content.cjs +3 -3
- package/build/card/content.cjs.map +1 -1
- package/build/card/full-bleed.cjs +3 -3
- package/build/card/full-bleed.cjs.map +1 -1
- package/build/card/header.cjs +3 -3
- package/build/card/header.cjs.map +1 -1
- package/build/card/root.cjs +3 -3
- package/build/card/root.cjs.map +1 -1
- package/build/card/title.cjs +3 -3
- package/build/card/title.cjs.map +1 -1
- package/build/collapsible-card/header.cjs +3 -3
- package/build/collapsible-card/header.cjs.map +2 -2
- package/build/empty-state/title.cjs.map +2 -2
- package/build/form/primitives/field/description.cjs +17 -4
- package/build/form/primitives/field/description.cjs.map +3 -3
- package/build/form/primitives/field/details.cjs +3 -3
- package/build/form/primitives/field/details.cjs.map +2 -2
- package/build/form/primitives/field/label.cjs +3 -3
- package/build/form/primitives/field/label.cjs.map +2 -2
- package/build/form/primitives/fieldset/description.cjs +20 -4
- package/build/form/primitives/fieldset/description.cjs.map +3 -3
- package/build/form/primitives/fieldset/details.cjs +3 -3
- package/build/form/primitives/fieldset/details.cjs.map +2 -2
- package/build/form/primitives/fieldset/legend.cjs +3 -3
- package/build/form/primitives/fieldset/legend.cjs.map +2 -2
- package/build/form/primitives/input/input.cjs +23 -7
- package/build/form/primitives/input/input.cjs.map +3 -3
- package/build/form/primitives/input-layout/input-layout.cjs +10 -0
- package/build/form/primitives/input-layout/input-layout.cjs.map +3 -3
- package/build/form/primitives/select/trigger.cjs +3 -3
- package/build/form/primitives/select/trigger.cjs.map +2 -2
- package/build/form/primitives/textarea/textarea.cjs +20 -1
- package/build/form/primitives/textarea/textarea.cjs.map +3 -3
- package/build/index.cjs +3 -0
- package/build/index.cjs.map +2 -2
- package/build/link/link.cjs +16 -6
- package/build/link/link.cjs.map +3 -3
- package/build/popover/arrow.cjs +94 -0
- package/build/popover/arrow.cjs.map +7 -0
- package/build/popover/close.cjs +45 -0
- package/build/popover/close.cjs.map +7 -0
- package/build/popover/context.cjs +76 -0
- package/build/popover/context.cjs.map +7 -0
- package/build/popover/description.cjs +70 -0
- package/build/popover/description.cjs.map +7 -0
- package/build/popover/index.cjs +49 -0
- package/build/popover/index.cjs.map +7 -0
- package/build/popover/popup.cjs +138 -0
- package/build/popover/popup.cjs.map +7 -0
- package/build/popover/root.cjs +35 -0
- package/build/popover/root.cjs.map +7 -0
- package/build/popover/title.cjs +56 -0
- package/build/popover/title.cjs.map +7 -0
- package/build/popover/trigger.cjs +38 -0
- package/build/popover/trigger.cjs.map +7 -0
- package/build/popover/types.cjs +19 -0
- package/build/popover/types.cjs.map +7 -0
- package/build/text/text.cjs +20 -5
- package/build/text/text.cjs.map +3 -3
- package/build/utils/use-deprioritized-initial-focus.cjs.map +2 -2
- package/build-module/alert-dialog/context.mjs +6 -1
- package/build-module/alert-dialog/context.mjs.map +2 -2
- package/build-module/alert-dialog/popup.mjs +107 -33
- package/build-module/alert-dialog/popup.mjs.map +4 -4
- package/build-module/alert-dialog/root.mjs +113 -7
- package/build-module/alert-dialog/root.mjs.map +2 -2
- package/build-module/alert-dialog/trigger.mjs +4 -4
- package/build-module/alert-dialog/trigger.mjs.map +3 -3
- package/build-module/button/button.mjs +16 -6
- package/build-module/button/button.mjs.map +3 -3
- package/build-module/card/content.mjs +3 -3
- package/build-module/card/content.mjs.map +1 -1
- package/build-module/card/full-bleed.mjs +3 -3
- package/build-module/card/full-bleed.mjs.map +1 -1
- package/build-module/card/header.mjs +3 -3
- package/build-module/card/header.mjs.map +1 -1
- package/build-module/card/root.mjs +3 -3
- package/build-module/card/root.mjs.map +1 -1
- package/build-module/card/title.mjs +3 -3
- package/build-module/card/title.mjs.map +1 -1
- package/build-module/collapsible-card/header.mjs +3 -3
- package/build-module/collapsible-card/header.mjs.map +2 -2
- package/build-module/empty-state/title.mjs.map +2 -2
- package/build-module/form/primitives/field/description.mjs +17 -4
- package/build-module/form/primitives/field/description.mjs.map +3 -3
- package/build-module/form/primitives/field/details.mjs +3 -3
- package/build-module/form/primitives/field/details.mjs.map +2 -2
- package/build-module/form/primitives/field/label.mjs +3 -3
- package/build-module/form/primitives/field/label.mjs.map +2 -2
- package/build-module/form/primitives/fieldset/description.mjs +20 -4
- package/build-module/form/primitives/fieldset/description.mjs.map +3 -3
- package/build-module/form/primitives/fieldset/details.mjs +3 -3
- package/build-module/form/primitives/fieldset/details.mjs.map +2 -2
- package/build-module/form/primitives/fieldset/legend.mjs +3 -3
- package/build-module/form/primitives/fieldset/legend.mjs.map +2 -2
- package/build-module/form/primitives/input/input.mjs +23 -7
- package/build-module/form/primitives/input/input.mjs.map +3 -3
- package/build-module/form/primitives/input-layout/input-layout.mjs +10 -0
- package/build-module/form/primitives/input-layout/input-layout.mjs.map +3 -3
- package/build-module/form/primitives/select/trigger.mjs +3 -3
- package/build-module/form/primitives/select/trigger.mjs.map +2 -2
- package/build-module/form/primitives/textarea/textarea.mjs +20 -1
- package/build-module/form/primitives/textarea/textarea.mjs.map +3 -3
- package/build-module/index.mjs +2 -0
- package/build-module/index.mjs.map +2 -2
- package/build-module/link/link.mjs +16 -6
- package/build-module/link/link.mjs.map +3 -3
- package/build-module/popover/arrow.mjs +59 -0
- package/build-module/popover/arrow.mjs.map +7 -0
- package/build-module/popover/close.mjs +20 -0
- package/build-module/popover/close.mjs.map +7 -0
- package/build-module/popover/context.mjs +57 -0
- package/build-module/popover/context.mjs.map +7 -0
- package/build-module/popover/description.mjs +35 -0
- package/build-module/popover/description.mjs.map +7 -0
- package/build-module/popover/index.mjs +18 -0
- package/build-module/popover/index.mjs.map +7 -0
- package/build-module/popover/popup.mjs +105 -0
- package/build-module/popover/popup.mjs.map +7 -0
- package/build-module/popover/root.mjs +10 -0
- package/build-module/popover/root.mjs.map +7 -0
- package/build-module/popover/title.mjs +31 -0
- package/build-module/popover/title.mjs.map +7 -0
- package/build-module/popover/trigger.mjs +13 -0
- package/build-module/popover/trigger.mjs.map +7 -0
- package/build-module/popover/types.mjs +1 -0
- package/build-module/popover/types.mjs.map +7 -0
- package/build-module/text/text.mjs +20 -5
- package/build-module/text/text.mjs.map +3 -3
- package/build-module/utils/use-deprioritized-initial-focus.mjs.map +2 -2
- package/build-types/alert-dialog/context.d.ts +6 -3
- package/build-types/alert-dialog/context.d.ts.map +1 -1
- package/build-types/alert-dialog/popup.d.ts.map +1 -1
- package/build-types/alert-dialog/root.d.ts +2 -8
- package/build-types/alert-dialog/root.d.ts.map +1 -1
- package/build-types/alert-dialog/stories/index.story.d.ts +18 -6
- package/build-types/alert-dialog/stories/index.story.d.ts.map +1 -1
- package/build-types/alert-dialog/trigger.d.ts +2 -1
- package/build-types/alert-dialog/trigger.d.ts.map +1 -1
- package/build-types/alert-dialog/types.d.ts +57 -26
- package/build-types/alert-dialog/types.d.ts.map +1 -1
- package/build-types/button/button.d.ts.map +1 -1
- package/build-types/card/stories/index.story.d.ts.map +1 -1
- package/build-types/empty-state/title.d.ts.map +1 -1
- package/build-types/form/primitives/field/description.d.ts.map +1 -1
- package/build-types/form/primitives/fieldset/description.d.ts.map +1 -1
- package/build-types/form/primitives/input/input.d.ts.map +1 -1
- package/build-types/form/primitives/input-layout/input-layout.d.ts.map +1 -1
- package/build-types/form/primitives/textarea/textarea.d.ts.map +1 -1
- package/build-types/form/stories/shared.d.ts.map +1 -1
- package/build-types/index.d.ts +1 -0
- package/build-types/index.d.ts.map +1 -1
- package/build-types/link/link.d.ts.map +1 -1
- package/build-types/popover/arrow.d.ts +10 -0
- package/build-types/popover/arrow.d.ts.map +1 -0
- package/build-types/popover/close.d.ts +11 -0
- package/build-types/popover/close.d.ts.map +1 -0
- package/build-types/popover/context.d.ts +22 -0
- package/build-types/popover/context.d.ts.map +1 -0
- package/build-types/popover/description.d.ts +10 -0
- package/build-types/popover/description.d.ts.map +1 -0
- package/build-types/popover/index.d.ts +9 -0
- package/build-types/popover/index.d.ts.map +1 -0
- package/build-types/popover/popup.d.ts +11 -0
- package/build-types/popover/popup.d.ts.map +1 -0
- package/build-types/popover/root.d.ts +37 -0
- package/build-types/popover/root.d.ts.map +1 -0
- package/build-types/popover/stories/index.story.d.ts +211 -0
- package/build-types/popover/stories/index.story.d.ts.map +1 -0
- package/build-types/popover/stories/utils.d.ts +25 -0
- package/build-types/popover/stories/utils.d.ts.map +1 -0
- package/build-types/popover/test/index.test.d.ts +2 -0
- package/build-types/popover/test/index.test.d.ts.map +1 -0
- package/build-types/popover/title.d.ts +20 -0
- package/build-types/popover/title.d.ts.map +1 -0
- package/build-types/popover/trigger.d.ts +10 -0
- package/build-types/popover/trigger.d.ts.map +1 -0
- package/build-types/popover/types.d.ts +83 -0
- package/build-types/popover/types.d.ts.map +1 -0
- package/build-types/text/stories/index.story.d.ts +4 -0
- package/build-types/text/stories/index.story.d.ts.map +1 -1
- package/build-types/text/text.d.ts.map +1 -1
- package/build-types/utils/use-deprioritized-initial-focus.d.ts +6 -5
- package/build-types/utils/use-deprioritized-initial-focus.d.ts.map +1 -1
- package/package.json +11 -11
- package/src/alert-dialog/context.tsx +12 -4
- package/src/alert-dialog/popup.tsx +91 -33
- package/src/alert-dialog/root.tsx +191 -13
- package/src/alert-dialog/stories/index.story.tsx +116 -65
- package/src/alert-dialog/style.module.css +11 -0
- package/src/alert-dialog/test/index.test.tsx +1265 -347
- package/src/alert-dialog/trigger.tsx +2 -2
- package/src/alert-dialog/types.ts +59 -28
- package/src/button/button.tsx +2 -0
- package/src/button/style.module.css +4 -0
- package/src/card/stories/index.story.tsx +0 -1
- package/src/card/style.module.css +1 -1
- package/src/card/test/index.test.tsx +0 -1
- package/src/empty-state/title.tsx +0 -1
- package/src/form/primitives/field/description.tsx +6 -1
- package/src/form/primitives/fieldset/description.tsx +9 -1
- package/src/form/primitives/input/input.tsx +6 -1
- package/src/form/primitives/input/style.module.css +4 -0
- package/src/form/primitives/input-layout/input-layout.tsx +2 -0
- package/src/form/primitives/textarea/textarea.tsx +10 -1
- package/src/form/stories/shared.tsx +4 -2
- package/src/index.ts +1 -0
- package/src/link/link.tsx +2 -0
- package/src/link/style.module.css +10 -0
- package/src/popover/arrow.tsx +49 -0
- package/src/popover/close.tsx +24 -0
- package/src/popover/context.tsx +100 -0
- package/src/popover/description.tsx +34 -0
- package/src/popover/index.ts +9 -0
- package/src/popover/popup.tsx +106 -0
- package/src/popover/root.tsx +41 -0
- package/src/popover/stories/index.story.tsx +1315 -0
- package/src/popover/stories/utils.tsx +91 -0
- package/src/popover/style.module.css +64 -0
- package/src/popover/test/index.test.tsx +727 -0
- package/src/popover/title.tsx +50 -0
- package/src/popover/trigger.tsx +17 -0
- package/src/popover/types.ts +113 -0
- package/src/text/stories/index.story.tsx +4 -2
- package/src/text/style.module.css +26 -0
- package/src/text/test/index.test.tsx +1 -4
- package/src/text/text.tsx +8 -1
- package/src/utils/css/field.module.css +4 -1
- package/src/utils/css/focus.module.css +7 -5
- package/src/utils/css/global-css-defense.module.css +117 -0
- package/src/utils/use-deprioritized-initial-focus.ts +5 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { AlertDialog as _AlertDialog } from '@base-ui/react/alert-dialog';
|
|
1
2
|
import { forwardRef } from '@wordpress/element';
|
|
2
3
|
|
|
3
|
-
import * as Dialog from '../dialog';
|
|
4
4
|
import type { TriggerProps } from './types';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -8,7 +8,7 @@ import type { TriggerProps } from './types';
|
|
|
8
8
|
*/
|
|
9
9
|
const Trigger = forwardRef< HTMLButtonElement, TriggerProps >(
|
|
10
10
|
function AlertDialogTrigger( props, ref ) {
|
|
11
|
-
return <
|
|
11
|
+
return <_AlertDialog.Trigger ref={ ref } { ...props } />;
|
|
12
12
|
}
|
|
13
13
|
);
|
|
14
14
|
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import type { AlertDialog as _AlertDialog } from '@base-ui/react/alert-dialog';
|
|
2
2
|
import type { ReactNode } from 'react';
|
|
3
3
|
|
|
4
|
-
import type {
|
|
4
|
+
import type { ComponentProps } from '../utils/types';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The return type of `onConfirm`. Return `void` (or nothing) to auto-close
|
|
8
|
+
* the dialog after the confirm handler completes. Return `{ close: false }`
|
|
9
|
+
* to keep the dialog open (e.g. for validation errors).
|
|
10
|
+
*
|
|
11
|
+
* Return `{ error: '...' }` to display a built-in error message below the
|
|
12
|
+
* action buttons. When `error` is provided, the dialog stays open
|
|
13
|
+
* regardless of the `close` value.
|
|
14
|
+
*/
|
|
15
|
+
export type ConfirmResult = void | { close?: boolean; error?: string };
|
|
5
16
|
|
|
6
17
|
export interface RootProps
|
|
7
18
|
extends Pick<
|
|
@@ -14,6 +25,43 @@ export interface RootProps
|
|
|
14
25
|
*/
|
|
15
26
|
children: ReactNode;
|
|
16
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Callback fired when the user confirms the action.
|
|
30
|
+
*
|
|
31
|
+
* - Synchronous handlers: the dialog closes immediately after the
|
|
32
|
+
* handler returns.
|
|
33
|
+
* - Async handlers: the dialog enters a "pending" state (buttons
|
|
34
|
+
* disabled, spinner shown on the confirm button) until the promise
|
|
35
|
+
* settles.
|
|
36
|
+
*
|
|
37
|
+
* Return `{ close: false }` to keep the dialog open after the handler
|
|
38
|
+
* completes (e.g. for server-side validation). Return `void` or
|
|
39
|
+
* `{ close: true }` to close the dialog (the default).
|
|
40
|
+
*
|
|
41
|
+
* Return `{ error: '...' }` to show a built-in error message below
|
|
42
|
+
* the action buttons. The dialog stays open regardless of the `close`
|
|
43
|
+
* value. The error is announced to screen readers and is automatically
|
|
44
|
+
* cleared on the next confirm attempt or when the dialog reopens.
|
|
45
|
+
*
|
|
46
|
+
* If the promise rejects (or the handler throws) without returning an
|
|
47
|
+
* `error`, the dialog stays open and returns to idle without showing
|
|
48
|
+
* a visible error message. The error is logged to the console.
|
|
49
|
+
* To show a user-facing message on failure, catch the error and
|
|
50
|
+
* return `{ close: false, error: '...' }`.
|
|
51
|
+
*/
|
|
52
|
+
onConfirm?: () => ConfirmResult | Promise< ConfirmResult >;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface TriggerProps extends ComponentProps< 'button' > {
|
|
56
|
+
/**
|
|
57
|
+
* The content to be rendered inside the component.
|
|
58
|
+
*/
|
|
59
|
+
children?: ReactNode;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface PopupProps
|
|
63
|
+
extends ComponentProps< 'div' >,
|
|
64
|
+
Pick< _AlertDialog.Popup.Props, 'initialFocus' | 'finalFocus' > {
|
|
17
65
|
/**
|
|
18
66
|
* The semantic intent of the dialog, which determines its styling.
|
|
19
67
|
*
|
|
@@ -28,26 +76,27 @@ export interface RootProps
|
|
|
28
76
|
* @default 'default'
|
|
29
77
|
*/
|
|
30
78
|
intent?: 'default' | 'irreversible';
|
|
31
|
-
}
|
|
32
79
|
|
|
33
|
-
export type TriggerProps = DialogTriggerProps;
|
|
34
|
-
|
|
35
|
-
export interface PopupProps {
|
|
36
80
|
/**
|
|
37
81
|
* The title displayed in the dialog header. This serves as both the
|
|
38
|
-
* visible heading and the accessible label for the
|
|
82
|
+
* visible heading and the accessible label (`aria-labelledby`) for the
|
|
83
|
+
* dialog. Must be a plain string to ensure a predictable accessible name.
|
|
39
84
|
*/
|
|
40
85
|
title: string;
|
|
41
86
|
|
|
42
87
|
/**
|
|
43
|
-
*
|
|
88
|
+
* An optional description displayed below the title. Rendered using
|
|
89
|
+
* Base UI's `AlertDialog.Description` for proper `aria-describedby`
|
|
90
|
+
* association with the dialog. Must be a plain string to ensure a
|
|
91
|
+
* predictable accessible description.
|
|
44
92
|
*/
|
|
45
|
-
|
|
93
|
+
description?: string;
|
|
46
94
|
|
|
47
95
|
/**
|
|
48
|
-
*
|
|
96
|
+
* Optional body content displayed between the description and the
|
|
97
|
+
* action buttons. Use for supplementary details or form fields.
|
|
49
98
|
*/
|
|
50
|
-
|
|
99
|
+
children?: ReactNode;
|
|
51
100
|
|
|
52
101
|
/**
|
|
53
102
|
* Custom text for the confirm button.
|
|
@@ -62,22 +111,4 @@ export interface PopupProps {
|
|
|
62
111
|
* @default 'Cancel'
|
|
63
112
|
*/
|
|
64
113
|
cancelButtonText?: string;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Whether the confirm action is in a loading state (e.g. an async
|
|
68
|
-
* operation is in progress). When `true`, the confirm button shows a
|
|
69
|
-
* spinner and the cancel button is disabled.
|
|
70
|
-
*
|
|
71
|
-
* **Important:** Passing this prop — even as `false` — opts into
|
|
72
|
-
* manual-close mode: the confirm button will no longer auto-close the
|
|
73
|
-
* dialog. The consumer is responsible for setting `open={false}` when
|
|
74
|
-
* the operation completes. Omit the prop entirely for the default
|
|
75
|
-
* auto-close-on-confirm behavior.
|
|
76
|
-
*
|
|
77
|
-
* To implement an async confirm flow, use controlled mode
|
|
78
|
-
* (`open` / `onOpenChange`) and manage the loading state externally:
|
|
79
|
-
* prevent closing in `onOpenChange` while loading, and set
|
|
80
|
-
* `open={false}` once the operation completes.
|
|
81
|
-
*/
|
|
82
|
-
loading?: boolean;
|
|
83
114
|
}
|
package/src/button/button.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import { type ButtonProps } from './types';
|
|
|
7
7
|
import styles from './style.module.css';
|
|
8
8
|
import resetStyles from '../utils/css/resets.module.css';
|
|
9
9
|
import focusStyles from '../utils/css/focus.module.css';
|
|
10
|
+
import defenseStyles from '../utils/css/global-css-defense.module.css';
|
|
10
11
|
|
|
11
12
|
export const Button = forwardRef< HTMLButtonElement, ButtonProps >(
|
|
12
13
|
function Button(
|
|
@@ -25,6 +26,7 @@ export const Button = forwardRef< HTMLButtonElement, ButtonProps >(
|
|
|
25
26
|
ref
|
|
26
27
|
) {
|
|
27
28
|
const mergedClassName = clsx(
|
|
29
|
+
defenseStyles.button,
|
|
28
30
|
resetStyles[ 'box-sizing' ],
|
|
29
31
|
focusStyles[ 'outset-ring--focus-except-active' ],
|
|
30
32
|
variant !== 'unstyled' && styles.button,
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
--wp-ui-button-border-color-active: var(--wp-ui-button-background-color-active);
|
|
29
29
|
--wp-ui-button-border-color-disabled: var(--wp-ui-button-background-color-disabled);
|
|
30
30
|
|
|
31
|
+
--_gcd-button-font-family: var(--wpds-font-family-body);
|
|
32
|
+
--_gcd-button-font-size: var(--wp-ui-button-font-size);
|
|
33
|
+
--_gcd-button-font-weight: var(--wp-ui-button-font-weight);
|
|
34
|
+
|
|
31
35
|
/* Styles */
|
|
32
36
|
position: relative;
|
|
33
37
|
display: inline-flex;
|
|
@@ -116,7 +116,6 @@ export const CustomSemantics: Story = {
|
|
|
116
116
|
children: (
|
|
117
117
|
<>
|
|
118
118
|
<Card.Header>
|
|
119
|
-
{ /* eslint-disable-next-line jsx-a11y/heading-has-content -- content provided via render prop */ }
|
|
120
119
|
<Card.Title render={ <h2 /> }>Section heading</Card.Title>
|
|
121
120
|
</Card.Header>
|
|
122
121
|
<Card.Content>
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
border-radius: var(--wpds-border-radius-lg);
|
|
13
13
|
overflow: clip;
|
|
14
14
|
background-color: var(--wpds-color-bg-surface-neutral-strong);
|
|
15
|
+
color: var(--wpds-color-fg-content-neutral);
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
/* Padding is applied to the individual header/content elements to enable
|
|
@@ -40,6 +41,5 @@
|
|
|
40
41
|
|
|
41
42
|
.title {
|
|
42
43
|
margin: 0;
|
|
43
|
-
color: var(--wpds-color-fg-content-neutral);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -12,7 +12,6 @@ export const Title = forwardRef< HTMLHeadingElement, EmptyStateTitleProps >(
|
|
|
12
12
|
return (
|
|
13
13
|
<Text
|
|
14
14
|
variant="heading-lg"
|
|
15
|
-
// eslint-disable-next-line jsx-a11y/heading-has-content -- content provided via render prop
|
|
16
15
|
render={ render ?? <h2 ref={ ref } { ...props } /> }
|
|
17
16
|
className={ clsx( styles.title, className ) }
|
|
18
17
|
>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
2
|
import { Field as _Field } from '@base-ui/react/field';
|
|
3
3
|
import { forwardRef } from '@wordpress/element';
|
|
4
|
+
import defenseStyles from '../../../utils/css/global-css-defense.module.css';
|
|
4
5
|
import fieldStyles from '../../../utils/css/field.module.css';
|
|
5
6
|
import type { FieldDescriptionProps } from './types';
|
|
6
7
|
|
|
@@ -11,7 +12,11 @@ export const Description = forwardRef<
|
|
|
11
12
|
return (
|
|
12
13
|
<_Field.Description
|
|
13
14
|
ref={ ref }
|
|
14
|
-
className={ clsx(
|
|
15
|
+
className={ clsx(
|
|
16
|
+
defenseStyles.p,
|
|
17
|
+
fieldStyles.description,
|
|
18
|
+
className
|
|
19
|
+
) }
|
|
15
20
|
{ ...restProps }
|
|
16
21
|
/>
|
|
17
22
|
);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
2
|
import { mergeProps, useRender } from '@base-ui/react';
|
|
3
3
|
import { forwardRef, useEffect, useId } from '@wordpress/element';
|
|
4
|
+
import defenseStyles from '../../../utils/css/global-css-defense.module.css';
|
|
4
5
|
import fieldStyles from '../../../utils/css/field.module.css';
|
|
5
6
|
import { useFieldsetContext } from './context';
|
|
6
7
|
import type { FieldsetDescriptionProps } from './types';
|
|
@@ -27,7 +28,14 @@ export const FieldsetDescription = forwardRef<
|
|
|
27
28
|
render,
|
|
28
29
|
ref,
|
|
29
30
|
props: mergeProps< 'p' >(
|
|
30
|
-
{
|
|
31
|
+
{
|
|
32
|
+
className: clsx(
|
|
33
|
+
defenseStyles.p,
|
|
34
|
+
fieldStyles.description,
|
|
35
|
+
className
|
|
36
|
+
),
|
|
37
|
+
id,
|
|
38
|
+
},
|
|
31
39
|
restProps
|
|
32
40
|
),
|
|
33
41
|
} );
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Input as _Input } from '@base-ui/react/input';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import { forwardRef } from '@wordpress/element';
|
|
4
|
+
import defenseStyles from '../../../utils/css/global-css-defense.module.css';
|
|
4
5
|
import focusStyles from '../../../utils/css/focus.module.css';
|
|
5
6
|
import styles from './style.module.css';
|
|
6
7
|
import type { InputProps } from './types';
|
|
@@ -22,7 +23,11 @@ export const Input = forwardRef< HTMLElement, InputProps >( function Input(
|
|
|
22
23
|
prefix={ prefix }
|
|
23
24
|
suffix={ suffix }
|
|
24
25
|
>
|
|
25
|
-
<_Input
|
|
26
|
+
<_Input
|
|
27
|
+
ref={ ref }
|
|
28
|
+
className={ clsx( defenseStyles.input, styles.input ) }
|
|
29
|
+
{ ...restProps }
|
|
30
|
+
/>
|
|
26
31
|
</InputLayout>
|
|
27
32
|
);
|
|
28
33
|
} );
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
@layer wp-ui-components {
|
|
4
4
|
.input {
|
|
5
|
+
--_gcd-input-padding:
|
|
6
|
+
var(--wp-ui-input-padding-block, 0)
|
|
7
|
+
var(--wp-ui-input-layout-padding-inline, 0);
|
|
8
|
+
|
|
5
9
|
padding-block: var(--wp-ui-input-padding-block, 0);
|
|
6
10
|
padding-inline: var(--wp-ui-input-layout-padding-inline, 0);
|
|
7
11
|
width: 100%;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
2
|
import { Children, forwardRef } from '@wordpress/element';
|
|
3
|
+
import defenseStyles from '../../../utils/css/global-css-defense.module.css';
|
|
3
4
|
import resetStyles from '../../../utils/css/resets.module.css';
|
|
4
5
|
import styles from './style.module.css';
|
|
5
6
|
import type { InputLayoutProps } from './types';
|
|
@@ -26,6 +27,7 @@ export const InputLayout = forwardRef< HTMLDivElement, InputLayoutProps >(
|
|
|
26
27
|
<div
|
|
27
28
|
ref={ ref }
|
|
28
29
|
className={ clsx(
|
|
30
|
+
defenseStyles.div,
|
|
29
31
|
resetStyles[ 'box-sizing' ],
|
|
30
32
|
styles[ 'input-layout' ],
|
|
31
33
|
styles[ `is-size-${ size }` ],
|
|
@@ -4,6 +4,7 @@ import { cloneElement, forwardRef } from '@wordpress/element';
|
|
|
4
4
|
import styles from './style.module.css';
|
|
5
5
|
import type { TextareaProps } from './types';
|
|
6
6
|
import { Input } from '../input';
|
|
7
|
+
import defenseStyles from '../../../utils/css/global-css-defense.module.css';
|
|
7
8
|
|
|
8
9
|
const wrappedRender = (
|
|
9
10
|
render: NonNullable< TextareaProps[ 'render' ] >,
|
|
@@ -39,7 +40,15 @@ export const Textarea = forwardRef< HTMLTextAreaElement, TextareaProps >(
|
|
|
39
40
|
style={ style }
|
|
40
41
|
render={ wrappedRender(
|
|
41
42
|
render || ( ( props ) => <textarea { ...props } /> ),
|
|
42
|
-
{
|
|
43
|
+
{
|
|
44
|
+
className: clsx(
|
|
45
|
+
defenseStyles.textarea,
|
|
46
|
+
styles.textarea
|
|
47
|
+
),
|
|
48
|
+
ref,
|
|
49
|
+
rows,
|
|
50
|
+
...restProps,
|
|
51
|
+
}
|
|
43
52
|
) }
|
|
44
53
|
value={ value }
|
|
45
54
|
defaultValue={ defaultValue }
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Link } from '../..';
|
|
2
|
+
|
|
1
3
|
export const WITH_DETAILS_DESCRIPTION = `\
|
|
2
4
|
To add rich content (such as links) to the description, use the \`details\` prop.
|
|
3
5
|
|
|
@@ -11,9 +13,9 @@ so the readout is not unnecessarily verbose for screen reader users.`;
|
|
|
11
13
|
export const DETAILS_EXAMPLE = (
|
|
12
14
|
<>
|
|
13
15
|
Details can include{ ' ' }
|
|
14
|
-
<
|
|
16
|
+
<Link href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a">
|
|
15
17
|
links to more information
|
|
16
|
-
</
|
|
18
|
+
</Link>{ ' ' }
|
|
17
19
|
and other semantic elements.
|
|
18
20
|
</>
|
|
19
21
|
);
|
package/src/index.ts
CHANGED
package/src/link/link.tsx
CHANGED
|
@@ -6,6 +6,7 @@ import { type LinkProps } from './types';
|
|
|
6
6
|
import resetStyles from '../utils/css/resets.module.css';
|
|
7
7
|
import focusStyles from '../utils/css/focus.module.css';
|
|
8
8
|
import styles from './style.module.css';
|
|
9
|
+
import defenseStyles from '../utils/css/global-css-defense.module.css';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* A styled anchor element with support for semantic color tones and an
|
|
@@ -39,6 +40,7 @@ export const Link = forwardRef< HTMLAnchorElement, LinkProps >( function Link(
|
|
|
39
40
|
ref,
|
|
40
41
|
props: mergeProps< 'a' >( props, {
|
|
41
42
|
className: clsx(
|
|
43
|
+
defenseStyles.a,
|
|
42
44
|
resetStyles[ 'box-sizing' ],
|
|
43
45
|
focusStyles[ 'outset-ring--focus' ],
|
|
44
46
|
variant !== 'unstyled' && styles.link,
|
|
@@ -9,28 +9,38 @@
|
|
|
9
9
|
/* Brand tone */
|
|
10
10
|
.is-brand,
|
|
11
11
|
.is-brand:visited {
|
|
12
|
+
--_gcd-a-color: var(--wpds-color-fg-interactive-brand);
|
|
13
|
+
|
|
12
14
|
color: var(--wpds-color-fg-interactive-brand);
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
.is-brand:hover,
|
|
16
18
|
.is-brand:active {
|
|
19
|
+
--_gcd-a-color: var(--wpds-color-fg-interactive-brand-active);
|
|
20
|
+
|
|
17
21
|
color: var(--wpds-color-fg-interactive-brand-active);
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
/* Neutral tone */
|
|
21
25
|
.is-neutral,
|
|
22
26
|
.is-neutral:visited {
|
|
27
|
+
--_gcd-a-color: var(--wpds-color-fg-interactive-neutral);
|
|
28
|
+
|
|
23
29
|
color: var(--wpds-color-fg-interactive-neutral);
|
|
24
30
|
text-decoration-color: var(--wpds-color-stroke-interactive-neutral);
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
.is-neutral:hover,
|
|
28
34
|
.is-neutral:active {
|
|
35
|
+
--_gcd-a-color: var(--wpds-color-fg-interactive-neutral-active);
|
|
36
|
+
|
|
29
37
|
color: var(--wpds-color-fg-interactive-neutral-active);
|
|
30
38
|
}
|
|
31
39
|
|
|
32
40
|
/* Unstyled variant */
|
|
33
41
|
.is-unstyled {
|
|
42
|
+
--_gcd-a-color: inherit;
|
|
43
|
+
|
|
34
44
|
color: inherit;
|
|
35
45
|
text-decoration: none;
|
|
36
46
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Popover as _Popover } from '@base-ui/react/popover';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { forwardRef } from '@wordpress/element';
|
|
4
|
+
import styles from './style.module.css';
|
|
5
|
+
import type { ArrowProps } from './types';
|
|
6
|
+
|
|
7
|
+
function DefaultArrowSvg( props: React.ComponentProps< 'svg' > ) {
|
|
8
|
+
return (
|
|
9
|
+
<svg
|
|
10
|
+
width="20"
|
|
11
|
+
height="10"
|
|
12
|
+
viewBox="0 0 20 10"
|
|
13
|
+
fill="none"
|
|
14
|
+
{ ...props }
|
|
15
|
+
>
|
|
16
|
+
<path
|
|
17
|
+
d="M20 10H0V8h1.465a4 4 0 0 0 2.676-1.027l5.19-4.388c.378-.341.96-.341 1.338 0l5.19 4.388A4 4 0 0 0 18.535 8H20z"
|
|
18
|
+
className={ styles[ 'arrow-fill' ] }
|
|
19
|
+
/>
|
|
20
|
+
<path
|
|
21
|
+
d="M10 3.097 4.81 7.486A5 5 0 0 1 1.465 8.77H0V8h1.465a4 4 0 0 0 2.676-1.027l5.19-4.388c.378-.341.96-.341 1.338 0l5.19 4.388A4 4 0 0 0 18.535 8H20v.77h-1.465a5 5 0 0 1-3.345-1.284z"
|
|
22
|
+
className={ styles[ 'arrow-stroke' ] }
|
|
23
|
+
/>
|
|
24
|
+
</svg>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Renders an optional arrow element that points toward the anchor.
|
|
30
|
+
*
|
|
31
|
+
* Must be placed inside `Popover.Popup`. The arrow automatically rotates
|
|
32
|
+
* to match the current placement side.
|
|
33
|
+
*/
|
|
34
|
+
const Arrow = forwardRef< HTMLDivElement, ArrowProps >( function PopoverArrow(
|
|
35
|
+
{ children, className, ...props },
|
|
36
|
+
ref
|
|
37
|
+
) {
|
|
38
|
+
return (
|
|
39
|
+
<_Popover.Arrow
|
|
40
|
+
ref={ ref }
|
|
41
|
+
className={ clsx( styles.arrow, className ) }
|
|
42
|
+
{ ...props }
|
|
43
|
+
>
|
|
44
|
+
{ children ?? <DefaultArrowSvg /> }
|
|
45
|
+
</_Popover.Arrow>
|
|
46
|
+
);
|
|
47
|
+
} );
|
|
48
|
+
|
|
49
|
+
export { Arrow };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Popover as _Popover } from '@base-ui/react/popover';
|
|
2
|
+
import { forwardRef } from '@wordpress/element';
|
|
3
|
+
import type { CloseProps } from './types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Renders a button that closes the popover when clicked.
|
|
7
|
+
*
|
|
8
|
+
* When the popover opens, initial focus skips this button in favor of
|
|
9
|
+
* the first interactive element inside the popup (unless `initialFocus`
|
|
10
|
+
* on `Popover.Popup` overrides this behavior).
|
|
11
|
+
*/
|
|
12
|
+
const Close = forwardRef< HTMLButtonElement, CloseProps >(
|
|
13
|
+
function PopoverClose( props, ref ) {
|
|
14
|
+
return (
|
|
15
|
+
<_Popover.Close
|
|
16
|
+
ref={ ref }
|
|
17
|
+
data-wp-ui-popover-close=""
|
|
18
|
+
{ ...props }
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export { Close };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createContext,
|
|
3
|
+
useCallback,
|
|
4
|
+
useContext,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
useRef,
|
|
8
|
+
} from '@wordpress/element';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Whether validation is enabled. This is a build-time constant that allows
|
|
12
|
+
* bundlers to tree-shake all validation code in production builds.
|
|
13
|
+
*/
|
|
14
|
+
const VALIDATION_ENABLED = process.env.NODE_ENV !== 'production';
|
|
15
|
+
|
|
16
|
+
type PopoverValidationContextType = {
|
|
17
|
+
registerTitle: ( element: HTMLElement | null ) => void;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const PopoverValidationContext = VALIDATION_ENABLED
|
|
21
|
+
? createContext< PopoverValidationContextType | null >( null )
|
|
22
|
+
: ( null as unknown as React.Context< PopoverValidationContextType | null > );
|
|
23
|
+
|
|
24
|
+
function usePopoverValidationContextDev() {
|
|
25
|
+
return useContext( PopoverValidationContext );
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function usePopoverValidationContextProd() {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Hook to access the popover validation context.
|
|
34
|
+
* Returns null in production or if not within a Popover.Popup.
|
|
35
|
+
*/
|
|
36
|
+
export const usePopoverValidationContext = VALIDATION_ENABLED
|
|
37
|
+
? usePopoverValidationContextDev
|
|
38
|
+
: usePopoverValidationContextProd;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Development-only provider that tracks whether Popover.Title is rendered.
|
|
42
|
+
*/
|
|
43
|
+
function PopoverValidationProviderDev( {
|
|
44
|
+
children,
|
|
45
|
+
}: {
|
|
46
|
+
children: React.ReactNode;
|
|
47
|
+
} ) {
|
|
48
|
+
const titleElementRef = useRef< HTMLElement | null >( null );
|
|
49
|
+
|
|
50
|
+
const registerTitle = useCallback( ( element: HTMLElement | null ) => {
|
|
51
|
+
titleElementRef.current = element;
|
|
52
|
+
}, [] );
|
|
53
|
+
|
|
54
|
+
const contextValue = useMemo(
|
|
55
|
+
() => ( { registerTitle } ),
|
|
56
|
+
[ registerTitle ]
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
useEffect( () => {
|
|
60
|
+
const titleElement = titleElementRef.current;
|
|
61
|
+
|
|
62
|
+
if ( ! titleElement ) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
'Popover: Missing <Popover.Title>. ' +
|
|
65
|
+
'For accessibility, every popover requires a title. ' +
|
|
66
|
+
'If needed, the title can be visually hidden but must not be omitted.'
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const textContent = titleElement.textContent?.trim();
|
|
71
|
+
if ( ! textContent ) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
'Popover: <Popover.Title> cannot be empty. ' +
|
|
74
|
+
'Provide meaningful text content for the popover title.'
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}, [] );
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<PopoverValidationContext.Provider value={ contextValue }>
|
|
81
|
+
{ children }
|
|
82
|
+
</PopoverValidationContext.Provider>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function PopoverValidationProviderProd( {
|
|
87
|
+
children,
|
|
88
|
+
}: {
|
|
89
|
+
children: React.ReactNode;
|
|
90
|
+
} ) {
|
|
91
|
+
return <>{ children }</>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Provider component that validates Popover.Title presence in development mode.
|
|
96
|
+
* In production, this component is a no-op and just renders children.
|
|
97
|
+
*/
|
|
98
|
+
export const PopoverValidationProvider = VALIDATION_ENABLED
|
|
99
|
+
? PopoverValidationProviderDev
|
|
100
|
+
: PopoverValidationProviderProd;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Popover as _Popover } from '@base-ui/react/popover';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { forwardRef } from '@wordpress/element';
|
|
4
|
+
import { Text } from '../text';
|
|
5
|
+
import styles from './style.module.css';
|
|
6
|
+
import type { DescriptionProps } from './types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Renders an optional paragraph that describes the popover content.
|
|
10
|
+
*
|
|
11
|
+
* The rendered element is linked to the popup via `aria-describedby`.
|
|
12
|
+
* Uses the `body-md` text variant by default.
|
|
13
|
+
*/
|
|
14
|
+
const Description = forwardRef< HTMLParagraphElement, DescriptionProps >(
|
|
15
|
+
function PopoverDescription(
|
|
16
|
+
{ className, children, render, ...props },
|
|
17
|
+
ref
|
|
18
|
+
) {
|
|
19
|
+
return (
|
|
20
|
+
<Text
|
|
21
|
+
ref={ ref }
|
|
22
|
+
variant="body-md"
|
|
23
|
+
render={
|
|
24
|
+
<_Popover.Description render={ render } { ...props } />
|
|
25
|
+
}
|
|
26
|
+
className={ clsx( styles.description, className ) }
|
|
27
|
+
>
|
|
28
|
+
{ children }
|
|
29
|
+
</Text>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
export { Description };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Arrow } from './arrow';
|
|
2
|
+
import { Close } from './close';
|
|
3
|
+
import { Description } from './description';
|
|
4
|
+
import { Popup } from './popup';
|
|
5
|
+
import { Root } from './root';
|
|
6
|
+
import { Title } from './title';
|
|
7
|
+
import { Trigger } from './trigger';
|
|
8
|
+
|
|
9
|
+
export { Arrow, Close, Description, Popup, Root, Title, Trigger };
|