@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,139 @@
|
|
|
1
|
+
# Flow
|
|
2
|
+
|
|
3
|
+
**Category:** display
|
|
4
|
+
**Description:** The declarative, AI-first flow surface — render a node/edge graph from plain serializable data.
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Rendering a graph from data — the common case and the agent-emittable surface
|
|
9
|
+
- Flowcharts, DAGs, pipelines, and mind-maps from plain nodes/edges arrays
|
|
10
|
+
|
|
11
|
+
## When NOT to use
|
|
12
|
+
|
|
13
|
+
- A scripted, sequenced walkthrough — use FlowStory
|
|
14
|
+
- Heavy graph editing (undo/redo, resize/rotate) — out of scope
|
|
15
|
+
|
|
16
|
+
## Anti-patterns
|
|
17
|
+
|
|
18
|
+
### Declarative serializable data is what an agent can emit and what stays in sync with props.
|
|
19
|
+
|
|
20
|
+
**Bad:** `Imperatively building the graph with graph.addNode(...)`
|
|
21
|
+
**Good:** `<Flow nodes={…} edges={…} />`
|
|
22
|
+
**Why:** Declarative serializable data is what an agent can emit and what stays in sync with props.
|
|
23
|
+
|
|
24
|
+
## Related components
|
|
25
|
+
|
|
26
|
+
- **FlowStory** (alternative): Scripted, captioned storyline animation.
|
|
27
|
+
- **FlowNode** (contains): Renders a node per entry.
|
|
28
|
+
- **FlowEdge** (contains): Renders an edge per entry.
|
|
29
|
+
|
|
30
|
+
## Accessibility rationale
|
|
31
|
+
|
|
32
|
+
role="application" canvas; nodes are focusable groups; controls are real i18n-labeled buttons.
|
|
33
|
+
|
|
34
|
+
## Props
|
|
35
|
+
|
|
36
|
+
| Name | Type | Required | Default | Description |
|
|
37
|
+
| --------------- | ------------------------------------------------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
38
|
+
| `nodes` | `FlowNode[]` | Yes | — | Initial nodes (serializable). |
|
|
39
|
+
| `edges` | `FlowEdge[]` | Yes | — | Initial edges (serializable). |
|
|
40
|
+
| `onNodesChange` | `(nodes: FlowNode[]) => void` | No | — | Called with the next nodes when they change (drag, add, remove). |
|
|
41
|
+
| `onEdgesChange` | `(edges: FlowEdge[]) => void` | No | — | Called with the next edges when they change. |
|
|
42
|
+
| `onConnect` | `(connection: Connection) => void` | No | — | Called when two handles are connected to form a new edge. |
|
|
43
|
+
| `nodeTypes` | `Record<string, NodeRenderer>` | No | — | Custom node renderers keyed by node.type. |
|
|
44
|
+
| `fitView` | `boolean` | No | true | When true, fits the graph to the viewport on mount. |
|
|
45
|
+
| `background` | `boolean \| FlowBackgroundProps` | No | false | Background pattern — true for the default dots, or a config object. |
|
|
46
|
+
| `controls` | `boolean` | No | false | Whether to show the controls. |
|
|
47
|
+
| `minimap` | `boolean` | No | false | When true, shows the minimap overlay. |
|
|
48
|
+
| `layout` | `'grid' \| 'layered' \| ((nodes, edges) => FlowNode[])` | No | — | Optional dependency-free layout. |
|
|
49
|
+
| `interactive` | `boolean` | No | true | When false (view mode), nodes cannot be selected, dragged, or connected and handles are hidden; pan/zoom still work. |
|
|
50
|
+
| `className` | `string` | No | — | Additional CSS class names merged onto the root element. |
|
|
51
|
+
|
|
52
|
+
## Tokens
|
|
53
|
+
|
|
54
|
+
- `--cascivo-color-bg`
|
|
55
|
+
- `--cascivo-color-surface`
|
|
56
|
+
- `--cascivo-color-accent`
|
|
57
|
+
|
|
58
|
+
## Examples
|
|
59
|
+
|
|
60
|
+
### Declarative pipeline
|
|
61
|
+
|
|
62
|
+
A flow from plain serializable data, with background, controls, and an animated edge.
|
|
63
|
+
|
|
64
|
+
```jsx
|
|
65
|
+
;() => (
|
|
66
|
+
<Flow
|
|
67
|
+
style={{ height: 280 }}
|
|
68
|
+
background
|
|
69
|
+
controls
|
|
70
|
+
nodes={[
|
|
71
|
+
{ id: 'a', position: { x: 0, y: 60 }, data: { label: 'Client' } },
|
|
72
|
+
{ id: 'b', position: { x: 240, y: 60 }, data: { label: 'Gateway' } },
|
|
73
|
+
{ id: 'c', position: { x: 480, y: 60 }, data: { label: 'Service' } },
|
|
74
|
+
]}
|
|
75
|
+
edges={[
|
|
76
|
+
{ id: 'ab', source: 'a', target: 'b', animated: true, label: 'request' },
|
|
77
|
+
{ id: 'bc', source: 'b', target: 'c' },
|
|
78
|
+
]}
|
|
79
|
+
/>
|
|
80
|
+
)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Layered layout
|
|
84
|
+
|
|
85
|
+
Let the dependency-free layered layout arrange a small DAG.
|
|
86
|
+
|
|
87
|
+
```jsx
|
|
88
|
+
;() => (
|
|
89
|
+
<Flow
|
|
90
|
+
style={{ height: 300 }}
|
|
91
|
+
layout="layered"
|
|
92
|
+
background
|
|
93
|
+
minimap
|
|
94
|
+
nodes={[
|
|
95
|
+
{ id: 'a', position: { x: 0, y: 0 }, data: { label: 'Ingest' } },
|
|
96
|
+
{ id: 'b', position: { x: 0, y: 0 }, data: { label: 'Transform' } },
|
|
97
|
+
{ id: 'c', position: { x: 0, y: 0 }, data: { label: 'Validate' } },
|
|
98
|
+
{ id: 'd', position: { x: 0, y: 0 }, data: { label: 'Load' } },
|
|
99
|
+
]}
|
|
100
|
+
edges={[
|
|
101
|
+
{ id: 'ab', source: 'a', target: 'b' },
|
|
102
|
+
{ id: 'ac', source: 'a', target: 'c' },
|
|
103
|
+
{ id: 'bd', source: 'b', target: 'd' },
|
|
104
|
+
{ id: 'cd', source: 'c', target: 'd' },
|
|
105
|
+
]}
|
|
106
|
+
/>
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Boundaries
|
|
111
|
+
|
|
112
|
+
| Area | Level | Note |
|
|
113
|
+
| --------- | -------- | -------------------------------------------- |
|
|
114
|
+
| rendering | flexible | Custom node renderers via nodeTypes. |
|
|
115
|
+
| layout | flexible | grid \| layered \| bring-your-own positions. |
|
|
116
|
+
| chrome | flexible | Optional background / controls / minimap. |
|
|
117
|
+
|
|
118
|
+
## AI context prompt
|
|
119
|
+
|
|
120
|
+
Copy this into an LLM context bar before editing this component:
|
|
121
|
+
|
|
122
|
+
```text
|
|
123
|
+
I am modifying the cascivo Flow component (display). The declarative, AI-first flow surface — render a node/edge graph from plain serializable data.
|
|
124
|
+
|
|
125
|
+
Architecture constraints — follow exactly:
|
|
126
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
127
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
128
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
129
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
130
|
+
- CSS logical properties only (RTL-safe).
|
|
131
|
+
|
|
132
|
+
Flow is strictly bound to these tokens — use only these, do not invent token names:
|
|
133
|
+
--cascivo-color-bg, --cascivo-color-surface, --cascivo-color-accent
|
|
134
|
+
|
|
135
|
+
Accessibility: role "application", WCAG 2.1-AA, keyboard: Tab (focus nodes)/Enter/Space (select)/Drag (pan/move)/Wheel (zoom). Keep it AA.
|
|
136
|
+
Flexible: rendering, layout, chrome.
|
|
137
|
+
|
|
138
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
139
|
+
```
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Form
|
|
2
|
+
|
|
3
|
+
**Category:** inputs
|
|
4
|
+
**Description:** Typed signal-based form store (createForm/useForm) with sync/async validation and a thin Form element wrapper
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Collecting and submitting a set of related field values together
|
|
9
|
+
- Running sync or async validation (including Standard Schema like zod/valibot/arktype) before invoking onValid
|
|
10
|
+
- Tracking per-field touched state and errors via the signal-based store from useForm/createForm
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- A single standalone value with no submission step — render a bare Input
|
|
15
|
+
- Inline editing of one read-only value — use Editable
|
|
16
|
+
|
|
17
|
+
## Anti-patterns
|
|
18
|
+
|
|
19
|
+
### The store centralizes values, errors, touched, and submitting as signals; rolling your own reintroduces the re-render and validation-timing bugs the store solves
|
|
20
|
+
|
|
21
|
+
**Bad:** `<form onSubmit={...}> with hand-rolled useState per field`
|
|
22
|
+
**Good:** `const form = useForm({ initialValues, validate }); <Form form={form} onValid={...}>`
|
|
23
|
+
**Why:** The store centralizes values, errors, touched, and submitting as signals; rolling your own reintroduces the re-render and validation-timing bugs the store solves
|
|
24
|
+
|
|
25
|
+
## Related components
|
|
26
|
+
|
|
27
|
+
- **Input** (contains): Form wraps field controls like Input, wiring value/onChange/onBlur/error from form.field()
|
|
28
|
+
- **FileUploader** (contains): File attachments can participate in a Form submission
|
|
29
|
+
|
|
30
|
+
## Accessibility rationale
|
|
31
|
+
|
|
32
|
+
Renders a native <form> with noValidate so validation messages come from the component (surfaced per field via Input error/role="alert") rather than inconsistent browser bubbles, while Enter-to-submit and the form role are preserved by the platform element.
|
|
33
|
+
|
|
34
|
+
## Props
|
|
35
|
+
|
|
36
|
+
| Name | Type | Required | Default | Description |
|
|
37
|
+
| ----------- | -------------------------------------- | -------- | ------- | ---------------------------------------------------------------- |
|
|
38
|
+
| `form` | `FormStore<T>` | Yes | — | The form store holding values, validation, and submission state. |
|
|
39
|
+
| `onValid` | `(values: T) => void \| Promise<void>` | Yes | — | Called with the values when the form passes validation. |
|
|
40
|
+
| `children` | `ReactNode` | Yes | — | Content rendered inside the component. |
|
|
41
|
+
| `className` | `string` | No | — | Additional CSS class names merged onto the root element. |
|
|
42
|
+
|
|
43
|
+
## Tokens
|
|
44
|
+
|
|
45
|
+
- `--cascivo-space-4`
|
|
46
|
+
|
|
47
|
+
## Examples
|
|
48
|
+
|
|
49
|
+
### Basic form with validation
|
|
50
|
+
|
|
51
|
+
```jsx
|
|
52
|
+
function Demo() {
|
|
53
|
+
const form = useForm({
|
|
54
|
+
initialValues: { email: '' },
|
|
55
|
+
validate: (v) => (v.email.includes('@') ? {} : { email: 'Invalid email' }),
|
|
56
|
+
})
|
|
57
|
+
const email = form.field('email')
|
|
58
|
+
return (
|
|
59
|
+
<Form form={form} onValid={console.log}>
|
|
60
|
+
<Input
|
|
61
|
+
label="Email"
|
|
62
|
+
value={email.value}
|
|
63
|
+
onChange={(e) => email.onChange(e.currentTarget.value)}
|
|
64
|
+
onBlur={email.onBlur}
|
|
65
|
+
error={email.error}
|
|
66
|
+
/>
|
|
67
|
+
<Button type="submit">Save</Button>
|
|
68
|
+
</Form>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Boundaries
|
|
74
|
+
|
|
75
|
+
| Area | Level | Note |
|
|
76
|
+
| ------------------------- | -------- | ----------------------------------------------------------------------------------------------------- |
|
|
77
|
+
| validation strategy | flexible | Use schema, validate, or both; schema runs first and validate only if the schema passes |
|
|
78
|
+
| field control composition | flexible | Any control can be wired via form.field(name); children are free-form |
|
|
79
|
+
| submit semantics | strict | onValid only fires when validation produces no errors; submission is guarded by the submitting signal |
|
|
80
|
+
|
|
81
|
+
## AI context prompt
|
|
82
|
+
|
|
83
|
+
Copy this into an LLM context bar before editing this component:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
I am modifying the cascivo Form component (inputs). Typed signal-based form store (createForm/useForm) with sync/async validation and a thin Form element wrapper
|
|
87
|
+
|
|
88
|
+
Architecture constraints — follow exactly:
|
|
89
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
90
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
91
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
92
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
93
|
+
- CSS logical properties only (RTL-safe).
|
|
94
|
+
|
|
95
|
+
Form is strictly bound to these tokens — use only these, do not invent token names:
|
|
96
|
+
--cascivo-space-4
|
|
97
|
+
|
|
98
|
+
Accessibility: role "form", WCAG 2.2-AA, keyboard: Tab/Enter. Keep it AA.
|
|
99
|
+
|
|
100
|
+
Do not change (strict): submit semantics — onValid only fires when validation produces no errors; submission is guarded by the submitting signal
|
|
101
|
+
Flexible: validation strategy, field control composition.
|
|
102
|
+
|
|
103
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
104
|
+
```
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# HeaderPanel
|
|
2
|
+
|
|
3
|
+
**Category:** navigation
|
|
4
|
+
**Description:** Non-modal panel anchored below the shell header at the inline-end edge — hosts notifications, app switcher, user settings
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Hosting a non-modal panel anchored under the shell header (notifications, switcher, settings)
|
|
9
|
+
- Showing supplementary content triggered by a ShellHeader icon action
|
|
10
|
+
- Light-dismiss content that should not block the rest of the app
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- Content that must block interaction until resolved — use Modal
|
|
15
|
+
- A small contextual menu attached to a trigger — use Dropdown or Popover
|
|
16
|
+
|
|
17
|
+
## Anti-patterns
|
|
18
|
+
|
|
19
|
+
### HeaderPanel is non-modal and light-dismissable; blocking flows need modal semantics
|
|
20
|
+
|
|
21
|
+
**Bad:** `Using HeaderPanel for a blocking confirmation`
|
|
22
|
+
**Good:** `<Modal> or <AlertDialog> for decisions that must block`
|
|
23
|
+
**Why:** HeaderPanel is non-modal and light-dismissable; blocking flows need modal semantics
|
|
24
|
+
|
|
25
|
+
## Related components
|
|
26
|
+
|
|
27
|
+
- **ShellHeader** (pairs-with): Opened by a ShellHeader action whose active state mirrors the panel open state
|
|
28
|
+
- **Switcher** (contains): A Switcher commonly lives inside a HeaderPanel
|
|
29
|
+
|
|
30
|
+
## Accessibility rationale
|
|
31
|
+
|
|
32
|
+
role="region" with the label prop names the panel as a landmark; Escape closes it and focus is managed so keyboard users can dismiss it without a mouse
|
|
33
|
+
|
|
34
|
+
## Props
|
|
35
|
+
|
|
36
|
+
| Name | Type | Required | Default | Description |
|
|
37
|
+
| ----------- | ------------------- | -------- | ------- | -------------------------------------------------------- |
|
|
38
|
+
| `open` | `boolean` | Yes | — | Controlled open state |
|
|
39
|
+
| `onClose` | `() => void` | Yes | — | Called on close button click or light-dismiss |
|
|
40
|
+
| `label` | `string` | Yes | — | Accessible label for the region (shown as header title) |
|
|
41
|
+
| `children` | `ReactNode` | Yes | — | Content rendered inside the component. |
|
|
42
|
+
| `labels` | `HeaderPanelLabels` | No | — | i18n overrides |
|
|
43
|
+
| `className` | `string` | No | — | Additional CSS class names merged onto the root element. |
|
|
44
|
+
|
|
45
|
+
## Tokens
|
|
46
|
+
|
|
47
|
+
- `--cascivo-shell-header-block-size`
|
|
48
|
+
- `--cascivo-shell-panel-inline-size`
|
|
49
|
+
- `--cascivo-color-surface`
|
|
50
|
+
- `--cascivo-color-border`
|
|
51
|
+
- `--cascivo-shadow-md`
|
|
52
|
+
- `--cascivo-motion-enter`
|
|
53
|
+
|
|
54
|
+
## Examples
|
|
55
|
+
|
|
56
|
+
### Notification panel
|
|
57
|
+
|
|
58
|
+
Pair with a ShellHeader action: action active=open, onAction toggles open
|
|
59
|
+
|
|
60
|
+
```jsx
|
|
61
|
+
<HeaderPanel open={open} onClose={() => setOpen(false)} label="Notifications">
|
|
62
|
+
<p>3 unread messages</p>
|
|
63
|
+
</HeaderPanel>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Boundaries
|
|
67
|
+
|
|
68
|
+
| Area | Level | Note |
|
|
69
|
+
| ----------- | -------- | --------------------------------------------------------------------- |
|
|
70
|
+
| content | flexible | Children are arbitrary panel content |
|
|
71
|
+
| token names | strict | Surface, shadow, and sizing must resolve to --cascivo-\* shell tokens |
|
|
72
|
+
|
|
73
|
+
## AI context prompt
|
|
74
|
+
|
|
75
|
+
Copy this into an LLM context bar before editing this component:
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
I am modifying the cascivo HeaderPanel component (navigation). Non-modal panel anchored below the shell header at the inline-end edge — hosts notifications, app switcher, user settings
|
|
79
|
+
|
|
80
|
+
Architecture constraints — follow exactly:
|
|
81
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
82
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
83
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
84
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
85
|
+
- CSS logical properties only (RTL-safe).
|
|
86
|
+
|
|
87
|
+
HeaderPanel is strictly bound to these tokens — use only these, do not invent token names:
|
|
88
|
+
--cascivo-shell-header-block-size, --cascivo-shell-panel-inline-size, --cascivo-color-surface, --cascivo-color-border, --cascivo-shadow-md, --cascivo-motion-enter
|
|
89
|
+
|
|
90
|
+
Accessibility: role "region", WCAG 2.2-AA, keyboard: Escape/Tab. Keep it AA.
|
|
91
|
+
|
|
92
|
+
Do not change (strict): token names — Surface, shadow, and sizing must resolve to --cascivo-* shell tokens
|
|
93
|
+
Flexible: content.
|
|
94
|
+
|
|
95
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
96
|
+
```
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Header
|
|
2
|
+
|
|
3
|
+
**Category:** navigation
|
|
4
|
+
**Description:** App top bar with brand, primary navigation links, and an actions slot
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Providing a simple marketing or app top bar with brand, links, and actions
|
|
9
|
+
- Anchoring primary navigation across pages of a site
|
|
10
|
+
- Keeping the bar visible while scrolling (sticky)
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- Dense console apps with dropdown nav, global icon actions, and a hamburger — use ShellHeader
|
|
15
|
+
- Section headings within page content — use Heading
|
|
16
|
+
|
|
17
|
+
## Anti-patterns
|
|
18
|
+
|
|
19
|
+
### Header is intentionally simple; console patterns belong to ShellHeader which provides them natively
|
|
20
|
+
|
|
21
|
+
**Bad:** `Building complex multi-menu console chrome on top of Header`
|
|
22
|
+
**Good:** `<ShellHeader> for console-grade navigation`
|
|
23
|
+
**Why:** Header is intentionally simple; console patterns belong to ShellHeader which provides them natively
|
|
24
|
+
|
|
25
|
+
## Related components
|
|
26
|
+
|
|
27
|
+
- **ShellHeader** (alternative): ShellHeader is the console-grade header with dropdowns and icon actions
|
|
28
|
+
|
|
29
|
+
## Accessibility rationale
|
|
30
|
+
|
|
31
|
+
role="banner" marks the page header landmark; the active link is marked aria-current="page", and links/actions are real focusable controls so keyboard users can navigate the bar
|
|
32
|
+
|
|
33
|
+
## Props
|
|
34
|
+
|
|
35
|
+
| Name | Type | Required | Default | Description |
|
|
36
|
+
| ----------- | ----------------------------------------------------- | -------- | ------- | -------------------------------------------------------------- |
|
|
37
|
+
| `brand` | `React.ReactNode` | No | — | Product name or logo area, typically wraps a link |
|
|
38
|
+
| `links` | `{ label: string; href: string; active?: boolean }[]` | No | — | Primary navigation links; active link gets aria-current="page" |
|
|
39
|
+
| `actions` | `React.ReactNode` | No | — | Right-aligned slot for buttons or an avatar |
|
|
40
|
+
| `sticky` | `boolean` | No | false | When true, the header sticks to the top on scroll. |
|
|
41
|
+
| `className` | `string` | No | — | Additional CSS class names merged onto the root element. |
|
|
42
|
+
|
|
43
|
+
## Tokens
|
|
44
|
+
|
|
45
|
+
- `--cascivo-header-bg`
|
|
46
|
+
- `--cascivo-color-surface`
|
|
47
|
+
- `--cascivo-color-border`
|
|
48
|
+
- `--cascivo-color-text`
|
|
49
|
+
- `--cascivo-color-text-subtle`
|
|
50
|
+
- `--cascivo-color-bg-subtle`
|
|
51
|
+
- `--cascivo-focus-ring`
|
|
52
|
+
- `--cascivo-z-raised`
|
|
53
|
+
|
|
54
|
+
## Examples
|
|
55
|
+
|
|
56
|
+
### Basic
|
|
57
|
+
|
|
58
|
+
```jsx
|
|
59
|
+
<Header brand="cascivo" links={[{ label: 'Docs', href: '/docs' }]} />
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### With actions
|
|
63
|
+
|
|
64
|
+
```jsx
|
|
65
|
+
<Header brand="cascivo" actions={<Button size="sm">Sign in</Button>} />
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Sticky
|
|
69
|
+
|
|
70
|
+
```jsx
|
|
71
|
+
<Header sticky brand="cascivo" links={links} />
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Boundaries
|
|
75
|
+
|
|
76
|
+
| Area | Level | Note |
|
|
77
|
+
| ----------------- | -------- | ---------------------------------------------------------------- |
|
|
78
|
+
| links and actions | flexible | Brand, links, and actions slots are optional and composable |
|
|
79
|
+
| token names | strict | Surface, border, and z-index must resolve to --cascivo-\* tokens |
|
|
80
|
+
|
|
81
|
+
## AI context prompt
|
|
82
|
+
|
|
83
|
+
Copy this into an LLM context bar before editing this component:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
I am modifying the cascivo Header component (navigation). App top bar with brand, primary navigation links, and an actions slot
|
|
87
|
+
|
|
88
|
+
Architecture constraints — follow exactly:
|
|
89
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
90
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
91
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
92
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
93
|
+
- CSS logical properties only (RTL-safe).
|
|
94
|
+
|
|
95
|
+
Header is strictly bound to these tokens — use only these, do not invent token names:
|
|
96
|
+
--cascivo-header-bg, --cascivo-color-surface, --cascivo-color-border, --cascivo-color-text, --cascivo-color-text-subtle, --cascivo-color-bg-subtle, --cascivo-focus-ring, --cascivo-z-raised
|
|
97
|
+
|
|
98
|
+
Accessibility: role "banner", WCAG 2.2-AA, keyboard: Tab. Keep it AA.
|
|
99
|
+
|
|
100
|
+
Do not change (strict): token names — Surface, border, and z-index must resolve to --cascivo-* tokens
|
|
101
|
+
Flexible: links and actions.
|
|
102
|
+
|
|
103
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
104
|
+
```
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Heading
|
|
2
|
+
|
|
3
|
+
**Category:** display
|
|
4
|
+
**Description:** Section heading with semantic level decoupled from visual size
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Titling a page or section as part of the document outline
|
|
9
|
+
- Keeping the semantic heading level correct while choosing the visual size independently
|
|
10
|
+
|
|
11
|
+
## When NOT to use
|
|
12
|
+
|
|
13
|
+
- Emphasizing inline or body text — use Text with a weight
|
|
14
|
+
- Long-form rendered content — let Prose style its own headings
|
|
15
|
+
|
|
16
|
+
## Anti-patterns
|
|
17
|
+
|
|
18
|
+
### Skipping heading levels breaks the document outline screen-reader users rely on to navigate
|
|
19
|
+
|
|
20
|
+
**Bad:** `<Heading level={4} size="2xl"> chosen only to look big, skipping h2/h3`
|
|
21
|
+
**Good:** `Keep levels sequential; use size to control scale within the correct level`
|
|
22
|
+
**Why:** Skipping heading levels breaks the document outline screen-reader users rely on to navigate
|
|
23
|
+
|
|
24
|
+
## Related components
|
|
25
|
+
|
|
26
|
+
- **Text** (alternative): Text is for body copy; Heading is for outline structure
|
|
27
|
+
- **Prose** (alternative): Prose styles headings inside authored long-form content
|
|
28
|
+
|
|
29
|
+
## Accessibility rationale
|
|
30
|
+
|
|
31
|
+
Renders a real <h1>–<h6> from the level prop so the heading appears in the accessibility tree at the correct level; visual size is decoupled so styling never forces an incorrect level
|
|
32
|
+
|
|
33
|
+
## Props
|
|
34
|
+
|
|
35
|
+
| Name | Type | Required | Default | Description |
|
|
36
|
+
| ------- | --------------------------------------- | -------- | -------------------------------------------------------- | ----------------------------------------------------- |
|
|
37
|
+
| `level` | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | No | 2 | Heading level (1–6) mapping to h1–h6. |
|
|
38
|
+
| `size` | `'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl'` | No | derived from level (1→2xl, 2→xl, 3→lg, 4→md, 5→sm, 6→sm) | Visual size of the component (e.g. 'sm', 'md', 'lg'). |
|
|
39
|
+
|
|
40
|
+
## Tokens
|
|
41
|
+
|
|
42
|
+
- `--cascivo-font-display`
|
|
43
|
+
- `--cascivo-font-semibold`
|
|
44
|
+
- `--cascivo-leading-tight`
|
|
45
|
+
- `--cascivo-tracking-tight`
|
|
46
|
+
- `--cascivo-color-text`
|
|
47
|
+
- `--cascivo-text-base`
|
|
48
|
+
- `--cascivo-text-lg`
|
|
49
|
+
- `--cascivo-text-xl`
|
|
50
|
+
- `--cascivo-text-2xl`
|
|
51
|
+
- `--cascivo-text-3xl`
|
|
52
|
+
|
|
53
|
+
## Examples
|
|
54
|
+
|
|
55
|
+
### Default
|
|
56
|
+
|
|
57
|
+
```jsx
|
|
58
|
+
<Heading>Section title</Heading>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Page title
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
<Heading level={1}>Page title</Heading>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Decoupled size
|
|
68
|
+
|
|
69
|
+
Keep the document outline correct while controlling the visual scale
|
|
70
|
+
|
|
71
|
+
```jsx
|
|
72
|
+
<Heading level={2} size="2xl">
|
|
73
|
+
Visually large, semantically h2
|
|
74
|
+
</Heading>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Boundaries
|
|
78
|
+
|
|
79
|
+
| Area | Level | Note |
|
|
80
|
+
| -------------- | -------- | ------------------------------------------------------------ |
|
|
81
|
+
| size | flexible | size may override the level-derived default for visual scale |
|
|
82
|
+
| level sequence | strict | Levels must not skip — maintain a valid heading hierarchy |
|
|
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 Heading component (display). Section heading with semantic level decoupled from visual size
|
|
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
|
+
Heading is strictly bound to these tokens — use only these, do not invent token names:
|
|
99
|
+
--cascivo-font-display, --cascivo-font-semibold, --cascivo-leading-tight, --cascivo-tracking-tight, --cascivo-color-text, --cascivo-text-base, --cascivo-text-lg, --cascivo-text-xl, --cascivo-text-2xl, --cascivo-text-3xl
|
|
100
|
+
|
|
101
|
+
Accessibility: role "heading", WCAG 2.2-AA. Keep it AA.
|
|
102
|
+
|
|
103
|
+
Do not change (strict): level sequence — Levels must not skip — maintain a valid heading hierarchy
|
|
104
|
+
Flexible: size.
|
|
105
|
+
|
|
106
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
107
|
+
```
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# HoverCard
|
|
2
|
+
|
|
3
|
+
**Category:** overlay
|
|
4
|
+
**Description:** Hover-triggered popover with configurable open/close delay
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Showing a rich preview (avatar, summary, links) when a user hovers or focuses a trigger
|
|
9
|
+
- Supplementary, non-essential context the user can ignore without losing functionality
|
|
10
|
+
- Cases needing an open/close delay so brief mouse passes do not flicker the card
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- Short plain-text hints — use Tooltip
|
|
15
|
+
- Content the user must interact with or that should trap focus — use Popover or Modal
|
|
16
|
+
- Touch-primary flows where there is no hover — prefer a tap-triggered Popover
|
|
17
|
+
|
|
18
|
+
## Anti-patterns
|
|
19
|
+
|
|
20
|
+
### Hover surfaces are transient and unreachable by touch and many keyboard paths, so essential controls get lost
|
|
21
|
+
|
|
22
|
+
**Bad:** `Putting required actions (buttons users must click) inside HoverCardContent`
|
|
23
|
+
**Good:** `Use a Popover triggered by click so the surface is reliably reachable`
|
|
24
|
+
**Why:** Hover surfaces are transient and unreachable by touch and many keyboard paths, so essential controls get lost
|
|
25
|
+
|
|
26
|
+
## Related components
|
|
27
|
+
|
|
28
|
+
- **Tooltip** (alternative): Use Tooltip for brief text labels rather than rich preview content
|
|
29
|
+
- **Popover** (alternative): Use Popover for click-triggered, interactive, focus-managed content
|
|
30
|
+
|
|
31
|
+
## Accessibility rationale
|
|
32
|
+
|
|
33
|
+
The trigger opens on both mouseenter and focus (and closes on mouseleave/blur) so keyboard users get the same preview, and the content is marked role="complementary" to signal it is supplementary rather than a required dialog; the open/close delays prevent accidental flicker.
|
|
34
|
+
|
|
35
|
+
## Props
|
|
36
|
+
|
|
37
|
+
| Name | Type | Required | Default | Description |
|
|
38
|
+
| ------------ | ----------------- | -------- | ------- | ----------------------------------------------------------- |
|
|
39
|
+
| `children` | `React.ReactNode` | Yes | — | A HoverCardTrigger and HoverCardContent pair. |
|
|
40
|
+
| `openDelay` | `number` | No | 300 | Delay (ms) before the card opens on hover/focus. |
|
|
41
|
+
| `closeDelay` | `number` | No | 100 | Delay (ms) before the card closes after hover/focus leaves. |
|
|
42
|
+
|
|
43
|
+
## Tokens
|
|
44
|
+
|
|
45
|
+
- `--cascivo-color-surface`
|
|
46
|
+
- `--cascivo-color-border`
|
|
47
|
+
- `--cascivo-radius-md`
|
|
48
|
+
- `--cascivo-shadow-md`
|
|
49
|
+
- `--cascivo-motion-enter`
|
|
50
|
+
- `--cascivo-motion-exit`
|
|
51
|
+
|
|
52
|
+
## Examples
|
|
53
|
+
|
|
54
|
+
### Profile preview
|
|
55
|
+
|
|
56
|
+
```jsx
|
|
57
|
+
<HoverCard>
|
|
58
|
+
<HoverCardTrigger>
|
|
59
|
+
<a href="/users/ada">@ada</a>
|
|
60
|
+
</HoverCardTrigger>
|
|
61
|
+
<HoverCardContent>
|
|
62
|
+
<Avatar name="Ada Lovelace" />
|
|
63
|
+
<p>Wrote the first program.</p>
|
|
64
|
+
</HoverCardContent>
|
|
65
|
+
</HoverCard>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Custom delays
|
|
69
|
+
|
|
70
|
+
```jsx
|
|
71
|
+
<HoverCard openDelay={500} closeDelay={200}>
|
|
72
|
+
<HoverCardTrigger>Definition</HoverCardTrigger>
|
|
73
|
+
<HoverCardContent>A longer explanation shown on hover or focus.</HoverCardContent>
|
|
74
|
+
</HoverCard>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Boundaries
|
|
78
|
+
|
|
79
|
+
| Area | Level | Note |
|
|
80
|
+
| ---------------- | -------- | ------------------------------------------------------------------------------------------ |
|
|
81
|
+
| token names | strict | Surface, border, radius, shadow, and motion must resolve to the listed --cascivo-\* tokens |
|
|
82
|
+
| open/close delay | flexible | openDelay and closeDelay are tunable per instance (defaults 300/100ms) |
|
|
83
|
+
| content | flexible | HoverCardContent accepts arbitrary children |
|
|
84
|
+
|
|
85
|
+
## AI context prompt
|
|
86
|
+
|
|
87
|
+
Copy this into an LLM context bar before editing this component:
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
I am modifying the cascivo HoverCard component (overlay). Hover-triggered popover with configurable open/close delay
|
|
91
|
+
|
|
92
|
+
Architecture constraints — follow exactly:
|
|
93
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
94
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
95
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
96
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
97
|
+
- CSS logical properties only (RTL-safe).
|
|
98
|
+
|
|
99
|
+
HoverCard is strictly bound to these tokens — use only these, do not invent token names:
|
|
100
|
+
--cascivo-color-surface, --cascivo-color-border, --cascivo-radius-md, --cascivo-shadow-md, --cascivo-motion-enter, --cascivo-motion-exit
|
|
101
|
+
|
|
102
|
+
Accessibility: role "complementary", WCAG 2.2-AA, keyboard: Tab/Escape. Keep it AA.
|
|
103
|
+
|
|
104
|
+
Do not change (strict): token names — Surface, border, radius, shadow, and motion must resolve to the listed --cascivo-* tokens
|
|
105
|
+
Flexible: open/close delay, content.
|
|
106
|
+
|
|
107
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
108
|
+
```
|