@cascivo/mcp 0.1.8 → 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 -22
- 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 +5 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +374 -64
- package/dist/index.mjs.map +1 -1
- package/dist/marketplace.json +70 -0
- package/dist/registry.json +5622 -786
- package/dist/tokens.catalog.json +2375 -0
- package/dist/tokens.variants.json +3291 -0
- package/package.json +4 -3
- package/readme.body.md +53 -22
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Toc
|
|
2
|
+
|
|
3
|
+
**Category:** navigation
|
|
4
|
+
**Description:** Table of contents with scroll-spy highlighting of the active section
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Long-form pages (docs, articles) that benefit from in-page jump links
|
|
9
|
+
- Highlighting which section is currently in view as the reader scrolls
|
|
10
|
+
|
|
11
|
+
## When NOT to use
|
|
12
|
+
|
|
13
|
+
- Top-level site navigation between pages — use NavigationMenu or SideNav
|
|
14
|
+
- Showing hierarchy depth of the current page — use Breadcrumb
|
|
15
|
+
|
|
16
|
+
## Anti-patterns
|
|
17
|
+
|
|
18
|
+
### Toc links to sections within the current document, not to other pages
|
|
19
|
+
|
|
20
|
+
**Bad:** `Using Toc as the primary site navigation between routes`
|
|
21
|
+
**Good:** `<NavigationMenu> / <SideNav> for cross-page navigation`
|
|
22
|
+
**Why:** Toc links to sections within the current document, not to other pages
|
|
23
|
+
|
|
24
|
+
## Related components
|
|
25
|
+
|
|
26
|
+
- **SideNav** (alternative): SideNav navigates between pages; Toc navigates within one page
|
|
27
|
+
- **Breadcrumb** (alternative): Breadcrumb shows ancestor hierarchy; Toc shows in-page sections
|
|
28
|
+
|
|
29
|
+
## Accessibility rationale
|
|
30
|
+
|
|
31
|
+
Rendered as a <nav> landmark with a label; entries are real anchor links and the active one is marked aria-current="location" so assistive tech announces the current section
|
|
32
|
+
|
|
33
|
+
## Props
|
|
34
|
+
|
|
35
|
+
| Name | Type | Required | Default | Description |
|
|
36
|
+
| ---------------- | ------------------------------------------------- | -------- | ------- | ---------------------------------------------------------------- |
|
|
37
|
+
| `items` | `{ id: string; label: string; level?: number }[]` | Yes | — | The items to render. |
|
|
38
|
+
| `activeId` | `string` | No | — | Controlled active item id; disables built-in scroll-spy when set |
|
|
39
|
+
| `onActiveChange` | `(id: string) => void` | No | — | Called with the id of the active section when it changes. |
|
|
40
|
+
| `labels` | `{ nav?: string }` | No | — | Overrides for the component’s user-visible strings (i18n). |
|
|
41
|
+
| `className` | `string` | No | — | Additional CSS class names merged onto the root element. |
|
|
42
|
+
|
|
43
|
+
## Tokens
|
|
44
|
+
|
|
45
|
+
- `--cascivo-font-sans`
|
|
46
|
+
- `--cascivo-color-text`
|
|
47
|
+
- `--cascivo-color-text-muted`
|
|
48
|
+
- `--cascivo-color-accent`
|
|
49
|
+
- `--cascivo-focus-ring`
|
|
50
|
+
- `--cascivo-target-min-coarse`
|
|
51
|
+
|
|
52
|
+
## Examples
|
|
53
|
+
|
|
54
|
+
### Basic
|
|
55
|
+
|
|
56
|
+
```jsx
|
|
57
|
+
<Toc
|
|
58
|
+
items={[
|
|
59
|
+
{ id: 'intro', label: 'Introduction' },
|
|
60
|
+
{ id: 'usage', label: 'Usage' },
|
|
61
|
+
{ id: 'api', label: 'API', level: 3 },
|
|
62
|
+
]}
|
|
63
|
+
/>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Controlled active item
|
|
67
|
+
|
|
68
|
+
Pass activeId to drive the highlight yourself; scroll-spy is disabled.
|
|
69
|
+
|
|
70
|
+
```jsx
|
|
71
|
+
<Toc
|
|
72
|
+
activeId="usage"
|
|
73
|
+
items={[
|
|
74
|
+
{ id: 'intro', label: 'Introduction' },
|
|
75
|
+
{ id: 'usage', label: 'Usage' },
|
|
76
|
+
]}
|
|
77
|
+
/>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Boundaries
|
|
81
|
+
|
|
82
|
+
| Area | Level | Note |
|
|
83
|
+
| ----------- | -------- | ------------------------------------------------------------------------ |
|
|
84
|
+
| activeId | flexible | Control the highlight externally, or omit it for built-in scroll-spy |
|
|
85
|
+
| token names | strict | Colors, focus ring, and touch target must resolve to --cascivo-\* tokens |
|
|
86
|
+
|
|
87
|
+
## AI context prompt
|
|
88
|
+
|
|
89
|
+
Copy this into an LLM context bar before editing this component:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
I am modifying the cascivo Toc component (navigation). Table of contents with scroll-spy highlighting of the active section
|
|
93
|
+
|
|
94
|
+
Architecture constraints — follow exactly:
|
|
95
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
96
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
97
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
98
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
99
|
+
- CSS logical properties only (RTL-safe).
|
|
100
|
+
|
|
101
|
+
Toc is strictly bound to these tokens — use only these, do not invent token names:
|
|
102
|
+
--cascivo-font-sans, --cascivo-color-text, --cascivo-color-text-muted, --cascivo-color-accent, --cascivo-focus-ring, --cascivo-target-min-coarse
|
|
103
|
+
|
|
104
|
+
Accessibility: role "navigation", WCAG 2.2-AA, keyboard: Tab/Enter. Keep it AA.
|
|
105
|
+
|
|
106
|
+
Do not change (strict): token names — Colors, focus ring, and touch target must resolve to --cascivo-* tokens
|
|
107
|
+
Flexible: activeId.
|
|
108
|
+
|
|
109
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
110
|
+
```
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# ToggleGroup
|
|
2
|
+
|
|
3
|
+
**Category:** inputs
|
|
4
|
+
**Description:** A set of toggle buttons for single or multiple selection
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Choosing one value from a small, mutually exclusive set that should stay visible (type="single")
|
|
9
|
+
- Toggling several independent options in a compact segmented control (type="multiple")
|
|
10
|
+
|
|
11
|
+
## When NOT to use
|
|
12
|
+
|
|
13
|
+
- The options are independent actions, not a selection — use ButtonGroup
|
|
14
|
+
- There are many options or they need labels and descriptions — use Radio or Checkbox groups
|
|
15
|
+
|
|
16
|
+
## Anti-patterns
|
|
17
|
+
|
|
18
|
+
### Single-select used as a controlled value should be driven by value/onValueChange so the source of truth lives with the parent
|
|
19
|
+
|
|
20
|
+
**Bad:** `<ToggleGroup type="single" items={items} onValueChange={save} />`
|
|
21
|
+
**Good:** `<ToggleGroup type="single" value={align} onValueChange={setAlign} items={items} />`
|
|
22
|
+
**Why:** Single-select used as a controlled value should be driven by value/onValueChange so the source of truth lives with the parent
|
|
23
|
+
|
|
24
|
+
## Related components
|
|
25
|
+
|
|
26
|
+
- **ButtonGroup** (alternative): Use when the buttons fire independent actions rather than select a value
|
|
27
|
+
- **Toggle** (alternative): Use a single Toggle for one standalone binary option
|
|
28
|
+
|
|
29
|
+
## Accessibility rationale
|
|
30
|
+
|
|
31
|
+
Single mode renders role="radiogroup" with role="radio" + aria-checked items; multiple mode uses a plain group of buttons with aria-pressed. Roving tabindex makes the set one tab stop and arrow keys move between items, matching the APG radiogroup/toolbar patterns
|
|
32
|
+
|
|
33
|
+
## Props
|
|
34
|
+
|
|
35
|
+
| Name | Type | Required | Default | Description |
|
|
36
|
+
| --------------- | --------------------------------------------------------------------------------- | -------- | ---------- | ------------------------------------------------------------------------------ |
|
|
37
|
+
| `type` | `'single' \| 'multiple'` | Yes | — | Whether one or multiple items can be pressed at once ('single' \| 'multiple'). |
|
|
38
|
+
| `value` | `string \| string[]` | No | — | The controlled value. |
|
|
39
|
+
| `defaultValue` | `string \| string[]` | No | — | The initial value when uncontrolled. |
|
|
40
|
+
| `onValueChange` | `(value: string \| string[]) => void` | No | — | Called with the new value when it changes. |
|
|
41
|
+
| `items` | `{ value: string; label?: string; icon?: React.ReactNode; disabled?: boolean }[]` | Yes | — | The items to render. |
|
|
42
|
+
| `orientation` | `'horizontal' \| 'vertical'` | No | horizontal | Layout orientation of the component. |
|
|
43
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | No | md | Visual size of the component (e.g. 'sm', 'md', 'lg'). |
|
|
44
|
+
| `disabled` | `boolean` | No | false | When true, disables the control and removes it from the tab order. |
|
|
45
|
+
|
|
46
|
+
## Tokens
|
|
47
|
+
|
|
48
|
+
- `--cascivo-control-height-sm`
|
|
49
|
+
- `--cascivo-control-height-md`
|
|
50
|
+
- `--cascivo-control-height-lg`
|
|
51
|
+
- `--cascivo-radius-control`
|
|
52
|
+
- `--cascivo-radius-item`
|
|
53
|
+
- `--cascivo-color-bg-subtle`
|
|
54
|
+
- `--cascivo-color-surface`
|
|
55
|
+
- `--cascivo-color-text`
|
|
56
|
+
- `--cascivo-shadow-sm`
|
|
57
|
+
- `--cascivo-focus-ring`
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
### Single selection
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
<ToggleGroup
|
|
65
|
+
type="single"
|
|
66
|
+
defaultValue="left"
|
|
67
|
+
items={[
|
|
68
|
+
{ value: 'left', label: 'Left' },
|
|
69
|
+
{ value: 'center', label: 'Center' },
|
|
70
|
+
{ value: 'right', label: 'Right' },
|
|
71
|
+
]}
|
|
72
|
+
/>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Multiple selection
|
|
76
|
+
|
|
77
|
+
```jsx
|
|
78
|
+
<ToggleGroup
|
|
79
|
+
type="multiple"
|
|
80
|
+
defaultValue={['bold']}
|
|
81
|
+
items={[
|
|
82
|
+
{ value: 'bold', label: 'Bold' },
|
|
83
|
+
{ value: 'italic', label: 'Italic' },
|
|
84
|
+
]}
|
|
85
|
+
/>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Boundaries
|
|
89
|
+
|
|
90
|
+
| Area | Level | Note |
|
|
91
|
+
| ------------ | -------- | ------------------------------------------------------------------------------------ |
|
|
92
|
+
| token names | strict | Item height must resolve to --cascivo-control-height-\* to align with other controls |
|
|
93
|
+
| item content | flexible | Items may use a text label, an icon, or both; consumer owns the icon set |
|
|
94
|
+
|
|
95
|
+
## AI context prompt
|
|
96
|
+
|
|
97
|
+
Copy this into an LLM context bar before editing this component:
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
I am modifying the cascivo ToggleGroup component (inputs). A set of toggle buttons for single or multiple selection
|
|
101
|
+
|
|
102
|
+
Architecture constraints — follow exactly:
|
|
103
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
104
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
105
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
106
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
107
|
+
- CSS logical properties only (RTL-safe).
|
|
108
|
+
|
|
109
|
+
ToggleGroup is strictly bound to these tokens — use only these, do not invent token names:
|
|
110
|
+
--cascivo-control-height-sm, --cascivo-control-height-md, --cascivo-control-height-lg, --cascivo-radius-control, --cascivo-radius-item, --cascivo-color-bg-subtle, --cascivo-color-surface, --cascivo-color-text, --cascivo-shadow-sm, --cascivo-focus-ring
|
|
111
|
+
|
|
112
|
+
Accessibility: role "radiogroup", WCAG 2.2-AA, keyboard: ArrowRight/ArrowLeft/ArrowUp/ArrowDown/Home/End/Enter/Space. Keep it AA.
|
|
113
|
+
|
|
114
|
+
Do not change (strict): token names — Item height must resolve to --cascivo-control-height-* to align with other controls
|
|
115
|
+
Flexible: item content.
|
|
116
|
+
|
|
117
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
118
|
+
```
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Toggle
|
|
2
|
+
|
|
3
|
+
**Category:** inputs
|
|
4
|
+
**Description:** On/off switch built as an accessible button
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Flipping a single binary setting that takes effect immediately (e.g. notifications on/off)
|
|
9
|
+
- On/off state where a physical switch metaphor reads better than a checkmark
|
|
10
|
+
- Settings screens where the change applies live without a separate submit
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- Selecting items in a form that is submitted later — use Checkbox
|
|
15
|
+
- Choosing one option among several mutually exclusive labels — use SegmentedControl or Radio
|
|
16
|
+
|
|
17
|
+
## Anti-patterns
|
|
18
|
+
|
|
19
|
+
### A switch implies an instant on/off setting; agreement that is submitted with the form is a checkbox
|
|
20
|
+
|
|
21
|
+
**Bad:** `<Toggle label="I accept the terms" /> inside a submitted form`
|
|
22
|
+
**Good:** `<Checkbox label="I accept the terms" />`
|
|
23
|
+
**Why:** A switch implies an instant on/off setting; agreement that is submitted with the form is a checkbox
|
|
24
|
+
|
|
25
|
+
### The `label` prop renders visible text and is the accessible name; when a heading already names the control, use aria-label so the name is not shown (and read) twice
|
|
26
|
+
|
|
27
|
+
**Bad:** `<h3>Dark mode</h3><Toggle label="Dark mode" /> — the label repeats the heading`
|
|
28
|
+
**Good:** `<h3>Dark mode</h3><Toggle aria-label="Dark mode" />`
|
|
29
|
+
**Why:** The `label` prop renders visible text and is the accessible name; when a heading already names the control, use aria-label so the name is not shown (and read) twice
|
|
30
|
+
|
|
31
|
+
## Related components
|
|
32
|
+
|
|
33
|
+
- **Checkbox** (alternative): Use for form selections submitted later rather than instant settings
|
|
34
|
+
- **SegmentedControl** (alternative): Use when choosing among several exclusive options, not just on/off
|
|
35
|
+
|
|
36
|
+
## Accessibility rationale
|
|
37
|
+
|
|
38
|
+
Renders a <button role="switch"> with aria-checked reflecting state, so assistive tech announces it as a switch and Space/Enter toggle it via native button activation.
|
|
39
|
+
|
|
40
|
+
## Props
|
|
41
|
+
|
|
42
|
+
| Name | Type | Required | Default | Description |
|
|
43
|
+
| ---------------- | ---------------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
44
|
+
| `checked` | `boolean` | No | — | Whether the control is checked (controlled). |
|
|
45
|
+
| `defaultChecked` | `boolean` | No | false | Whether the control is checked on first render (uncontrolled). |
|
|
46
|
+
| `onChange` | `(checked: boolean) => void` | No | — | Called when the value changes. |
|
|
47
|
+
| `label` | `string` | No | — | Visible text label beside the switch; it also becomes the accessible name. When a heading already labels the control, omit this and pass aria-label instead to avoid duplicated text. |
|
|
48
|
+
| `size` | `'sm' \| 'md'` | No | md | Visual size of the component (e.g. 'sm', 'md', 'lg'). |
|
|
49
|
+
| `disabled` | `boolean` | No | false | When true, disables the control and removes it from the tab order. |
|
|
50
|
+
|
|
51
|
+
## Tokens
|
|
52
|
+
|
|
53
|
+
- `--cascivo-color-accent`
|
|
54
|
+
- `--cascivo-color-border-strong`
|
|
55
|
+
- `--cascivo-color-surface`
|
|
56
|
+
- `--cascivo-radius-full`
|
|
57
|
+
- `--cascivo-focus-ring`
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
### Uncontrolled
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
<Toggle label="Notifications" defaultChecked />
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Controlled
|
|
68
|
+
|
|
69
|
+
```jsx
|
|
70
|
+
<Toggle checked={enabled} onChange={setEnabled} label="Dark mode" />
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Boundaries
|
|
74
|
+
|
|
75
|
+
| Area | Level | Note |
|
|
76
|
+
| ----------- | -------- | -------------------------------------------------------------------------------------- |
|
|
77
|
+
| token names | strict | Track and thumb colors must resolve to --cascivo-color-\* / radius / focus-ring tokens |
|
|
78
|
+
| label copy | flexible | Optional label describing the setting being toggled |
|
|
79
|
+
|
|
80
|
+
## AI context prompt
|
|
81
|
+
|
|
82
|
+
Copy this into an LLM context bar before editing this component:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
I am modifying the cascivo Toggle component (inputs). On/off switch built as an accessible button
|
|
86
|
+
|
|
87
|
+
Architecture constraints — follow exactly:
|
|
88
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
89
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
90
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
91
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
92
|
+
- CSS logical properties only (RTL-safe).
|
|
93
|
+
|
|
94
|
+
Toggle is strictly bound to these tokens — use only these, do not invent token names:
|
|
95
|
+
--cascivo-color-accent, --cascivo-color-border-strong, --cascivo-color-surface, --cascivo-radius-full, --cascivo-focus-ring
|
|
96
|
+
|
|
97
|
+
Accessibility: role "switch", WCAG 2.2-AA, keyboard: Space/Enter. Keep it AA.
|
|
98
|
+
|
|
99
|
+
Do not change (strict): token names — Track and thumb colors must resolve to --cascivo-color-* / radius / focus-ring tokens
|
|
100
|
+
Flexible: label copy.
|
|
101
|
+
|
|
102
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
103
|
+
```
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Toggletip
|
|
2
|
+
|
|
3
|
+
**Category:** overlay
|
|
4
|
+
**Description:** A click-triggered info popover for supplementary, selectable content
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Revealing brief supplementary information on demand when the user clicks an info affordance
|
|
9
|
+
- Content that must be selectable or contain a link, where a hover Tooltip would be unreachable
|
|
10
|
+
- Touch-friendly hint surfaces where hover is unavailable
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- A passive label that should appear on hover/focus without a click — use Tooltip
|
|
15
|
+
- A blocking, focus-trapping dialog for a task — use Modal
|
|
16
|
+
- Rich forms or pickers anchored to a trigger — use Popover
|
|
17
|
+
- A list of one-shot actions behind a button — use MenuButton
|
|
18
|
+
|
|
19
|
+
## Anti-patterns
|
|
20
|
+
|
|
21
|
+
### Hover tooltips disappear on pointer-out and are not keyboard- or touch-reachable for interaction, so interactive or copyable content needs a click-toggled bubble
|
|
22
|
+
|
|
23
|
+
**Bad:** `Using a hover Tooltip to hold a link or text the user needs to read or copy`
|
|
24
|
+
**Good:** `Use a Toggletip so the content stays open on click and remains reachable and selectable`
|
|
25
|
+
**Why:** Hover tooltips disappear on pointer-out and are not keyboard- or touch-reachable for interaction, so interactive or copyable content needs a click-toggled bubble
|
|
26
|
+
|
|
27
|
+
### An icon-only button with no accessible name cannot be operated by screen-reader or voice users
|
|
28
|
+
|
|
29
|
+
**Bad:** `Giving the trigger an icon with no text and no labels.label override`
|
|
30
|
+
**Good:** `Provide labels.label or rely on the built-in i18n accessible name`
|
|
31
|
+
**Why:** An icon-only button with no accessible name cannot be operated by screen-reader or voice users
|
|
32
|
+
|
|
33
|
+
## Related components
|
|
34
|
+
|
|
35
|
+
- **Tooltip** (alternative): Use Tooltip for non-interactive hints shown on hover/focus rather than click
|
|
36
|
+
- **Popover** (alternative): Use Popover for richer interactive content like forms or pickers
|
|
37
|
+
- **MenuButton** (alternative): Use MenuButton when the trigger should reveal a list of actions
|
|
38
|
+
|
|
39
|
+
## Accessibility rationale
|
|
40
|
+
|
|
41
|
+
The trigger is a real <button> with aria-expanded reflecting open state and aria-controls pointing at the bubble; an icon-only trigger gets an accessible name from labels.label or the built-in i18n catalog. The bubble is role="status" so its content is announced when it opens, and unlike a hover tooltip the content remains visible and reachable for selection and links. DismissableLayer provides Escape and outside-pointer dismissal, and high-contrast and reduced-motion preferences are honored in CSS.
|
|
42
|
+
|
|
43
|
+
## Props
|
|
44
|
+
|
|
45
|
+
| Name | Type | Required | Default | Description |
|
|
46
|
+
| -------------- | ------------------------------------------------------------------------------------------------------ | -------- | ------- | ------------------------------------------------------------- |
|
|
47
|
+
| `trigger` | `ReactNode` | Yes | — | Trigger content, rendered inside a button (e.g. an info icon) |
|
|
48
|
+
| `children` | `ReactNode` | Yes | — | The popover content — interactive and selectable |
|
|
49
|
+
| `placement` | `'top' \| 'bottom' \| 'left' \| 'right' \| 'top-start' \| 'top-end' \| 'bottom-start' \| 'bottom-end'` | No | 'top' | Side and alignment of the bubble relative to the trigger |
|
|
50
|
+
| `defaultOpen` | `boolean` | No | false | Initial open state when uncontrolled |
|
|
51
|
+
| `open` | `boolean` | No | — | Controlled open state |
|
|
52
|
+
| `onOpenChange` | `(open: boolean) => void` | No | — | Called whenever the open state should change |
|
|
53
|
+
| `labels` | `{ label?: string }` | No | — | Override the trigger accessible name |
|
|
54
|
+
|
|
55
|
+
## Tokens
|
|
56
|
+
|
|
57
|
+
- `--cascivo-color-surface`
|
|
58
|
+
- `--cascivo-color-border`
|
|
59
|
+
- `--cascivo-color-text`
|
|
60
|
+
- `--cascivo-color-bg-subtle`
|
|
61
|
+
- `--cascivo-radius-control`
|
|
62
|
+
- `--cascivo-radius-overlay`
|
|
63
|
+
- `--cascivo-shadow-md`
|
|
64
|
+
- `--cascivo-focus-ring`
|
|
65
|
+
- `--cascivo-motion-enter`
|
|
66
|
+
- `--cascivo-z-tooltip`
|
|
67
|
+
|
|
68
|
+
## Examples
|
|
69
|
+
|
|
70
|
+
### Info toggletip
|
|
71
|
+
|
|
72
|
+
An info button that reveals supplementary text on click
|
|
73
|
+
|
|
74
|
+
```jsx
|
|
75
|
+
<Toggletip trigger={<InfoIcon />}>Your password must contain at least 12 characters.</Toggletip>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Controlled
|
|
79
|
+
|
|
80
|
+
Drive the open state from the parent
|
|
81
|
+
|
|
82
|
+
```jsx
|
|
83
|
+
<Toggletip trigger={<InfoIcon />} open={open} onOpenChange={setOpen} placement="bottom-start">
|
|
84
|
+
<a href="/docs">Learn more</a>
|
|
85
|
+
</Toggletip>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Boundaries
|
|
89
|
+
|
|
90
|
+
| Area | Level | Note |
|
|
91
|
+
| -------------------- | -------- | ---------------------------------------------------------------------------- |
|
|
92
|
+
| token names | strict | Trigger and bubble styling must resolve to the listed --cascivo-\* tokens |
|
|
93
|
+
| content | flexible | trigger and children accept arbitrary ReactNode supplied by the consumer |
|
|
94
|
+
| open state ownership | flexible | Use uncontrolled (defaultOpen) or controlled (open + onOpenChange) as needed |
|
|
95
|
+
|
|
96
|
+
## AI context prompt
|
|
97
|
+
|
|
98
|
+
Copy this into an LLM context bar before editing this component:
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
I am modifying the cascivo Toggletip component (overlay). A click-triggered info popover for supplementary, selectable content
|
|
102
|
+
|
|
103
|
+
Architecture constraints — follow exactly:
|
|
104
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
105
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
106
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
107
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
108
|
+
- CSS logical properties only (RTL-safe).
|
|
109
|
+
|
|
110
|
+
Toggletip is strictly bound to these tokens — use only these, do not invent token names:
|
|
111
|
+
--cascivo-color-surface, --cascivo-color-border, --cascivo-color-text, --cascivo-color-bg-subtle, --cascivo-radius-control, --cascivo-radius-overlay, --cascivo-shadow-md, --cascivo-focus-ring, --cascivo-motion-enter, --cascivo-z-tooltip
|
|
112
|
+
|
|
113
|
+
Accessibility: role "status", WCAG 2.2-AA, keyboard: Enter/Space/Escape. Keep it AA.
|
|
114
|
+
|
|
115
|
+
Do not change (strict): token names — Trigger and bubble styling must resolve to the listed --cascivo-* tokens
|
|
116
|
+
Flexible: content, open state ownership.
|
|
117
|
+
|
|
118
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
119
|
+
```
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Tooltip
|
|
2
|
+
|
|
3
|
+
**Category:** overlay
|
|
4
|
+
**Description:** Contextual label shown on hover or focus
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Labeling an icon-only control or clarifying a terse element on hover or focus
|
|
9
|
+
- Showing brief, supplementary text that is non-essential to completing the task
|
|
10
|
+
- Progressive disclosure of a short hint anchored to a trigger element
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- The content is interactive (links, buttons, inputs) — use Popover
|
|
15
|
+
- Richer non-interactive preview content is needed — use HoverCard
|
|
16
|
+
- The information is essential and must always be visible — render it inline instead
|
|
17
|
+
|
|
18
|
+
## Anti-patterns
|
|
19
|
+
|
|
20
|
+
### Tooltips are hover/focus hints and cannot reliably hold focusable content; interactive content belongs in a Popover
|
|
21
|
+
|
|
22
|
+
**Bad:** `<Tooltip content={<button>Undo</button>}><Icon /></Tooltip>`
|
|
23
|
+
**Good:** `<Popover><button>Undo</button></Popover>`
|
|
24
|
+
**Why:** Tooltips are hover/focus hints and cannot reliably hold focusable content; interactive content belongs in a Popover
|
|
25
|
+
|
|
26
|
+
## Related components
|
|
27
|
+
|
|
28
|
+
- **Popover** (alternative): Use when the floating content is interactive
|
|
29
|
+
- **HoverCard** (alternative): Use for richer non-interactive preview content
|
|
30
|
+
- **Button** (pairs-with): Commonly wraps an icon button to explain its action
|
|
31
|
+
|
|
32
|
+
## Accessibility rationale
|
|
33
|
+
|
|
34
|
+
The floating element uses role="tooltip" and is linked to the trigger via aria-describedby only while visible; it shows on both hover and keyboard focus so it is reachable without a pointer.
|
|
35
|
+
|
|
36
|
+
## Props
|
|
37
|
+
|
|
38
|
+
| Name | Type | Required | Default | Description |
|
|
39
|
+
| ----------- | ---------------------------------------- | -------- | ------- | ----------------------------------------- |
|
|
40
|
+
| `content` | `ReactNode` | Yes | — | The tooltip content shown on hover/focus. |
|
|
41
|
+
| `placement` | `'top' \| 'right' \| 'bottom' \| 'left'` | No | top | Placement relative to the trigger. |
|
|
42
|
+
| `children` | `ReactElement` | Yes | — | Content rendered inside the component. |
|
|
43
|
+
| `delay` | `number` | No | 200 | Milliseconds to wait before showing |
|
|
44
|
+
|
|
45
|
+
## Tokens
|
|
46
|
+
|
|
47
|
+
- `--cascivo-color-text`
|
|
48
|
+
- `--cascivo-color-text-on-accent`
|
|
49
|
+
- `--cascivo-radius-sm`
|
|
50
|
+
- `--cascivo-z-tooltip`
|
|
51
|
+
|
|
52
|
+
## Examples
|
|
53
|
+
|
|
54
|
+
### Basic
|
|
55
|
+
|
|
56
|
+
```jsx
|
|
57
|
+
<Tooltip content="Copy to clipboard">
|
|
58
|
+
<Button>Copy</Button>
|
|
59
|
+
</Tooltip>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Boundaries
|
|
63
|
+
|
|
64
|
+
| Area | Level | Note |
|
|
65
|
+
| --------- | -------- | -------------------------------------------------------------------- |
|
|
66
|
+
| placement | strict | Limited to top \| right \| bottom \| left, positioned via CSS anchor |
|
|
67
|
+
| delay | flexible | Consumer can tune the show delay (default 200ms) |
|
|
68
|
+
|
|
69
|
+
## AI context prompt
|
|
70
|
+
|
|
71
|
+
Copy this into an LLM context bar before editing this component:
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
I am modifying the cascivo Tooltip component (overlay). Contextual label shown on hover or focus
|
|
75
|
+
|
|
76
|
+
Architecture constraints — follow exactly:
|
|
77
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
78
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
79
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
80
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
81
|
+
- CSS logical properties only (RTL-safe).
|
|
82
|
+
|
|
83
|
+
Tooltip is strictly bound to these tokens — use only these, do not invent token names:
|
|
84
|
+
--cascivo-color-text, --cascivo-color-text-on-accent, --cascivo-radius-sm, --cascivo-z-tooltip
|
|
85
|
+
|
|
86
|
+
Accessibility: role "tooltip", WCAG 2.2-AA, keyboard: Tab/Escape. Keep it AA.
|
|
87
|
+
|
|
88
|
+
Do not change (strict): placement — Limited to top | right | bottom | left, positioned via CSS anchor
|
|
89
|
+
Flexible: delay.
|
|
90
|
+
|
|
91
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
92
|
+
```
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# TreeView
|
|
2
|
+
|
|
3
|
+
**Category:** display
|
|
4
|
+
**Description:** Hierarchical, expandable tree of nodes with keyboard navigation and selection
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Showing nested, parent/child data the user expands and collapses (file trees, org charts, nav)
|
|
9
|
+
- Letting the user pick one or several nodes from a hierarchy
|
|
10
|
+
- Navigating deep structures where indentation communicates depth
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- A flat, non-nested list of choices — use List or StructuredList
|
|
15
|
+
- A small set of mutually exclusive sections of prose — use Accordion
|
|
16
|
+
|
|
17
|
+
## Anti-patterns
|
|
18
|
+
|
|
19
|
+
### A tree with no hierarchy adds twisties and ARIA tree semantics for content that is flat
|
|
20
|
+
|
|
21
|
+
**Bad:** `A single-level TreeView with no children on any node`
|
|
22
|
+
**Good:** `A List or StructuredList`
|
|
23
|
+
**Why:** A tree with no hierarchy adds twisties and ARIA tree semantics for content that is flat
|
|
24
|
+
|
|
25
|
+
## Related components
|
|
26
|
+
|
|
27
|
+
- **Accordion** (alternative): Accordion stacks a few sequential disclosure sections; TreeView models arbitrary-depth hierarchy
|
|
28
|
+
- **StructuredList** (alternative): StructuredList is flat tabular rows; TreeView is nested with expand/collapse
|
|
29
|
+
|
|
30
|
+
## Accessibility rationale
|
|
31
|
+
|
|
32
|
+
Implements the WAI-ARIA TreeView pattern: role=tree on the root, role=treeitem with aria-level/posinset/setsize and aria-expanded on each node, a single roving tabindex, and full APG keyboard support (arrows expand/collapse and move, Home/End, Enter/Space select, printable-character typeahead)
|
|
33
|
+
|
|
34
|
+
## Props
|
|
35
|
+
|
|
36
|
+
| Name | Type | Required | Default | Description |
|
|
37
|
+
| ------------------ | ----------------------------------------------------------------------------- | -------- | ------- | -------------------------------------------------------------------- |
|
|
38
|
+
| `items` | `{ id: string; label: ReactNode; icon?: ReactNode; children?: TreeNode[] }[]` | Yes | — | The items to render. |
|
|
39
|
+
| `selectionMode` | `'single' \| 'multi'` | No | single | Whether one or multiple nodes can be selected ('single' \| 'multi'). |
|
|
40
|
+
| `selected` | `string \| string[]` | No | — | The controlled selected node id(s). |
|
|
41
|
+
| `defaultSelected` | `string \| string[]` | No | — | The initially selected node id(s) when uncontrolled. |
|
|
42
|
+
| `onSelectChange` | `(selected: string \| string[]) => void` | No | — | Called with the new selection when it changes. |
|
|
43
|
+
| `expanded` | `string[]` | No | — | The controlled set of expanded node ids. |
|
|
44
|
+
| `defaultExpanded` | `string[]` | No | — | The initially expanded node ids when uncontrolled. |
|
|
45
|
+
| `onExpandedChange` | `(expanded: string[]) => void` | No | — | Called with the new expanded set when it changes. |
|
|
46
|
+
|
|
47
|
+
## Tokens
|
|
48
|
+
|
|
49
|
+
- `--cascivo-tree-indent`
|
|
50
|
+
- `--cascivo-color-border`
|
|
51
|
+
- `--cascivo-color-bg-subtle`
|
|
52
|
+
- `--cascivo-color-text`
|
|
53
|
+
- `--cascivo-color-text-subtle`
|
|
54
|
+
- `--cascivo-radius-control`
|
|
55
|
+
- `--cascivo-focus-ring`
|
|
56
|
+
- `--cascivo-duration-200`
|
|
57
|
+
- `--cascivo-ease-out`
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
### Single select
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
<TreeView
|
|
65
|
+
defaultExpanded={['src']}
|
|
66
|
+
items={[{ id: 'src', label: 'src', children: [{ id: 'index', label: 'index.ts' }] }]}
|
|
67
|
+
/>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Multi select
|
|
71
|
+
|
|
72
|
+
```jsx
|
|
73
|
+
<TreeView selectionMode="multi" items={nodes} onSelectChange={(ids) => set(ids)} />
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Boundaries
|
|
77
|
+
|
|
78
|
+
| Area | Level | Note |
|
|
79
|
+
| -------------- | -------- | ---------------------------------------------------------------------------------------- |
|
|
80
|
+
| selectionMode | flexible | single vs multi is the consumer’s choice based on the interaction |
|
|
81
|
+
| keyboard model | strict | Arrow/Home/End/typeahead behavior follows the APG tree pattern and must not be re-mapped |
|
|
82
|
+
| indent token | flexible | Per-level indent is driven by --cascivo-tree-indent and may be overridden |
|
|
83
|
+
|
|
84
|
+
## AI context prompt
|
|
85
|
+
|
|
86
|
+
Copy this into an LLM context bar before editing this component:
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
I am modifying the cascivo TreeView component (display). Hierarchical, expandable tree of nodes with keyboard navigation and selection
|
|
90
|
+
|
|
91
|
+
Architecture constraints — follow exactly:
|
|
92
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
93
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
94
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
95
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
96
|
+
- CSS logical properties only (RTL-safe).
|
|
97
|
+
|
|
98
|
+
TreeView is strictly bound to these tokens — use only these, do not invent token names:
|
|
99
|
+
--cascivo-tree-indent, --cascivo-color-border, --cascivo-color-bg-subtle, --cascivo-color-text, --cascivo-color-text-subtle, --cascivo-radius-control, --cascivo-focus-ring, --cascivo-duration-200, --cascivo-ease-out
|
|
100
|
+
|
|
101
|
+
Accessibility: role "tree", WCAG 2.2-AA, keyboard: ArrowDown/ArrowUp/ArrowRight/ArrowLeft/Home/End/Enter/Space/Typeahead. Keep it AA.
|
|
102
|
+
|
|
103
|
+
Do not change (strict): keyboard model — Arrow/Home/End/typeahead behavior follows the APG tree pattern and must not be re-mapped
|
|
104
|
+
Flexible: selectionMode, indent token.
|
|
105
|
+
|
|
106
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
107
|
+
```
|