@wordpress/ui 0.8.0 → 0.9.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/README.md +106 -0
- package/build/badge/badge.cjs +3 -3
- package/build/badge/badge.cjs.map +2 -2
- package/build/button/button.cjs +7 -7
- package/build/button/button.cjs.map +2 -2
- package/build/card/content.cjs +54 -0
- package/build/card/content.cjs.map +7 -0
- package/build/card/full-bleed.cjs +57 -0
- package/build/card/full-bleed.cjs.map +7 -0
- package/build/card/header.cjs +54 -0
- package/build/card/header.cjs.map +7 -0
- package/build/card/index.cjs +43 -0
- package/build/card/index.cjs.map +7 -0
- package/build/card/root.cjs +73 -0
- package/build/card/root.cjs.map +7 -0
- package/build/card/title.cjs +55 -0
- package/build/card/title.cjs.map +7 -0
- package/build/card/types.cjs +19 -0
- package/build/card/types.cjs.map +7 -0
- package/build/collapsible/index.cjs +37 -0
- package/build/collapsible/index.cjs.map +7 -0
- package/build/collapsible/panel.cjs +38 -0
- package/build/collapsible/panel.cjs.map +7 -0
- package/build/collapsible/root.cjs +38 -0
- package/build/collapsible/root.cjs.map +7 -0
- package/build/collapsible/trigger.cjs +38 -0
- package/build/collapsible/trigger.cjs.map +7 -0
- package/build/collapsible/types.cjs +19 -0
- package/build/collapsible/types.cjs.map +7 -0
- package/build/collapsible-card/content.cjs +77 -0
- package/build/collapsible-card/content.cjs.map +7 -0
- package/build/collapsible-card/header.cjs +102 -0
- package/build/collapsible-card/header.cjs.map +7 -0
- package/build/collapsible-card/index.cjs +37 -0
- package/build/collapsible-card/index.cjs.map +7 -0
- package/build/collapsible-card/root.cjs +56 -0
- package/build/collapsible-card/root.cjs.map +7 -0
- package/build/collapsible-card/types.cjs +19 -0
- package/build/collapsible-card/types.cjs.map +7 -0
- package/build/dialog/footer.cjs +3 -3
- package/build/dialog/footer.cjs.map +2 -2
- package/build/dialog/header.cjs +3 -3
- package/build/dialog/header.cjs.map +2 -2
- package/build/dialog/popup.cjs +3 -3
- package/build/dialog/popup.cjs.map +2 -2
- package/build/dialog/title.cjs +3 -3
- package/build/dialog/title.cjs.map +2 -2
- package/build/dialog/types.cjs.map +1 -1
- package/build/form/primitives/field/label.cjs +6 -1
- package/build/form/primitives/field/label.cjs.map +2 -2
- package/build/form/primitives/field/types.cjs.map +1 -1
- package/build/form/primitives/fieldset/legend.cjs +5 -1
- package/build/form/primitives/fieldset/legend.cjs.map +2 -2
- package/build/form/primitives/fieldset/types.cjs.map +1 -1
- package/build/form/primitives/input/input.cjs +4 -4
- package/build/form/primitives/input/input.cjs.map +2 -2
- package/build/form/primitives/input-layout/slot.cjs +3 -2
- package/build/form/primitives/input-layout/slot.cjs.map +2 -2
- package/build/form/primitives/select/item.cjs +3 -3
- package/build/form/primitives/select/item.cjs.map +2 -2
- package/build/form/primitives/select/popup.cjs +3 -3
- package/build/form/primitives/select/popup.cjs.map +2 -2
- package/build/form/primitives/select/trigger.cjs +7 -7
- package/build/form/primitives/select/trigger.cjs.map +2 -2
- package/build/index.cjs +13 -0
- package/build/index.cjs.map +2 -2
- package/build/link/index.cjs +31 -0
- package/build/link/index.cjs.map +7 -0
- package/build/link/link.cjs +125 -0
- package/build/link/link.cjs.map +7 -0
- package/build/link/types.cjs +19 -0
- package/build/link/types.cjs.map +7 -0
- package/build/notice/action-button.cjs +3 -3
- package/build/notice/action-button.cjs.map +2 -2
- package/build/notice/action-link.cjs +17 -18
- package/build/notice/action-link.cjs.map +2 -2
- package/build/notice/actions.cjs +3 -3
- package/build/notice/actions.cjs.map +2 -2
- package/build/notice/close-icon.cjs +3 -3
- package/build/notice/close-icon.cjs.map +2 -2
- package/build/notice/description.cjs +26 -15
- package/build/notice/description.cjs.map +3 -3
- package/build/notice/root.cjs +3 -3
- package/build/notice/root.cjs.map +2 -2
- package/build/notice/title.cjs +26 -12
- package/build/notice/title.cjs.map +3 -3
- package/build/notice/types.cjs.map +1 -1
- package/build/tabs/list.cjs +3 -3
- package/build/tabs/list.cjs.map +2 -2
- package/build/tabs/panel.cjs +3 -3
- package/build/tabs/panel.cjs.map +2 -2
- package/build/tabs/tab.cjs +3 -3
- package/build/tabs/tab.cjs.map +2 -2
- package/build/text/index.cjs +31 -0
- package/build/text/index.cjs.map +7 -0
- package/build/text/text.cjs +65 -0
- package/build/text/text.cjs.map +7 -0
- package/build/text/types.cjs +19 -0
- package/build/text/types.cjs.map +7 -0
- package/build/tooltip/popup.cjs +1 -1
- package/build/tooltip/popup.cjs.map +1 -1
- package/build/visually-hidden/visually-hidden.cjs +3 -3
- package/build/visually-hidden/visually-hidden.cjs.map +2 -2
- package/build-module/badge/badge.mjs +3 -3
- package/build-module/badge/badge.mjs.map +2 -2
- package/build-module/button/button.mjs +7 -7
- package/build-module/button/button.mjs.map +2 -2
- package/build-module/card/content.mjs +29 -0
- package/build-module/card/content.mjs.map +7 -0
- package/build-module/card/full-bleed.mjs +32 -0
- package/build-module/card/full-bleed.mjs.map +7 -0
- package/build-module/card/header.mjs +29 -0
- package/build-module/card/header.mjs.map +7 -0
- package/build-module/card/index.mjs +14 -0
- package/build-module/card/index.mjs.map +7 -0
- package/build-module/card/root.mjs +38 -0
- package/build-module/card/root.mjs.map +7 -0
- package/build-module/card/title.mjs +30 -0
- package/build-module/card/title.mjs.map +7 -0
- package/build-module/card/types.mjs +1 -0
- package/build-module/card/types.mjs.map +7 -0
- package/build-module/collapsible/index.mjs +10 -0
- package/build-module/collapsible/index.mjs.map +7 -0
- package/build-module/collapsible/panel.mjs +13 -0
- package/build-module/collapsible/panel.mjs.map +7 -0
- package/build-module/collapsible/root.mjs +13 -0
- package/build-module/collapsible/root.mjs.map +7 -0
- package/build-module/collapsible/trigger.mjs +13 -0
- package/build-module/collapsible/trigger.mjs.map +7 -0
- package/build-module/collapsible/types.mjs +1 -0
- package/build-module/collapsible/types.mjs.map +7 -0
- package/build-module/collapsible-card/content.mjs +42 -0
- package/build-module/collapsible-card/content.mjs.map +7 -0
- package/build-module/collapsible-card/header.mjs +67 -0
- package/build-module/collapsible-card/header.mjs.map +7 -0
- package/build-module/collapsible-card/index.mjs +10 -0
- package/build-module/collapsible-card/index.mjs.map +7 -0
- package/build-module/collapsible-card/root.mjs +21 -0
- package/build-module/collapsible-card/root.mjs.map +7 -0
- package/build-module/collapsible-card/types.mjs +1 -0
- package/build-module/collapsible-card/types.mjs.map +7 -0
- package/build-module/dialog/footer.mjs +3 -3
- package/build-module/dialog/footer.mjs.map +2 -2
- package/build-module/dialog/header.mjs +3 -3
- package/build-module/dialog/header.mjs.map +2 -2
- package/build-module/dialog/popup.mjs +3 -3
- package/build-module/dialog/popup.mjs.map +2 -2
- package/build-module/dialog/title.mjs +3 -3
- package/build-module/dialog/title.mjs.map +2 -2
- package/build-module/form/primitives/field/label.mjs +6 -1
- package/build-module/form/primitives/field/label.mjs.map +2 -2
- package/build-module/form/primitives/fieldset/legend.mjs +5 -1
- package/build-module/form/primitives/fieldset/legend.mjs.map +2 -2
- package/build-module/form/primitives/input/input.mjs +4 -4
- package/build-module/form/primitives/input/input.mjs.map +2 -2
- package/build-module/form/primitives/input-layout/slot.mjs +3 -2
- package/build-module/form/primitives/input-layout/slot.mjs.map +2 -2
- package/build-module/form/primitives/select/item.mjs +3 -3
- package/build-module/form/primitives/select/item.mjs.map +2 -2
- package/build-module/form/primitives/select/popup.mjs +3 -3
- package/build-module/form/primitives/select/popup.mjs.map +2 -2
- package/build-module/form/primitives/select/trigger.mjs +7 -7
- package/build-module/form/primitives/select/trigger.mjs.map +2 -2
- package/build-module/index.mjs +8 -0
- package/build-module/index.mjs.map +2 -2
- package/build-module/link/index.mjs +6 -0
- package/build-module/link/index.mjs.map +7 -0
- package/build-module/link/link.mjs +90 -0
- package/build-module/link/link.mjs.map +7 -0
- package/build-module/link/types.mjs +1 -0
- package/build-module/link/types.mjs.map +7 -0
- package/build-module/notice/action-button.mjs +3 -3
- package/build-module/notice/action-button.mjs.map +2 -2
- package/build-module/notice/action-link.mjs +17 -18
- package/build-module/notice/action-link.mjs.map +2 -2
- package/build-module/notice/actions.mjs +3 -3
- package/build-module/notice/actions.mjs.map +2 -2
- package/build-module/notice/close-icon.mjs +3 -3
- package/build-module/notice/close-icon.mjs.map +2 -2
- package/build-module/notice/description.mjs +16 -15
- package/build-module/notice/description.mjs.map +2 -2
- package/build-module/notice/root.mjs +3 -3
- package/build-module/notice/root.mjs.map +2 -2
- package/build-module/notice/title.mjs +16 -12
- package/build-module/notice/title.mjs.map +2 -2
- package/build-module/tabs/list.mjs +3 -3
- package/build-module/tabs/list.mjs.map +2 -2
- package/build-module/tabs/panel.mjs +3 -3
- package/build-module/tabs/panel.mjs.map +2 -2
- package/build-module/tabs/tab.mjs +3 -3
- package/build-module/tabs/tab.mjs.map +2 -2
- package/build-module/text/index.mjs +6 -0
- package/build-module/text/index.mjs.map +7 -0
- package/build-module/text/text.mjs +30 -0
- package/build-module/text/text.mjs.map +7 -0
- package/build-module/text/types.mjs +1 -0
- package/build-module/text/types.mjs.map +7 -0
- package/build-module/tooltip/popup.mjs +1 -1
- package/build-module/tooltip/popup.mjs.map +1 -1
- package/build-module/visually-hidden/visually-hidden.mjs +3 -3
- package/build-module/visually-hidden/visually-hidden.mjs.map +2 -2
- package/build-types/card/content.d.ts +6 -0
- package/build-types/card/content.d.ts.map +1 -0
- package/build-types/card/full-bleed.d.ts +9 -0
- package/build-types/card/full-bleed.d.ts.map +1 -0
- package/build-types/card/header.d.ts +7 -0
- package/build-types/card/header.d.ts.map +1 -0
- package/build-types/card/index.d.ts +7 -0
- package/build-types/card/index.d.ts.map +1 -0
- package/build-types/card/root.d.ts +23 -0
- package/build-types/card/root.d.ts.map +1 -0
- package/build-types/card/stories/index.story.d.ts +22 -0
- package/build-types/card/stories/index.story.d.ts.map +1 -0
- package/build-types/card/test/index.test.d.ts +2 -0
- package/build-types/card/test/index.test.d.ts.map +1 -0
- package/build-types/card/title.d.ts +7 -0
- package/build-types/card/title.d.ts.map +1 -0
- package/build-types/card/types.d.ts +34 -0
- package/build-types/card/types.d.ts.map +1 -0
- package/build-types/collapsible/index.d.ts +5 -0
- package/build-types/collapsible/index.d.ts.map +1 -0
- package/build-types/collapsible/panel.d.ts +16 -0
- package/build-types/collapsible/panel.d.ts.map +1 -0
- package/build-types/collapsible/root.d.ts +15 -0
- package/build-types/collapsible/root.d.ts.map +1 -0
- package/build-types/collapsible/stories/index.story.d.ts +18 -0
- package/build-types/collapsible/stories/index.story.d.ts.map +1 -0
- package/build-types/collapsible/test/index.test.d.ts +2 -0
- package/build-types/collapsible/test/index.test.d.ts.map +1 -0
- package/build-types/collapsible/trigger.d.ts +15 -0
- package/build-types/collapsible/trigger.d.ts.map +1 -0
- package/build-types/collapsible/types.d.ts +22 -0
- package/build-types/collapsible/types.d.ts.map +1 -0
- package/build-types/collapsible-card/content.d.ts +7 -0
- package/build-types/collapsible-card/content.d.ts.map +1 -0
- package/build-types/collapsible-card/header.d.ts +12 -0
- package/build-types/collapsible-card/header.d.ts.map +1 -0
- package/build-types/collapsible-card/index.d.ts +5 -0
- package/build-types/collapsible-card/index.d.ts.map +1 -0
- package/build-types/collapsible-card/root.d.ts +24 -0
- package/build-types/collapsible-card/root.d.ts.map +1 -0
- package/build-types/collapsible-card/stories/index.story.d.ts +28 -0
- package/build-types/collapsible-card/stories/index.story.d.ts.map +1 -0
- package/build-types/collapsible-card/test/index.test.d.ts +2 -0
- package/build-types/collapsible-card/test/index.test.d.ts.map +1 -0
- package/build-types/collapsible-card/types.d.ts +52 -0
- package/build-types/collapsible-card/types.d.ts.map +1 -0
- package/build-types/dialog/types.d.ts +3 -3
- package/build-types/form/primitives/field/label.d.ts +1 -0
- package/build-types/form/primitives/field/label.d.ts.map +1 -1
- package/build-types/form/primitives/field/stories/index.story.d.ts +5 -0
- package/build-types/form/primitives/field/stories/index.story.d.ts.map +1 -1
- package/build-types/form/primitives/field/types.d.ts +7 -0
- package/build-types/form/primitives/field/types.d.ts.map +1 -1
- package/build-types/form/primitives/fieldset/legend.d.ts +1 -0
- package/build-types/form/primitives/fieldset/legend.d.ts.map +1 -1
- package/build-types/form/primitives/fieldset/stories/index.story.d.ts +5 -0
- package/build-types/form/primitives/fieldset/stories/index.story.d.ts.map +1 -1
- package/build-types/form/primitives/fieldset/types.d.ts +7 -0
- package/build-types/form/primitives/fieldset/types.d.ts.map +1 -1
- package/build-types/form/primitives/input-layout/slot.d.ts.map +1 -1
- package/build-types/index.d.ts +5 -0
- package/build-types/index.d.ts.map +1 -1
- package/build-types/link/index.d.ts +2 -0
- package/build-types/link/index.d.ts.map +1 -0
- package/build-types/link/link.d.ts +7 -0
- package/build-types/link/link.d.ts.map +1 -0
- package/build-types/link/stories/index.story.d.ts +18 -0
- package/build-types/link/stories/index.story.d.ts.map +1 -0
- package/build-types/link/test/index.test.d.ts +2 -0
- package/build-types/link/test/index.test.d.ts.map +1 -0
- package/build-types/link/types.d.ts +33 -0
- package/build-types/link/types.d.ts.map +1 -0
- package/build-types/notice/action-link.d.ts +0 -2
- package/build-types/notice/action-link.d.ts.map +1 -1
- package/build-types/notice/description.d.ts +1 -1
- package/build-types/notice/description.d.ts.map +1 -1
- package/build-types/notice/title.d.ts.map +1 -1
- package/build-types/notice/types.d.ts +3 -2
- package/build-types/notice/types.d.ts.map +1 -1
- package/build-types/text/index.d.ts +2 -0
- package/build-types/text/index.d.ts.map +1 -0
- package/build-types/text/stories/index.story.d.ts +9 -0
- package/build-types/text/stories/index.story.d.ts.map +1 -0
- package/build-types/text/test/index.test.d.ts +2 -0
- package/build-types/text/test/index.test.d.ts.map +1 -0
- package/build-types/text/text.d.ts +7 -0
- package/build-types/text/text.d.ts.map +1 -0
- package/build-types/text/types.d.ts +15 -0
- package/build-types/text/types.d.ts.map +1 -0
- package/package.json +14 -14
- package/src/badge/style.module.css +5 -2
- package/src/button/style.module.css +2 -0
- package/src/card/content.tsx +20 -0
- package/src/card/full-bleed.tsx +26 -0
- package/src/card/header.tsx +21 -0
- package/src/card/index.ts +7 -0
- package/src/card/root.tsx +42 -0
- package/src/card/stories/index.story.tsx +128 -0
- package/src/card/style.module.css +48 -0
- package/src/card/test/index.test.tsx +96 -0
- package/src/card/title.tsx +22 -0
- package/src/card/types.ts +38 -0
- package/src/collapsible/index.ts +5 -0
- package/src/collapsible/panel.tsx +16 -0
- package/src/collapsible/root.tsx +15 -0
- package/src/collapsible/stories/index.story.tsx +108 -0
- package/src/collapsible/test/index.test.tsx +228 -0
- package/src/collapsible/trigger.tsx +15 -0
- package/src/collapsible/types.ts +24 -0
- package/src/collapsible-card/content.tsx +33 -0
- package/src/collapsible-card/header.tsx +53 -0
- package/src/collapsible-card/index.ts +5 -0
- package/src/collapsible-card/root.tsx +37 -0
- package/src/collapsible-card/stories/index.story.tsx +207 -0
- package/src/collapsible-card/style.module.css +78 -0
- package/src/collapsible-card/test/index.test.tsx +181 -0
- package/src/collapsible-card/types.ts +54 -0
- package/src/dialog/style.module.css +5 -5
- package/src/dialog/types.ts +3 -3
- package/src/form/primitives/field/label.tsx +9 -1
- package/src/form/primitives/field/stories/index.story.tsx +17 -0
- package/src/form/primitives/field/test/index.test.tsx +13 -0
- package/src/form/primitives/field/types.ts +7 -0
- package/src/form/primitives/fieldset/legend.tsx +8 -1
- package/src/form/primitives/fieldset/stories/index.story.tsx +20 -0
- package/src/form/primitives/fieldset/test/index.test.tsx +14 -0
- package/src/form/primitives/fieldset/types.ts +7 -0
- package/src/form/primitives/input-layout/slot.tsx +6 -2
- package/src/index.ts +5 -0
- package/src/link/index.ts +1 -0
- package/src/link/link.tsx +73 -0
- package/src/link/stories/index.story.tsx +92 -0
- package/src/link/style.module.css +68 -0
- package/src/link/test/index.test.tsx +93 -0
- package/src/link/types.ts +36 -0
- package/src/notice/action-link.tsx +12 -18
- package/src/notice/description.tsx +12 -14
- package/src/notice/style.module.css +9 -22
- package/src/notice/test/index.test.tsx +2 -2
- package/src/notice/title.tsx +11 -10
- package/src/notice/types.ts +3 -2
- package/src/tabs/style.module.css +1 -1
- package/src/text/index.ts +1 -0
- package/src/text/stories/index.story.tsx +68 -0
- package/src/text/style.module.css +67 -0
- package/src/text/test/index.test.tsx +46 -0
- package/src/text/text.tsx +25 -0
- package/src/text/types.ts +25 -0
- package/src/tooltip/popup.tsx +1 -1
- package/src/utils/css/focus.module.css +4 -2
- package/src/utils/css/item-popup.module.css +1 -0
- package/src/utils/css/select-trigger.module.css +1 -0
- package/src/visually-hidden/style.module.css +1 -0
- package/AGENTS.md +0 -9
- package/CLAUDE.md +0 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
@layer wp-ui-utilities, wp-ui-components, wp-ui-compositions, wp-ui-overrides;
|
|
2
|
+
|
|
3
|
+
@layer wp-ui-components {
|
|
4
|
+
.link {
|
|
5
|
+
text-underline-offset: 0.2em;
|
|
6
|
+
text-decoration-thickness: 0.5px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* Brand tone */
|
|
10
|
+
.is-brand,
|
|
11
|
+
.is-brand:visited {
|
|
12
|
+
color: var(--wpds-color-fg-interactive-brand);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.is-brand:hover,
|
|
16
|
+
.is-brand:active {
|
|
17
|
+
color: var(--wpds-color-fg-interactive-brand-active);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Neutral tone */
|
|
21
|
+
.is-neutral,
|
|
22
|
+
.is-neutral:visited {
|
|
23
|
+
color: var(--wpds-color-fg-interactive-neutral);
|
|
24
|
+
text-decoration-color: var(--wpds-color-stroke-interactive-neutral);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.is-neutral:hover,
|
|
28
|
+
.is-neutral:active {
|
|
29
|
+
color: var(--wpds-color-fg-interactive-neutral-active);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Unstyled variant */
|
|
33
|
+
.is-unstyled {
|
|
34
|
+
color: inherit;
|
|
35
|
+
text-decoration: none;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Link icon pattern — arrow rendered via ::after pseudo-element to avoid
|
|
39
|
+
* Twemoji replacement and text-selection issues. Root <a> gets
|
|
40
|
+
* text-decoration:none; the link-contents span re-applies it.
|
|
41
|
+
* text-underline-offset is inherited and propagates from .link
|
|
42
|
+
* automatically. text-decoration-thickness and text-decoration-color
|
|
43
|
+
* are NOT inherited, so they are explicitly redeclared on
|
|
44
|
+
* .link-contents (the latter via `inherit` to carry the neutral
|
|
45
|
+
* tone's custom color token through). */
|
|
46
|
+
.has-link-icon {
|
|
47
|
+
text-decoration: none;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.link-contents {
|
|
51
|
+
text-decoration: underline;
|
|
52
|
+
text-decoration-color: inherit;
|
|
53
|
+
text-decoration-thickness: 0.5px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.link-icon {
|
|
57
|
+
margin-inline-start: var(--wpds-dimension-padding-xs);
|
|
58
|
+
font-weight: var(--wpds-font-weight-regular);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.link-icon::after {
|
|
62
|
+
content: "\2197";
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.link-icon:dir(rtl)::after {
|
|
66
|
+
content: "\2196";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { createRef } from '@wordpress/element';
|
|
4
|
+
import { Link } from '../index';
|
|
5
|
+
|
|
6
|
+
describe( 'Link', () => {
|
|
7
|
+
it( 'forwards ref', () => {
|
|
8
|
+
const ref = createRef< HTMLAnchorElement >();
|
|
9
|
+
|
|
10
|
+
render(
|
|
11
|
+
<Link ref={ ref } href="/">
|
|
12
|
+
Home
|
|
13
|
+
</Link>
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
expect( ref.current ).toBeInstanceOf( HTMLAnchorElement );
|
|
17
|
+
} );
|
|
18
|
+
|
|
19
|
+
describe( 'openInNewTab', () => {
|
|
20
|
+
it( 'sets target="_blank" when true', () => {
|
|
21
|
+
render(
|
|
22
|
+
<Link href="https://example.com" openInNewTab>
|
|
23
|
+
External
|
|
24
|
+
</Link>
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
expect( screen.getByRole( 'link' ) ).toHaveAttribute(
|
|
28
|
+
'target',
|
|
29
|
+
'_blank'
|
|
30
|
+
);
|
|
31
|
+
} );
|
|
32
|
+
|
|
33
|
+
it( 'does not set target="_blank" when false', () => {
|
|
34
|
+
render( <Link href="https://example.com">External</Link> );
|
|
35
|
+
|
|
36
|
+
expect( screen.getByRole( 'link' ) ).not.toHaveAttribute(
|
|
37
|
+
'target'
|
|
38
|
+
);
|
|
39
|
+
} );
|
|
40
|
+
|
|
41
|
+
it( 'renders an accessible arrow indicator', () => {
|
|
42
|
+
render(
|
|
43
|
+
<Link href="https://example.com" openInNewTab>
|
|
44
|
+
External
|
|
45
|
+
</Link>
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
expect(
|
|
49
|
+
screen.getByLabelText( '(opens in a new tab)' )
|
|
50
|
+
).toBeInTheDocument();
|
|
51
|
+
} );
|
|
52
|
+
|
|
53
|
+
it( 'prevents default for internal anchor links', async () => {
|
|
54
|
+
const user = userEvent.setup();
|
|
55
|
+
const onClick = jest.fn();
|
|
56
|
+
|
|
57
|
+
render(
|
|
58
|
+
<Link href="#section" openInNewTab onClick={ onClick }>
|
|
59
|
+
Jump
|
|
60
|
+
</Link>
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
await user.click( screen.getByRole( 'link' ) );
|
|
64
|
+
|
|
65
|
+
expect( onClick ).toHaveBeenCalledTimes( 1 );
|
|
66
|
+
expect( onClick.mock.calls[ 0 ][ 0 ].defaultPrevented ).toBe(
|
|
67
|
+
true
|
|
68
|
+
);
|
|
69
|
+
} );
|
|
70
|
+
|
|
71
|
+
it( 'does not prevent default for external links', async () => {
|
|
72
|
+
const user = userEvent.setup();
|
|
73
|
+
const onClick = jest.fn();
|
|
74
|
+
|
|
75
|
+
render(
|
|
76
|
+
<Link
|
|
77
|
+
href="https://example.com"
|
|
78
|
+
openInNewTab
|
|
79
|
+
onClick={ onClick }
|
|
80
|
+
>
|
|
81
|
+
External
|
|
82
|
+
</Link>
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
await user.click( screen.getByRole( 'link' ) );
|
|
86
|
+
|
|
87
|
+
expect( onClick ).toHaveBeenCalledTimes( 1 );
|
|
88
|
+
expect( onClick.mock.calls[ 0 ][ 0 ].defaultPrevented ).toBe(
|
|
89
|
+
false
|
|
90
|
+
);
|
|
91
|
+
} );
|
|
92
|
+
} );
|
|
93
|
+
} );
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type ComponentProps } from '../utils/types';
|
|
3
|
+
|
|
4
|
+
export interface LinkProps extends Omit< ComponentProps< 'a' >, 'target' > {
|
|
5
|
+
/**
|
|
6
|
+
* The visual treatment of the link.
|
|
7
|
+
*
|
|
8
|
+
* - `default`: Applies tone-based color and underline styles.
|
|
9
|
+
* - `unstyled`: Strips all visual styles so consumers can bring their own.
|
|
10
|
+
*
|
|
11
|
+
* @default "default"
|
|
12
|
+
*/
|
|
13
|
+
variant?: 'default' | 'unstyled';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The tone of the link. Tone describes a semantic color intent.
|
|
17
|
+
* Only applies when `variant` is `default`.
|
|
18
|
+
*
|
|
19
|
+
* @default "brand"
|
|
20
|
+
*/
|
|
21
|
+
tone?: 'brand' | 'neutral';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Whether to open the link in a new browser tab.
|
|
25
|
+
* When true, sets `target="_blank"`, appends a visual arrow indicator,
|
|
26
|
+
* and prevents navigation for internal anchors (`#`-prefixed hrefs).
|
|
27
|
+
*
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
openInNewTab?: boolean;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The content to be rendered inside the component.
|
|
34
|
+
*/
|
|
35
|
+
children?: ReactNode;
|
|
36
|
+
}
|
|
@@ -1,28 +1,22 @@
|
|
|
1
|
-
import { forwardRef } from '@wordpress/element';
|
|
2
|
-
import { useRender, mergeProps } from '@base-ui/react';
|
|
3
1
|
import clsx from 'clsx';
|
|
2
|
+
import { forwardRef } from '@wordpress/element';
|
|
3
|
+
import { Link } from '../link';
|
|
4
4
|
import type { ActionLinkProps } from './types';
|
|
5
5
|
import styles from './style.module.css';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* An action link for use within Notice.Actions.
|
|
9
|
-
*
|
|
10
|
-
* TODO: This should use a shared Link component.
|
|
11
9
|
*/
|
|
12
10
|
export const ActionLink = forwardRef< HTMLAnchorElement, ActionLinkProps >(
|
|
13
|
-
function NoticeActionLink( { className,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
),
|
|
24
|
-
} );
|
|
25
|
-
|
|
26
|
-
return element;
|
|
11
|
+
function NoticeActionLink( { className, ...props }, ref ) {
|
|
12
|
+
return (
|
|
13
|
+
<Link
|
|
14
|
+
ref={ ref }
|
|
15
|
+
className={ clsx( styles[ 'action-link' ], className ) }
|
|
16
|
+
{ ...props }
|
|
17
|
+
tone="neutral"
|
|
18
|
+
variant="default"
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
27
21
|
}
|
|
28
22
|
);
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import { forwardRef } from '@wordpress/element';
|
|
2
|
-
import
|
|
2
|
+
import clsx from 'clsx';
|
|
3
3
|
import type { DescriptionProps } from './types';
|
|
4
|
+
import { Text } from '../text';
|
|
4
5
|
import styles from './style.module.css';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* The description text for a notice.
|
|
8
9
|
*/
|
|
9
|
-
export const Description = forwardRef<
|
|
10
|
-
function NoticeDescription( {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
{
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
} );
|
|
20
|
-
|
|
21
|
-
return element;
|
|
10
|
+
export const Description = forwardRef< HTMLSpanElement, DescriptionProps >(
|
|
11
|
+
function NoticeDescription( { className, ...props }, ref ) {
|
|
12
|
+
return (
|
|
13
|
+
<Text
|
|
14
|
+
ref={ ref }
|
|
15
|
+
variant="body-md"
|
|
16
|
+
className={ clsx( styles.description, className ) }
|
|
17
|
+
{ ...props }
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
22
20
|
}
|
|
23
21
|
);
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
--wp-ui-notice-text-color: var(--wpds-color-fg-content-neutral);
|
|
11
11
|
--wp-ui-notice-decorative-icon-color: var(--wpds-color-fg-content-neutral);
|
|
12
12
|
|
|
13
|
+
container-type: inline-size;
|
|
13
14
|
display: grid;
|
|
14
15
|
align-items: start;
|
|
15
16
|
grid-template-columns: auto 1fr auto;
|
|
@@ -31,10 +32,6 @@
|
|
|
31
32
|
|
|
32
33
|
padding-block: var(--text-vertical-padding);
|
|
33
34
|
|
|
34
|
-
font-family: var(--wpds-font-family-heading);
|
|
35
|
-
font-size: var(--wpds-font-size-md);
|
|
36
|
-
font-weight: var(--wpds-font-weight-medium);
|
|
37
|
-
line-height: var(--wpds-font-line-height-sm);
|
|
38
35
|
color: var(--wp-ui-notice-text-color);
|
|
39
36
|
}
|
|
40
37
|
|
|
@@ -43,10 +40,6 @@
|
|
|
43
40
|
|
|
44
41
|
padding-block: var(--text-vertical-padding);
|
|
45
42
|
|
|
46
|
-
font-family: var(--wpds-font-family-body);
|
|
47
|
-
font-size: var(--wpds-font-size-md);
|
|
48
|
-
font-weight: var(--wpds-font-weight-regular);
|
|
49
|
-
line-height: var(--wpds-font-line-height-sm);
|
|
50
43
|
text-wrap: pretty;
|
|
51
44
|
color: var(--wp-ui-notice-text-color);
|
|
52
45
|
}
|
|
@@ -76,20 +69,6 @@
|
|
|
76
69
|
font-weight: var(--wpds-font-weight-regular);
|
|
77
70
|
line-height: var(--wpds-font-line-height-sm);
|
|
78
71
|
margin-block: auto;
|
|
79
|
-
text-underline-offset: 0.2em;
|
|
80
|
-
text-decoration-thickness: 0.5px;
|
|
81
|
-
color: var(--wpds-color-fg-interactive-neutral);
|
|
82
|
-
text-decoration-color: var(--wpds-color-stroke-interactive-neutral);
|
|
83
|
-
|
|
84
|
-
&:visited {
|
|
85
|
-
color: var(--wpds-color-fg-interactive-neutral);
|
|
86
|
-
text-decoration-color: var(--wpds-color-stroke-interactive-neutral);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
&:hover,
|
|
90
|
-
&:active {
|
|
91
|
-
color: var(--wpds-color-fg-interactive-neutral-active);
|
|
92
|
-
}
|
|
93
72
|
|
|
94
73
|
/* Add more horizontal space when following another action link/button */
|
|
95
74
|
&:not(:first-child) {
|
|
@@ -135,6 +114,14 @@
|
|
|
135
114
|
--wp-ui-notice-text-color: var(--wpds-color-fg-content-error);
|
|
136
115
|
--wp-ui-notice-decorative-icon-color: var(--wpds-color-fg-content-error-weak);
|
|
137
116
|
}
|
|
117
|
+
|
|
118
|
+
/* Matches --wpds-dimension-surface-width-sm (container queries don't support custom properties). */
|
|
119
|
+
@container (max-width: 320px) {
|
|
120
|
+
.notice:has(.title) .description,
|
|
121
|
+
.notice:has(.title) .actions {
|
|
122
|
+
grid-column: 1 / 3;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
138
125
|
}
|
|
139
126
|
|
|
140
127
|
@layer wp-ui-compositions {
|
|
@@ -8,7 +8,7 @@ describe( 'Notice', () => {
|
|
|
8
8
|
it( 'forwards ref', () => {
|
|
9
9
|
const rootRef = createRef< HTMLDivElement >();
|
|
10
10
|
const titleRef = createRef< HTMLSpanElement >();
|
|
11
|
-
const descriptionRef = createRef<
|
|
11
|
+
const descriptionRef = createRef< HTMLSpanElement >();
|
|
12
12
|
const actionsRef = createRef< HTMLDivElement >();
|
|
13
13
|
const actionButtonRef = createRef< HTMLButtonElement >();
|
|
14
14
|
const actionLinkRef = createRef< HTMLAnchorElement >();
|
|
@@ -36,7 +36,7 @@ describe( 'Notice', () => {
|
|
|
36
36
|
);
|
|
37
37
|
expect( rootRef.current ).toBeInstanceOf( HTMLDivElement );
|
|
38
38
|
expect( titleRef.current ).toBeInstanceOf( HTMLSpanElement );
|
|
39
|
-
expect( descriptionRef.current ).toBeInstanceOf(
|
|
39
|
+
expect( descriptionRef.current ).toBeInstanceOf( HTMLSpanElement );
|
|
40
40
|
expect( actionsRef.current ).toBeInstanceOf( HTMLDivElement );
|
|
41
41
|
expect( actionButtonRef.current ).toBeInstanceOf(
|
|
42
42
|
HTMLButtonElement
|
package/src/notice/title.tsx
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { forwardRef } from '@wordpress/element';
|
|
2
|
-
import
|
|
2
|
+
import clsx from 'clsx';
|
|
3
3
|
import type { TitleProps } from './types';
|
|
4
|
+
import { Text } from '../text';
|
|
4
5
|
import styles from './style.module.css';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* A short heading that communicates the main message of the notice.
|
|
8
9
|
*/
|
|
9
10
|
export const Title = forwardRef< HTMLSpanElement, TitleProps >(
|
|
10
|
-
function NoticeTitle( {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
function NoticeTitle( { className, ...props }, ref ) {
|
|
12
|
+
return (
|
|
13
|
+
<Text
|
|
14
|
+
ref={ ref }
|
|
15
|
+
variant="heading-md"
|
|
16
|
+
className={ clsx( styles.title, className ) }
|
|
17
|
+
{ ...props }
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
19
20
|
}
|
|
20
21
|
);
|
package/src/notice/types.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { ComponentProps } from '../utils/types';
|
|
|
3
3
|
import type { IconProps } from '../icon/types';
|
|
4
4
|
import type { ButtonProps } from '../button/types';
|
|
5
5
|
import type { IconButtonProps } from '../icon-button/types';
|
|
6
|
+
import type { LinkProps } from '../link/types';
|
|
6
7
|
|
|
7
8
|
export type NoticeIntent = 'warning' | 'success' | 'error' | 'info' | 'neutral';
|
|
8
9
|
|
|
@@ -47,7 +48,7 @@ export interface TitleProps extends ComponentProps< 'span' > {
|
|
|
47
48
|
children?: ReactNode;
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
export interface DescriptionProps extends ComponentProps< '
|
|
51
|
+
export interface DescriptionProps extends ComponentProps< 'span' > {
|
|
51
52
|
/**
|
|
52
53
|
* The description text of the notice.
|
|
53
54
|
*/
|
|
@@ -92,7 +93,7 @@ export interface ActionButtonProps
|
|
|
92
93
|
children?: ReactNode;
|
|
93
94
|
}
|
|
94
95
|
|
|
95
|
-
export interface ActionLinkProps extends
|
|
96
|
+
export interface ActionLinkProps extends Omit< LinkProps, 'variant' | 'tone' > {
|
|
96
97
|
/**
|
|
97
98
|
* The content to be rendered inside the component.
|
|
98
99
|
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Text } from './text';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/* eslint-disable jsx-a11y/heading-has-content */
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
|
+
import { Text } from '../index';
|
|
4
|
+
import { Stack } from '../../stack';
|
|
5
|
+
|
|
6
|
+
const meta: Meta< typeof Text > = {
|
|
7
|
+
title: 'Design System/Components/Text',
|
|
8
|
+
component: Text,
|
|
9
|
+
};
|
|
10
|
+
export default meta;
|
|
11
|
+
|
|
12
|
+
type Story = StoryObj< typeof Text >;
|
|
13
|
+
|
|
14
|
+
export const Default: Story = {
|
|
15
|
+
args: {
|
|
16
|
+
variant: 'body-md',
|
|
17
|
+
children: 'The quick brown fox jumps over the lazy dog.',
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const AllVariants: Story = {
|
|
22
|
+
render: () => (
|
|
23
|
+
<Stack
|
|
24
|
+
direction="column"
|
|
25
|
+
gap="lg"
|
|
26
|
+
style={ { color: 'var(--wpds-color-fg-content-neutral)' } }
|
|
27
|
+
>
|
|
28
|
+
{ (
|
|
29
|
+
[
|
|
30
|
+
'heading-2xl',
|
|
31
|
+
'heading-xl',
|
|
32
|
+
'heading-lg',
|
|
33
|
+
'heading-md',
|
|
34
|
+
'heading-sm',
|
|
35
|
+
'body-xl',
|
|
36
|
+
'body-lg',
|
|
37
|
+
'body-md',
|
|
38
|
+
'body-sm',
|
|
39
|
+
] as const
|
|
40
|
+
).map( ( variant ) => (
|
|
41
|
+
<Stack key={ variant } direction="column" gap="xs">
|
|
42
|
+
<Text variant="heading-sm">{ variant }</Text>
|
|
43
|
+
<Text variant={ variant }>
|
|
44
|
+
The quick brown fox jumps over the lazy dog.
|
|
45
|
+
</Text>
|
|
46
|
+
</Stack>
|
|
47
|
+
) ) }
|
|
48
|
+
</Stack>
|
|
49
|
+
),
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const WithRenderProp: Story = {
|
|
53
|
+
render: () => (
|
|
54
|
+
<Stack direction="column" gap="md">
|
|
55
|
+
<Text variant="heading-2xl" render={ <h1 /> }>
|
|
56
|
+
Page Title
|
|
57
|
+
</Text>
|
|
58
|
+
<Text variant="heading-xl" render={ <h2 /> }>
|
|
59
|
+
Section Heading
|
|
60
|
+
</Text>
|
|
61
|
+
<Text variant="body-md" render={ <p /> }>
|
|
62
|
+
A paragraph of body text rendered as a semantic paragraph
|
|
63
|
+
element.
|
|
64
|
+
</Text>
|
|
65
|
+
</Stack>
|
|
66
|
+
),
|
|
67
|
+
};
|
|
68
|
+
/* eslint-enable jsx-a11y/heading-has-content */
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
@layer wp-ui-utilities, wp-ui-components, wp-ui-compositions, wp-ui-overrides;
|
|
2
|
+
|
|
3
|
+
@layer wp-ui-components {
|
|
4
|
+
.heading-2xl {
|
|
5
|
+
font-family: var(--wpds-font-family-heading);
|
|
6
|
+
font-size: var(--wpds-font-size-2xl);
|
|
7
|
+
line-height: var(--wpds-font-line-height-2xl);
|
|
8
|
+
font-weight: var(--wpds-font-weight-medium);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.heading-xl {
|
|
12
|
+
font-family: var(--wpds-font-family-heading);
|
|
13
|
+
font-size: var(--wpds-font-size-xl);
|
|
14
|
+
line-height: var(--wpds-font-line-height-md);
|
|
15
|
+
font-weight: var(--wpds-font-weight-medium);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.heading-lg {
|
|
19
|
+
font-family: var(--wpds-font-family-heading);
|
|
20
|
+
font-size: var(--wpds-font-size-lg);
|
|
21
|
+
line-height: var(--wpds-font-line-height-sm);
|
|
22
|
+
font-weight: var(--wpds-font-weight-medium);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.heading-md {
|
|
26
|
+
font-family: var(--wpds-font-family-heading);
|
|
27
|
+
font-size: var(--wpds-font-size-md);
|
|
28
|
+
line-height: var(--wpds-font-line-height-sm);
|
|
29
|
+
font-weight: var(--wpds-font-weight-medium);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.heading-sm {
|
|
33
|
+
font-family: var(--wpds-font-family-heading);
|
|
34
|
+
font-size: var(--wpds-font-size-xs);
|
|
35
|
+
line-height: var(--wpds-font-line-height-xs);
|
|
36
|
+
font-weight: var(--wpds-font-weight-medium);
|
|
37
|
+
text-transform: uppercase;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.body-xl {
|
|
41
|
+
font-family: var(--wpds-font-family-body);
|
|
42
|
+
font-size: var(--wpds-font-size-xl);
|
|
43
|
+
line-height: var(--wpds-font-line-height-xl);
|
|
44
|
+
font-weight: var(--wpds-font-weight-regular);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.body-lg {
|
|
48
|
+
font-family: var(--wpds-font-family-body);
|
|
49
|
+
font-size: var(--wpds-font-size-lg);
|
|
50
|
+
line-height: var(--wpds-font-line-height-md);
|
|
51
|
+
font-weight: var(--wpds-font-weight-regular);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.body-md {
|
|
55
|
+
font-family: var(--wpds-font-family-body);
|
|
56
|
+
font-size: var(--wpds-font-size-md);
|
|
57
|
+
line-height: var(--wpds-font-line-height-sm);
|
|
58
|
+
font-weight: var(--wpds-font-weight-regular);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.body-sm {
|
|
62
|
+
font-family: var(--wpds-font-family-body);
|
|
63
|
+
font-size: var(--wpds-font-size-sm);
|
|
64
|
+
line-height: var(--wpds-font-line-height-xs);
|
|
65
|
+
font-weight: var(--wpds-font-weight-regular);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import { createRef } from '@wordpress/element';
|
|
3
|
+
import { Text } from '../index';
|
|
4
|
+
|
|
5
|
+
describe( 'Text', () => {
|
|
6
|
+
it( 'forwards ref', () => {
|
|
7
|
+
const ref = createRef< HTMLSpanElement >();
|
|
8
|
+
|
|
9
|
+
render( <Text ref={ ref }>Content</Text> );
|
|
10
|
+
|
|
11
|
+
expect( ref.current ).toBeInstanceOf( HTMLSpanElement );
|
|
12
|
+
} );
|
|
13
|
+
|
|
14
|
+
it( 'renders children', () => {
|
|
15
|
+
render( <Text>Hello world</Text> );
|
|
16
|
+
|
|
17
|
+
expect( screen.getByText( 'Hello world' ) ).toBeVisible();
|
|
18
|
+
} );
|
|
19
|
+
|
|
20
|
+
it( 'forwards props to the rendered element', () => {
|
|
21
|
+
render( <Text data-testid="text">Content</Text> );
|
|
22
|
+
|
|
23
|
+
expect( screen.getByTestId( 'text' ) ).toBeInTheDocument();
|
|
24
|
+
} );
|
|
25
|
+
|
|
26
|
+
it( 'forwards the className to the rendered element', () => {
|
|
27
|
+
render(
|
|
28
|
+
<Text data-testid="text" className="custom-class">
|
|
29
|
+
Content
|
|
30
|
+
</Text>
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
expect( screen.getByTestId( 'text' ) ).toHaveClass( 'custom-class' );
|
|
34
|
+
} );
|
|
35
|
+
|
|
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
|
+
);
|
|
41
|
+
|
|
42
|
+
expect(
|
|
43
|
+
screen.getByRole( 'heading', { level: 2, name: 'Section title' } )
|
|
44
|
+
).toBeVisible();
|
|
45
|
+
} );
|
|
46
|
+
} );
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useRender, mergeProps } from '@base-ui/react';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { forwardRef } from '@wordpress/element';
|
|
4
|
+
import { type TextProps } from './types';
|
|
5
|
+
import styles from './style.module.css';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A text component for rendering content with predefined typographic variants.
|
|
9
|
+
* Built on design tokens for consistent typography across the UI.
|
|
10
|
+
*/
|
|
11
|
+
export const Text = forwardRef< HTMLSpanElement, TextProps >( function Text(
|
|
12
|
+
{ variant = 'body-md', render, className, ...props },
|
|
13
|
+
ref
|
|
14
|
+
) {
|
|
15
|
+
const element = useRender( {
|
|
16
|
+
render,
|
|
17
|
+
defaultTagName: 'span',
|
|
18
|
+
ref,
|
|
19
|
+
props: mergeProps< 'span' >( props, {
|
|
20
|
+
className: clsx( styles[ variant ], className ),
|
|
21
|
+
} ),
|
|
22
|
+
} );
|
|
23
|
+
|
|
24
|
+
return element;
|
|
25
|
+
} );
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ComponentProps } from '../utils/types';
|
|
2
|
+
|
|
3
|
+
export interface TextProps extends ComponentProps< 'span' > {
|
|
4
|
+
/**
|
|
5
|
+
* The typographic variant to apply, controlling font family, size,
|
|
6
|
+
* line height, and weight.
|
|
7
|
+
*
|
|
8
|
+
* @default "body-md"
|
|
9
|
+
*/
|
|
10
|
+
variant?:
|
|
11
|
+
| 'heading-2xl'
|
|
12
|
+
| 'heading-xl'
|
|
13
|
+
| 'heading-lg'
|
|
14
|
+
| 'heading-md'
|
|
15
|
+
| 'heading-sm'
|
|
16
|
+
| 'body-xl'
|
|
17
|
+
| 'body-lg'
|
|
18
|
+
| 'body-md'
|
|
19
|
+
| 'body-sm';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The content to be rendered inside the component.
|
|
23
|
+
*/
|
|
24
|
+
children?: React.ReactNode;
|
|
25
|
+
}
|
package/src/tooltip/popup.tsx
CHANGED