@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
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Popover as _Popover } from '@base-ui/react/popover';
|
|
2
|
+
import { useMergeRefs } from '@wordpress/compose';
|
|
3
|
+
import { forwardRef, useLayoutEffect, useRef } from '@wordpress/element';
|
|
4
|
+
import { Text } from '../text';
|
|
5
|
+
import { usePopoverValidationContext } from './context';
|
|
6
|
+
import type { TitleProps } from './types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Renders a heading that labels the popover for accessibility.
|
|
10
|
+
*
|
|
11
|
+
* **Required** — every popover must include a `Popover.Title`, even if
|
|
12
|
+
* visually hidden. The rendered element is linked to the popup via
|
|
13
|
+
* `aria-labelledby`. Uses the `heading-xl` text variant, matching Dialog.
|
|
14
|
+
*
|
|
15
|
+
* To visually hide the title while keeping it accessible, wrap it with
|
|
16
|
+
* `VisuallyHidden` using the `render` prop:
|
|
17
|
+
*
|
|
18
|
+
* ```jsx
|
|
19
|
+
* <VisuallyHidden render={ <Popover.Title /> }>
|
|
20
|
+
* Accessible title text
|
|
21
|
+
* </VisuallyHidden>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
const Title = forwardRef< HTMLHeadingElement, TitleProps >(
|
|
25
|
+
function PopoverTitle(
|
|
26
|
+
{ className, children, render, ...props },
|
|
27
|
+
forwardedRef
|
|
28
|
+
) {
|
|
29
|
+
const validationContext = usePopoverValidationContext();
|
|
30
|
+
const internalRef = useRef< HTMLHeadingElement >( null );
|
|
31
|
+
const mergedRef = useMergeRefs( [ internalRef, forwardedRef ] );
|
|
32
|
+
|
|
33
|
+
useLayoutEffect( () => {
|
|
34
|
+
validationContext?.registerTitle( internalRef.current );
|
|
35
|
+
}, [ validationContext ] );
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<Text
|
|
39
|
+
ref={ mergedRef }
|
|
40
|
+
variant="heading-xl"
|
|
41
|
+
render={ <_Popover.Title render={ render } { ...props } /> }
|
|
42
|
+
className={ className }
|
|
43
|
+
>
|
|
44
|
+
{ children }
|
|
45
|
+
</Text>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
export { Title };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Popover as _Popover } from '@base-ui/react/popover';
|
|
2
|
+
import { forwardRef } from '@wordpress/element';
|
|
3
|
+
import type { TriggerProps } from './types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Renders a button that toggles the popover popup when clicked.
|
|
7
|
+
*
|
|
8
|
+
* Renders as a `<button>` by default. Also supports hover-triggered
|
|
9
|
+
* popovers via the `openOnHover`, `delay`, and `closeDelay` props.
|
|
10
|
+
*/
|
|
11
|
+
const Trigger = forwardRef< HTMLButtonElement, TriggerProps >(
|
|
12
|
+
function PopoverTrigger( props, ref ) {
|
|
13
|
+
return <_Popover.Trigger ref={ ref } { ...props } />;
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
export { Trigger };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { Popover as _Popover } from '@base-ui/react/popover';
|
|
3
|
+
import type { ComponentProps } from '../utils/types';
|
|
4
|
+
|
|
5
|
+
export interface RootProps
|
|
6
|
+
extends Pick<
|
|
7
|
+
_Popover.Root.Props,
|
|
8
|
+
'open' | 'onOpenChange' | 'defaultOpen' | 'modal'
|
|
9
|
+
> {
|
|
10
|
+
/**
|
|
11
|
+
* The popover sub-components (`Popover.Trigger`, `Popover.Popup`, etc.).
|
|
12
|
+
*/
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TriggerProps
|
|
17
|
+
extends ComponentProps< 'button' >,
|
|
18
|
+
Pick< _Popover.Trigger.Props, 'openOnHover' | 'delay' | 'closeDelay' > {
|
|
19
|
+
/**
|
|
20
|
+
* The content to be rendered inside the component.
|
|
21
|
+
*/
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* `Popover.Popup` maps to two Base UI elements internally: the
|
|
27
|
+
* **Positioner** (outer, handles fixed positioning and z-index) and the
|
|
28
|
+
* **Popup** (inner, holds content and visual styles).
|
|
29
|
+
*
|
|
30
|
+
* `style` and `className` are forwarded to the **Positioner** so that
|
|
31
|
+
* z-index overrides (`--wp-ui-popover-z-index`) and Base UI CSS variables
|
|
32
|
+
* (`--available-height`, `--available-width`) work correctly. All other
|
|
33
|
+
* HTML attributes are forwarded to the inner **Popup** element.
|
|
34
|
+
*/
|
|
35
|
+
export interface PopupProps
|
|
36
|
+
extends ComponentProps< 'div' >,
|
|
37
|
+
Pick<
|
|
38
|
+
_Popover.Positioner.Props,
|
|
39
|
+
| 'align'
|
|
40
|
+
| 'alignOffset'
|
|
41
|
+
| 'anchor'
|
|
42
|
+
| 'arrowPadding'
|
|
43
|
+
| 'collisionAvoidance'
|
|
44
|
+
| 'collisionBoundary'
|
|
45
|
+
| 'collisionPadding'
|
|
46
|
+
| 'side'
|
|
47
|
+
| 'sideOffset'
|
|
48
|
+
| 'sticky'
|
|
49
|
+
>,
|
|
50
|
+
Pick< _Popover.Popup.Props, 'initialFocus' | 'finalFocus' > {
|
|
51
|
+
/**
|
|
52
|
+
* Whether to render a backdrop overlay behind the popover.
|
|
53
|
+
*
|
|
54
|
+
* Typically used with `modal` to signal that interaction with the rest
|
|
55
|
+
* of the page is blocked. The backdrop is a semi-transparent dark overlay.
|
|
56
|
+
*
|
|
57
|
+
* @default false
|
|
58
|
+
*/
|
|
59
|
+
backdrop?: boolean;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The content to be rendered inside the component.
|
|
63
|
+
*/
|
|
64
|
+
children?: ReactNode;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A parent element to render the portal into.
|
|
68
|
+
*
|
|
69
|
+
* Useful for cross-document rendering, such as rendering a popover
|
|
70
|
+
* in a parent document when the trigger is inside an iframe.
|
|
71
|
+
*/
|
|
72
|
+
container?: _Popover.Portal.Props[ 'container' ];
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The visual style variant of the popup.
|
|
76
|
+
*
|
|
77
|
+
* - `'default'` — standard surface styling with background, padding,
|
|
78
|
+
* border radius, and shadow.
|
|
79
|
+
* - `'unstyled'` — no visual treatment; useful as a blank positioning
|
|
80
|
+
* container for fully custom content.
|
|
81
|
+
*
|
|
82
|
+
* @default 'default'
|
|
83
|
+
*/
|
|
84
|
+
variant?: 'default' | 'unstyled';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface ArrowProps extends ComponentProps< 'div' > {
|
|
88
|
+
/**
|
|
89
|
+
* Custom arrow visuals to render inside the positioned container.
|
|
90
|
+
*/
|
|
91
|
+
children?: ReactNode;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface TitleProps extends ComponentProps< 'h2' > {
|
|
95
|
+
/**
|
|
96
|
+
* The title content to be rendered.
|
|
97
|
+
*/
|
|
98
|
+
children?: ReactNode;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface DescriptionProps extends ComponentProps< 'p' > {
|
|
102
|
+
/**
|
|
103
|
+
* The description content to be rendered.
|
|
104
|
+
*/
|
|
105
|
+
children?: ReactNode;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface CloseProps extends ComponentProps< 'button' > {
|
|
109
|
+
/**
|
|
110
|
+
* The content to be rendered inside the component.
|
|
111
|
+
*/
|
|
112
|
+
children?: ReactNode;
|
|
113
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable jsx-a11y/heading-has-content */
|
|
2
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
2
|
import { Text } from '../index';
|
|
4
3
|
import { Stack } from '../../stack';
|
|
@@ -18,6 +17,10 @@ export const Default: Story = {
|
|
|
18
17
|
},
|
|
19
18
|
};
|
|
20
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Important: Setting the `variant` prop to a `heading` variant will not automatically render a heading element.
|
|
22
|
+
* Use the `render` prop to render a heading element with the appropriate level.
|
|
23
|
+
*/
|
|
21
24
|
export const AllVariants: Story = {
|
|
22
25
|
render: () => (
|
|
23
26
|
<Stack
|
|
@@ -65,4 +68,3 @@ export const WithRenderProp: Story = {
|
|
|
65
68
|
</Stack>
|
|
66
69
|
),
|
|
67
70
|
};
|
|
68
|
-
/* eslint-enable jsx-a11y/heading-has-content */
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
@layer wp-ui-utilities, wp-ui-components, wp-ui-compositions, wp-ui-overrides;
|
|
2
2
|
|
|
3
3
|
@layer wp-ui-components {
|
|
4
|
+
.text {
|
|
5
|
+
margin: 0;
|
|
6
|
+
}
|
|
7
|
+
|
|
4
8
|
.heading-2xl {
|
|
9
|
+
--_gcd-heading-font-size: var(--wpds-font-size-2xl);
|
|
10
|
+
|
|
5
11
|
font-family: var(--wpds-font-family-heading);
|
|
6
12
|
font-size: var(--wpds-font-size-2xl);
|
|
7
13
|
line-height: var(--wpds-font-line-height-2xl);
|
|
@@ -9,6 +15,8 @@
|
|
|
9
15
|
}
|
|
10
16
|
|
|
11
17
|
.heading-xl {
|
|
18
|
+
--_gcd-heading-font-size: var(--wpds-font-size-xl);
|
|
19
|
+
|
|
12
20
|
font-family: var(--wpds-font-family-heading);
|
|
13
21
|
font-size: var(--wpds-font-size-xl);
|
|
14
22
|
line-height: var(--wpds-font-line-height-md);
|
|
@@ -16,6 +24,8 @@
|
|
|
16
24
|
}
|
|
17
25
|
|
|
18
26
|
.heading-lg {
|
|
27
|
+
--_gcd-heading-font-size: var(--wpds-font-size-lg);
|
|
28
|
+
|
|
19
29
|
font-family: var(--wpds-font-family-heading);
|
|
20
30
|
font-size: var(--wpds-font-size-lg);
|
|
21
31
|
line-height: var(--wpds-font-line-height-sm);
|
|
@@ -23,6 +33,8 @@
|
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
.heading-md {
|
|
36
|
+
--_gcd-heading-font-size: var(--wpds-font-size-md);
|
|
37
|
+
|
|
26
38
|
font-family: var(--wpds-font-family-heading);
|
|
27
39
|
font-size: var(--wpds-font-size-md);
|
|
28
40
|
line-height: var(--wpds-font-line-height-sm);
|
|
@@ -30,6 +42,8 @@
|
|
|
30
42
|
}
|
|
31
43
|
|
|
32
44
|
.heading-sm {
|
|
45
|
+
--_gcd-heading-font-size: var(--wpds-font-size-xs);
|
|
46
|
+
|
|
33
47
|
font-family: var(--wpds-font-family-heading);
|
|
34
48
|
font-size: var(--wpds-font-size-xs);
|
|
35
49
|
line-height: var(--wpds-font-line-height-xs);
|
|
@@ -38,6 +52,9 @@
|
|
|
38
52
|
}
|
|
39
53
|
|
|
40
54
|
.body-xl {
|
|
55
|
+
--_gcd-p-font-size: var(--wpds-font-size-xl);
|
|
56
|
+
--_gcd-p-line-height: var(--wpds-font-line-height-xl);
|
|
57
|
+
|
|
41
58
|
font-family: var(--wpds-font-family-body);
|
|
42
59
|
font-size: var(--wpds-font-size-xl);
|
|
43
60
|
line-height: var(--wpds-font-line-height-xl);
|
|
@@ -45,6 +62,9 @@
|
|
|
45
62
|
}
|
|
46
63
|
|
|
47
64
|
.body-lg {
|
|
65
|
+
--_gcd-p-font-size: var(--wpds-font-size-lg);
|
|
66
|
+
--_gcd-p-line-height: var(--wpds-font-line-height-md);
|
|
67
|
+
|
|
48
68
|
font-family: var(--wpds-font-family-body);
|
|
49
69
|
font-size: var(--wpds-font-size-lg);
|
|
50
70
|
line-height: var(--wpds-font-line-height-md);
|
|
@@ -52,6 +72,9 @@
|
|
|
52
72
|
}
|
|
53
73
|
|
|
54
74
|
.body-md {
|
|
75
|
+
--_gcd-p-font-size: var(--wpds-font-size-md);
|
|
76
|
+
--_gcd-p-line-height: var(--wpds-font-line-height-sm);
|
|
77
|
+
|
|
55
78
|
font-family: var(--wpds-font-family-body);
|
|
56
79
|
font-size: var(--wpds-font-size-md);
|
|
57
80
|
line-height: var(--wpds-font-line-height-sm);
|
|
@@ -59,6 +82,9 @@
|
|
|
59
82
|
}
|
|
60
83
|
|
|
61
84
|
.body-sm {
|
|
85
|
+
--_gcd-p-font-size: var(--wpds-font-size-sm);
|
|
86
|
+
--_gcd-p-line-height: var(--wpds-font-line-height-xs);
|
|
87
|
+
|
|
62
88
|
font-family: var(--wpds-font-family-body);
|
|
63
89
|
font-size: var(--wpds-font-size-sm);
|
|
64
90
|
line-height: var(--wpds-font-line-height-xs);
|
|
@@ -34,10 +34,7 @@ describe( 'Text', () => {
|
|
|
34
34
|
} );
|
|
35
35
|
|
|
36
36
|
it( 'supports the render prop', () => {
|
|
37
|
-
render(
|
|
38
|
-
// eslint-disable-next-line jsx-a11y/heading-has-content
|
|
39
|
-
<Text render={ <h2 /> }>Section title</Text>
|
|
40
|
-
);
|
|
37
|
+
render( <Text render={ <h2 /> }>Section title</Text> );
|
|
41
38
|
|
|
42
39
|
expect(
|
|
43
40
|
screen.getByRole( 'heading', { level: 2, name: 'Section title' } )
|
package/src/text/text.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import clsx from 'clsx';
|
|
|
3
3
|
import { forwardRef } from '@wordpress/element';
|
|
4
4
|
import { type TextProps } from './types';
|
|
5
5
|
import styles from './style.module.css';
|
|
6
|
+
import defenseStyles from '../utils/css/global-css-defense.module.css';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* A text component for rendering content with predefined typographic variants.
|
|
@@ -17,7 +18,13 @@ export const Text = forwardRef< HTMLSpanElement, TextProps >( function Text(
|
|
|
17
18
|
defaultTagName: 'span',
|
|
18
19
|
ref,
|
|
19
20
|
props: mergeProps< 'span' >( props, {
|
|
20
|
-
className: clsx(
|
|
21
|
+
className: clsx(
|
|
22
|
+
styles.text,
|
|
23
|
+
variant.startsWith( 'heading-' ) && defenseStyles.heading,
|
|
24
|
+
variant.startsWith( 'body-' ) && defenseStyles.p,
|
|
25
|
+
styles[ variant ],
|
|
26
|
+
className
|
|
27
|
+
),
|
|
21
28
|
} ),
|
|
22
29
|
} );
|
|
23
30
|
|
|
@@ -18,7 +18,10 @@
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
.description {
|
|
21
|
-
|
|
21
|
+
--_gcd-p-font-size: var(--wpds-font-size-sm);
|
|
22
|
+
--_gcd-p-line-height: var(--wpds-font-line-height-xs);
|
|
23
|
+
--_gcd-p-margin: 0;
|
|
24
|
+
|
|
22
25
|
font-family: var(--wpds-font-family-body);
|
|
23
26
|
font-size: var(--wpds-font-size-sm);
|
|
24
27
|
line-height: var(--wpds-font-line-height-xs);
|
|
@@ -9,14 +9,14 @@
|
|
|
9
9
|
.outset-ring--focus-within-visible,
|
|
10
10
|
.outset-ring--focus-parent-visible {
|
|
11
11
|
@media not ( prefers-reduced-motion ) {
|
|
12
|
+
--_gcd-a-transition: outline 0.1s ease-out;
|
|
13
|
+
|
|
12
14
|
transition: outline 0.1s ease-out;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
/* Outline width must be kept at 0 even with a transparent color,
|
|
16
18
|
or else the outline will be visible in forced-colors mode. */
|
|
17
|
-
outline
|
|
18
|
-
outline-style: solid;
|
|
19
|
-
outline-color: transparent;
|
|
19
|
+
outline: 0 solid transparent;
|
|
20
20
|
outline-offset: 1px;
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -27,7 +27,9 @@
|
|
|
27
27
|
.outset-ring--focus-within-except-active:focus-within:not(:has(:active)),
|
|
28
28
|
.outset-ring--focus-within-visible:focus-within:has(:focus-visible),
|
|
29
29
|
:focus-visible .outset-ring--focus-parent-visible {
|
|
30
|
-
outline
|
|
31
|
-
outline
|
|
30
|
+
--_gcd-a-outline: var(--wpds-border-width-focus) solid var(--wpds-color-stroke-focus-brand);
|
|
31
|
+
--_gcd-div-outline: var(--wpds-border-width-focus) solid var(--wpds-color-stroke-focus-brand);
|
|
32
|
+
|
|
33
|
+
outline: var(--wpds-border-width-focus) solid var(--wpds-color-stroke-focus-brand);
|
|
32
34
|
}
|
|
33
35
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Unlayered defense against wp-admin global CSS (common.css, forms.css).
|
|
3
|
+
*
|
|
4
|
+
* CSS cascade layers always lose to unlayered styles, so @wordpress/ui's
|
|
5
|
+
* layered component styles get overridden by wp-admin's broad bare-element
|
|
6
|
+
* selectors. This file provides unlayered, class-scoped defenses that
|
|
7
|
+
* restore control to the component.
|
|
8
|
+
*
|
|
9
|
+
* Mechanism (custom property bridge):
|
|
10
|
+
* .input { font-size: var(--_gcd-input-font-size, inherit); }
|
|
11
|
+
*
|
|
12
|
+
* - The class selector beats admin bare-element selectors in specificity.
|
|
13
|
+
* - Each property reads a custom property. The fallback values are what
|
|
14
|
+
* makes sense for @wordpress/ui, to minimize the number of overrides
|
|
15
|
+
* in each individual component stylesheet.
|
|
16
|
+
* - Component CSS modules only need to define the custom properties for
|
|
17
|
+
* the specific properties they want to override.
|
|
18
|
+
* - Custom property definitions aren't suppressed by cascade layers, so the
|
|
19
|
+
* layered value propagates through to the unlayered declaration.
|
|
20
|
+
*
|
|
21
|
+
* Usage: apply the element-specific class directly to each element that
|
|
22
|
+
* needs defense (e.g. defenseStyles.input on an <input>).
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
* ==========================================================================
|
|
27
|
+
* forms.css defense - https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-admin/css/forms.css
|
|
28
|
+
* ==========================================================================
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
.button {
|
|
32
|
+
box-sizing: var(--_gcd-button-box-sizing, border-box);
|
|
33
|
+
font-family: var(--_gcd-button-font-family, inherit);
|
|
34
|
+
font-size: var(--_gcd-button-font-size, inherit);
|
|
35
|
+
font-weight: var(--_gcd-button-font-weight, inherit);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.input {
|
|
39
|
+
box-sizing: var(--_gcd-input-box-sizing, border-box);
|
|
40
|
+
font-family: var(--_gcd-input-font-family, inherit);
|
|
41
|
+
font-size: var(--_gcd-input-font-size, inherit);
|
|
42
|
+
font-weight: var(--_gcd-input-font-weight, inherit);
|
|
43
|
+
margin: var(--_gcd-input-margin, 0);
|
|
44
|
+
|
|
45
|
+
/* Also targets textarea elements, which the `Input` primitive can render as. We combine these textarea defenses
|
|
46
|
+
into the input defenses to minimize the number of tokens, but they should be split if it ever becomes necessary. */
|
|
47
|
+
&:is(textarea, [type="text"], [type="password"], [type="color"], [type="date"], [type="datetime"], [type="datetime-local"], [type="email"], [type="month"], [type="number"], [type="search"], [type="tel"], [type="time"], [type="url"], [type="week"]) {
|
|
48
|
+
box-shadow: var(--_gcd-input-box-shadow, 0 0 0 transparent);
|
|
49
|
+
border-radius: var(--_gcd-input-border-radius, 0);
|
|
50
|
+
border: var(--_gcd-input-border, none);
|
|
51
|
+
background-color: var(--_gcd-input-background-color, transparent);
|
|
52
|
+
color: var(--_gcd-input-color, var(--wpds-color-fg-interactive-neutral));
|
|
53
|
+
|
|
54
|
+
&:focus {
|
|
55
|
+
border-color: var(--_gcd-input-border-color-focus, var(--wp-admin-theme-color));
|
|
56
|
+
box-shadow: var(--_gcd-input-box-shadow-focus, none);
|
|
57
|
+
outline: var(--_gcd-input-outline-focus, none);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
&:disabled {
|
|
61
|
+
background: var(--_gcd-input-background-disabled, transparent);
|
|
62
|
+
border-color: var(--_gcd-input-border-color-disabled, transparent);
|
|
63
|
+
box-shadow: var(--_gcd-input-box-shadow-disabled, none);
|
|
64
|
+
color: var(--_gcd-input-color-disabled, var(--wpds-color-fg-interactive-neutral-disabled));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
&::placeholder {
|
|
68
|
+
color: var(--_gcd-input-placeholder-color, var(--wpds-color-fg-interactive-neutral-disabled));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
&:is(textarea, [type="text"], [type="password"], [type="date"], [type="datetime"], [type="datetime-local"], [type="email"], [type="month"], [type="number"], [type="search"], [type="tel"], [type="time"], [type="url"], [type="week"]) {
|
|
73
|
+
padding: var(--_gcd-input-padding, 0);
|
|
74
|
+
line-height: var(--_gcd-input-line-height, inherit);
|
|
75
|
+
min-height: var(--_gcd-input-min-height, auto);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.textarea {
|
|
80
|
+
box-sizing: var(--_gcd-textarea-box-sizing, border-box);
|
|
81
|
+
overflow: var(--_gcd-textarea-overflow, auto);
|
|
82
|
+
resize: var(--_gcd-textarea-resize, block);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/*
|
|
86
|
+
* ==========================================================================
|
|
87
|
+
* common.css defense - https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-admin/css/common.css
|
|
88
|
+
* ==========================================================================
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
.div {
|
|
92
|
+
outline: var(--_gcd-div-outline, 0 solid transparent);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Narrowed down to p elements only, to support element multiplicity of Text component. */
|
|
96
|
+
p.p {
|
|
97
|
+
font-size: var(--_gcd-p-font-size, 13px);
|
|
98
|
+
line-height: var(--_gcd-p-line-height, 1.5);
|
|
99
|
+
margin: var(--_gcd-p-margin, 0);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Narrowed down to h[1-6] elements only, to support element multiplicity of Text component. */
|
|
103
|
+
:is(h1, h2, h3, h4, h5, h6).heading {
|
|
104
|
+
color: var(--_gcd-heading-color, var(--wpds-color-fg-content-neutral));
|
|
105
|
+
font-size: var(--_gcd-heading-font-size, inherit);
|
|
106
|
+
font-weight: var(--_gcd-heading-font-weight, var(--wpds-font-weight-medium));
|
|
107
|
+
margin: var(--_gcd-heading-margin, 0);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.a,
|
|
111
|
+
.a:is(:hover, :focus, :active) {
|
|
112
|
+
outline: var(--_gcd-a-outline, 0 solid transparent);
|
|
113
|
+
color: var(--_gcd-a-color, inherit);
|
|
114
|
+
box-shadow: var(--_gcd-a-box-shadow, none);
|
|
115
|
+
border-radius: var(--_gcd-a-border-radius, 0);
|
|
116
|
+
transition: var(--_gcd-a-transition, none);
|
|
117
|
+
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Popover as _Popover } from '@base-ui/react/popover';
|
|
2
2
|
import { useMemo, useRef } from '@wordpress/element';
|
|
3
3
|
import { tabbable } from 'tabbable';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* The `initialFocus` type shared by Base UI overlay popups (Dialog, Popover,
|
|
7
|
+
* AlertDialog, etc.). We derive it from `Popover.Popup.Props` here, but it
|
|
8
|
+
* is identical across all overlay components.
|
|
8
9
|
*/
|
|
9
|
-
type InitialFocus =
|
|
10
|
+
type InitialFocus = _Popover.Popup.Props[ 'initialFocus' ];
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Options matching Base UI's internal tabbable configuration.
|