@charcuterie/ui 4.5.0 → 4.6.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/README.md +7 -2
- package/dist/Card/Card.d.ts +5 -2
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +23 -3
- package/dist/Card/Card.js.map +1 -1
- package/dist/Overlay/OverlayPanel.d.ts.map +1 -1
- package/dist/Overlay/OverlayPanel.js +54 -2
- package/dist/Overlay/OverlayPanel.js.map +1 -1
- package/dist/Overlay/OverlayStack.d.ts +5 -0
- package/dist/Overlay/OverlayStack.d.ts.map +1 -1
- package/dist/Overlay/OverlayStack.js +2 -0
- package/dist/Overlay/OverlayStack.js.map +1 -1
- package/dist/Toast/ToastRegion.d.ts +61 -0
- package/dist/Toast/ToastRegion.d.ts.map +1 -1
- package/dist/Toast/ToastRegion.js +80 -3
- package/dist/Toast/ToastRegion.js.map +1 -1
- package/dist/Toolbar/useToolbarOverflow.d.ts.map +1 -1
- package/dist/Toolbar/useToolbarOverflow.js +39 -0
- package/dist/Toolbar/useToolbarOverflow.js.map +1 -1
- package/package.json +3 -2
- package/src/Accordion/Accordion.mdx +1 -1
- package/src/Accordion/Accordion.stories.tsx +3 -1
- package/src/Accordion/Accordion.test.tsx +4 -4
- package/src/ActionTiles/ActionTiles.mdx +1 -1
- package/src/ActionTiles/ActionTiles.stories.tsx +3 -1
- package/src/ActionTiles/ActionTiles.test.tsx +3 -3
- package/src/AdaptiveGrid/AdaptiveGrid.mdx +1 -1
- package/src/AdaptiveGrid/AdaptiveGrid.stories.tsx +3 -1
- package/src/AdaptiveGrid/AdaptiveGrid.test.tsx +5 -5
- package/src/Alert/Alert.mdx +1 -1
- package/src/Alert/Alert.stories.tsx +3 -1
- package/src/Alert/Alert.test.tsx +2 -2
- package/src/Avatar/Avatar.mdx +1 -1
- package/src/Avatar/Avatar.stories.tsx +4 -1
- package/src/Avatar/Avatar.test.tsx +2 -2
- package/src/Badge/Badge.mdx +1 -1
- package/src/Badge/Badge.stories.tsx +3 -1
- package/src/Badge/Badge.test.tsx +3 -3
- package/src/BadgeButton/BadgeButton.mdx +1 -1
- package/src/BadgeButton/BadgeButton.stories.tsx +3 -1
- package/src/BadgeButton/BadgeButton.test.tsx +2 -2
- package/src/Board/Board.mdx +1 -1
- package/src/Board/Board.stories.tsx +4 -1
- package/src/Board/Board.test.tsx +2 -2
- package/src/Button/Button.mdx +1 -1
- package/src/Button/Button.stories.tsx +3 -1
- package/src/Button/Button.test.tsx +2 -2
- package/src/ButtonLink/ButtonLink.mdx +1 -1
- package/src/ButtonLink/ButtonLink.stories.tsx +3 -1
- package/src/ButtonLink/ButtonLink.test.tsx +3 -3
- package/src/Card/Card.mdx +21 -1
- package/src/Card/Card.stories.tsx +91 -1
- package/src/Card/Card.test.tsx +60 -3
- package/src/Card/Card.tsx +24 -2
- package/src/Checkbox/Checkbox.mdx +1 -1
- package/src/Checkbox/Checkbox.stories.tsx +3 -1
- package/src/Checkbox/Checkbox.test.tsx +4 -4
- package/src/ColorSchemeSwitcher/ColorSchemeSwitcher.mdx +1 -1
- package/src/ColorSchemeSwitcher/ColorSchemeSwitcher.stories.tsx +3 -1
- package/src/ColorSchemeSwitcher/ColorSchemeSwitcher.test.tsx +5 -5
- package/src/ColorSchemeToggle/ColorSchemeToggle.mdx +1 -1
- package/src/ColorSchemeToggle/ColorSchemeToggle.stories.tsx +3 -1
- package/src/ColorSchemeToggle/ColorSchemeToggle.test.tsx +5 -5
- package/src/Combobox/Combobox.mdx +1 -1
- package/src/Combobox/Combobox.stories.tsx +3 -1
- package/src/Combobox/Combobox.test.tsx +2 -2
- package/src/CopyButton/CopyButton.mdx +1 -1
- package/src/CopyButton/CopyButton.stories.tsx +4 -1
- package/src/CopyButton/CopyButton.test.tsx +3 -3
- package/src/DataTable/DataTable.mdx +1 -1
- package/src/DataTable/DataTable.stories.tsx +3 -1
- package/src/DataTable/DataTable.test.tsx +3 -3
- package/src/DatePicker/DatePicker.mdx +1 -1
- package/src/DatePicker/DatePicker.stories.tsx +3 -1
- package/src/DatePicker/DatePicker.test.tsx +3 -3
- package/src/DatePicker/plainDate.test.ts +21 -3
- package/src/Dialog/Dialog.mdx +1 -1
- package/src/Dialog/Dialog.stories.tsx +3 -1
- package/src/Dialog/Dialog.test.tsx +2 -2
- package/src/DropRail/DropRail.mdx +1 -1
- package/src/DropRail/DropRail.stories.tsx +4 -1
- package/src/DropRail/DropRail.test.tsx +4 -4
- package/src/EmptyState/EmptyState.mdx +1 -1
- package/src/EmptyState/EmptyState.stories.tsx +3 -1
- package/src/EmptyState/EmptyState.test.tsx +2 -2
- package/src/Field/Field.mdx +1 -1
- package/src/Field/Field.stories.tsx +3 -1
- package/src/Field/Field.test.tsx +4 -4
- package/src/FileDropZone/FileDropZone.mdx +1 -1
- package/src/FileDropZone/FileDropZone.stories.tsx +3 -1
- package/src/FileDropZone/FileDropZone.test.tsx +3 -3
- package/src/Header/Header.mdx +1 -1
- package/src/Header/Header.stories.tsx +3 -1
- package/src/IconButton/IconButton.mdx +1 -1
- package/src/IconButton/IconButton.stories.tsx +3 -1
- package/src/IconButton/IconButton.test.tsx +2 -2
- package/src/Lightbox/Lightbox.mdx +1 -1
- package/src/Lightbox/Lightbox.stories.tsx +3 -1
- package/src/Lightbox/Lightbox.test.tsx +2 -2
- package/src/Listbox/Listbox.mdx +1 -1
- package/src/Listbox/Listbox.stories.tsx +3 -1
- package/src/Listbox/Listbox.test.tsx +5 -5
- package/src/LiveStatusIndicator/LiveStatusIndicator.mdx +1 -1
- package/src/LiveStatusIndicator/LiveStatusIndicator.stories.tsx +3 -1
- package/src/LiveStatusIndicator/LiveStatusIndicator.test.tsx +2 -2
- package/src/LogViewer/LogViewer.mdx +1 -1
- package/src/LogViewer/LogViewer.stories.tsx +3 -1
- package/src/LogViewer/LogViewer.test.tsx +2 -2
- package/src/Main/Main.mdx +1 -1
- package/src/Main/Main.stories.tsx +3 -1
- package/src/Main/Main.test.tsx +3 -3
- package/src/MarkdownEditor/MarkdownEditor.mdx +1 -1
- package/src/MarkdownEditor/MarkdownEditor.stories.tsx +3 -1
- package/src/MarkdownEditor/MarkdownEditor.test.tsx +4 -4
- package/src/MarkdownLine/MarkdownLine.mdx +1 -1
- package/src/MarkdownLine/MarkdownLine.stories.tsx +4 -1
- package/src/MarkdownLine/MarkdownLine.test.tsx +3 -3
- package/src/MediaTile/MediaTile.stories.tsx +3 -1
- package/src/MediaTile/MediaTile.test.tsx +2 -2
- package/src/Menu/Menu.mdx +1 -1
- package/src/Menu/Menu.stories.tsx +3 -1
- package/src/Modal/Modal.mdx +1 -1
- package/src/Modal/Modal.stories.tsx +3 -1
- package/src/Modal/Modal.test.tsx +3 -3
- package/src/Nav/Nav.mdx +1 -1
- package/src/Nav/Nav.stories.tsx +3 -1
- package/src/Nav/Nav.test.tsx +6 -6
- package/src/NavBar/NavBar.mdx +1 -1
- package/src/NavBar/NavBar.stories.tsx +3 -1
- package/src/NavBar/NavBar.test.tsx +3 -3
- package/src/Overlay/OverlayPanel.tsx +63 -2
- package/src/Overlay/OverlayStack.tsx +7 -1
- package/src/Picker/Picker.mdx +1 -1
- package/src/Picker/Picker.stories.tsx +3 -1
- package/src/Picker/Picker.test.tsx +2 -2
- package/src/Popover/Popover.mdx +1 -1
- package/src/Popover/Popover.stories.tsx +3 -1
- package/src/Popover/Popover.test.tsx +2 -2
- package/src/PortraitTiles/PortraitTiles.mdx +1 -1
- package/src/PortraitTiles/PortraitTiles.stories.tsx +3 -1
- package/src/PortraitTiles/PortraitTiles.test.tsx +5 -5
- package/src/ProgressBar/ProgressBar.mdx +1 -1
- package/src/ProgressBar/ProgressBar.stories.tsx +3 -1
- package/src/ProgressBar/ProgressBar.test.tsx +2 -2
- package/src/QueryBuilder/QueryBuilder.mdx +1 -1
- package/src/QueryBuilder/QueryBuilder.stories.tsx +3 -1
- package/src/QueryBuilder/QueryBuilder.test.tsx +2 -2
- package/src/RadioGroup/RadioGroup.mdx +1 -1
- package/src/RadioGroup/RadioGroup.stories.tsx +3 -1
- package/src/RadioGroup/RadioGroup.test.tsx +2 -2
- package/src/Rail/Rail.mdx +1 -1
- package/src/Rail/Rail.stories.tsx +3 -1
- package/src/Rail/Rail.test.tsx +2 -2
- package/src/RangeSlider/RangeSlider.mdx +1 -1
- package/src/RangeSlider/RangeSlider.stories.tsx +3 -1
- package/src/RangeSlider/RangeSlider.test.tsx +7 -3
- package/src/ReorderList/ReorderList.mdx +1 -1
- package/src/ReorderList/ReorderList.stories.tsx +3 -1
- package/src/ReorderList/ReorderList.test.tsx +7 -7
- package/src/RouterLink/UnstyledLink.stories.tsx +4 -1
- package/src/RouterLink/UnstyledLink.test.tsx +2 -2
- package/src/SearchInput/SearchInput.mdx +1 -1
- package/src/SearchInput/SearchInput.stories.tsx +3 -1
- package/src/SegmentedControl/SegmentedControl.mdx +1 -1
- package/src/SegmentedControl/SegmentedControl.stories.tsx +3 -1
- package/src/SegmentedControl/SegmentedControl.test.tsx +2 -2
- package/src/Select/Select.mdx +1 -1
- package/src/Select/Select.stories.tsx +3 -1
- package/src/Select/Select.test.tsx +4 -4
- package/src/Shell/Shell.mdx +1 -1
- package/src/Shell/Shell.stories.tsx +3 -1
- package/src/Shell/Shell.test.tsx +2 -2
- package/src/Skeleton/Skeleton.mdx +1 -1
- package/src/Skeleton/Skeleton.stories.tsx +3 -1
- package/src/Skeleton/Skeleton.test.tsx +2 -2
- package/src/Slider/Slider.mdx +1 -1
- package/src/Slider/Slider.stories.tsx +3 -1
- package/src/Slider/Slider.test.tsx +2 -2
- package/src/SortableTableHeader/SortableTableHeader.mdx +1 -1
- package/src/SortableTableHeader/SortableTableHeader.stories.tsx +3 -1
- package/src/SortableTableHeader/SortableTableHeader.test.tsx +3 -3
- package/src/Spinner/Spinner.mdx +1 -1
- package/src/Spinner/Spinner.stories.tsx +3 -1
- package/src/Spinner/Spinner.test.tsx +2 -2
- package/src/Stepper/Stepper.mdx +1 -1
- package/src/Stepper/Stepper.stories.tsx +4 -1
- package/src/Stepper/Stepper.test.tsx +7 -7
- package/src/Swatch/Swatch.mdx +1 -1
- package/src/Swatch/Swatch.stories.tsx +4 -1
- package/src/Swatch/Swatch.test.tsx +3 -3
- package/src/Switch/Switch.mdx +1 -1
- package/src/Switch/Switch.stories.tsx +3 -1
- package/src/Switch/Switch.test.tsx +2 -2
- package/src/Tabs/Tabs.mdx +1 -1
- package/src/Tabs/Tabs.stories.tsx +3 -1
- package/src/Tabs/Tabs.test.tsx +3 -3
- package/src/TextLink/TextLink.mdx +1 -1
- package/src/TextLink/TextLink.stories.tsx +3 -1
- package/src/TextLink/TextLink.test.tsx +4 -4
- package/src/TimecodeInput/TimecodeInput.mdx +1 -1
- package/src/TimecodeInput/TimecodeInput.stories.tsx +3 -1
- package/src/Toast/Toast.mdx +1 -1
- package/src/Toast/Toast.stories.tsx +157 -1
- package/src/Toast/Toast.test.tsx +2 -2
- package/src/Toast/ToastRegion.test.tsx +172 -0
- package/src/Toast/ToastRegion.tsx +120 -32
- package/src/Toolbar/Toolbar.mdx +1 -1
- package/src/Toolbar/Toolbar.stories.tsx +3 -1
- package/src/Toolbar/Toolbar.test.tsx +89 -5
- package/src/Toolbar/useToolbarOverflow.ts +43 -0
- package/src/Tooltip/Tooltip.mdx +1 -1
- package/src/Tooltip/Tooltip.stories.tsx +3 -1
- package/src/Tooltip/Tooltip.test.tsx +2 -2
- package/src/VirtualizedGrid/VirtualizedGrid.mdx +1 -1
- package/src/VirtualizedGrid/VirtualizedGrid.stories.tsx +4 -1
- package/src/VirtualizedGrid/VirtualizedGrid.test.tsx +5 -5
- package/src/VisuallyHidden/VisuallyHidden.mdx +1 -1
- package/src/VisuallyHidden/VisuallyHidden.stories.tsx +3 -1
- package/src/markdownEditorCodeMirror/MarkdownEditorCodeMirror.mdx +1 -1
- package/src/markdownEditorCodeMirror/MarkdownEditorCodeMirror.stories.tsx +3 -1
- package/src/markdownEditorCodeMirror/MarkdownEditorCodeMirror.test.tsx +3 -3
- package/src/markdownEditorCodeMirror/MarkdownView.mdx +1 -1
- package/src/markdownEditorCodeMirror/MarkdownView.stories.tsx +4 -1
- package/src/markdownEditorCodeMirror/MarkdownView.test.tsx +44 -20
- package/src/reactRouter/ReactRouterAdapter.stories.tsx +3 -1
- package/src/reactRouter/ReactRouterAdapter.test.tsx +2 -2
package/src/Card/Card.tsx
CHANGED
|
@@ -83,7 +83,10 @@ const PADDING_CLASS: Record<CardPadding, string> = {
|
|
|
83
83
|
*
|
|
84
84
|
* `aria-labelledby` rather than `aria-label`, because the heading is
|
|
85
85
|
* on screen already and stating the name twice is how the two drift
|
|
86
|
-
* apart.
|
|
86
|
+
* apart. A card with **no** `heading` keeps the `aria-labelledby`
|
|
87
|
+
* the call site passed, for the app that draws its own title row
|
|
88
|
+
* inside the card — the name still points at text on screen, which
|
|
89
|
+
* is the same rule one level out.
|
|
87
90
|
*
|
|
88
91
|
* **Density is not a prop here.** mux-magic's inventory turned up a
|
|
89
92
|
* `CardDensityProvider` in the withdrawn bambuddy evidence, and it
|
|
@@ -94,6 +97,7 @@ const PADDING_CLASS: Record<CardPadding, string> = {
|
|
|
94
97
|
* a layout fact rather than a density one.
|
|
95
98
|
*/
|
|
96
99
|
export const Card = ({
|
|
100
|
+
"aria-labelledby": ariaLabelledBy,
|
|
97
101
|
accentEdge,
|
|
98
102
|
actions,
|
|
99
103
|
children,
|
|
@@ -122,12 +126,30 @@ export const Card = ({
|
|
|
122
126
|
? style
|
|
123
127
|
: { ...accentEdgeStyle, ...style }
|
|
124
128
|
|
|
129
|
+
// The caller's own pointer is the FALLBACK, not the loser. This
|
|
130
|
+
// attribute is written *after* the spread, so `undefined` here
|
|
131
|
+
// does not mean "leave whatever the call site passed": it
|
|
132
|
+
// overwrites it, React then drops the attribute entirely, and the
|
|
133
|
+
// card's accessible name falls back to its whole subtree with
|
|
134
|
+
// nothing failing — not typecheck, not axe, not a render. A
|
|
135
|
+
// `role="button"` tile in mail-sifter naming itself
|
|
136
|
+
// `aria-labelledby="recent-tile-heading"` announced as "Recent
|
|
137
|
+
// Mail 6 40 arrived in the last 24 hours, 34 done".
|
|
138
|
+
//
|
|
139
|
+
// `heading` still wins when it is given, because that is the name
|
|
140
|
+
// the reader can see and this component renders it. Do not
|
|
141
|
+
// "simplify" this back to a ternary ending in `undefined`.
|
|
142
|
+
//
|
|
143
|
+
// `aria-label` needs no equivalent: the component never writes
|
|
144
|
+
// one, so the spread carries the caller's through untouched.
|
|
145
|
+
const labelledById = heading ? headingId : ariaLabelledBy
|
|
146
|
+
|
|
125
147
|
const Heading = `h${headingLevel}` as const
|
|
126
148
|
|
|
127
149
|
return (
|
|
128
150
|
<section
|
|
129
151
|
{...sectionProps}
|
|
130
|
-
aria-labelledby={
|
|
152
|
+
aria-labelledby={labelledById}
|
|
131
153
|
className={toClassName(
|
|
132
154
|
// `@container` here, not on a wrapper, is what lets the
|
|
133
155
|
// header stack at narrow widths *inside a wide viewport* —
|
|
@@ -16,7 +16,7 @@ Here the box is `bg-surface-sunken`, its border `border-border-strong`, and the
|
|
|
16
16
|
the kiosk with no per-app override. `BooleanField` becomes a thin wrapper that binds this
|
|
17
17
|
to a `CommandField`.
|
|
18
18
|
|
|
19
|
-
<Canvas of={CheckboxStories.
|
|
19
|
+
<Canvas of={CheckboxStories.Playground} />
|
|
20
20
|
|
|
21
21
|
## Props
|
|
22
22
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { playgroundParameters } from "@charcuterie/storybook-config/story-parameters"
|
|
1
2
|
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
3
|
|
|
3
4
|
import { controlSizeArgType } from "../argTypes.storyHelpers.ts"
|
|
@@ -29,7 +30,8 @@ export default meta
|
|
|
29
30
|
|
|
30
31
|
type Story = StoryObj<typeof meta>
|
|
31
32
|
|
|
32
|
-
export const
|
|
33
|
+
export const Playground: Story = {
|
|
34
|
+
parameters: playgroundParameters,
|
|
33
35
|
args: { label: "Delete originals after import" },
|
|
34
36
|
}
|
|
35
37
|
|
|
@@ -9,7 +9,7 @@ import * as stories from "./Checkbox.stories.tsx"
|
|
|
9
9
|
|
|
10
10
|
const {
|
|
11
11
|
AllStates,
|
|
12
|
-
|
|
12
|
+
Playground,
|
|
13
13
|
Interactive,
|
|
14
14
|
WithDescriptions,
|
|
15
15
|
WithValues,
|
|
@@ -17,7 +17,7 @@ const {
|
|
|
17
17
|
|
|
18
18
|
test("it is a checkbox a screen reader can name", async () => {
|
|
19
19
|
const { canvas, canvasElement } =
|
|
20
|
-
await mountStory(
|
|
20
|
+
await mountStory(Playground)
|
|
21
21
|
|
|
22
22
|
const checkbox = expectAgentDrivable(canvas, {
|
|
23
23
|
name: "Delete originals after import",
|
|
@@ -151,7 +151,7 @@ test("value names the member, and a group reads back the ticked ones", async ()
|
|
|
151
151
|
})
|
|
152
152
|
|
|
153
153
|
test("a box with no value stays out of the way", async () => {
|
|
154
|
-
const { canvas } = await mountStory(
|
|
154
|
+
const { canvas } = await mountStory(Playground)
|
|
155
155
|
|
|
156
156
|
// `value` is optional and a lone boolean should omit it. React drops
|
|
157
157
|
// an `undefined` attribute entirely rather than writing an empty
|
|
@@ -252,7 +252,7 @@ test("each box owns its own description, and the group owns the group's", async
|
|
|
252
252
|
})
|
|
253
253
|
|
|
254
254
|
test("a box with no description writes no aria-describedby", async () => {
|
|
255
|
-
const { canvas } = await mountStory(
|
|
255
|
+
const { canvas } = await mountStory(Playground)
|
|
256
256
|
|
|
257
257
|
// The slot is opt-in. React drops an `undefined` attribute rather
|
|
258
258
|
// than writing an empty string, so a box without a hint points at
|
|
@@ -12,7 +12,7 @@ the [`useColorScheme`](/) hook to the three defaults from `@charcuterie/logic/br
|
|
|
12
12
|
[`ColorSchemeToggle`](?path=/docs/components-colorschemetoggle--docs). Drop it in and the app
|
|
13
13
|
follows the OS, remembers the user's choice, and re-themes with zero React re-render.
|
|
14
14
|
|
|
15
|
-
<Canvas of={ColorSchemeSwitcherStories.
|
|
15
|
+
<Canvas of={ColorSchemeSwitcherStories.Playground} />
|
|
16
16
|
|
|
17
17
|
## Props
|
|
18
18
|
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
ColorSchemeResolver,
|
|
4
4
|
ResolvedColorScheme,
|
|
5
5
|
} from "@charcuterie/logic"
|
|
6
|
+
import { playgroundParameters } from "@charcuterie/storybook-config/story-parameters"
|
|
6
7
|
import type { Meta, StoryObj } from "@storybook/react"
|
|
7
8
|
import { useRef, useState } from "react"
|
|
8
9
|
import type { ColorSchemeIcons } from "../ColorSchemeToggle/ColorSchemeToggle.tsx"
|
|
@@ -113,6 +114,7 @@ type Story = StoryObj<typeof meta>
|
|
|
113
114
|
* scoped to the demo panel, which is exactly how a non-browser host
|
|
114
115
|
* (Electron `nativeTheme`) wires it — by replacing those seams.
|
|
115
116
|
*/
|
|
116
|
-
export const
|
|
117
|
+
export const Playground: Story = {
|
|
118
|
+
parameters: playgroundParameters,
|
|
117
119
|
render: () => <ScopedSwitcherDemo />,
|
|
118
120
|
}
|
|
@@ -7,7 +7,7 @@ import { mountStory } from "../mountStory.testHelpers.ts"
|
|
|
7
7
|
import { expectAgentDrivable } from "../testing/index.ts"
|
|
8
8
|
import * as stories from "./ColorSchemeSwitcher.stories.tsx"
|
|
9
9
|
|
|
10
|
-
const {
|
|
10
|
+
const { Playground } = composeStories(stories)
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* The connected switcher is agent-drivable and cycles like the
|
|
@@ -15,7 +15,7 @@ const { Default } = composeStories(stories)
|
|
|
15
15
|
* reaches the applier: the demo panel's `data-scheme` tracks it.
|
|
16
16
|
*/
|
|
17
17
|
test("it renders a named, drivable button", async () => {
|
|
18
|
-
const { canvas } = await mountStory(
|
|
18
|
+
const { canvas } = await mountStory(Playground)
|
|
19
19
|
|
|
20
20
|
expectAgentDrivable(canvas, {
|
|
21
21
|
name: /colour scheme/i,
|
|
@@ -24,7 +24,7 @@ test("it renders a named, drivable button", async () => {
|
|
|
24
24
|
})
|
|
25
25
|
|
|
26
26
|
test("system resolves through the injected resolver to the panel", async () => {
|
|
27
|
-
const { canvasElement } = await mountStory(
|
|
27
|
+
const { canvasElement } = await mountStory(Playground)
|
|
28
28
|
|
|
29
29
|
const panel = canvasElement.querySelector("[data-scheme]")
|
|
30
30
|
|
|
@@ -33,7 +33,7 @@ test("system resolves through the injected resolver to the panel", async () => {
|
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
test("cycling to a concrete mode re-applies the scheme", async () => {
|
|
36
|
-
const { canvasElement } = await mountStory(
|
|
36
|
+
const { canvasElement } = await mountStory(Playground)
|
|
37
37
|
|
|
38
38
|
const canvas = within(canvasElement)
|
|
39
39
|
|
|
@@ -53,7 +53,7 @@ test("cycling to a concrete mode re-applies the scheme", async () => {
|
|
|
53
53
|
})
|
|
54
54
|
|
|
55
55
|
test("the connected switcher forwards the neutral intent by default", async () => {
|
|
56
|
-
const { canvasElement } = await mountStory(
|
|
56
|
+
const { canvasElement } = await mountStory(Playground)
|
|
57
57
|
|
|
58
58
|
const button = canvasElement.querySelector("button")
|
|
59
59
|
|
|
@@ -16,7 +16,7 @@ That split is deliberate. The browser dependency lives one layer up in
|
|
|
16
16
|
runs unchanged in any runtime — a plain React app wires `onCycle` to `useState`, an Electron
|
|
17
17
|
or React-Native host wires it to `useColorScheme` with its own resolver.
|
|
18
18
|
|
|
19
|
-
<Canvas of={ColorSchemeToggleStories.
|
|
19
|
+
<Canvas of={ColorSchemeToggleStories.Playground} />
|
|
20
20
|
|
|
21
21
|
## Props
|
|
22
22
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ColorSchemeMode } from "@charcuterie/logic"
|
|
2
|
+
import { playgroundParameters } from "@charcuterie/storybook-config/story-parameters"
|
|
2
3
|
import type { Meta, StoryObj } from "@storybook/react"
|
|
3
4
|
import { useState } from "react"
|
|
4
5
|
|
|
@@ -71,7 +72,8 @@ type Story = StoryObj<typeof meta>
|
|
|
71
72
|
* The accessible name states the current mode and the next one, so
|
|
72
73
|
* it changes as the button cycles — that is what the test asserts.
|
|
73
74
|
*/
|
|
74
|
-
export const
|
|
75
|
+
export const Playground: Story = {
|
|
76
|
+
parameters: playgroundParameters,
|
|
75
77
|
render: (toggleProps) => {
|
|
76
78
|
const [mode, setMode] =
|
|
77
79
|
useState<ColorSchemeMode>("system")
|
|
@@ -10,7 +10,7 @@ import { mountStory } from "../mountStory.testHelpers.ts"
|
|
|
10
10
|
import { expectAgentDrivable } from "../testing/index.ts"
|
|
11
11
|
import meta, * as stories from "./ColorSchemeToggle.stories.tsx"
|
|
12
12
|
|
|
13
|
-
const { AllModes,
|
|
13
|
+
const { AllModes, Playground } = composeStories(stories)
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* The name states the current mode — a screen reader that lands on
|
|
@@ -18,7 +18,7 @@ const { AllModes, Default } = composeStories(stories)
|
|
|
18
18
|
* and an agent can find it.
|
|
19
19
|
*/
|
|
20
20
|
test("the toggle is named for its current mode", async () => {
|
|
21
|
-
const { canvas } = await mountStory(
|
|
21
|
+
const { canvas } = await mountStory(Playground)
|
|
22
22
|
|
|
23
23
|
expectAgentDrivable(canvas, {
|
|
24
24
|
name: /colour scheme: system/i,
|
|
@@ -27,7 +27,7 @@ test("the toggle is named for its current mode", async () => {
|
|
|
27
27
|
})
|
|
28
28
|
|
|
29
29
|
test("a press cycles the mode and updates the name", async () => {
|
|
30
|
-
const { canvas } = await mountStory(
|
|
30
|
+
const { canvas } = await mountStory(Playground)
|
|
31
31
|
|
|
32
32
|
const button = expectAgentDrivable(canvas, {
|
|
33
33
|
name: /colour scheme: system/i,
|
|
@@ -53,7 +53,7 @@ test("a press cycles the mode and updates the name", async () => {
|
|
|
53
53
|
|
|
54
54
|
test("the icon is hidden from assistive tech; the name carries it", async () => {
|
|
55
55
|
const { canvas, canvasElement } =
|
|
56
|
-
await mountStory(
|
|
56
|
+
await mountStory(Playground)
|
|
57
57
|
|
|
58
58
|
expectAgentDrivable(canvas, {
|
|
59
59
|
name: /colour scheme/i,
|
|
@@ -90,7 +90,7 @@ test("each mode renders its own control", async () => {
|
|
|
90
90
|
* action on real app chrome.
|
|
91
91
|
*/
|
|
92
92
|
test("defaults to the neutral intent, not accent", async () => {
|
|
93
|
-
const { canvasElement } = await mountStory(
|
|
93
|
+
const { canvasElement } = await mountStory(Playground)
|
|
94
94
|
|
|
95
95
|
const button = canvasElement.querySelector("button")
|
|
96
96
|
|
|
@@ -13,7 +13,7 @@ Use it when the list is long enough to search or filter; reach for
|
|
|
13
13
|
[`Listbox`](?path=/docs/components-listbox--docs) for a short rich-option list, and the
|
|
14
14
|
native [`Select`](?path=/docs/components-select--docs) for a plain one.
|
|
15
15
|
|
|
16
|
-
<Canvas of={ComboboxStories.
|
|
16
|
+
<Canvas of={ComboboxStories.Playground} />
|
|
17
17
|
|
|
18
18
|
## Props
|
|
19
19
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useVisibility } from "@charcuterie/logic"
|
|
2
|
+
import { playgroundParameters } from "@charcuterie/storybook-config/story-parameters"
|
|
2
3
|
import type { ControlSize } from "@charcuterie/tokens"
|
|
3
4
|
import type { Meta, StoryObj } from "@storybook/react"
|
|
4
5
|
import type { ReactNode } from "react"
|
|
@@ -150,7 +151,8 @@ const ComboboxHarness = ({
|
|
|
150
151
|
)
|
|
151
152
|
}
|
|
152
153
|
|
|
153
|
-
export const
|
|
154
|
+
export const Playground: Story = {
|
|
155
|
+
parameters: playgroundParameters,
|
|
154
156
|
args: {
|
|
155
157
|
isVisible: false,
|
|
156
158
|
onDismiss: () => {},
|
|
@@ -11,7 +11,7 @@ const {
|
|
|
11
11
|
AllVariants,
|
|
12
12
|
AttachedInputDrillDown,
|
|
13
13
|
ChosenValueOnOpen,
|
|
14
|
-
|
|
14
|
+
Playground,
|
|
15
15
|
DisabledFirstOption,
|
|
16
16
|
Interactive,
|
|
17
17
|
LongFooter,
|
|
@@ -42,7 +42,7 @@ const openMulti = async () => {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
const openDefault = async () => {
|
|
45
|
-
const mounted = await mountStory(
|
|
45
|
+
const mounted = await mountStory(Playground)
|
|
46
46
|
|
|
47
47
|
await userEvent.click(
|
|
48
48
|
expectAgentDrivable(mounted.canvas, {
|
|
@@ -9,7 +9,7 @@ import * as CopyButtonStories from "./CopyButton.stories";
|
|
|
9
9
|
**A button that puts a string on the clipboard and says so.** Press it, the label turns to
|
|
10
10
|
`Copied`, and the caller is told whether that is true.
|
|
11
11
|
|
|
12
|
-
<Canvas of={CopyButtonStories.
|
|
12
|
+
<Canvas of={CopyButtonStories.Playground} />
|
|
13
13
|
|
|
14
14
|
## Props
|
|
15
15
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { playgroundParameters } from "@charcuterie/storybook-config/story-parameters"
|
|
1
2
|
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
3
|
import { userEvent, within } from "storybook/test"
|
|
3
4
|
|
|
@@ -29,7 +30,9 @@ export default meta
|
|
|
29
30
|
|
|
30
31
|
type Story = StoryObj<typeof meta>
|
|
31
32
|
|
|
32
|
-
export const
|
|
33
|
+
export const Playground: Story = {
|
|
34
|
+
parameters: playgroundParameters,
|
|
35
|
+
}
|
|
33
36
|
|
|
34
37
|
/**
|
|
35
38
|
* The confirmation, held open. `confirmDuration` is enormous here so
|
|
@@ -16,11 +16,11 @@ import { expectAgentDrivable } from "../testing/index.ts"
|
|
|
16
16
|
import meta, * as stories from "./CopyButton.stories.tsx"
|
|
17
17
|
import { copyText } from "./copyText.ts"
|
|
18
18
|
|
|
19
|
-
const { Confirmed,
|
|
19
|
+
const { Confirmed, Playground, Refused } =
|
|
20
20
|
composeStories(stories)
|
|
21
21
|
|
|
22
22
|
test("is a button an agent can find by role and name", async () => {
|
|
23
|
-
const { canvas } = await mountStory(
|
|
23
|
+
const { canvas } = await mountStory(Playground)
|
|
24
24
|
|
|
25
25
|
const button = expectAgentDrivable(canvas, {
|
|
26
26
|
name: "Copy",
|
|
@@ -170,7 +170,7 @@ test("a prevented click copies nothing", async () => {
|
|
|
170
170
|
})
|
|
171
171
|
|
|
172
172
|
test("has no axe violations", async () => {
|
|
173
|
-
const { canvasElement } = await mountStory(
|
|
173
|
+
const { canvasElement } = await mountStory(Playground)
|
|
174
174
|
|
|
175
175
|
await expectNoAxeViolations(canvasElement)
|
|
176
176
|
})
|
|
@@ -10,7 +10,7 @@ import * as DataTableStories from "./DataTable.stories";
|
|
|
10
10
|
optional selection column, and the sort *announcement* — the data itself stays the
|
|
11
11
|
consumer's.
|
|
12
12
|
|
|
13
|
-
<Canvas of={DataTableStories.
|
|
13
|
+
<Canvas of={DataTableStories.Playground} />
|
|
14
14
|
|
|
15
15
|
## Props
|
|
16
16
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { playgroundParameters } from "@charcuterie/storybook-config/story-parameters"
|
|
1
2
|
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
3
|
import type { ReactNode } from "react"
|
|
3
4
|
import { useState } from "react"
|
|
@@ -266,7 +267,8 @@ type Story = StoryObj<typeof meta>
|
|
|
266
267
|
* of the split: the component says *which* column is sorted, the
|
|
267
268
|
* consumer says what that means for a priority enum.
|
|
268
269
|
*/
|
|
269
|
-
export const
|
|
270
|
+
export const Playground: Story = {
|
|
271
|
+
parameters: playgroundParameters,
|
|
270
272
|
render: () => (
|
|
271
273
|
<TaskTable
|
|
272
274
|
initialSort={{
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "../viewport.testHelpers.ts"
|
|
12
12
|
import * as stories from "./DataTable.stories.tsx"
|
|
13
13
|
|
|
14
|
-
const { AllVariants,
|
|
14
|
+
const { AllVariants, Playground, Interactive, Responsive } =
|
|
15
15
|
composeStories(stories)
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -23,7 +23,7 @@ const { AllVariants, Default, Interactive, Responsive } =
|
|
|
23
23
|
*/
|
|
24
24
|
test("the table is drivable by role and name", async () => {
|
|
25
25
|
const { canvas, canvasElement } =
|
|
26
|
-
await mountStory(
|
|
26
|
+
await mountStory(Playground)
|
|
27
27
|
|
|
28
28
|
const table = expectAgentDrivable(canvas, {
|
|
29
29
|
name: "Tasks",
|
|
@@ -43,7 +43,7 @@ test("the table is drivable by role and name", async () => {
|
|
|
43
43
|
* cannot be sorted", where `"none"` would say the opposite.
|
|
44
44
|
*/
|
|
45
45
|
test("sortable columns announce, unsortable ones stay silent", async () => {
|
|
46
|
-
const { canvas } = await mountStory(
|
|
46
|
+
const { canvas } = await mountStory(Playground)
|
|
47
47
|
|
|
48
48
|
const updated = expectAgentDrivable(canvas, {
|
|
49
49
|
name: "Updated",
|
|
@@ -11,7 +11,7 @@ it. The consumer that shaped it is **Docket** — due dates, scheduled dates, ph
|
|
|
11
11
|
ranges, and a staleness threshold counted in days
|
|
12
12
|
([decision](../../../docs/decisions/2026-08-19-a-date-is-a-calendar-date-not-an-instant.md)).
|
|
13
13
|
|
|
14
|
-
<Canvas of={DatePickerStories.
|
|
14
|
+
<Canvas of={DatePickerStories.Playground} />
|
|
15
15
|
|
|
16
16
|
## Props
|
|
17
17
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { playgroundParameters } from "@charcuterie/storybook-config/story-parameters"
|
|
1
2
|
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
3
|
import type { ReactNode } from "react"
|
|
3
4
|
import { useState } from "react"
|
|
@@ -99,7 +100,8 @@ const DatePickerHarness = ({
|
|
|
99
100
|
* `19 aug`, `2026-08-19` and a bare `19` all resolve, and the line
|
|
100
101
|
* underneath shows what they resolved to before anything commits.
|
|
101
102
|
*/
|
|
102
|
-
export const
|
|
103
|
+
export const Playground: Story = {
|
|
104
|
+
parameters: playgroundParameters,
|
|
103
105
|
args: { label: "Due date" },
|
|
104
106
|
render: () => <DatePickerHarness label="Due date" />,
|
|
105
107
|
}
|
|
@@ -12,11 +12,11 @@ import {
|
|
|
12
12
|
} from "../viewport.testHelpers.ts"
|
|
13
13
|
import * as stories from "./DatePicker.stories.tsx"
|
|
14
14
|
|
|
15
|
-
const { AllVariants,
|
|
15
|
+
const { AllVariants, Playground, Interactive } =
|
|
16
16
|
composeStories(stories)
|
|
17
17
|
|
|
18
18
|
const openDefault = async () => {
|
|
19
|
-
const mounted = await mountStory(
|
|
19
|
+
const mounted = await mountStory(Playground)
|
|
20
20
|
|
|
21
21
|
const input = expectAgentDrivable(mounted.canvas, {
|
|
22
22
|
name: "Due date",
|
|
@@ -415,7 +415,7 @@ test("a container narrower than --cq-xs drops the weekday headers to one letter"
|
|
|
415
415
|
// clamped to the space available and the calendar reads *that*.
|
|
416
416
|
await setViewport({ height: 700, width: 260 })
|
|
417
417
|
|
|
418
|
-
const { body, canvas } = await mountStory(
|
|
418
|
+
const { body, canvas } = await mountStory(Playground)
|
|
419
419
|
|
|
420
420
|
await userEvent.click(
|
|
421
421
|
expectAgentDrivable(canvas, {
|
|
@@ -155,16 +155,34 @@ test("the day number round-trips across four centuries", () => {
|
|
|
155
155
|
year: 2101,
|
|
156
156
|
})
|
|
157
157
|
|
|
158
|
+
// ⚠️ ONE assertion, not 74 000 of them.
|
|
159
|
+
//
|
|
160
|
+
// This loop covers about 74 000 days, and it used to call `expect` on every
|
|
161
|
+
// one. Vitest builds an assertion object per call, so the assertion overhead
|
|
162
|
+
// WAS the whole cost of the test — it ran right up against the default 5 000
|
|
163
|
+
// ms timeout and started failing on 2026-09-14 when the hosted runners got
|
|
164
|
+
// slower. Collecting the mismatches and asserting once removes the overhead
|
|
165
|
+
// and keeps every day covered.
|
|
166
|
+
//
|
|
167
|
+
// It also reports better. The old shape stopped at the first bad day; this
|
|
168
|
+
// one names every day that failed, which is what you want from a round-trip
|
|
169
|
+
// over a century rule.
|
|
170
|
+
const mismatchedDayNumbers = []
|
|
171
|
+
|
|
158
172
|
for (
|
|
159
173
|
let dayNumber = from;
|
|
160
174
|
dayNumber <= to;
|
|
161
175
|
dayNumber += 1
|
|
162
176
|
) {
|
|
163
|
-
|
|
164
|
-
getDayNumber(getPlainDateFromDayNumber(dayNumber))
|
|
165
|
-
|
|
177
|
+
if (
|
|
178
|
+
getDayNumber(getPlainDateFromDayNumber(dayNumber)) !==
|
|
179
|
+
dayNumber
|
|
180
|
+
)
|
|
181
|
+
mismatchedDayNumbers.push(dayNumber)
|
|
166
182
|
}
|
|
167
183
|
|
|
184
|
+
expect(mismatchedDayNumbers).toEqual([])
|
|
185
|
+
|
|
168
186
|
expect(
|
|
169
187
|
getDayNumber({ day: 1, month: 1, year: 1970 }),
|
|
170
188
|
).toBe(0)
|
package/src/Dialog/Dialog.mdx
CHANGED
|
@@ -12,7 +12,7 @@ Close button, a scrolling body, an optional footer, and five sizes. This is what
|
|
|
12
12
|
and hands the generic one back to the base layer
|
|
13
13
|
([decision](../../../docs/decisions/2026-08-03-modal-is-the-base-layer-and-dialog-is-the-component.md)).
|
|
14
14
|
|
|
15
|
-
<Canvas of={DialogStories.
|
|
15
|
+
<Canvas of={DialogStories.Playground} />
|
|
16
16
|
|
|
17
17
|
## Props
|
|
18
18
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useVisibility } from "@charcuterie/logic"
|
|
2
|
+
import { playgroundParameters } from "@charcuterie/storybook-config/story-parameters"
|
|
2
3
|
import type { Meta, StoryObj } from "@storybook/react"
|
|
3
4
|
import type { ReactNode } from "react"
|
|
4
5
|
import { useRef } from "react"
|
|
@@ -121,7 +122,8 @@ const InitialFocusDemo = (): ReactNode => {
|
|
|
121
122
|
)
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
export const
|
|
125
|
+
export const Playground: Story = {
|
|
126
|
+
parameters: playgroundParameters,
|
|
125
127
|
args: {
|
|
126
128
|
heading: "Bay 3",
|
|
127
129
|
isVisible: false,
|
|
@@ -13,7 +13,7 @@ import * as stories from "./Dialog.stories.tsx"
|
|
|
13
13
|
const {
|
|
14
14
|
AllStates,
|
|
15
15
|
AllVariants,
|
|
16
|
-
|
|
16
|
+
Playground,
|
|
17
17
|
InitialFocus,
|
|
18
18
|
Interactive,
|
|
19
19
|
NoBody,
|
|
@@ -49,7 +49,7 @@ test("a dialog with no body renders from heading and footer alone", async () =>
|
|
|
49
49
|
})
|
|
50
50
|
|
|
51
51
|
test("the dialog is reachable from a body-scoped query", async () => {
|
|
52
|
-
const { body, canvas } = await mountStory(
|
|
52
|
+
const { body, canvas } = await mountStory(Playground)
|
|
53
53
|
|
|
54
54
|
await userEvent.click(
|
|
55
55
|
expectAgentDrivable(canvas, {
|
|
@@ -9,7 +9,7 @@ import * as DropRailStories from "./DropRail.stories";
|
|
|
9
9
|
Every destination at once, brought to the pointer instead of the pointer being carried to
|
|
10
10
|
it.
|
|
11
11
|
|
|
12
|
-
<Canvas of={DropRailStories.
|
|
12
|
+
<Canvas of={DropRailStories.Playground} />
|
|
13
13
|
|
|
14
14
|
## Props
|
|
15
15
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { playgroundParameters } from "@charcuterie/storybook-config/story-parameters"
|
|
1
2
|
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
3
|
import { useState } from "react"
|
|
3
4
|
|
|
@@ -170,7 +171,9 @@ type Story = StoryObj<typeof meta>
|
|
|
170
171
|
* group the card is already in — visible, unofferable, and saying so
|
|
171
172
|
* to a screen reader rather than only by being dimmer.
|
|
172
173
|
*/
|
|
173
|
-
export const
|
|
174
|
+
export const Playground: Story = {
|
|
175
|
+
parameters: playgroundParameters,
|
|
176
|
+
}
|
|
174
177
|
|
|
175
178
|
/**
|
|
176
179
|
* The case the component exists for. Thirty-four destinations do not
|
|
@@ -6,7 +6,7 @@ import { expectNoAxeViolations } from "../expectNoAxeViolations.testHelpers.ts"
|
|
|
6
6
|
import { mountStory } from "../mountStory.testHelpers.ts"
|
|
7
7
|
import * as stories from "./DropRail.stories.tsx"
|
|
8
8
|
|
|
9
|
-
const { AllStates,
|
|
9
|
+
const { AllStates, Playground, InAList, ManyTargets } =
|
|
10
10
|
composeStories(stories)
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -25,7 +25,7 @@ const { AllStates, Default, InAList, ManyTargets } =
|
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
27
|
test("the rail is a listbox of destinations", async () => {
|
|
28
|
-
const { canvas } = await mountStory(
|
|
28
|
+
const { canvas } = await mountStory(Playground)
|
|
29
29
|
|
|
30
30
|
const rail = canvas.getByRole("listbox", {
|
|
31
31
|
name: "Move to which project",
|
|
@@ -51,7 +51,7 @@ test("a closed rail renders nothing at all", async () => {
|
|
|
51
51
|
})
|
|
52
52
|
|
|
53
53
|
test("the group a card is already in is shown but not offerable", async () => {
|
|
54
|
-
const { canvas } = await mountStory(
|
|
54
|
+
const { canvas } = await mountStory(Playground)
|
|
55
55
|
|
|
56
56
|
const current = canvas.getByRole("option", {
|
|
57
57
|
name: /Atlas Ingest/,
|
|
@@ -64,7 +64,7 @@ test("the group a card is already in is shown but not offerable", async () => {
|
|
|
64
64
|
})
|
|
65
65
|
|
|
66
66
|
test("an archived destination is refused", async () => {
|
|
67
|
-
const { canvas } = await mountStory(
|
|
67
|
+
const { canvas } = await mountStory(Playground)
|
|
68
68
|
|
|
69
69
|
expect(
|
|
70
70
|
canvas.getByRole("option", {
|
|
@@ -14,7 +14,7 @@ Designed fresh rather than ported: the two repos that had a real `EmptyState` wi
|
|
|
14
14
|
variants were bambuddy and spoolbuddy, which are upstream projects rather than Kevin's
|
|
15
15
|
code, so that evidence was withdrawn from the plan.
|
|
16
16
|
|
|
17
|
-
<Canvas of={EmptyStateStories.
|
|
17
|
+
<Canvas of={EmptyStateStories.Playground} />
|
|
18
18
|
|
|
19
19
|
## Props
|
|
20
20
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { playgroundParameters } from "@charcuterie/storybook-config/story-parameters"
|
|
1
2
|
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
3
|
import { Button } from "../Button/Button.tsx"
|
|
3
4
|
import {
|
|
@@ -30,7 +31,8 @@ type Story = StoryObj<typeof meta>
|
|
|
30
31
|
* The heading is the handle. Eleven copies of "Nothing here" in a
|
|
31
32
|
* `<div>` are indistinguishable to an agent; a named heading is not.
|
|
32
33
|
*/
|
|
33
|
-
export const
|
|
34
|
+
export const Playground: Story = {
|
|
35
|
+
parameters: playgroundParameters,
|
|
34
36
|
args: {
|
|
35
37
|
description:
|
|
36
38
|
"Insert a disc and rip-deck will pick it up automatically.",
|
|
@@ -6,11 +6,11 @@ import { mountStory } from "../mountStory.testHelpers.ts"
|
|
|
6
6
|
import { expectAgentDrivable } from "../testing/index.ts"
|
|
7
7
|
import * as stories from "./EmptyState.stories.tsx"
|
|
8
8
|
|
|
9
|
-
const {
|
|
9
|
+
const { Playground, DeeplyNested, Interactive } =
|
|
10
10
|
composeStories(stories)
|
|
11
11
|
|
|
12
12
|
test("the heading is the handle", async () => {
|
|
13
|
-
const { canvas } = await mountStory(
|
|
13
|
+
const { canvas } = await mountStory(Playground)
|
|
14
14
|
|
|
15
15
|
expectAgentDrivable(canvas, {
|
|
16
16
|
name: "No discs queued",
|
package/src/Field/Field.mdx
CHANGED
|
@@ -25,7 +25,7 @@ wrong in the *other* file. Half of them are broken and nothing says which half.
|
|
|
25
25
|
the argument for a component rather than a convention — here the id is minted and consumed
|
|
26
26
|
in one place and cannot be spelled twice.
|
|
27
27
|
|
|
28
|
-
<Canvas of={FieldStories.
|
|
28
|
+
<Canvas of={FieldStories.Playground} />
|
|
29
29
|
|
|
30
30
|
`Field` is also how a `Picker` (or `Button`, or an app's own control) sits next to
|
|
31
31
|
its label **without butting against the last word**. Those controls are
|