@fpkit/acss 0.5.11 → 0.5.13
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/README.md +514 -18
- package/libs/chunk-23ANBDCR.js +8 -0
- package/libs/chunk-23ANBDCR.js.map +1 -0
- package/libs/chunk-2LTJ7HHX.cjs +18 -0
- package/libs/chunk-2LTJ7HHX.cjs.map +1 -0
- package/libs/chunk-2Y7W75TT.js +9 -0
- package/libs/chunk-2Y7W75TT.js.map +1 -0
- package/libs/chunk-3MKLDCKQ.cjs +31 -0
- package/libs/chunk-3MKLDCKQ.cjs.map +1 -0
- package/libs/chunk-5M57K4SW.js +8 -0
- package/libs/chunk-5M57K4SW.js.map +1 -0
- package/libs/chunk-5S4ORA4C.cjs +15 -0
- package/libs/chunk-5S4ORA4C.cjs.map +1 -0
- package/libs/chunk-772NRB75.js +9 -0
- package/libs/chunk-772NRB75.js.map +1 -0
- package/libs/chunk-AHDJGCG5.cjs +15 -0
- package/libs/chunk-AHDJGCG5.cjs.map +1 -0
- package/libs/chunk-B7F5FS6D.cjs +16 -0
- package/libs/chunk-B7F5FS6D.cjs.map +1 -0
- package/libs/chunk-BHRQBJRY.js +8 -0
- package/libs/chunk-BHRQBJRY.js.map +1 -0
- package/libs/chunk-D4YLRWAO.cjs +18 -0
- package/libs/chunk-D4YLRWAO.cjs.map +1 -0
- package/libs/chunk-ETFLFC2S.js +10 -0
- package/libs/chunk-ETFLFC2S.js.map +1 -0
- package/libs/chunk-G55UJ53G.cjs +16 -0
- package/libs/chunk-G55UJ53G.cjs.map +1 -0
- package/libs/chunk-GZ4QFPRY.js +9 -0
- package/libs/chunk-GZ4QFPRY.js.map +1 -0
- package/libs/chunk-IYUN2EW3.cjs +15 -0
- package/libs/chunk-IYUN2EW3.cjs.map +1 -0
- package/libs/chunk-J32EZPYD.cjs +15 -0
- package/libs/chunk-J32EZPYD.cjs.map +1 -0
- package/libs/chunk-JJ43O4Y5.js +8 -0
- package/libs/chunk-JJ43O4Y5.js.map +1 -0
- package/libs/chunk-KUKIVRC2.js +7 -0
- package/libs/chunk-KUKIVRC2.js.map +1 -0
- package/libs/chunk-L75OQKEI.cjs +13 -0
- package/libs/chunk-L75OQKEI.cjs.map +1 -0
- package/libs/chunk-LT5KZ2QW.cjs +22 -0
- package/libs/chunk-LT5KZ2QW.cjs.map +1 -0
- package/libs/chunk-M5RRNTVX.cjs +15 -0
- package/libs/chunk-M5RRNTVX.cjs.map +1 -0
- package/libs/chunk-NGTJDDFO.js +8 -0
- package/libs/chunk-NGTJDDFO.js.map +1 -0
- package/libs/chunk-OK5QEIMD.cjs +17 -0
- package/libs/chunk-OK5QEIMD.cjs.map +1 -0
- package/libs/chunk-P2DC76ZZ.cjs +18 -0
- package/libs/chunk-P2DC76ZZ.cjs.map +1 -0
- package/libs/chunk-P7TTEYCD.js +7 -0
- package/libs/chunk-P7TTEYCD.js.map +1 -0
- package/libs/chunk-PQ2K3BM6.cjs +17 -0
- package/libs/chunk-PQ2K3BM6.cjs.map +1 -0
- package/libs/chunk-QLZWHAMK.js +8 -0
- package/libs/chunk-QLZWHAMK.js.map +1 -0
- package/libs/chunk-RIVUMPOG.js +8 -0
- package/libs/chunk-RIVUMPOG.js.map +1 -0
- package/libs/chunk-ROZI23GS.cjs +15 -0
- package/libs/chunk-ROZI23GS.cjs.map +1 -0
- package/libs/chunk-S7BABR7Z.cjs +13 -0
- package/libs/chunk-S7BABR7Z.cjs.map +1 -0
- package/libs/chunk-SMYRLO3E.js +8 -0
- package/libs/chunk-SMYRLO3E.js.map +1 -0
- package/libs/chunk-TYRCEX2L.js +8 -0
- package/libs/chunk-TYRCEX2L.js.map +1 -0
- package/libs/chunk-VUH3FXGJ.js +11 -0
- package/libs/chunk-VUH3FXGJ.js.map +1 -0
- package/libs/chunk-XBA562WW.js +8 -0
- package/libs/chunk-XBA562WW.js.map +1 -0
- package/libs/chunk-XTQKWY7W.cjs +32 -0
- package/libs/chunk-XTQKWY7W.cjs.map +1 -0
- package/libs/chunk-ZANSFMTD.js +9 -0
- package/libs/chunk-ZANSFMTD.js.map +1 -0
- package/libs/component-props-a8a2f97e.d.ts +38 -0
- package/libs/components/alert/alert.css +1 -1
- package/libs/components/alert/alert.css.map +1 -1
- package/libs/components/alert/alert.min.css +2 -2
- package/libs/components/badge/badge.css +1 -1
- package/libs/components/badge/badge.css.map +1 -1
- package/libs/components/badge/badge.min.css +2 -2
- package/libs/components/breadcrumbs/breadcrumb.cjs +24 -0
- package/libs/components/breadcrumbs/breadcrumb.cjs.map +1 -0
- package/libs/components/breadcrumbs/breadcrumb.d.cts +290 -0
- package/libs/components/breadcrumbs/breadcrumb.d.ts +290 -0
- package/libs/components/breadcrumbs/breadcrumb.js +5 -0
- package/libs/components/breadcrumbs/breadcrumb.js.map +1 -0
- package/libs/components/button.cjs +19 -0
- package/libs/components/button.cjs.map +1 -0
- package/libs/components/button.d.cts +16 -0
- package/libs/components/button.d.ts +16 -0
- package/libs/components/button.js +4 -0
- package/libs/components/button.js.map +1 -0
- package/libs/components/buttons/button.css +1 -1
- package/libs/components/buttons/button.css.map +1 -1
- package/libs/components/buttons/button.min.css +2 -2
- package/libs/components/card.cjs +31 -0
- package/libs/components/card.cjs.map +1 -0
- package/libs/components/card.d.cts +302 -0
- package/libs/components/card.d.ts +302 -0
- package/libs/components/card.js +4 -0
- package/libs/components/card.js.map +1 -0
- package/libs/components/cards/card.css +1 -1
- package/libs/components/cards/card.css.map +1 -1
- package/libs/components/cards/card.min.css +2 -2
- package/libs/components/details/details.css +1 -1
- package/libs/components/details/details.css.map +1 -1
- package/libs/components/details/details.min.css +2 -2
- package/libs/components/dialog/dialog.cjs +22 -0
- package/libs/components/dialog/dialog.cjs.map +1 -0
- package/libs/components/dialog/dialog.css +1 -1
- package/libs/components/dialog/dialog.css.map +1 -1
- package/libs/components/dialog/dialog.d.cts +105 -0
- package/libs/components/dialog/dialog.d.ts +105 -0
- package/libs/components/dialog/dialog.js +7 -0
- package/libs/components/dialog/dialog.js.map +1 -0
- package/libs/components/dialog/dialog.min.css +2 -2
- package/libs/components/form/fields.cjs +19 -0
- package/libs/components/form/fields.cjs.map +1 -0
- package/libs/components/form/fields.d.cts +24 -0
- package/libs/components/form/fields.d.ts +24 -0
- package/libs/components/form/fields.js +4 -0
- package/libs/components/form/fields.js.map +1 -0
- package/libs/components/form/inputs.cjs +19 -0
- package/libs/components/form/inputs.cjs.map +1 -0
- package/libs/components/form/inputs.d.cts +2 -0
- package/libs/components/form/inputs.d.ts +2 -0
- package/libs/components/form/inputs.js +4 -0
- package/libs/components/form/inputs.js.map +1 -0
- package/libs/components/form/textarea.cjs +19 -0
- package/libs/components/form/textarea.cjs.map +1 -0
- package/libs/components/form/textarea.d.cts +29 -0
- package/libs/components/form/textarea.d.ts +29 -0
- package/libs/components/form/textarea.js +4 -0
- package/libs/components/form/textarea.js.map +1 -0
- package/libs/components/heading/heading.cjs +10 -0
- package/libs/components/heading/heading.cjs.map +1 -0
- package/libs/components/heading/heading.d.cts +3 -0
- package/libs/components/heading/heading.d.ts +3 -0
- package/libs/components/heading/heading.js +4 -0
- package/libs/components/heading/heading.js.map +1 -0
- package/libs/components/icons/icon.cjs +19 -0
- package/libs/components/icons/icon.cjs.map +1 -0
- package/libs/{icons-31ace3de.d.ts → components/icons/icon.d.cts} +151 -61
- package/libs/components/icons/icon.d.ts +445 -0
- package/libs/components/icons/icon.js +4 -0
- package/libs/components/icons/icon.js.map +1 -0
- package/libs/components/images/img.css +1 -1
- package/libs/components/images/img.css.map +1 -1
- package/libs/components/images/img.min.css +2 -2
- package/libs/components/link/link.cjs +19 -0
- package/libs/components/link/link.cjs.map +1 -0
- package/libs/components/link/link.d.cts +19 -0
- package/libs/components/link/link.d.ts +19 -0
- package/libs/components/link/link.js +4 -0
- package/libs/components/link/link.js.map +1 -0
- package/libs/components/list/list.cjs +23 -0
- package/libs/components/list/list.cjs.map +1 -0
- package/libs/components/list/list.d.cts +39 -0
- package/libs/components/list/list.d.ts +39 -0
- package/libs/components/list/list.js +4 -0
- package/libs/components/list/list.js.map +1 -0
- package/libs/components/modal.cjs +14 -0
- package/libs/components/modal.cjs.map +1 -0
- package/libs/components/modal.d.cts +35 -0
- package/libs/components/modal.d.ts +35 -0
- package/libs/components/modal.js +5 -0
- package/libs/components/modal.js.map +1 -0
- package/libs/components/nav/nav.cjs +28 -0
- package/libs/components/nav/nav.cjs.map +1 -0
- package/libs/components/nav/nav.d.cts +44 -0
- package/libs/components/nav/nav.d.ts +44 -0
- package/libs/components/nav/nav.js +5 -0
- package/libs/components/nav/nav.js.map +1 -0
- package/libs/components/popover/popover.cjs +23 -0
- package/libs/components/popover/popover.cjs.map +1 -0
- package/libs/components/popover/popover.d.cts +40 -0
- package/libs/components/popover/popover.d.ts +40 -0
- package/libs/components/popover/popover.js +4 -0
- package/libs/components/popover/popover.js.map +1 -0
- package/libs/components/tables/table.cjs +21 -0
- package/libs/components/tables/table.cjs.map +1 -0
- package/libs/components/tables/table.d.cts +36 -0
- package/libs/components/tables/table.d.ts +36 -0
- package/libs/components/tables/table.js +4 -0
- package/libs/components/tables/table.js.map +1 -0
- package/libs/components/text/text.cjs +23 -0
- package/libs/components/text/text.cjs.map +1 -0
- package/libs/components/text/text.d.cts +30 -0
- package/libs/components/text/text.d.ts +30 -0
- package/libs/components/text/text.js +4 -0
- package/libs/components/text/text.js.map +1 -0
- package/libs/heading-3648c538.d.ts +250 -0
- package/libs/hooks.cjs +7 -0
- package/libs/hooks.d.cts +5 -0
- package/libs/hooks.d.ts +5 -0
- package/libs/hooks.js +3 -0
- package/libs/icons.cjs +3 -2
- package/libs/icons.d.cts +3 -1
- package/libs/icons.d.ts +3 -1
- package/libs/icons.js +2 -1
- package/libs/index.cjs +174 -62
- package/libs/index.cjs.map +1 -1
- package/libs/index.css +1 -1
- package/libs/index.css.map +1 -1
- package/libs/index.d.cts +529 -446
- package/libs/index.d.ts +529 -446
- package/libs/index.js +36 -7
- package/libs/index.js.map +1 -1
- package/libs/inputs-f3a216db.d.ts +45 -0
- package/libs/ui-645f95b5.d.ts +285 -0
- package/package.json +2 -2
- package/src/components/README-UI.mdx +416 -0
- package/src/components/alert/ACCESSIBILITY.md +319 -0
- package/src/components/alert/README.mdx +475 -19
- package/src/components/alert/alert.scss +113 -6
- package/src/components/alert/alert.stories.tsx +372 -0
- package/src/components/alert/alert.test.tsx +762 -0
- package/src/components/alert/alert.tsx +331 -66
- package/src/components/alert/views/alert-actions.tsx +13 -0
- package/src/components/alert/views/alert-content.tsx +17 -0
- package/src/components/alert/views/alert-icon.tsx +53 -0
- package/src/components/alert/views/alert-screen-reader-text.tsx +30 -0
- package/src/components/alert/views/alert-title.tsx +23 -0
- package/src/components/alert/views/alert-view.tsx +158 -0
- package/src/components/alert/views/index.ts +12 -0
- package/src/components/badge/badge.mdx +186 -49
- package/src/components/badge/badge.scss +20 -2
- package/src/components/badge/badge.stories.tsx +160 -14
- package/src/components/badge/badge.test.tsx +179 -0
- package/src/components/badge/badge.tsx +97 -4
- package/src/components/breadcrumbs/README.mdx +364 -45
- package/src/components/breadcrumbs/__snapshots__/breadcrumb.test.tsx.snap +152 -0
- package/src/components/breadcrumbs/breadcrumb.stories.tsx +7 -3
- package/src/components/breadcrumbs/breadcrumb.test.tsx +490 -0
- package/src/components/breadcrumbs/breadcrumb.tsx +427 -170
- package/src/components/button.ts +2 -0
- package/src/components/buttons/button.scss +34 -31
- package/src/components/buttons/button.stories.tsx +35 -0
- package/src/components/card.ts +2 -0
- package/src/components/cards/README.mdx +657 -0
- package/src/components/cards/card.scss +22 -0
- package/src/components/cards/card.stories.tsx +167 -5
- package/src/components/cards/card.test.tsx +360 -20
- package/src/components/cards/card.tsx +200 -79
- package/src/components/cards/card.types.ts +135 -0
- package/src/components/cards/card.utils.ts +79 -0
- package/src/components/details/ACCESSIBILITY-REVIEW-LIVE.md +1050 -0
- package/src/components/details/ACCESSIBILITY-REVIEW.md +502 -0
- package/src/components/details/README.mdx +437 -69
- package/src/components/details/details.scss +16 -0
- package/src/components/details/details.test.tsx +385 -0
- package/src/components/details/details.tsx +101 -69
- package/src/components/details/details.types.ts +76 -0
- package/src/components/dialog/README.mdx +513 -110
- package/src/components/dialog/dialog-modal.tsx +79 -56
- package/src/components/dialog/dialog.scss +53 -3
- package/src/components/dialog/dialog.stories.tsx +10 -7
- package/src/components/dialog/dialog.test.tsx +450 -0
- package/src/components/dialog/dialog.tsx +69 -59
- package/src/components/dialog/dialog.types.ts +133 -0
- package/src/components/dialog/views/dialog-footer.tsx +54 -11
- package/src/components/dialog/views/dialog-header.tsx +20 -15
- package/src/components/heading/heading.stories.tsx +44 -4
- package/src/components/heading/heading.tsx +89 -23
- package/src/components/icons/README.mdx +332 -0
- package/src/components/icons/icon.stories.tsx +74 -1
- package/src/components/icons/icon.tsx +89 -1
- package/src/components/icons/types.ts +47 -0
- package/src/components/images/README.mdx +340 -24
- package/src/components/images/img.scss +19 -3
- package/src/components/images/img.stories.tsx +424 -15
- package/src/components/images/img.test.tsx +354 -25
- package/src/components/images/img.tsx +186 -63
- package/src/components/images/img.types.ts +211 -0
- package/src/components/modal.ts +1 -0
- package/src/components/title/MIGRATION.md +199 -0
- package/src/components/title/README.md +326 -0
- package/src/components/title/README.mdx +452 -0
- package/src/components/title/title.stories.tsx +393 -0
- package/src/components/title/title.test.tsx +251 -0
- package/src/components/title/title.tsx +219 -0
- package/src/components/ui.stories.tsx +894 -0
- package/src/components/ui.test.tsx +559 -0
- package/src/components/ui.tsx +266 -15
- package/src/components/word-count/README.md +240 -0
- package/src/hooks.ts +1 -0
- package/src/index.ts +51 -19
- package/src/sass/_properties.scss +1 -0
- package/src/styles/alert/alert.css +94 -4
- package/src/styles/alert/alert.css.map +1 -1
- package/src/styles/badge/badge.css +20 -2
- package/src/styles/badge/badge.css.map +1 -1
- package/src/styles/buttons/button.css +31 -31
- package/src/styles/buttons/button.css.map +1 -1
- package/src/styles/cards/card.css +16 -0
- package/src/styles/cards/card.css.map +1 -1
- package/src/styles/details/details.css +19 -0
- package/src/styles/details/details.css.map +1 -1
- package/src/styles/dialog/dialog.css +43 -2
- package/src/styles/dialog/dialog.css.map +1 -1
- package/src/styles/images/img.css +15 -3
- package/src/styles/images/img.css.map +1 -1
- package/src/styles/index.css +240 -43
- package/src/styles/index.css.map +1 -1
- package/src/test/setup.d.ts +9 -0
- package/src/test/setup.ts +53 -1
- package/libs/chunk-PWVRDQ3R.js +0 -8
- package/libs/chunk-PWVRDQ3R.js.map +0 -1
- package/libs/chunk-SVS4MX3U.cjs +0 -31
- package/libs/chunk-SVS4MX3U.cjs.map +0 -1
- package/src/components/cards/README.md +0 -80
- package/src/components/dialog/hooks/useClickOutside.ts +0 -33
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import { StoryObj, Meta } from "@storybook/react-vite";
|
|
2
|
+
import { within, expect } from "storybook/test";
|
|
3
|
+
|
|
4
|
+
import Title from "./title";
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof Title> = {
|
|
7
|
+
title: "FP.REACT Components/Title",
|
|
8
|
+
component: Title,
|
|
9
|
+
tags: ["version:2.0.0", "autodocs"],
|
|
10
|
+
parameters: {
|
|
11
|
+
actions: { argTypesRegex: "^on.*" },
|
|
12
|
+
docs: {
|
|
13
|
+
description: {
|
|
14
|
+
component: `
|
|
15
|
+
A semantic heading component for document structure and hierarchy.
|
|
16
|
+
|
|
17
|
+
The Title component renders semantic HTML headings (h1-h6) with proper accessibility support,
|
|
18
|
+
ensuring WCAG 2.1 AA compliance by maintaining semantic document structure for screen readers.
|
|
19
|
+
|
|
20
|
+
## Key Features
|
|
21
|
+
|
|
22
|
+
- **Semantic HTML**: Renders actual heading elements (h1-h6) for proper document outline
|
|
23
|
+
- **Accessibility**: Full ARIA support and proper heading hierarchy
|
|
24
|
+
- **Flexible Styling**: Supports fpkit's UI system, custom classes, and inline styles
|
|
25
|
+
- **Type Safety**: Fully typed with TypeScript
|
|
26
|
+
- **Performance**: Memoized to prevent unnecessary re-renders
|
|
27
|
+
|
|
28
|
+
## Migration from Heading
|
|
29
|
+
|
|
30
|
+
If you're migrating from the deprecated \`Heading\` component:
|
|
31
|
+
|
|
32
|
+
\`\`\`tsx
|
|
33
|
+
// Before (deprecated):
|
|
34
|
+
<Heading type="h2">Section Title</Heading>
|
|
35
|
+
|
|
36
|
+
// After:
|
|
37
|
+
<Title level="h2">Section Title</Title>
|
|
38
|
+
\`\`\`
|
|
39
|
+
|
|
40
|
+
**Note**: Default level changed from \`h3\` to \`h2\`.
|
|
41
|
+
|
|
42
|
+
📖 [View Full Documentation](?path=/docs/fp-react-components-title-readme--docs)
|
|
43
|
+
`,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
argTypes: {
|
|
48
|
+
level: {
|
|
49
|
+
control: { type: "select" },
|
|
50
|
+
options: ["h1", "h2", "h3", "h4", "h5", "h6"],
|
|
51
|
+
description: "The semantic heading level to render",
|
|
52
|
+
table: {
|
|
53
|
+
type: { summary: "h1 | h2 | h3 | h4 | h5 | h6" },
|
|
54
|
+
defaultValue: { summary: "h2" },
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
children: {
|
|
58
|
+
control: "text",
|
|
59
|
+
description: "The content to display in the heading",
|
|
60
|
+
},
|
|
61
|
+
id: {
|
|
62
|
+
control: "text",
|
|
63
|
+
description: "Unique identifier for the heading (useful for anchor links)",
|
|
64
|
+
},
|
|
65
|
+
ui: {
|
|
66
|
+
control: "text",
|
|
67
|
+
description: "Data attribute for UI framework styling hooks",
|
|
68
|
+
},
|
|
69
|
+
className: {
|
|
70
|
+
control: "text",
|
|
71
|
+
description: "CSS class names to apply",
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
args: {
|
|
75
|
+
children: "Default Title",
|
|
76
|
+
},
|
|
77
|
+
} satisfies Meta<typeof Title>;
|
|
78
|
+
|
|
79
|
+
export default meta;
|
|
80
|
+
type Story = StoryObj<typeof Title>;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Default Title component using h2 (the default heading level).
|
|
84
|
+
*/
|
|
85
|
+
export const Default: Story = {
|
|
86
|
+
args: {},
|
|
87
|
+
play: async ({ canvasElement }) => {
|
|
88
|
+
const canvas = within(canvasElement);
|
|
89
|
+
expect(canvas.getByText(/default title/i)).toBeInTheDocument();
|
|
90
|
+
expect(canvas.getByRole("heading", { level: 2 })).toBeInTheDocument();
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Page title using h1. Typically used once per page for the main title.
|
|
96
|
+
*/
|
|
97
|
+
export const PageTitle: Story = {
|
|
98
|
+
args: {
|
|
99
|
+
level: "h1",
|
|
100
|
+
children: "Main Page Title",
|
|
101
|
+
},
|
|
102
|
+
parameters: {
|
|
103
|
+
docs: {
|
|
104
|
+
description: {
|
|
105
|
+
story: "Use h1 for the main page title. Each page should have exactly one h1 for proper document structure and SEO.",
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
play: async ({ canvasElement }) => {
|
|
110
|
+
const canvas = within(canvasElement);
|
|
111
|
+
expect(canvas.getByRole("heading", { level: 1 })).toHaveTextContent("Main Page Title");
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Section heading using h2. Used for major sections on the page.
|
|
117
|
+
*/
|
|
118
|
+
export const SectionHeading: Story = {
|
|
119
|
+
args: {
|
|
120
|
+
level: "h2",
|
|
121
|
+
children: "Section Heading",
|
|
122
|
+
},
|
|
123
|
+
parameters: {
|
|
124
|
+
docs: {
|
|
125
|
+
description: {
|
|
126
|
+
story: "h2 is the default level and commonly used for major sections.",
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
play: async ({ canvasElement }) => {
|
|
131
|
+
const canvas = within(canvasElement);
|
|
132
|
+
expect(canvas.getByRole("heading", { level: 2 })).toBeInTheDocument();
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Subsection heading using h3.
|
|
138
|
+
*/
|
|
139
|
+
export const SubsectionHeading: Story = {
|
|
140
|
+
args: {
|
|
141
|
+
level: "h3",
|
|
142
|
+
children: "Subsection Heading",
|
|
143
|
+
},
|
|
144
|
+
play: async ({ canvasElement }) => {
|
|
145
|
+
const canvas = within(canvasElement);
|
|
146
|
+
expect(canvas.getByRole("heading", { level: 3 })).toBeInTheDocument();
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* H4 heading for nested content.
|
|
152
|
+
*/
|
|
153
|
+
export const LevelFour: Story = {
|
|
154
|
+
args: {
|
|
155
|
+
level: "h4",
|
|
156
|
+
children: "Level Four Heading",
|
|
157
|
+
},
|
|
158
|
+
play: async ({ canvasElement }) => {
|
|
159
|
+
const canvas = within(canvasElement);
|
|
160
|
+
expect(canvas.getByRole("heading", { level: 4 })).toBeInTheDocument();
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* H5 heading for deeply nested content.
|
|
166
|
+
*/
|
|
167
|
+
export const LevelFive: Story = {
|
|
168
|
+
args: {
|
|
169
|
+
level: "h5",
|
|
170
|
+
children: "Level Five Heading",
|
|
171
|
+
},
|
|
172
|
+
play: async ({ canvasElement }) => {
|
|
173
|
+
const canvas = within(canvasElement);
|
|
174
|
+
expect(canvas.getByRole("heading", { level: 5 })).toBeInTheDocument();
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* H6 heading - the deepest heading level.
|
|
180
|
+
*/
|
|
181
|
+
export const LevelSix: Story = {
|
|
182
|
+
args: {
|
|
183
|
+
level: "h6",
|
|
184
|
+
children: "Level Six Heading",
|
|
185
|
+
},
|
|
186
|
+
play: async ({ canvasElement }) => {
|
|
187
|
+
const canvas = within(canvasElement);
|
|
188
|
+
expect(canvas.getByRole("heading", { level: 6 })).toBeInTheDocument();
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Example of proper heading hierarchy for accessibility.
|
|
194
|
+
*/
|
|
195
|
+
export const ProperHierarchy: Story = {
|
|
196
|
+
render: () => (
|
|
197
|
+
<div>
|
|
198
|
+
<Title level="h1">Page Title</Title>
|
|
199
|
+
<p>Introduction paragraph...</p>
|
|
200
|
+
|
|
201
|
+
<Title level="h2">First Major Section</Title>
|
|
202
|
+
<p>Section content...</p>
|
|
203
|
+
|
|
204
|
+
<Title level="h3">Subsection 1.1</Title>
|
|
205
|
+
<p>Subsection content...</p>
|
|
206
|
+
|
|
207
|
+
<Title level="h3">Subsection 1.2</Title>
|
|
208
|
+
<p>Subsection content...</p>
|
|
209
|
+
|
|
210
|
+
<Title level="h2">Second Major Section</Title>
|
|
211
|
+
<p>Section content...</p>
|
|
212
|
+
|
|
213
|
+
<Title level="h3">Subsection 2.1</Title>
|
|
214
|
+
<p>Subsection content...</p>
|
|
215
|
+
|
|
216
|
+
<Title level="h4">Sub-subsection 2.1.1</Title>
|
|
217
|
+
<p>Deep nested content...</p>
|
|
218
|
+
</div>
|
|
219
|
+
),
|
|
220
|
+
parameters: {
|
|
221
|
+
docs: {
|
|
222
|
+
description: {
|
|
223
|
+
story: `
|
|
224
|
+
**✅ GOOD: Proper heading hierarchy**
|
|
225
|
+
|
|
226
|
+
This example demonstrates correct heading hierarchy:
|
|
227
|
+
- One h1 for the page title
|
|
228
|
+
- h2 for major sections
|
|
229
|
+
- h3 for subsections
|
|
230
|
+
- h4 for nested subsections
|
|
231
|
+
- No skipped levels
|
|
232
|
+
|
|
233
|
+
This structure helps screen reader users navigate the page effectively and improves SEO.
|
|
234
|
+
`,
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
play: async ({ canvasElement }) => {
|
|
239
|
+
const canvas = within(canvasElement);
|
|
240
|
+
expect(canvas.getAllByRole("heading", { level: 1 })).toHaveLength(1);
|
|
241
|
+
expect(canvas.getAllByRole("heading", { level: 2 })).toHaveLength(2);
|
|
242
|
+
expect(canvas.getAllByRole("heading", { level: 3 })).toHaveLength(3);
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Example showing improper heading hierarchy (accessibility violation).
|
|
248
|
+
*/
|
|
249
|
+
export const ImproperHierarchy: Story = {
|
|
250
|
+
render: () => (
|
|
251
|
+
<div>
|
|
252
|
+
<Title level="h1">Page Title</Title>
|
|
253
|
+
<p>Introduction...</p>
|
|
254
|
+
|
|
255
|
+
{/* ❌ BAD: Skipping from h1 to h4 */}
|
|
256
|
+
<Title level="h4" styles={{ color: "red" }}>
|
|
257
|
+
Skipped h2 and h3 (Accessibility Issue!)
|
|
258
|
+
</Title>
|
|
259
|
+
<p>This violates WCAG guidelines...</p>
|
|
260
|
+
</div>
|
|
261
|
+
),
|
|
262
|
+
parameters: {
|
|
263
|
+
docs: {
|
|
264
|
+
description: {
|
|
265
|
+
story: `
|
|
266
|
+
**❌ BAD: Improper heading hierarchy**
|
|
267
|
+
|
|
268
|
+
This example shows an accessibility violation - skipping from h1 to h4 without h2 or h3 in between.
|
|
269
|
+
|
|
270
|
+
**Issues:**
|
|
271
|
+
- Confuses screen reader users
|
|
272
|
+
- Violates WCAG 2.4.6 (Headings and Labels)
|
|
273
|
+
- Poor document structure
|
|
274
|
+
|
|
275
|
+
**Solution:** Always maintain sequential heading levels.
|
|
276
|
+
`,
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Title with custom ID for anchor linking.
|
|
284
|
+
*/
|
|
285
|
+
export const WithAnchorLink: Story = {
|
|
286
|
+
args: {
|
|
287
|
+
level: "h2",
|
|
288
|
+
id: "getting-started",
|
|
289
|
+
children: "Getting Started",
|
|
290
|
+
},
|
|
291
|
+
parameters: {
|
|
292
|
+
docs: {
|
|
293
|
+
description: {
|
|
294
|
+
story: "Use the `id` prop to create anchor links. Users can link directly to this section with `#getting-started`.",
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
play: async ({ canvasElement }) => {
|
|
299
|
+
const canvas = within(canvasElement);
|
|
300
|
+
const heading = canvas.getByRole("heading", { level: 2 });
|
|
301
|
+
expect(heading).toHaveAttribute("id", "getting-started");
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Title with custom styling using fpkit's UI data attribute.
|
|
307
|
+
*/
|
|
308
|
+
export const WithUIAttribute: Story = {
|
|
309
|
+
args: {
|
|
310
|
+
level: "h2",
|
|
311
|
+
ui: "section-title",
|
|
312
|
+
children: "Styled Section Title",
|
|
313
|
+
},
|
|
314
|
+
parameters: {
|
|
315
|
+
docs: {
|
|
316
|
+
description: {
|
|
317
|
+
story: "Use the `ui` prop to apply fpkit's component-specific styles via data attributes.",
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
play: async ({ canvasElement }) => {
|
|
322
|
+
const canvas = within(canvasElement);
|
|
323
|
+
const heading = canvas.getByRole("heading", { level: 2 });
|
|
324
|
+
expect(heading).toHaveAttribute("data-ui", "section-title");
|
|
325
|
+
},
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Title with custom CSS classes.
|
|
330
|
+
*/
|
|
331
|
+
export const WithCustomClasses: Story = {
|
|
332
|
+
args: {
|
|
333
|
+
level: "h2",
|
|
334
|
+
className: "text-primary font-bold",
|
|
335
|
+
children: "Custom Styled Title",
|
|
336
|
+
},
|
|
337
|
+
parameters: {
|
|
338
|
+
docs: {
|
|
339
|
+
description: {
|
|
340
|
+
story: "Apply custom CSS classes using the `className` prop.",
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Title with inline styles.
|
|
348
|
+
*/
|
|
349
|
+
export const WithInlineStyles: Story = {
|
|
350
|
+
args: {
|
|
351
|
+
level: "h2",
|
|
352
|
+
styles: {
|
|
353
|
+
color: "#0066cc",
|
|
354
|
+
fontWeight: 700,
|
|
355
|
+
marginBottom: "1rem",
|
|
356
|
+
},
|
|
357
|
+
children: "Inline Styled Title",
|
|
358
|
+
},
|
|
359
|
+
parameters: {
|
|
360
|
+
docs: {
|
|
361
|
+
description: {
|
|
362
|
+
story: "Apply inline styles using the `styles` prop. Useful for dynamic styling or CSS-in-JS.",
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Accessible title with ARIA label for additional context.
|
|
370
|
+
*/
|
|
371
|
+
export const WithAriaLabel: Story = {
|
|
372
|
+
args: {
|
|
373
|
+
level: "h2",
|
|
374
|
+
"aria-label": "User dashboard statistics overview",
|
|
375
|
+
children: "Dashboard",
|
|
376
|
+
},
|
|
377
|
+
parameters: {
|
|
378
|
+
docs: {
|
|
379
|
+
description: {
|
|
380
|
+
story: `
|
|
381
|
+
Use \`aria-label\` when the visible text doesn't provide enough context for screen reader users.
|
|
382
|
+
|
|
383
|
+
**Example:** "Dashboard" becomes "User dashboard statistics overview" for assistive technologies.
|
|
384
|
+
`,
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
play: async ({ canvasElement }) => {
|
|
389
|
+
const canvas = within(canvasElement);
|
|
390
|
+
const heading = canvas.getByRole("heading", { level: 2 });
|
|
391
|
+
expect(heading).toHaveAttribute("aria-label", "User dashboard statistics overview");
|
|
392
|
+
},
|
|
393
|
+
};
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import React from "react";
|
|
4
|
+
|
|
5
|
+
import Title from "./title";
|
|
6
|
+
|
|
7
|
+
describe("Title Component", () => {
|
|
8
|
+
describe("Rendering", () => {
|
|
9
|
+
it("should render with default h2 level", () => {
|
|
10
|
+
render(<Title>Default Title</Title>);
|
|
11
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
12
|
+
expect(heading).toBeInTheDocument();
|
|
13
|
+
expect(heading).toHaveTextContent("Default Title");
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("should render children content", () => {
|
|
17
|
+
render(<Title>Test Content</Title>);
|
|
18
|
+
expect(screen.getByText("Test Content")).toBeInTheDocument();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should render complex children with elements", () => {
|
|
22
|
+
render(
|
|
23
|
+
<Title>
|
|
24
|
+
<span data-testid="icon">📄</span>
|
|
25
|
+
<span>Document Title</span>
|
|
26
|
+
</Title>
|
|
27
|
+
);
|
|
28
|
+
expect(screen.getByTestId("icon")).toBeInTheDocument();
|
|
29
|
+
expect(screen.getByText("Document Title")).toBeInTheDocument();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe("Heading Levels", () => {
|
|
34
|
+
it.each([
|
|
35
|
+
["h1", 1],
|
|
36
|
+
["h2", 2],
|
|
37
|
+
["h3", 3],
|
|
38
|
+
["h4", 4],
|
|
39
|
+
["h5", 5],
|
|
40
|
+
["h6", 6],
|
|
41
|
+
] as const)("should render %s with level %i", (level, numericLevel) => {
|
|
42
|
+
render(<Title level={level}>Heading {level}</Title>);
|
|
43
|
+
const heading = screen.getByRole("heading", { level: numericLevel });
|
|
44
|
+
expect(heading).toBeInTheDocument();
|
|
45
|
+
expect(heading.tagName.toLowerCase()).toBe(level);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe("Props and Attributes", () => {
|
|
50
|
+
it("should apply id attribute", () => {
|
|
51
|
+
render(<Title id="test-heading">Title with ID</Title>);
|
|
52
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
53
|
+
expect(heading).toHaveAttribute("id", "test-heading");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should apply data-ui attribute", () => {
|
|
57
|
+
render(<Title ui="section-title">Styled Title</Title>);
|
|
58
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
59
|
+
expect(heading).toHaveAttribute("data-ui", "section-title");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("should apply className", () => {
|
|
63
|
+
render(<Title className="custom-class">Classed Title</Title>);
|
|
64
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
65
|
+
expect(heading).toHaveClass("custom-class");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("should apply multiple class names", () => {
|
|
69
|
+
render(<Title className="class-one class-two">Title</Title>);
|
|
70
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
71
|
+
expect(heading).toHaveClass("class-one");
|
|
72
|
+
expect(heading).toHaveClass("class-two");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("should apply inline styles", () => {
|
|
76
|
+
const styles = { color: "red", fontSize: "24px" };
|
|
77
|
+
render(<Title styles={styles}>Styled Title</Title>);
|
|
78
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
79
|
+
// Browsers convert color values, so check for rgb format
|
|
80
|
+
expect(heading).toHaveStyle({ color: "rgb(255, 0, 0)", fontSize: "24px" });
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe("Accessibility", () => {
|
|
85
|
+
it("should have proper heading role", () => {
|
|
86
|
+
render(<Title level="h1">Accessible Title</Title>);
|
|
87
|
+
const heading = screen.getByRole("heading", { level: 1 });
|
|
88
|
+
expect(heading).toBeInTheDocument();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("should support aria-label", () => {
|
|
92
|
+
render(
|
|
93
|
+
<Title aria-label="Dashboard overview">Dashboard</Title>
|
|
94
|
+
);
|
|
95
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
96
|
+
expect(heading).toHaveAttribute("aria-label", "Dashboard overview");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("should support aria-labelledby", () => {
|
|
100
|
+
render(
|
|
101
|
+
<>
|
|
102
|
+
<div id="label-element">Section Label</div>
|
|
103
|
+
<Title aria-labelledby="label-element">Title</Title>
|
|
104
|
+
</>
|
|
105
|
+
);
|
|
106
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
107
|
+
expect(heading).toHaveAttribute("aria-labelledby", "label-element");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("should support aria-describedby", () => {
|
|
111
|
+
render(
|
|
112
|
+
<>
|
|
113
|
+
<p id="description">This is a description</p>
|
|
114
|
+
<Title aria-describedby="description">Title</Title>
|
|
115
|
+
</>
|
|
116
|
+
);
|
|
117
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
118
|
+
expect(heading).toHaveAttribute("aria-describedby", "description");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("should be findable by accessible name", () => {
|
|
122
|
+
render(<Title>Findable Heading</Title>);
|
|
123
|
+
expect(
|
|
124
|
+
screen.getByRole("heading", { name: "Findable Heading" })
|
|
125
|
+
).toBeInTheDocument();
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe("Ref Forwarding", () => {
|
|
130
|
+
it("should forward ref to the heading element", () => {
|
|
131
|
+
const ref = React.createRef<HTMLHeadingElement>();
|
|
132
|
+
render(<Title ref={ref}>Title with Ref</Title>);
|
|
133
|
+
|
|
134
|
+
expect(ref.current).toBeInstanceOf(HTMLHeadingElement);
|
|
135
|
+
expect(ref.current?.tagName.toLowerCase()).toBe("h2");
|
|
136
|
+
expect(ref.current?.textContent).toBe("Title with Ref");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("should allow focus via ref", () => {
|
|
140
|
+
const ref = React.createRef<HTMLHeadingElement>();
|
|
141
|
+
render(<Title ref={ref} tabIndex={-1}>Focusable Title</Title>);
|
|
142
|
+
|
|
143
|
+
ref.current?.focus();
|
|
144
|
+
expect(ref.current).toHaveFocus();
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe("Component API", () => {
|
|
149
|
+
it("should have displayName set", () => {
|
|
150
|
+
expect(Title.displayName).toBe("Title");
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("should accept all native heading attributes", () => {
|
|
154
|
+
render(
|
|
155
|
+
<Title
|
|
156
|
+
data-testid="custom-heading"
|
|
157
|
+
tabIndex={0}
|
|
158
|
+
title="Tooltip text"
|
|
159
|
+
>
|
|
160
|
+
Title
|
|
161
|
+
</Title>
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
const heading = screen.getByTestId("custom-heading");
|
|
165
|
+
expect(heading).toHaveAttribute("tabIndex", "0");
|
|
166
|
+
expect(heading).toHaveAttribute("title", "Tooltip text");
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe("Edge Cases", () => {
|
|
171
|
+
it("should handle empty string children", () => {
|
|
172
|
+
render(<Title>{""}</Title>);
|
|
173
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
174
|
+
expect(heading).toBeInTheDocument();
|
|
175
|
+
expect(heading).toHaveTextContent("");
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("should handle null children gracefully", () => {
|
|
179
|
+
render(<Title>{null}</Title>);
|
|
180
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
181
|
+
expect(heading).toBeInTheDocument();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("should handle multiple text nodes", () => {
|
|
185
|
+
render(
|
|
186
|
+
<Title>
|
|
187
|
+
Text one
|
|
188
|
+
{" "}
|
|
189
|
+
Text two
|
|
190
|
+
</Title>
|
|
191
|
+
);
|
|
192
|
+
const heading = screen.getByRole("heading", { level: 2 });
|
|
193
|
+
expect(heading).toHaveTextContent("Text one Text two");
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it("should handle conditional rendering", () => {
|
|
197
|
+
const showIcon = true;
|
|
198
|
+
render(
|
|
199
|
+
<Title>
|
|
200
|
+
{showIcon && <span data-testid="icon">📄</span>}
|
|
201
|
+
Document
|
|
202
|
+
</Title>
|
|
203
|
+
);
|
|
204
|
+
expect(screen.getByTestId("icon")).toBeInTheDocument();
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
describe("Integration with UI Component", () => {
|
|
209
|
+
it("should pass through all UI component props", () => {
|
|
210
|
+
render(
|
|
211
|
+
<Title
|
|
212
|
+
level="h3"
|
|
213
|
+
id="integration-test"
|
|
214
|
+
className="test-class"
|
|
215
|
+
styles={{ margin: "10px" }}
|
|
216
|
+
data-custom="value"
|
|
217
|
+
>
|
|
218
|
+
Integration Test
|
|
219
|
+
</Title>
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
const heading = screen.getByRole("heading", { level: 3 });
|
|
223
|
+
expect(heading).toHaveAttribute("id", "integration-test");
|
|
224
|
+
expect(heading).toHaveClass("test-class");
|
|
225
|
+
expect(heading).toHaveStyle({ margin: "10px" });
|
|
226
|
+
expect(heading).toHaveAttribute("data-custom", "value");
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
describe("Memoization", () => {
|
|
231
|
+
it("should be a memoized component", () => {
|
|
232
|
+
// Title is wrapped with React.memo, so it should have the memo properties
|
|
233
|
+
expect(Title.$$typeof).toBeDefined();
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
describe("Title Component - Backwards Compatibility", () => {
|
|
239
|
+
describe("Migration from Heading", () => {
|
|
240
|
+
it("should work with level prop (new API)", () => {
|
|
241
|
+
render(<Title level="h2">New API</Title>);
|
|
242
|
+
expect(screen.getByRole("heading", { level: 2 })).toHaveTextContent("New API");
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it("should use h2 as default (changed from h3)", () => {
|
|
246
|
+
// This tests the new default behavior
|
|
247
|
+
render(<Title>Default is now h2</Title>);
|
|
248
|
+
expect(screen.getByRole("heading", { level: 2 })).toBeInTheDocument();
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
});
|