@nationaldesignstudio/react 0.5.2 → 0.5.4
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/package.json +10 -2
- package/src/components/organisms/navbar/navbar.tsx +8 -8
- package/src/App.css +0 -0
- package/src/App.tsx +0 -7
- package/src/assets/fonts/PPNeueMontreal-Variable.woff2 +0 -0
- package/src/assets/react.svg +0 -1
- package/src/components/atoms/accordion/accordion.stories.tsx +0 -228
- package/src/components/atoms/accordion/accordion.test.tsx +0 -231
- package/src/components/atoms/accordion/index.ts +0 -6
- package/src/components/atoms/background/background.test.tsx +0 -213
- package/src/components/atoms/background/index.ts +0 -22
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-charcoal-outline-quiet-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-disabled-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-ivory-outline-quiet-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-large-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-medium-chromium-linux.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-darwin.png +0 -0
- package/src/components/atoms/button/__screenshots__/button.visual.test.tsx/button-size-small-chromium-linux.png +0 -0
- package/src/components/atoms/button/button.stories.tsx +0 -289
- package/src/components/atoms/button/button.test.tsx +0 -419
- package/src/components/atoms/button/button.visual.test.tsx +0 -98
- package/src/components/atoms/button/icon-button.stories.tsx +0 -260
- package/src/components/atoms/button/icon-button.test.tsx +0 -186
- package/src/components/atoms/button/index.ts +0 -6
- package/src/components/atoms/input/index.ts +0 -17
- package/src/components/atoms/input/input-group.stories.tsx +0 -646
- package/src/components/atoms/input/input-group.test.tsx +0 -362
- package/src/components/atoms/input/input.stories.tsx +0 -228
- package/src/components/atoms/input/input.test.tsx +0 -167
- package/src/components/atoms/ndstudio-footer/index.ts +0 -1
- package/src/components/atoms/pager-control/index.ts +0 -5
- package/src/components/atoms/pager-control/pager-control.stories.tsx +0 -207
- package/src/components/atoms/pager-control/pager-control.test.tsx +0 -130
- package/src/components/atoms/popover/index.ts +0 -30
- package/src/components/atoms/popover/popover.stories.tsx +0 -531
- package/src/components/atoms/popover/popover.test.tsx +0 -486
- package/src/components/atoms/select/index.ts +0 -18
- package/src/components/atoms/select/select.stories.tsx +0 -455
- package/src/components/atoms/tooltip/index.ts +0 -24
- package/src/components/atoms/tooltip/tooltip.stories.tsx +0 -348
- package/src/components/atoms/tooltip/tooltip.test.tsx +0 -363
- package/src/components/dev-tools/dev-toolbar/dev-toolbar.stories.tsx +0 -73
- package/src/components/dev-tools/dev-toolbar/index.ts +0 -1
- package/src/components/dev-tools/grid-overlay/index.ts +0 -1
- package/src/components/dev-tools/index.ts +0 -2
- package/src/components/foundation/typography/typography.stories.tsx +0 -401
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-default-vertical-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-default-vertical-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-horizontal-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-horizontal-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-minimal-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-minimal-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-actions-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-actions-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-eyebrow-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-eyebrow-chromium-linux.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-image-chromium-darwin.png +0 -0
- package/src/components/organisms/card/__screenshots__/card.visual.test.tsx/card-without-image-chromium-linux.png +0 -0
- package/src/components/organisms/card/card.stories.tsx +0 -293
- package/src/components/organisms/card/card.test.tsx +0 -247
- package/src/components/organisms/card/card.visual.test.tsx +0 -197
- package/src/components/organisms/card/index.ts +0 -26
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-darwin.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-active-link-chromium-linux.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-darwin.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-brand-only-chromium-linux.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-darwin.png +0 -0
- package/src/components/organisms/navbar/__screenshots__/navbar.visual.test.tsx/navbar-default-chromium-linux.png +0 -0
- package/src/components/organisms/navbar/index.ts +0 -18
- package/src/components/organisms/navbar/navbar.stories.tsx +0 -313
- package/src/components/organisms/navbar/navbar.test.tsx +0 -190
- package/src/components/organisms/navbar/navbar.visual.test.tsx +0 -85
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-darwin.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-icon-chromium-linux.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-darwin.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-custom-text-chromium-linux.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-darwin.png +0 -0
- package/src/components/organisms/us-gov-banner/__screenshots__/us-gov-banner.visual.test.tsx/us-gov-banner-default-chromium-linux.png +0 -0
- package/src/components/organisms/us-gov-banner/index.ts +0 -5
- package/src/components/organisms/us-gov-banner/us-gov-banner.stories.tsx +0 -35
- package/src/components/organisms/us-gov-banner/us-gov-banner.test.tsx +0 -107
- package/src/components/organisms/us-gov-banner/us-gov-banner.visual.test.tsx +0 -46
- package/src/components/sections/banner/banner.stories.tsx +0 -150
- package/src/components/sections/banner/banner.test.tsx +0 -185
- package/src/components/sections/banner/index.ts +0 -2
- package/src/components/sections/card-grid/card-grid.stories.tsx +0 -351
- package/src/components/sections/card-grid/index.ts +0 -1
- package/src/components/sections/faq-section/faq-section.stories.tsx +0 -453
- package/src/components/sections/faq-section/index.ts +0 -2
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-desktop-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-mobile-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a1-tablet-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-desktop-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-mobile-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a2-tablet-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-desktop-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-mobile-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-a3-tablet-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-custom-class-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-default-chromium-linux.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-darwin.png +0 -0
- package/src/components/sections/hero/__screenshots__/hero.visual.test.tsx/hero-long-title-chromium-linux.png +0 -0
- package/src/components/sections/hero/hero.stories.tsx +0 -397
- package/src/components/sections/hero/hero.test.tsx +0 -138
- package/src/components/sections/hero/hero.visual.test.tsx +0 -140
- package/src/components/sections/hero/index.ts +0 -23
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-darwin.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-h3-heading-chromium-linux.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-darwin.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-paragraphs-chromium-linux.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-darwin.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-multiple-sections-chromium-linux.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-darwin.png +0 -0
- package/src/components/sections/prose/__screenshots__/prose.visual.test.tsx/prose-single-section-chromium-linux.png +0 -0
- package/src/components/sections/prose/index.ts +0 -6
- package/src/components/sections/prose/prose.stories.tsx +0 -144
- package/src/components/sections/prose/prose.test.tsx +0 -178
- package/src/components/sections/prose/prose.visual.test.tsx +0 -105
- package/src/components/sections/quote-block/index.ts +0 -5
- package/src/components/sections/river/index.ts +0 -1
- package/src/components/sections/river/river.stories.tsx +0 -237
- package/src/components/sections/river/river.test.tsx +0 -268
- package/src/components/sections/tout/index.ts +0 -1
- package/src/components/sections/tout/tout.stories.tsx +0 -171
- package/src/components/sections/tout/tout.test.tsx +0 -242
- package/src/components/sections/two-column-section/index.ts +0 -5
- package/src/components/sections/two-column-section/two-column-section.stories.tsx +0 -285
- package/src/components/shared/index.ts +0 -5
- package/src/index.ts +0 -293
- package/src/main.tsx +0 -13
- package/src/stories/grid-system.stories.tsx +0 -309
- package/src/stories/introduction.mdx +0 -128
- package/src/stories/theme-provider.stories.tsx +0 -349
- package/src/stories/token-showcase.stories.tsx +0 -73
- package/src/stories/token-showcase.tsx +0 -777
- package/src/styles.css +0 -14
- package/src/tests/token-resolution.test.tsx +0 -298
- package/src/theme/theme-provider.test.tsx +0 -270
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { Prose, ProseSection } from ".";
|
|
3
|
-
|
|
4
|
-
const meta: Meta<typeof Prose> = {
|
|
5
|
-
title: "Sections/Prose",
|
|
6
|
-
component: Prose,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: "centered",
|
|
9
|
-
},
|
|
10
|
-
} as Meta<typeof Prose>;
|
|
11
|
-
|
|
12
|
-
export default meta;
|
|
13
|
-
type Story = StoryObj<typeof Prose>;
|
|
14
|
-
|
|
15
|
-
const sampleIntro =
|
|
16
|
-
"On the modern web, typography is not decoration; it's the cognitive interface. Before a user understands your product, policy, or program, they're unconsciously reading the structure of your type: the hierarchy of headings, the discipline of your spacing, the confidence or hesitation in your line lengths.";
|
|
17
|
-
|
|
18
|
-
const sampleParagraph1 =
|
|
19
|
-
"Style here isn't about clever fonts, it's about creating a system of visual cues that makes thinking easier. A consistent scale, clear contrast between roles, and careful use of weight and size become a kind of mental exoskeleton for the reader. Done well, typography lowers the friction of understanding to the point where attention can be spent on the content itself rather than on decoding the layout.";
|
|
20
|
-
|
|
21
|
-
const sampleParagraph2 =
|
|
22
|
-
'Rhythm is where that structure turns into a voice. Online, people experience your text as a sequence of micro-moments: the way a headline sits in space, how paragraphs breathe, where the eye can rest. Tight, compressed leading and dense blocks say, "this is serious, pay attention." Generous white space and measured line lengths say, "you have room to think." Over time, those choices form a recognizable persona, just as surely as a writing style does. When the rhythm is intentional, your site speaks with a calm, authoritative cadence that users begin to trust. When it\'s sloppy or inconsistent, the voice fractures, and so does the sense that there\'s a clear, competent mind behind the interface.';
|
|
23
|
-
|
|
24
|
-
// =============================================================================
|
|
25
|
-
// Default
|
|
26
|
-
// =============================================================================
|
|
27
|
-
|
|
28
|
-
export const Default: Story = {
|
|
29
|
-
render: () => (
|
|
30
|
-
<Prose>
|
|
31
|
-
<ProseSection heading="Headline - Medium" as="h2">
|
|
32
|
-
<p>{sampleIntro}</p>
|
|
33
|
-
</ProseSection>
|
|
34
|
-
<ProseSection heading="Headline - Small" as="h3">
|
|
35
|
-
<p>{sampleParagraph1}</p>
|
|
36
|
-
<p>{sampleParagraph2}</p>
|
|
37
|
-
</ProseSection>
|
|
38
|
-
</Prose>
|
|
39
|
-
),
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// =============================================================================
|
|
43
|
-
// Responsive Variants
|
|
44
|
-
// =============================================================================
|
|
45
|
-
|
|
46
|
-
export const Desktop: Story = {
|
|
47
|
-
render: () => (
|
|
48
|
-
<Prose>
|
|
49
|
-
<ProseSection heading="Headline - Medium" as="h2">
|
|
50
|
-
<p>{sampleIntro}</p>
|
|
51
|
-
</ProseSection>
|
|
52
|
-
<ProseSection heading="Headline - Small" as="h3">
|
|
53
|
-
<p>{sampleParagraph1}</p>
|
|
54
|
-
<p>{sampleParagraph2}</p>
|
|
55
|
-
</ProseSection>
|
|
56
|
-
</Prose>
|
|
57
|
-
),
|
|
58
|
-
globals: {
|
|
59
|
-
viewport: { value: "lg", isRotated: false },
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export const Tablet: Story = {
|
|
64
|
-
render: () => (
|
|
65
|
-
<Prose>
|
|
66
|
-
<ProseSection heading="Headline - Medium" as="h2">
|
|
67
|
-
<p>{sampleIntro}</p>
|
|
68
|
-
</ProseSection>
|
|
69
|
-
<ProseSection heading="Headline - Small" as="h3">
|
|
70
|
-
<p>{sampleParagraph1}</p>
|
|
71
|
-
<p>{sampleParagraph2}</p>
|
|
72
|
-
</ProseSection>
|
|
73
|
-
</Prose>
|
|
74
|
-
),
|
|
75
|
-
globals: {
|
|
76
|
-
viewport: { value: "md", isRotated: false },
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export const Mobile: Story = {
|
|
81
|
-
render: () => (
|
|
82
|
-
<Prose>
|
|
83
|
-
<ProseSection heading="Headline - Medium" as="h2">
|
|
84
|
-
<p>{sampleIntro}</p>
|
|
85
|
-
</ProseSection>
|
|
86
|
-
<ProseSection heading="Headline - Small" as="h3">
|
|
87
|
-
<p>{sampleParagraph1}</p>
|
|
88
|
-
<p>{sampleParagraph2}</p>
|
|
89
|
-
</ProseSection>
|
|
90
|
-
</Prose>
|
|
91
|
-
),
|
|
92
|
-
globals: {
|
|
93
|
-
viewport: { value: "sm", isRotated: false },
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
// =============================================================================
|
|
98
|
-
// Playground
|
|
99
|
-
// =============================================================================
|
|
100
|
-
|
|
101
|
-
export const Playground: Story = {
|
|
102
|
-
render: (args) => (
|
|
103
|
-
<Prose {...args}>
|
|
104
|
-
<ProseSection heading="Main Heading" as="h2">
|
|
105
|
-
<p>{sampleIntro}</p>
|
|
106
|
-
</ProseSection>
|
|
107
|
-
<ProseSection heading="Subheading" as="h3">
|
|
108
|
-
<p>{sampleParagraph1}</p>
|
|
109
|
-
<p>{sampleParagraph2}</p>
|
|
110
|
-
</ProseSection>
|
|
111
|
-
</Prose>
|
|
112
|
-
),
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
// =============================================================================
|
|
116
|
-
// Examples
|
|
117
|
-
// =============================================================================
|
|
118
|
-
|
|
119
|
-
export const SingleSection: Story = {
|
|
120
|
-
render: () => (
|
|
121
|
-
<Prose>
|
|
122
|
-
<ProseSection heading="About Our Mission" as="h2">
|
|
123
|
-
<p>{sampleIntro}</p>
|
|
124
|
-
<p>{sampleParagraph1}</p>
|
|
125
|
-
</ProseSection>
|
|
126
|
-
</Prose>
|
|
127
|
-
),
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
export const MultipleSections: Story = {
|
|
131
|
-
render: () => (
|
|
132
|
-
<Prose>
|
|
133
|
-
<ProseSection heading="Introduction" as="h2">
|
|
134
|
-
<p>{sampleIntro}</p>
|
|
135
|
-
</ProseSection>
|
|
136
|
-
<ProseSection heading="The Importance of Style" as="h3">
|
|
137
|
-
<p>{sampleParagraph1}</p>
|
|
138
|
-
</ProseSection>
|
|
139
|
-
<ProseSection heading="Finding Your Rhythm" as="h3">
|
|
140
|
-
<p>{sampleParagraph2}</p>
|
|
141
|
-
</ProseSection>
|
|
142
|
-
</Prose>
|
|
143
|
-
),
|
|
144
|
-
};
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
2
|
-
import { page } from "vitest/browser";
|
|
3
|
-
import { render } from "vitest-browser-react";
|
|
4
|
-
import { Prose, ProseSection } from "./prose";
|
|
5
|
-
|
|
6
|
-
describe("Prose", () => {
|
|
7
|
-
describe("Accessibility", () => {
|
|
8
|
-
test("ProseSection renders as section landmark", async () => {
|
|
9
|
-
render(
|
|
10
|
-
<Prose>
|
|
11
|
-
<ProseSection heading="Test Section" data-testid="section">
|
|
12
|
-
<p>Content</p>
|
|
13
|
-
</ProseSection>
|
|
14
|
-
</Prose>,
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
const section = page.getByTestId("section");
|
|
18
|
-
await expect.element(section).toBeInTheDocument();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test("ProseSection heading renders as h2 by default", async () => {
|
|
22
|
-
render(
|
|
23
|
-
<Prose>
|
|
24
|
-
<ProseSection heading="Default Heading">
|
|
25
|
-
<p>Content</p>
|
|
26
|
-
</ProseSection>
|
|
27
|
-
</Prose>,
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
await expect
|
|
31
|
-
.element(
|
|
32
|
-
page.getByRole("heading", { level: 2, name: "Default Heading" }),
|
|
33
|
-
)
|
|
34
|
-
.toBeInTheDocument();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test("ProseSection heading renders as h3 when specified", async () => {
|
|
38
|
-
render(
|
|
39
|
-
<Prose>
|
|
40
|
-
<ProseSection heading="H3 Heading" as="h3">
|
|
41
|
-
<p>Content</p>
|
|
42
|
-
</ProseSection>
|
|
43
|
-
</Prose>,
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
await expect
|
|
47
|
-
.element(page.getByRole("heading", { level: 3, name: "H3 Heading" }))
|
|
48
|
-
.toBeInTheDocument();
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test("prose content is readable", async () => {
|
|
52
|
-
render(
|
|
53
|
-
<Prose>
|
|
54
|
-
<ProseSection heading="Readable Content">
|
|
55
|
-
<p>This is some readable body text.</p>
|
|
56
|
-
</ProseSection>
|
|
57
|
-
</Prose>,
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
await expect
|
|
61
|
-
.element(page.getByText("This is some readable body text."))
|
|
62
|
-
.toBeInTheDocument();
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
describe("Props", () => {
|
|
67
|
-
test("Prose renders children", async () => {
|
|
68
|
-
render(
|
|
69
|
-
<Prose data-testid="prose">
|
|
70
|
-
<ProseSection heading="Child Section">
|
|
71
|
-
<p>Child content</p>
|
|
72
|
-
</ProseSection>
|
|
73
|
-
</Prose>,
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
await expect.element(page.getByText("Child content")).toBeInTheDocument();
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test("Prose supports custom className", async () => {
|
|
80
|
-
render(
|
|
81
|
-
<Prose className="custom-prose" data-testid="prose">
|
|
82
|
-
<ProseSection heading="Test">
|
|
83
|
-
<p>Content</p>
|
|
84
|
-
</ProseSection>
|
|
85
|
-
</Prose>,
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
const prose = page.getByTestId("prose");
|
|
89
|
-
await expect.element(prose).toHaveClass(/custom-prose/);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test("ProseSection supports custom className", async () => {
|
|
93
|
-
render(
|
|
94
|
-
<Prose>
|
|
95
|
-
<ProseSection
|
|
96
|
-
heading="Test"
|
|
97
|
-
className="custom-section"
|
|
98
|
-
data-testid="section"
|
|
99
|
-
>
|
|
100
|
-
<p>Content</p>
|
|
101
|
-
</ProseSection>
|
|
102
|
-
</Prose>,
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
const section = page.getByTestId("section");
|
|
106
|
-
await expect.element(section).toHaveClass(/custom-section/);
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
describe("Styling", () => {
|
|
111
|
-
test("Prose has max-width constraint", async () => {
|
|
112
|
-
render(
|
|
113
|
-
<Prose data-testid="prose">
|
|
114
|
-
<ProseSection heading="Test">
|
|
115
|
-
<p>Content</p>
|
|
116
|
-
</ProseSection>
|
|
117
|
-
</Prose>,
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
const prose = page.getByTestId("prose");
|
|
121
|
-
await expect.element(prose).toHaveClass(/max-w-\[700px\]/);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
test("h2 heading has correct typography class", async () => {
|
|
125
|
-
render(
|
|
126
|
-
<Prose>
|
|
127
|
-
<ProseSection heading="H2 Test">
|
|
128
|
-
<p>Content</p>
|
|
129
|
-
</ProseSection>
|
|
130
|
-
</Prose>,
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
const heading = page.getByRole("heading", { name: "H2 Test" });
|
|
134
|
-
await expect.element(heading).toHaveClass(/typography-h3/);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
test("h3 heading has correct typography class", async () => {
|
|
138
|
-
render(
|
|
139
|
-
<Prose>
|
|
140
|
-
<ProseSection heading="H3 Test" as="h3">
|
|
141
|
-
<p>Content</p>
|
|
142
|
-
</ProseSection>
|
|
143
|
-
</Prose>,
|
|
144
|
-
);
|
|
145
|
-
|
|
146
|
-
const heading = page.getByRole("heading", { name: "H3 Test" });
|
|
147
|
-
await expect.element(heading).toHaveClass(/typography-h4/);
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
describe("Composition", () => {
|
|
152
|
-
test("renders multiple sections", async () => {
|
|
153
|
-
render(
|
|
154
|
-
<Prose>
|
|
155
|
-
<ProseSection heading="First">
|
|
156
|
-
<p>First content</p>
|
|
157
|
-
</ProseSection>
|
|
158
|
-
<ProseSection heading="Second">
|
|
159
|
-
<p>Second content</p>
|
|
160
|
-
</ProseSection>
|
|
161
|
-
<ProseSection heading="Third">
|
|
162
|
-
<p>Third content</p>
|
|
163
|
-
</ProseSection>
|
|
164
|
-
</Prose>,
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
await expect
|
|
168
|
-
.element(page.getByRole("heading", { name: "First" }))
|
|
169
|
-
.toBeInTheDocument();
|
|
170
|
-
await expect
|
|
171
|
-
.element(page.getByRole("heading", { name: "Second" }))
|
|
172
|
-
.toBeInTheDocument();
|
|
173
|
-
await expect
|
|
174
|
-
.element(page.getByRole("heading", { name: "Third" }))
|
|
175
|
-
.toBeInTheDocument();
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
});
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { render } from "@testing-library/react";
|
|
2
|
-
import { describe, expect, test } from "vitest";
|
|
3
|
-
import { page } from "vitest/browser";
|
|
4
|
-
import { Prose, ProseSection } from "./prose";
|
|
5
|
-
|
|
6
|
-
describe("Prose Visual Regression", () => {
|
|
7
|
-
test("prose with single section renders correctly", async () => {
|
|
8
|
-
render(
|
|
9
|
-
<div
|
|
10
|
-
style={{ width: "800px", backgroundColor: "#ffffff", padding: "40px" }}
|
|
11
|
-
>
|
|
12
|
-
<Prose data-testid="prose">
|
|
13
|
-
<ProseSection heading="Section Heading">
|
|
14
|
-
<p>
|
|
15
|
-
This is a paragraph of body text that demonstrates the prose
|
|
16
|
-
component's typography and spacing. It should be easy to read and
|
|
17
|
-
properly formatted.
|
|
18
|
-
</p>
|
|
19
|
-
</ProseSection>
|
|
20
|
-
</Prose>
|
|
21
|
-
</div>,
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
await expect(page.getByTestId("prose")).toMatchScreenshot(
|
|
25
|
-
"prose-single-section",
|
|
26
|
-
);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test("prose with multiple sections renders correctly", async () => {
|
|
30
|
-
render(
|
|
31
|
-
<div
|
|
32
|
-
style={{ width: "800px", backgroundColor: "#ffffff", padding: "40px" }}
|
|
33
|
-
>
|
|
34
|
-
<Prose data-testid="prose">
|
|
35
|
-
<ProseSection heading="First Section">
|
|
36
|
-
<p>
|
|
37
|
-
This is the first section of content with some body text to
|
|
38
|
-
demonstrate spacing between sections.
|
|
39
|
-
</p>
|
|
40
|
-
</ProseSection>
|
|
41
|
-
<ProseSection heading="Second Section">
|
|
42
|
-
<p>
|
|
43
|
-
This is the second section showing how multiple sections stack
|
|
44
|
-
with proper gaps between them.
|
|
45
|
-
</p>
|
|
46
|
-
</ProseSection>
|
|
47
|
-
</Prose>
|
|
48
|
-
</div>,
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
await expect(page.getByTestId("prose")).toMatchScreenshot(
|
|
52
|
-
"prose-multiple-sections",
|
|
53
|
-
);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
test("prose with h3 heading renders correctly", async () => {
|
|
57
|
-
render(
|
|
58
|
-
<div
|
|
59
|
-
style={{ width: "800px", backgroundColor: "#ffffff", padding: "40px" }}
|
|
60
|
-
>
|
|
61
|
-
<Prose data-testid="prose">
|
|
62
|
-
<ProseSection heading="H3 Heading" as="h3">
|
|
63
|
-
<p>
|
|
64
|
-
This section uses an h3 heading which has smaller typography than
|
|
65
|
-
the default h2.
|
|
66
|
-
</p>
|
|
67
|
-
</ProseSection>
|
|
68
|
-
</Prose>
|
|
69
|
-
</div>,
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
await expect(page.getByTestId("prose")).toMatchScreenshot(
|
|
73
|
-
"prose-h3-heading",
|
|
74
|
-
);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test("prose with multiple paragraphs renders correctly", async () => {
|
|
78
|
-
render(
|
|
79
|
-
<div
|
|
80
|
-
style={{ width: "800px", backgroundColor: "#ffffff", padding: "40px" }}
|
|
81
|
-
>
|
|
82
|
-
<Prose data-testid="prose">
|
|
83
|
-
<ProseSection heading="Long Content">
|
|
84
|
-
<p>
|
|
85
|
-
First paragraph with some content to show how multiple paragraphs
|
|
86
|
-
are spaced within a prose section.
|
|
87
|
-
</p>
|
|
88
|
-
<p>
|
|
89
|
-
Second paragraph demonstrating the gap between paragraphs in the
|
|
90
|
-
prose component.
|
|
91
|
-
</p>
|
|
92
|
-
<p>
|
|
93
|
-
Third paragraph to show consistent spacing throughout the content
|
|
94
|
-
area.
|
|
95
|
-
</p>
|
|
96
|
-
</ProseSection>
|
|
97
|
-
</Prose>
|
|
98
|
-
</div>,
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
await expect(page.getByTestId("prose")).toMatchScreenshot(
|
|
102
|
-
"prose-multiple-paragraphs",
|
|
103
|
-
);
|
|
104
|
-
});
|
|
105
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { River, type RiverProps, riverVariants } from "./river";
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { Button } from "../../atoms/button";
|
|
3
|
-
import { River } from ".";
|
|
4
|
-
|
|
5
|
-
const meta: Meta<typeof River> = {
|
|
6
|
-
title: "Sections/River",
|
|
7
|
-
component: River,
|
|
8
|
-
parameters: {
|
|
9
|
-
layout: "fullscreen",
|
|
10
|
-
},
|
|
11
|
-
argTypes: {
|
|
12
|
-
variant: {
|
|
13
|
-
control: "select",
|
|
14
|
-
options: ["A", "B"],
|
|
15
|
-
description: "Layout variant",
|
|
16
|
-
},
|
|
17
|
-
headline: {
|
|
18
|
-
control: "text",
|
|
19
|
-
description: "The headline text",
|
|
20
|
-
},
|
|
21
|
-
body: {
|
|
22
|
-
control: "text",
|
|
23
|
-
description: "The body text",
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
decorators: [
|
|
27
|
-
(Story) => (
|
|
28
|
-
<div className="grid-container">
|
|
29
|
-
<Story />
|
|
30
|
-
</div>
|
|
31
|
-
),
|
|
32
|
-
],
|
|
33
|
-
} as Meta<typeof River>;
|
|
34
|
-
|
|
35
|
-
export default meta;
|
|
36
|
-
type Story = StoryObj<typeof River>;
|
|
37
|
-
|
|
38
|
-
const PlaceholderImage = () => (
|
|
39
|
-
<div className="bg-gray-200 w-full aspect-[4/3] rounded-lg flex items-center justify-center">
|
|
40
|
-
<span className="text-gray-500 typography-body-small">
|
|
41
|
-
Image Placeholder
|
|
42
|
-
</span>
|
|
43
|
-
</div>
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
export const Playground: Story = {
|
|
47
|
-
render: (args) => <River {...args} />,
|
|
48
|
-
};
|
|
49
|
-
Playground.args = {
|
|
50
|
-
variant: "A",
|
|
51
|
-
headline: "Feature Headline",
|
|
52
|
-
body: "Use rivers to present content with supporting media. They work great for feature highlights, product showcases, and storytelling sections.",
|
|
53
|
-
primaryAction: <Button>Primary Action</Button>,
|
|
54
|
-
secondaryAction: <Button variant="outline">Secondary</Button>,
|
|
55
|
-
media: <PlaceholderImage />,
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// =============================================================================
|
|
59
|
-
// Variants
|
|
60
|
-
// =============================================================================
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Variant A: Text on left, media on right (desktop)
|
|
64
|
-
*/
|
|
65
|
-
export const VariantA: Story = {
|
|
66
|
-
render: () => (
|
|
67
|
-
<River
|
|
68
|
-
variant="A"
|
|
69
|
-
headline="Text Left, Media Right"
|
|
70
|
-
body="Variant A places the text content on the left (9 columns) and media on the right (15 columns) on desktop viewports. On mobile and tablet, they stack vertically."
|
|
71
|
-
primaryAction={<Button>Primary Action</Button>}
|
|
72
|
-
secondaryAction={<Button variant="outline">Secondary</Button>}
|
|
73
|
-
media={<PlaceholderImage />}
|
|
74
|
-
/>
|
|
75
|
-
),
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Variant B: Media on left, text on right (desktop)
|
|
80
|
-
*/
|
|
81
|
-
export const VariantB: Story = {
|
|
82
|
-
render: () => (
|
|
83
|
-
<River
|
|
84
|
-
variant="B"
|
|
85
|
-
headline="Media Left, Text Right"
|
|
86
|
-
body="Variant B places the media on the left (15 columns) and text content on the right (9 columns) on desktop viewports. On mobile and tablet, they stack vertically with text first."
|
|
87
|
-
primaryAction={<Button>Primary Action</Button>}
|
|
88
|
-
secondaryAction={<Button variant="outline">Secondary</Button>}
|
|
89
|
-
media={<PlaceholderImage />}
|
|
90
|
-
/>
|
|
91
|
-
),
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
// =============================================================================
|
|
95
|
-
// Responsive Variants
|
|
96
|
-
// =============================================================================
|
|
97
|
-
|
|
98
|
-
export const VariantADesktop: Story = {
|
|
99
|
-
render: () => (
|
|
100
|
-
<River
|
|
101
|
-
variant="A"
|
|
102
|
-
headline="Desktop View"
|
|
103
|
-
body="On desktop (lg, 1440px), the content spans 9 columns and the media spans 15 columns in a horizontal layout."
|
|
104
|
-
primaryAction={<Button>Primary</Button>}
|
|
105
|
-
secondaryAction={<Button variant="outline">Secondary</Button>}
|
|
106
|
-
media={<PlaceholderImage />}
|
|
107
|
-
/>
|
|
108
|
-
),
|
|
109
|
-
globals: {
|
|
110
|
-
viewport: { value: "lg", isRotated: false },
|
|
111
|
-
},
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
export const VariantATablet: Story = {
|
|
115
|
-
render: () => (
|
|
116
|
-
<River
|
|
117
|
-
variant="A"
|
|
118
|
-
headline="Tablet View"
|
|
119
|
-
body="On tablet (md, 768px), the content and media stack vertically with the text above the media."
|
|
120
|
-
primaryAction={<Button>Primary</Button>}
|
|
121
|
-
secondaryAction={<Button variant="outline">Secondary</Button>}
|
|
122
|
-
media={<PlaceholderImage />}
|
|
123
|
-
/>
|
|
124
|
-
),
|
|
125
|
-
globals: {
|
|
126
|
-
viewport: { value: "md", isRotated: false },
|
|
127
|
-
},
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
export const VariantAMobile: Story = {
|
|
131
|
-
render: () => (
|
|
132
|
-
<River
|
|
133
|
-
variant="A"
|
|
134
|
-
headline="Mobile View"
|
|
135
|
-
body="On mobile (sm, 320px), content is stacked with smaller button sizing."
|
|
136
|
-
primaryAction={<Button size="sm">Primary</Button>}
|
|
137
|
-
secondaryAction={
|
|
138
|
-
<Button size="sm" variant="outline">
|
|
139
|
-
Secondary
|
|
140
|
-
</Button>
|
|
141
|
-
}
|
|
142
|
-
media={<PlaceholderImage />}
|
|
143
|
-
/>
|
|
144
|
-
),
|
|
145
|
-
globals: {
|
|
146
|
-
viewport: { value: "sm", isRotated: false },
|
|
147
|
-
},
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
export const VariantBDesktop: Story = {
|
|
151
|
-
render: () => (
|
|
152
|
-
<River
|
|
153
|
-
variant="B"
|
|
154
|
-
headline="Desktop View - Reversed"
|
|
155
|
-
body="Variant B reverses the layout, placing media on the left and content on the right."
|
|
156
|
-
primaryAction={<Button>Primary</Button>}
|
|
157
|
-
secondaryAction={<Button variant="outline">Secondary</Button>}
|
|
158
|
-
media={<PlaceholderImage />}
|
|
159
|
-
/>
|
|
160
|
-
),
|
|
161
|
-
globals: {
|
|
162
|
-
viewport: { value: "lg", isRotated: false },
|
|
163
|
-
},
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
// =============================================================================
|
|
167
|
-
// Examples
|
|
168
|
-
// =============================================================================
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Without secondary action
|
|
172
|
-
*/
|
|
173
|
-
export const SingleAction: Story = {
|
|
174
|
-
render: () => (
|
|
175
|
-
<River
|
|
176
|
-
variant="A"
|
|
177
|
-
headline="Single Action Button"
|
|
178
|
-
body="Rivers can also be used with just a primary action button when a secondary action isn't needed."
|
|
179
|
-
primaryAction={<Button>Learn More</Button>}
|
|
180
|
-
media={<PlaceholderImage />}
|
|
181
|
-
/>
|
|
182
|
-
),
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Alternating rivers for visual rhythm
|
|
187
|
-
*/
|
|
188
|
-
export const AlternatingRivers: Story = {
|
|
189
|
-
render: () => (
|
|
190
|
-
<>
|
|
191
|
-
<River
|
|
192
|
-
variant="A"
|
|
193
|
-
headline="First Feature"
|
|
194
|
-
body="Start with text on the left for the first section."
|
|
195
|
-
primaryAction={<Button>Explore</Button>}
|
|
196
|
-
media={<PlaceholderImage />}
|
|
197
|
-
/>
|
|
198
|
-
<River
|
|
199
|
-
variant="B"
|
|
200
|
-
headline="Second Feature"
|
|
201
|
-
body="Alternate to media on the left for visual variety."
|
|
202
|
-
primaryAction={<Button>Discover</Button>}
|
|
203
|
-
media={<PlaceholderImage />}
|
|
204
|
-
className="bg-gray-100"
|
|
205
|
-
/>
|
|
206
|
-
<River
|
|
207
|
-
variant="A"
|
|
208
|
-
headline="Third Feature"
|
|
209
|
-
body="Return to the original layout to create rhythm."
|
|
210
|
-
primaryAction={<Button>Learn More</Button>}
|
|
211
|
-
media={<PlaceholderImage />}
|
|
212
|
-
/>
|
|
213
|
-
</>
|
|
214
|
-
),
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* With actual image
|
|
219
|
-
*/
|
|
220
|
-
export const WithImage: Story = {
|
|
221
|
-
render: () => (
|
|
222
|
-
<River
|
|
223
|
-
variant="A"
|
|
224
|
-
headline="Real World Example"
|
|
225
|
-
body="Rivers work great with actual images, videos, or any media content. The media column is designed to accommodate various aspect ratios."
|
|
226
|
-
primaryAction={<Button>Get Started</Button>}
|
|
227
|
-
secondaryAction={<Button variant="outline">Learn More</Button>}
|
|
228
|
-
media={
|
|
229
|
-
<img
|
|
230
|
-
src="https://images.unsplash.com/photo-1551434678-e076c223a692?w=800&h=600&fit=crop"
|
|
231
|
-
alt="Team collaboration"
|
|
232
|
-
className="rounded-lg object-cover"
|
|
233
|
-
/>
|
|
234
|
-
}
|
|
235
|
-
/>
|
|
236
|
-
),
|
|
237
|
-
};
|