@cascivo/mcp 0.2.0 → 0.3.3
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/LICENSE +1 -1
- package/README.md +53 -23
- package/dist/context/accordion.md +93 -0
- package/dist/context/action-sheet.md +117 -0
- package/dist/context/alert-dialog.md +122 -0
- package/dist/context/alert.md +110 -0
- package/dist/context/app-shell.md +98 -0
- package/dist/context/aspect-ratio.md +92 -0
- package/dist/context/avatar-group.md +111 -0
- package/dist/context/avatar.md +100 -0
- package/dist/context/badge.md +119 -0
- package/dist/context/block/console-app.md +66 -0
- package/dist/context/block/dashboard-charts.md +61 -0
- package/dist/context/block/empty-dashboard.md +60 -0
- package/dist/context/block/login-page.md +60 -0
- package/dist/context/block/notification-center.md +61 -0
- package/dist/context/block/page-with-breadcrumb.md +54 -0
- package/dist/context/block/settings-form-page.md +60 -0
- package/dist/context/block/sidebar-app.md +55 -0
- package/dist/context/block/stats-cards.md +61 -0
- package/dist/context/block/users-table-page.md +61 -0
- package/dist/context/blockquote.md +95 -0
- package/dist/context/bottom-sheet.md +112 -0
- package/dist/context/breadcrumb.md +106 -0
- package/dist/context/button-group.md +100 -0
- package/dist/context/button.md +117 -0
- package/dist/context/calendar.md +118 -0
- package/dist/context/card.md +90 -0
- package/dist/context/carousel.md +101 -0
- package/dist/context/chart/area-chart.md +99 -0
- package/dist/context/chart/bar-chart.md +114 -0
- package/dist/context/chart/boxplot.md +82 -0
- package/dist/context/chart/bubble-chart.md +80 -0
- package/dist/context/chart/bullet.md +75 -0
- package/dist/context/chart/calendar.md +79 -0
- package/dist/context/chart/candlestick.md +104 -0
- package/dist/context/chart/combo-chart.md +78 -0
- package/dist/context/chart/funnel.md +87 -0
- package/dist/context/chart/gauge.md +87 -0
- package/dist/context/chart/heatmap.md +77 -0
- package/dist/context/chart/histogram.md +74 -0
- package/dist/context/chart/kpi.md +70 -0
- package/dist/context/chart/line-chart.md +113 -0
- package/dist/context/chart/meter.md +71 -0
- package/dist/context/chart/pie-chart.md +126 -0
- package/dist/context/chart/polar.md +92 -0
- package/dist/context/chart/radar.md +81 -0
- package/dist/context/chart/radial-bar.md +96 -0
- package/dist/context/chart/sankey.md +89 -0
- package/dist/context/chart/scatter-chart.md +90 -0
- package/dist/context/chart/sparkline.md +69 -0
- package/dist/context/chart/stream.md +88 -0
- package/dist/context/chart/sunburst.md +93 -0
- package/dist/context/chart/treemap.md +84 -0
- package/dist/context/chat-bubble.md +116 -0
- package/dist/context/checkbox-card.md +104 -0
- package/dist/context/checkbox.md +104 -0
- package/dist/context/code-snippet.md +118 -0
- package/dist/context/code.md +103 -0
- package/dist/context/collapsible.md +104 -0
- package/dist/context/color-picker.md +101 -0
- package/dist/context/combobox.md +125 -0
- package/dist/context/command-menu.md +121 -0
- package/dist/context/comparison.md +117 -0
- package/dist/context/contained-list.md +103 -0
- package/dist/context/context-menu.md +103 -0
- package/dist/context/copy-button.md +106 -0
- package/dist/context/data-list.md +99 -0
- package/dist/context/data-table.md +149 -0
- package/dist/context/date-picker.md +116 -0
- package/dist/context/date-range-picker.md +113 -0
- package/dist/context/dock.md +117 -0
- package/dist/context/drawer.md +111 -0
- package/dist/context/dropdown.md +96 -0
- package/dist/context/editable.md +101 -0
- package/dist/context/editor/code-editor.md +146 -0
- package/dist/context/editor/highlight.md +74 -0
- package/dist/context/empty-state.md +101 -0
- package/dist/context/fab.md +128 -0
- package/dist/context/field.md +118 -0
- package/dist/context/file-uploader.md +121 -0
- package/dist/context/filter.md +129 -0
- package/dist/context/flow/flow-background.md +103 -0
- package/dist/context/flow/flow-canvas.md +82 -0
- package/dist/context/flow/flow-controls.md +84 -0
- package/dist/context/flow/flow-edge.md +128 -0
- package/dist/context/flow/flow-handle.md +83 -0
- package/dist/context/flow/flow-minimap.md +89 -0
- package/dist/context/flow/flow-node.md +97 -0
- package/dist/context/flow/flow-panel.md +75 -0
- package/dist/context/flow/flow-story.md +145 -0
- package/dist/context/flow/flow.md +139 -0
- package/dist/context/form.md +104 -0
- package/dist/context/header-panel.md +96 -0
- package/dist/context/header.md +104 -0
- package/dist/context/heading.md +107 -0
- package/dist/context/hover-card.md +108 -0
- package/dist/context/icon-button.md +115 -0
- package/dist/context/image.md +115 -0
- package/dist/context/indicator.md +95 -0
- package/dist/context/inline-loading.md +101 -0
- package/dist/context/input-group.md +122 -0
- package/dist/context/input.md +101 -0
- package/dist/context/item.md +109 -0
- package/dist/context/join.md +97 -0
- package/dist/context/kbd.md +100 -0
- package/dist/context/label.md +117 -0
- package/dist/context/layout/app-shell.md +85 -0
- package/dist/context/layout/auth-layout.md +74 -0
- package/dist/context/layout/auto-grid.md +69 -0
- package/dist/context/layout/center.md +67 -0
- package/dist/context/layout/columns.md +70 -0
- package/dist/context/layout/dashboard-layout.md +68 -0
- package/dist/context/layout/grid.md +70 -0
- package/dist/context/layout/masonry.md +70 -0
- package/dist/context/layout/page-header.md +75 -0
- package/dist/context/layout/section.md +69 -0
- package/dist/context/layout/settings-layout.md +68 -0
- package/dist/context/layout/spacer.md +64 -0
- package/dist/context/layout/split-view.md +71 -0
- package/dist/context/layout/stack.md +93 -0
- package/dist/context/link.md +112 -0
- package/dist/context/list.md +109 -0
- package/dist/context/log-viewer.md +124 -0
- package/dist/context/menu-button.md +137 -0
- package/dist/context/menu.md +108 -0
- package/dist/context/menubar.md +92 -0
- package/dist/context/modal.md +96 -0
- package/dist/context/multi-select.md +104 -0
- package/dist/context/native-select.md +118 -0
- package/dist/context/navigation-menu.md +95 -0
- package/dist/context/notification.md +116 -0
- package/dist/context/number-input.md +117 -0
- package/dist/context/otp-input.md +98 -0
- package/dist/context/overflow-menu.md +107 -0
- package/dist/context/pagination.md +123 -0
- package/dist/context/password-input.md +100 -0
- package/dist/context/popover.md +108 -0
- package/dist/context/progress-bar.md +107 -0
- package/dist/context/progress-circle.md +101 -0
- package/dist/context/progress-indicator.md +105 -0
- package/dist/context/progress.md +109 -0
- package/dist/context/prose.md +110 -0
- package/dist/context/pull-to-refresh.md +101 -0
- package/dist/context/qr-code.md +101 -0
- package/dist/context/radial-progress.md +117 -0
- package/dist/context/radio-card.md +95 -0
- package/dist/context/radio.md +94 -0
- package/dist/context/rating-group.md +97 -0
- package/dist/context/relative-time.md +90 -0
- package/dist/context/resizable.md +102 -0
- package/dist/context/scroll-area.md +101 -0
- package/dist/context/search.md +113 -0
- package/dist/context/section/cta.md +83 -0
- package/dist/context/section/feature-grid.md +98 -0
- package/dist/context/section/hero.md +101 -0
- package/dist/context/section/media-masonry.md +77 -0
- package/dist/context/section/page-footer.md +101 -0
- package/dist/context/section/stats-band.md +81 -0
- package/dist/context/segmented-control.md +101 -0
- package/dist/context/select.md +101 -0
- package/dist/context/separator.md +88 -0
- package/dist/context/sheet.md +100 -0
- package/dist/context/shell-header.md +105 -0
- package/dist/context/side-nav.md +134 -0
- package/dist/context/skeleton.md +101 -0
- package/dist/context/skip-nav.md +103 -0
- package/dist/context/slider.md +98 -0
- package/dist/context/spinner.md +89 -0
- package/dist/context/stack.md +96 -0
- package/dist/context/stat.md +101 -0
- package/dist/context/status.md +105 -0
- package/dist/context/steps.md +124 -0
- package/dist/context/structured-list.md +107 -0
- package/dist/context/swap.md +100 -0
- package/dist/context/swipe-item.md +110 -0
- package/dist/context/switcher.md +97 -0
- package/dist/context/tabs.md +93 -0
- package/dist/context/tag.md +110 -0
- package/dist/context/tags-input.md +94 -0
- package/dist/context/text.md +111 -0
- package/dist/context/textarea.md +98 -0
- package/dist/context/tile.md +116 -0
- package/dist/context/time-picker.md +102 -0
- package/dist/context/timeline.md +93 -0
- package/dist/context/toast.md +91 -0
- package/dist/context/toc.md +110 -0
- package/dist/context/toggle-group.md +118 -0
- package/dist/context/toggle.md +103 -0
- package/dist/context/toggletip.md +119 -0
- package/dist/context/tooltip.md +92 -0
- package/dist/context/tree-view.md +107 -0
- package/dist/context/user.md +100 -0
- package/dist/context/visually-hidden.md +90 -0
- package/dist/context.json +22456 -0
- package/dist/index.d.mts +3 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +73 -32
- package/dist/index.mjs.map +1 -1
- package/dist/marketplace.json +70 -0
- package/dist/registry.json +2832 -358
- package/dist/tokens.catalog.json +2375 -0
- package/dist/tokens.variants.json +3291 -0
- package/package.json +4 -3
- package/readme.body.md +53 -23
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# DataTable
|
|
2
|
+
|
|
3
|
+
**Category:** display
|
|
4
|
+
**Description:** Signal-driven data table with client/server sort, filter, pagination, multi-selection, expandable rows, and CSS content-visibility row containment for large datasets
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Displaying tabular data with columns the user sorts, filters, or pages through
|
|
9
|
+
- Selecting rows for batch actions across a dataset
|
|
10
|
+
- Rendering large datasets that benefit from row containment and server-side sort/paging
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- A simple static list of items — use List
|
|
15
|
+
- Layout grids of cards or media — use a Card grid, not a data table
|
|
16
|
+
|
|
17
|
+
## Anti-patterns
|
|
18
|
+
|
|
19
|
+
### The full table machinery (sort, paging, selection) is overhead when there is no dataset to operate on
|
|
20
|
+
|
|
21
|
+
**Bad:** `Using DataTable for two columns of label/value pairs`
|
|
22
|
+
**Good:** `A description list or a small Card with Stat/Text`
|
|
23
|
+
**Why:** The full table machinery (sort, paging, selection) is overhead when there is no dataset to operate on
|
|
24
|
+
|
|
25
|
+
## Related components
|
|
26
|
+
|
|
27
|
+
- **Pagination** (contains): DataTable embeds pagination controls for paged data
|
|
28
|
+
- **EmptyState** (pairs-with): Render an EmptyState via the emptyState prop when there are no rows
|
|
29
|
+
|
|
30
|
+
## Accessibility rationale
|
|
31
|
+
|
|
32
|
+
Built on a native <table> with proper header semantics; sortable headers expose sort state, selection uses real checkboxes, and arrow-key navigation follows the grid pattern so keyboard users can traverse cells
|
|
33
|
+
|
|
34
|
+
## Props
|
|
35
|
+
|
|
36
|
+
| Name | Type | Required | Default | Description |
|
|
37
|
+
| ------------------- | ---------------------------------------------------------------------------------------- | -------- | -------- | ------------------------------------------------------------------------------- |
|
|
38
|
+
| `columns` | `Column<Row>[]` | Yes | — | The column definitions describing each table column. |
|
|
39
|
+
| `rows` | `Row[]` | Yes | — | Number of visible text rows. |
|
|
40
|
+
| `getRowId` | `(row: Row) => string` | No | — | Returns a stable unique id for a row. |
|
|
41
|
+
| `sort` | `SortState` | No | — | The controlled sort state. |
|
|
42
|
+
| `defaultSort` | `SortState` | No | — | The initial sort state when uncontrolled. |
|
|
43
|
+
| `sortMode` | `'client' \| 'server'` | No | 'client' | Whether sorting is handled client-side or by the server ('client' \| 'server'). |
|
|
44
|
+
| `onSortChange` | `(sort: SortState \| undefined) => void` | No | — | Called with the new sort state when it changes. |
|
|
45
|
+
| `searchable` | `boolean` | No | false | When true, shows a search/filter input. |
|
|
46
|
+
| `pagination` | `{ pageSize: number; pageSizeOptions?: number[] }` | No | — | Pagination configuration (page size and options). |
|
|
47
|
+
| `selection` | `{ mode: 'single' \| 'multi'; selected?: string[]; onChange?: (ids: string[]) => void }` | No | — | Row-selection configuration (mode and selected ids). |
|
|
48
|
+
| `batchActions` | `{ label: string; onClick: (selectedIds: string[]) => void }[]` | No | — | Actions applied to the currently selected rows. |
|
|
49
|
+
| `renderExpandedRow` | `(row: Row) => ReactNode` | No | — | Renders the expanded content for a row. |
|
|
50
|
+
| `density` | `'compact' \| 'normal' \| 'relaxed'` | No | 'normal' | Row density — 'compact', 'normal', or 'relaxed'. |
|
|
51
|
+
| `zebra` | `boolean` | No | false | When true, applies alternating row striping. |
|
|
52
|
+
| `stickyHeader` | `boolean` | No | false | When true, the header stays fixed while the body scrolls. |
|
|
53
|
+
| `loading` | `boolean` | No | false | When true, shows a loading state. |
|
|
54
|
+
| `emptyState` | `ReactNode` | No | — | Content shown when there are no rows. |
|
|
55
|
+
| `title` | `string` | No | — | Title text for the component. |
|
|
56
|
+
| `description` | `string` | No | — | Supporting description text. |
|
|
57
|
+
| `labels` | `DataTableLabels` | No | — | Overrides for the component’s user-visible strings (i18n). |
|
|
58
|
+
| `className` | `string` | No | — | Additional CSS class names merged onto the root element. |
|
|
59
|
+
|
|
60
|
+
## Tokens
|
|
61
|
+
|
|
62
|
+
- `--cascivo-color-surface`
|
|
63
|
+
- `--cascivo-color-bg-subtle`
|
|
64
|
+
- `--cascivo-color-border`
|
|
65
|
+
- `--cascivo-color-border-strong`
|
|
66
|
+
- `--cascivo-color-text`
|
|
67
|
+
- `--cascivo-color-text-muted`
|
|
68
|
+
- `--cascivo-color-accent`
|
|
69
|
+
- `--cascivo-font-sans`
|
|
70
|
+
- `--cascivo-text-sm`
|
|
71
|
+
- `--cascivo-text-xs`
|
|
72
|
+
- `--cascivo-font-semibold`
|
|
73
|
+
- `--cascivo-font-medium`
|
|
74
|
+
- `--cascivo-radius-lg`
|
|
75
|
+
- `--cascivo-radius-sm`
|
|
76
|
+
- `--cascivo-space-2`
|
|
77
|
+
- `--cascivo-space-3`
|
|
78
|
+
- `--cascivo-space-4`
|
|
79
|
+
- `--cascivo-data-table-max-height`
|
|
80
|
+
- `--cascivo-duration-150`
|
|
81
|
+
- `--cascivo-duration-500`
|
|
82
|
+
- `--cascivo-ease-out`
|
|
83
|
+
- `--cascivo-ease-in-out`
|
|
84
|
+
|
|
85
|
+
## Examples
|
|
86
|
+
|
|
87
|
+
### Basic table
|
|
88
|
+
|
|
89
|
+
```jsx
|
|
90
|
+
<DataTable
|
|
91
|
+
columns={[
|
|
92
|
+
{ key: 'name', header: 'Name', sortable: true },
|
|
93
|
+
{ key: 'role', header: 'Role' },
|
|
94
|
+
]}
|
|
95
|
+
rows={[
|
|
96
|
+
{ name: 'Alice', role: 'Engineer' },
|
|
97
|
+
{ name: 'Bob', role: 'Designer' },
|
|
98
|
+
]}
|
|
99
|
+
getRowId={(r) => r.name}
|
|
100
|
+
/>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Full-featured: selection, pagination, search
|
|
104
|
+
|
|
105
|
+
```jsx
|
|
106
|
+
<DataTable
|
|
107
|
+
columns={columns}
|
|
108
|
+
rows={rows}
|
|
109
|
+
getRowId={(r) => r.id}
|
|
110
|
+
searchable
|
|
111
|
+
pagination={{ pageSize: 10, pageSizeOptions: [10, 25, 50] }}
|
|
112
|
+
selection={{ mode: 'multi', onChange: setSelected }}
|
|
113
|
+
batchActions={[{ label: 'Delete', onClick: deleteRows }]}
|
|
114
|
+
stickyHeader
|
|
115
|
+
zebra
|
|
116
|
+
/>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Boundaries
|
|
120
|
+
|
|
121
|
+
| Area | Level | Note |
|
|
122
|
+
| -------------------- | -------- | ---------------------------------------------------------------------- |
|
|
123
|
+
| sortMode and density | flexible | Choose client/server sort and density to fit data size and layout |
|
|
124
|
+
| token names | strict | All surfaces, borders, and spacing must resolve to --cascivo-\* tokens |
|
|
125
|
+
|
|
126
|
+
## AI context prompt
|
|
127
|
+
|
|
128
|
+
Copy this into an LLM context bar before editing this component:
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
I am modifying the cascivo DataTable component (display). Signal-driven data table with client/server sort, filter, pagination, multi-selection, expandable rows, and CSS content-visibility row containment for large datasets
|
|
132
|
+
|
|
133
|
+
Architecture constraints — follow exactly:
|
|
134
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
135
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
136
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
137
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
138
|
+
- CSS logical properties only (RTL-safe).
|
|
139
|
+
|
|
140
|
+
DataTable is strictly bound to these tokens — use only these, do not invent token names:
|
|
141
|
+
--cascivo-color-surface, --cascivo-color-bg-subtle, --cascivo-color-border, --cascivo-color-border-strong, --cascivo-color-text, --cascivo-color-text-muted, --cascivo-color-accent, --cascivo-font-sans, --cascivo-text-sm, --cascivo-text-xs, --cascivo-font-semibold, --cascivo-font-medium, --cascivo-radius-lg, --cascivo-radius-sm, --cascivo-space-2, --cascivo-space-3, --cascivo-space-4, --cascivo-data-table-max-height, --cascivo-duration-150, --cascivo-duration-500, --cascivo-ease-out, --cascivo-ease-in-out
|
|
142
|
+
|
|
143
|
+
Accessibility: role "table", WCAG 2.2-AA, keyboard: Tab/ArrowUp/ArrowDown/ArrowLeft/ArrowRight/Enter/Space. Keep it AA.
|
|
144
|
+
|
|
145
|
+
Do not change (strict): token names — All surfaces, borders, and spacing must resolve to --cascivo-* tokens
|
|
146
|
+
Flexible: sortMode and density.
|
|
147
|
+
|
|
148
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
149
|
+
```
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# DatePicker
|
|
2
|
+
|
|
3
|
+
**Category:** inputs
|
|
4
|
+
**Description:** An accessible date-picker with a calendar popover.
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Picking a single calendar date in a form where a visual month grid helps (due dates, bookings)
|
|
9
|
+
- Date entry that benefits from min/max constraints and locale-aware formatting and week start
|
|
10
|
+
|
|
11
|
+
## When NOT to use
|
|
12
|
+
|
|
13
|
+
- Selecting a time of day — use TimePicker
|
|
14
|
+
- Free-form or approximate dates where a plain Input is faster, or a date already known by typing
|
|
15
|
+
|
|
16
|
+
## Anti-patterns
|
|
17
|
+
|
|
18
|
+
### The component parses and compares ISO dates; non-ISO values break selection, constraints, and onChange
|
|
19
|
+
|
|
20
|
+
**Bad:** `Passing a localized display string as value`
|
|
21
|
+
**Good:** `value/defaultValue/min/max are ISO YYYY-MM-DD; display formatting is handled internally`
|
|
22
|
+
**Why:** The component parses and compares ISO dates; non-ISO values break selection, constraints, and onChange
|
|
23
|
+
|
|
24
|
+
## Related components
|
|
25
|
+
|
|
26
|
+
- **TimePicker** (pairs-with): Combine when both a date and a time are needed
|
|
27
|
+
- **Input** (alternative): Use a plain input when a calendar grid is unnecessary
|
|
28
|
+
- **Form** (contained-by): Typically a field within a form with label/hint/error
|
|
29
|
+
|
|
30
|
+
## Accessibility rationale
|
|
31
|
+
|
|
32
|
+
The trigger is role="combobox" with aria-haspopup="dialog"/aria-expanded; the calendar is a role="dialog" containing a role="grid" with roving tabindex so arrow keys move a single focusable day, days expose aria-pressed for selection, aria-current="date" for today, and aria-disabled past min/max, and errors are wired via aria-invalid + aria-describedby with role="alert"
|
|
33
|
+
|
|
34
|
+
## Props
|
|
35
|
+
|
|
36
|
+
| Name | Type | Required | Default | Description |
|
|
37
|
+
| -------------- | -------------------------------------- | -------- | ------- | -------------------------------------- |
|
|
38
|
+
| `value` | `string` | No | — | Controlled ISO date value (YYYY-MM-DD) |
|
|
39
|
+
| `defaultValue` | `string` | No | — | Uncontrolled default value |
|
|
40
|
+
| `onChange` | `(value: string \| undefined) => void` | No | — | Called on date selection or clear |
|
|
41
|
+
| `min` | `string` | No | — | Minimum ISO date |
|
|
42
|
+
| `max` | `string` | No | — | Maximum ISO date |
|
|
43
|
+
| `clearable` | `boolean` | No | — | Shows a clear button |
|
|
44
|
+
| `label` | `string` | No | — | Field label |
|
|
45
|
+
| `hint` | `string` | No | — | Hint text |
|
|
46
|
+
| `error` | `string` | No | — | Error message |
|
|
47
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | No | — | Field size |
|
|
48
|
+
| `disabled` | `boolean` | No | — | Disables the picker |
|
|
49
|
+
| `labels` | `DatePickerLabels` | No | — | i18n label overrides |
|
|
50
|
+
|
|
51
|
+
## Tokens
|
|
52
|
+
|
|
53
|
+
- `--cascivo-date-picker-bg`
|
|
54
|
+
- `--cascivo-date-picker-border`
|
|
55
|
+
- `--cascivo-date-picker-radius`
|
|
56
|
+
- `--cascivo-date-picker-day-selected-bg`
|
|
57
|
+
- `--cascivo-date-picker-day-today-color`
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
### Basic
|
|
62
|
+
|
|
63
|
+
Uncontrolled date picker
|
|
64
|
+
|
|
65
|
+
```jsx
|
|
66
|
+
<DatePicker label="Date" />
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Clearable
|
|
70
|
+
|
|
71
|
+
With clear button
|
|
72
|
+
|
|
73
|
+
```jsx
|
|
74
|
+
<DatePicker label="Date" clearable />
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### With constraints
|
|
78
|
+
|
|
79
|
+
Date range constraint
|
|
80
|
+
|
|
81
|
+
```jsx
|
|
82
|
+
<DatePicker min="2024-01-01" max="2024-12-31" />
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Boundaries
|
|
86
|
+
|
|
87
|
+
| Area | Level | Note |
|
|
88
|
+
| ----------------- | -------- | ------------------------------------------------------------------------------------ |
|
|
89
|
+
| value format | strict | All date props are ISO YYYY-MM-DD strings |
|
|
90
|
+
| locale formatting | flexible | Display, weekday labels, and week start derive from the current i18n locale via Intl |
|
|
91
|
+
| token names | strict | Styling resolves to --cascivo-date-picker-\* component tokens |
|
|
92
|
+
|
|
93
|
+
## AI context prompt
|
|
94
|
+
|
|
95
|
+
Copy this into an LLM context bar before editing this component:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
I am modifying the cascivo DatePicker component (inputs). An accessible date-picker with a calendar popover.
|
|
99
|
+
|
|
100
|
+
Architecture constraints — follow exactly:
|
|
101
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
102
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
103
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
104
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
105
|
+
- CSS logical properties only (RTL-safe).
|
|
106
|
+
|
|
107
|
+
DatePicker is strictly bound to these tokens — use only these, do not invent token names:
|
|
108
|
+
--cascivo-date-picker-bg, --cascivo-date-picker-border, --cascivo-date-picker-radius, --cascivo-date-picker-day-selected-bg, --cascivo-date-picker-day-today-color
|
|
109
|
+
|
|
110
|
+
Accessibility: role "combobox", WCAG 2.2-AA, keyboard: Enter/Space/Escape/ArrowUp/ArrowDown/ArrowLeft/ArrowRight. Keep it AA.
|
|
111
|
+
|
|
112
|
+
Do not change (strict): value format — All date props are ISO YYYY-MM-DD strings; token names — Styling resolves to --cascivo-date-picker-* component tokens
|
|
113
|
+
Flexible: locale formatting.
|
|
114
|
+
|
|
115
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
116
|
+
```
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# DateRangePicker
|
|
2
|
+
|
|
3
|
+
**Category:** inputs
|
|
4
|
+
**Description:** A dual-calendar picker for selecting a contiguous date range.
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Selecting a contiguous start–end date range (reporting windows, bookings, filters)
|
|
9
|
+
- When two months visible at once and hover-preview of the in-between span aid selection
|
|
10
|
+
|
|
11
|
+
## When NOT to use
|
|
12
|
+
|
|
13
|
+
- Picking a single date — use DatePicker or Calendar
|
|
14
|
+
- Selecting many non-contiguous dates — a range picker only models one continuous span
|
|
15
|
+
|
|
16
|
+
## Anti-patterns
|
|
17
|
+
|
|
18
|
+
### Consumers expect range.start <= range.end; an unsorted range breaks downstream comparisons and queries
|
|
19
|
+
|
|
20
|
+
**Bad:** `Emitting the range in click order, so onValueChange can fire with end before start`
|
|
21
|
+
**Good:** `The two clicked dates are sorted before emitting, so start is always <= end`
|
|
22
|
+
**Why:** Consumers expect range.start <= range.end; an unsorted range breaks downstream comparisons and queries
|
|
23
|
+
|
|
24
|
+
## Related components
|
|
25
|
+
|
|
26
|
+
- **Calendar** (contains): Renders two Calendar instances side-by-side with synced navigation
|
|
27
|
+
- **DatePicker** (alternative): Use the single-date picker when only one date is needed
|
|
28
|
+
|
|
29
|
+
## Accessibility rationale
|
|
30
|
+
|
|
31
|
+
The trigger is role="combobox" with aria-haspopup="dialog"/aria-expanded; the popover is a role="dialog" containing two Calendar grids, each an APG role="grid" with roving tabindex; selection is two clicks (first sets the pending start, second emits the sorted range; clicking the same day twice clears), and the hover/keyboard preview marks in-between cells with data-in-range; Escape and outside-click close the panel
|
|
32
|
+
|
|
33
|
+
## Props
|
|
34
|
+
|
|
35
|
+
| Name | Type | Required | Default | Description |
|
|
36
|
+
| --------------- | -------------------------------------------------------- | -------- | ------- | -------------------------------------------------- |
|
|
37
|
+
| `value` | `{ start: Date; end: Date } \| null` | No | — | Controlled selected range |
|
|
38
|
+
| `defaultValue` | `{ start: Date; end: Date }` | No | — | Uncontrolled initial range |
|
|
39
|
+
| `onValueChange` | `(range: { start: Date; end: Date }) => void` | No | — | Called when a complete range is selected |
|
|
40
|
+
| `min` | `Date` | No | — | Earliest selectable date |
|
|
41
|
+
| `max` | `Date` | No | — | Latest selectable date |
|
|
42
|
+
| `disabled` | `(date: Date) => boolean` | No | — | Predicate to disable individual days |
|
|
43
|
+
| `presets` | `{ label: string; range: { start: Date; end: Date } }[]` | No | — | Quick-select preset ranges shown in a side column |
|
|
44
|
+
| `locale` | `string` | No | — | BCP-47 locale; defaults to the current i18n locale |
|
|
45
|
+
| `placeholder` | `string` | No | — | Empty-state trigger text |
|
|
46
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | No | — | Field/grid size |
|
|
47
|
+
| `labels` | `DateRangePickerLabels` | No | — | i18n label overrides |
|
|
48
|
+
|
|
49
|
+
## Tokens
|
|
50
|
+
|
|
51
|
+
- `--cascivo-calendar-bg`
|
|
52
|
+
- `--cascivo-calendar-day-selected-bg`
|
|
53
|
+
- `--cascivo-calendar-day-selected-fg`
|
|
54
|
+
- `--cascivo-calendar-range-bg`
|
|
55
|
+
|
|
56
|
+
## Examples
|
|
57
|
+
|
|
58
|
+
### Basic
|
|
59
|
+
|
|
60
|
+
Uncontrolled dual-calendar range picker
|
|
61
|
+
|
|
62
|
+
```jsx
|
|
63
|
+
<DateRangePicker />
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### With presets
|
|
67
|
+
|
|
68
|
+
Quick-select common ranges
|
|
69
|
+
|
|
70
|
+
```jsx
|
|
71
|
+
<DateRangePicker presets={[{ label: 'Last 7 days', range: last7 }]} />
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Constrained
|
|
75
|
+
|
|
76
|
+
Limits the selectable dates
|
|
77
|
+
|
|
78
|
+
```jsx
|
|
79
|
+
<DateRangePicker min={new Date(Date.UTC(2024, 0, 1))} max={new Date(Date.UTC(2024, 11, 31))} />
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Boundaries
|
|
83
|
+
|
|
84
|
+
| Area | Level | Note |
|
|
85
|
+
| ---------- | -------- | ------------------------------------------------------------------------------------------ |
|
|
86
|
+
| range type | strict | value/defaultValue are { start: Date; end: Date } with native Date objects compared in UTC |
|
|
87
|
+
| presets | flexible | Optional preset ranges render as quick-select buttons in a side column |
|
|
88
|
+
| locale | flexible | Display, weekday labels, and week start derive from the locale via Intl |
|
|
89
|
+
|
|
90
|
+
## AI context prompt
|
|
91
|
+
|
|
92
|
+
Copy this into an LLM context bar before editing this component:
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
I am modifying the cascivo DateRangePicker component (inputs). A dual-calendar picker for selecting a contiguous date range.
|
|
96
|
+
|
|
97
|
+
Architecture constraints — follow exactly:
|
|
98
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
99
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
100
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
101
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
102
|
+
- CSS logical properties only (RTL-safe).
|
|
103
|
+
|
|
104
|
+
DateRangePicker is strictly bound to these tokens — use only these, do not invent token names:
|
|
105
|
+
--cascivo-calendar-bg, --cascivo-calendar-day-selected-bg, --cascivo-calendar-day-selected-fg, --cascivo-calendar-range-bg
|
|
106
|
+
|
|
107
|
+
Accessibility: role "combobox", WCAG 2.2-AA, keyboard: Enter/Space/Escape/ArrowUp/ArrowDown/ArrowLeft/ArrowRight/Home/End/PageUp/PageDown. Keep it AA.
|
|
108
|
+
|
|
109
|
+
Do not change (strict): range type — value/defaultValue are { start: Date; end: Date } with native Date objects compared in UTC
|
|
110
|
+
Flexible: presets, locale.
|
|
111
|
+
|
|
112
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
113
|
+
```
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Dock
|
|
2
|
+
|
|
3
|
+
**Category:** navigation
|
|
4
|
+
**Description:** Fixed bottom navigation bar for mobile app shells with up to 5 items
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Mobile app-shell navigation with 3–5 top-level destinations
|
|
9
|
+
- When the primary navigation must be thumb-reachable on small screens
|
|
10
|
+
|
|
11
|
+
## When NOT to use
|
|
12
|
+
|
|
13
|
+
- Desktop navigation — the dock hides at the lg breakpoint (64rem)
|
|
14
|
+
- More than 5 items — labels become unreadable and tap targets too small
|
|
15
|
+
- Secondary or contextual navigation — use Tabs or SideNav instead
|
|
16
|
+
|
|
17
|
+
## Anti-patterns
|
|
18
|
+
|
|
19
|
+
### Tap targets become too small and labels collide on narrow screens
|
|
20
|
+
|
|
21
|
+
**Bad:** `Putting more than 5 items in the Dock`
|
|
22
|
+
**Good:** `Use an overflow menu or drawer for additional destinations`
|
|
23
|
+
**Why:** Tap targets become too small and labels collide on narrow screens
|
|
24
|
+
|
|
25
|
+
## Related components
|
|
26
|
+
|
|
27
|
+
- **SideNav** (alternative): SideNav is the desktop equivalent for primary navigation
|
|
28
|
+
- **Tabs** (alternative): Tabs are for in-page section switching, not app-level navigation
|
|
29
|
+
|
|
30
|
+
## Accessibility rationale
|
|
31
|
+
|
|
32
|
+
Wrapped in <nav> with aria-label; active item carries aria-current="page"; renders as <a> for href items and <button> for onClick items to preserve native semantics
|
|
33
|
+
|
|
34
|
+
## Props
|
|
35
|
+
|
|
36
|
+
| Name | Type | Required | Default | Description |
|
|
37
|
+
| ------------- | ------------ | -------- | ------- | ----------------------------------------------------------------------- |
|
|
38
|
+
| `items` | `DockItem[]` | Yes | — | Navigation items, each with a label, icon, and optional href or onClick |
|
|
39
|
+
| `activeIndex` | `number` | No | — | Index of the currently active item (0-based) |
|
|
40
|
+
| `className` | `string` | No | — | Additional CSS class names merged onto the root element. |
|
|
41
|
+
|
|
42
|
+
## Tokens
|
|
43
|
+
|
|
44
|
+
- `--cascivo-color-surface`
|
|
45
|
+
- `--cascivo-color-accent`
|
|
46
|
+
- `--cascivo-color-text-muted`
|
|
47
|
+
- `--cascivo-border-subtle`
|
|
48
|
+
- `--cascivo-ring-width`
|
|
49
|
+
- `--cascivo-ring-color`
|
|
50
|
+
- `--cascivo-ease-out`
|
|
51
|
+
- `--cascivo-target-min-coarse`
|
|
52
|
+
- `--cascivo-z-dock`
|
|
53
|
+
|
|
54
|
+
## Examples
|
|
55
|
+
|
|
56
|
+
### Basic mobile dock
|
|
57
|
+
|
|
58
|
+
Fixed bottom navigation for a mobile app shell
|
|
59
|
+
|
|
60
|
+
```jsx
|
|
61
|
+
<Dock
|
|
62
|
+
activeIndex={0}
|
|
63
|
+
items={[
|
|
64
|
+
{ label: 'Home', icon: '🏠', onClick: () => navigate('/') },
|
|
65
|
+
{ label: 'Search', icon: '🔍', onClick: () => navigate('/search') },
|
|
66
|
+
{ label: 'Profile', icon: '👤', onClick: () => navigate('/profile') },
|
|
67
|
+
]}
|
|
68
|
+
/>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### With hrefs
|
|
72
|
+
|
|
73
|
+
Link-based dock items for standard navigation
|
|
74
|
+
|
|
75
|
+
```jsx
|
|
76
|
+
<Dock
|
|
77
|
+
activeIndex={1}
|
|
78
|
+
items={[
|
|
79
|
+
{ label: 'Feed', icon: '📰', href: '/feed' },
|
|
80
|
+
{ label: 'Explore', icon: '🌐', href: '/explore' },
|
|
81
|
+
{ label: 'Notifications', icon: '🔔', href: '/notifications' },
|
|
82
|
+
{ label: 'Profile', icon: '👤', href: '/profile' },
|
|
83
|
+
]}
|
|
84
|
+
/>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Boundaries
|
|
88
|
+
|
|
89
|
+
| Area | Level | Note |
|
|
90
|
+
| ------------ | -------- | --------------------------------------------------------------------------------------- |
|
|
91
|
+
| item element | flexible | Renders <a> when href is provided, <button> otherwise — no wrapper needed |
|
|
92
|
+
| visibility | strict | Hidden at 64rem (lg) via display:none — not configurable to preserve mobile-only intent |
|
|
93
|
+
|
|
94
|
+
## AI context prompt
|
|
95
|
+
|
|
96
|
+
Copy this into an LLM context bar before editing this component:
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
I am modifying the cascivo Dock component (navigation). Fixed bottom navigation bar for mobile app shells with up to 5 items
|
|
100
|
+
|
|
101
|
+
Architecture constraints — follow exactly:
|
|
102
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
103
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
104
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
105
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
106
|
+
- CSS logical properties only (RTL-safe).
|
|
107
|
+
|
|
108
|
+
Dock is strictly bound to these tokens — use only these, do not invent token names:
|
|
109
|
+
--cascivo-color-surface, --cascivo-color-accent, --cascivo-color-text-muted, --cascivo-border-subtle, --cascivo-ring-width, --cascivo-ring-color, --cascivo-ease-out, --cascivo-target-min-coarse, --cascivo-z-dock
|
|
110
|
+
|
|
111
|
+
Accessibility: role "navigation", WCAG 2.2-AA, keyboard: Tab/Enter. Keep it AA.
|
|
112
|
+
|
|
113
|
+
Do not change (strict): visibility — Hidden at 64rem (lg) via display:none — not configurable to preserve mobile-only intent
|
|
114
|
+
Flexible: item element.
|
|
115
|
+
|
|
116
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
117
|
+
```
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Drawer
|
|
2
|
+
|
|
3
|
+
**Category:** overlay
|
|
4
|
+
**Description:** Edge-anchored dialog panel that slides in from a screen edge with CSS-only enter/exit motion
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- A side or edge panel for navigation, filters, or detail views that needs full-height space
|
|
9
|
+
- A modal surface that slides in and locks the page behind it while open
|
|
10
|
+
- A controllable open/close panel where the parent owns the state via open/onOpenChange
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- A short yes/no confirmation — use AlertDialog
|
|
15
|
+
- Small content anchored to a trigger element — use Popover
|
|
16
|
+
- A gesture-driven, swipe-to-dismiss sheet — use Sheet
|
|
17
|
+
|
|
18
|
+
## Anti-patterns
|
|
19
|
+
|
|
20
|
+
### A full edge panel with focus trap and scroll lock is overkill for a yes/no decision
|
|
21
|
+
|
|
22
|
+
**Bad:** `<Drawer title="Delete item?">Are you sure?</Drawer>`
|
|
23
|
+
**Good:** `<AlertDialog title="Delete item?" />`
|
|
24
|
+
**Why:** A full edge panel with focus trap and scroll lock is overkill for a yes/no decision
|
|
25
|
+
|
|
26
|
+
## Related components
|
|
27
|
+
|
|
28
|
+
- **Sheet** (alternative): Use Sheet when swipe/gesture dismissal is wanted; Drawer is a plain dialog panel
|
|
29
|
+
- **Modal** (alternative): Use a centered modal rather than an edge panel for focused decisions
|
|
30
|
+
|
|
31
|
+
## Accessibility rationale
|
|
32
|
+
|
|
33
|
+
Renders role="dialog" with aria-modal; the title labels it via aria-labelledby and the description via aria-describedby. FocusScope traps Tab focus and restores it on close; DismissableLayer handles Escape and outside-pointer dismissal.
|
|
34
|
+
|
|
35
|
+
## Props
|
|
36
|
+
|
|
37
|
+
| Name | Type | Required | Default | Description |
|
|
38
|
+
| ---------------- | --------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------- |
|
|
39
|
+
| `open` | `boolean` | No | — | Whether the component is open (controlled). |
|
|
40
|
+
| `defaultOpen` | `boolean` | No | — | Whether the component is open on first render (uncontrolled). |
|
|
41
|
+
| `onOpenChange` | `(open: boolean) => void` | No | — | Called with the next open state when it changes. |
|
|
42
|
+
| `side` | `'start' \| 'end' \| 'top' \| 'bottom'` | No | end | Edge the panel is anchored to. Drives the slide direction. |
|
|
43
|
+
| `size` | `string` | No | — | Panel size along its cross axis (width for start/end, height for top/bottom). |
|
|
44
|
+
| `title` | `React.ReactNode` | No | — | Title text for the component. |
|
|
45
|
+
| `description` | `React.ReactNode` | No | — | Supporting description text. |
|
|
46
|
+
| `children` | `React.ReactNode` | No | — | Content rendered inside the component. |
|
|
47
|
+
| `labels` | `{ close?: string }` | No | — | Overrides for the component’s user-visible strings (i18n). |
|
|
48
|
+
| `className` | `string` | No | — | Additional CSS class names merged onto the root element. |
|
|
49
|
+
| `swipeToDismiss` | `boolean` | No | false | Allow dragging the header toward its edge to dismiss (opt-in). |
|
|
50
|
+
|
|
51
|
+
## Tokens
|
|
52
|
+
|
|
53
|
+
- `--cascivo-color-surface`
|
|
54
|
+
- `--cascivo-color-border`
|
|
55
|
+
- `--cascivo-radius-overlay`
|
|
56
|
+
- `--cascivo-shadow-overlay`
|
|
57
|
+
- `--cascivo-motion-enter`
|
|
58
|
+
- `--cascivo-motion-exit`
|
|
59
|
+
|
|
60
|
+
## Examples
|
|
61
|
+
|
|
62
|
+
### Basic
|
|
63
|
+
|
|
64
|
+
```jsx
|
|
65
|
+
<Drawer open={isOpen} onOpenChange={setIsOpen} title="Settings">
|
|
66
|
+
<SettingsForm />
|
|
67
|
+
</Drawer>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Bottom drawer with swipe-to-dismiss
|
|
71
|
+
|
|
72
|
+
Dragging the header past a threshold toward the edge dismisses the panel.
|
|
73
|
+
|
|
74
|
+
```jsx
|
|
75
|
+
<Drawer defaultOpen side="bottom" size="20rem" swipeToDismiss title="Details">
|
|
76
|
+
<OrderDetails />
|
|
77
|
+
</Drawer>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Boundaries
|
|
81
|
+
|
|
82
|
+
| Area | Level | Note |
|
|
83
|
+
| ------------ | -------- | ----------------------------------------------------------------------------------- |
|
|
84
|
+
| side | strict | Limited to start \| end \| top \| bottom — drives the slide direction and animation |
|
|
85
|
+
| open state | flexible | Controlled (open/onOpenChange) or uncontrolled (defaultOpen) |
|
|
86
|
+
| body content | flexible | Any children; the consumer owns the panel contents |
|
|
87
|
+
|
|
88
|
+
## AI context prompt
|
|
89
|
+
|
|
90
|
+
Copy this into an LLM context bar before editing this component:
|
|
91
|
+
|
|
92
|
+
```text
|
|
93
|
+
I am modifying the cascivo Drawer component (overlay). Edge-anchored dialog panel that slides in from a screen edge with CSS-only enter/exit motion
|
|
94
|
+
|
|
95
|
+
Architecture constraints — follow exactly:
|
|
96
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
97
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
98
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
99
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
100
|
+
- CSS logical properties only (RTL-safe).
|
|
101
|
+
|
|
102
|
+
Drawer is strictly bound to these tokens — use only these, do not invent token names:
|
|
103
|
+
--cascivo-color-surface, --cascivo-color-border, --cascivo-radius-overlay, --cascivo-shadow-overlay, --cascivo-motion-enter, --cascivo-motion-exit
|
|
104
|
+
|
|
105
|
+
Accessibility: role "dialog", WCAG 2.2-AA, keyboard: Escape/Tab/Shift+Tab. Keep it AA.
|
|
106
|
+
|
|
107
|
+
Do not change (strict): side — Limited to start | end | top | bottom — drives the slide direction and animation
|
|
108
|
+
Flexible: open state, body content.
|
|
109
|
+
|
|
110
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
111
|
+
```
|