@cascivo/mcp 0.2.0 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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,115 @@
|
|
|
1
|
+
# IconButton
|
|
2
|
+
|
|
3
|
+
**Category:** inputs
|
|
4
|
+
**Description:** Square, icon-only button with a required accessible label
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- A compact, recognizable action where an icon alone communicates intent (close, edit, more)
|
|
9
|
+
- Dense toolbars or table rows where a text label would not fit
|
|
10
|
+
|
|
11
|
+
## When NOT to use
|
|
12
|
+
|
|
13
|
+
- The action is not universally recognizable by its icon — use a Button with a text label
|
|
14
|
+
- Navigating between pages — use an anchor (optionally via asChild)
|
|
15
|
+
|
|
16
|
+
## Anti-patterns
|
|
17
|
+
|
|
18
|
+
### An icon-only control has no visible text, so the label prop is the only accessible name screen readers can announce
|
|
19
|
+
|
|
20
|
+
**Bad:** `<IconButton label=""><TrashIcon /></IconButton>`
|
|
21
|
+
**Good:** `<IconButton label="Delete item"><TrashIcon /></IconButton>`
|
|
22
|
+
**Why:** An icon-only control has no visible text, so the label prop is the only accessible name screen readers can announce
|
|
23
|
+
|
|
24
|
+
## Related components
|
|
25
|
+
|
|
26
|
+
- **Button** (alternative): Use a Button when the action needs a visible text label
|
|
27
|
+
- **ButtonGroup** (contained-by): Icon buttons are commonly joined into a toolbar via ButtonGroup
|
|
28
|
+
|
|
29
|
+
## Accessibility rationale
|
|
30
|
+
|
|
31
|
+
Renders a native <button> with a mandatory aria-label so the icon-only control always exposes an accessible name; focus, role, and Enter/Space activation come from the platform
|
|
32
|
+
|
|
33
|
+
## Props
|
|
34
|
+
|
|
35
|
+
| Name | Type | Required | Default | Description |
|
|
36
|
+
| ---------- | -------------------------------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| `label` | `string` | Yes | — | Text label for the control. |
|
|
38
|
+
| `icon` | `React.ReactNode` | No | — | Icon element rendered in the component. |
|
|
39
|
+
| `variant` | `'ghost' \| 'outline' \| 'filled'` | No | ghost | Selects the visual style variant. |
|
|
40
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | No | md | Visual size of the component (e.g. 'sm', 'md', 'lg'). |
|
|
41
|
+
| `asChild` | `boolean` | No | false | When true, renders the child element as the root via Slot, merging props (polymorphic rendering). |
|
|
42
|
+
| `disabled` | `boolean` | No | false | When true, disables the control and removes it from the tab order. |
|
|
43
|
+
| `onClick` | `React.MouseEventHandler<HTMLButtonElement>` | No | — | Called when the element is clicked. |
|
|
44
|
+
|
|
45
|
+
## Tokens
|
|
46
|
+
|
|
47
|
+
- `--cascivo-control-height-sm`
|
|
48
|
+
- `--cascivo-control-height-md`
|
|
49
|
+
- `--cascivo-control-height-lg`
|
|
50
|
+
- `--cascivo-button-radius`
|
|
51
|
+
- `--cascivo-radius-control`
|
|
52
|
+
- `--cascivo-color-primary`
|
|
53
|
+
- `--cascivo-color-primary-fg`
|
|
54
|
+
- `--cascivo-color-bg-subtle`
|
|
55
|
+
- `--cascivo-color-border`
|
|
56
|
+
- `--cascivo-color-surface`
|
|
57
|
+
- `--cascivo-focus-ring`
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
### Ghost
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
<IconButton label="Settings">
|
|
65
|
+
<GearIcon />
|
|
66
|
+
</IconButton>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Filled
|
|
70
|
+
|
|
71
|
+
```jsx
|
|
72
|
+
<IconButton label="Add" variant="filled" icon={<PlusIcon />} />
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### As link
|
|
76
|
+
|
|
77
|
+
```jsx
|
|
78
|
+
<IconButton label="Home" asChild>
|
|
79
|
+
<a href="/">
|
|
80
|
+
<HomeIcon />
|
|
81
|
+
</a>
|
|
82
|
+
</IconButton>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Boundaries
|
|
86
|
+
|
|
87
|
+
| Area | Level | Note |
|
|
88
|
+
| ----------- | -------- | ----------------------------------------------------------------------------------------------------- |
|
|
89
|
+
| token names | strict | Sizing must resolve to --cascivo-control-height-\* so it stays square and aligned with other controls |
|
|
90
|
+
| icon choice | flexible | Any single icon node; consumer owns the icon set |
|
|
91
|
+
|
|
92
|
+
## AI context prompt
|
|
93
|
+
|
|
94
|
+
Copy this into an LLM context bar before editing this component:
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
I am modifying the cascivo IconButton component (inputs). Square, icon-only button with a required accessible label
|
|
98
|
+
|
|
99
|
+
Architecture constraints — follow exactly:
|
|
100
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
101
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
102
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
103
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
104
|
+
- CSS logical properties only (RTL-safe).
|
|
105
|
+
|
|
106
|
+
IconButton is strictly bound to these tokens — use only these, do not invent token names:
|
|
107
|
+
--cascivo-control-height-sm, --cascivo-control-height-md, --cascivo-control-height-lg, --cascivo-button-radius, --cascivo-radius-control, --cascivo-color-primary, --cascivo-color-primary-fg, --cascivo-color-bg-subtle, --cascivo-color-border, --cascivo-color-surface, --cascivo-focus-ring
|
|
108
|
+
|
|
109
|
+
Accessibility: role "button", WCAG 2.2-AA, keyboard: Enter/Space. Keep it AA.
|
|
110
|
+
|
|
111
|
+
Do not change (strict): token names — Sizing must resolve to --cascivo-control-height-* so it stays square and aligned with other controls
|
|
112
|
+
Flexible: icon choice.
|
|
113
|
+
|
|
114
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
115
|
+
```
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Image
|
|
2
|
+
|
|
3
|
+
**Category:** display
|
|
4
|
+
**Description:** Image with load state, blur-up placeholder, graceful fallback, and optional zoom
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Displaying a content image that should show a placeholder while loading and degrade gracefully on error
|
|
9
|
+
- Photos, thumbnails, or media that benefit from a blur-up placeholder or hover zoom
|
|
10
|
+
- Any image where a broken src should fall back rather than show a broken-image icon
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- Identity thumbnails for a person or entity — use Avatar
|
|
15
|
+
- Purely decorative shapes or a fixed-ratio layout box with no load behavior — use AspectRatio
|
|
16
|
+
|
|
17
|
+
## Anti-patterns
|
|
18
|
+
|
|
19
|
+
### Without alt the image is invisible to assistive tech; pass an empty alt only for decorative images
|
|
20
|
+
|
|
21
|
+
**Bad:** `<Image src="/photo.jpg" /> with no alt`
|
|
22
|
+
**Good:** `<Image src="/photo.jpg" alt="Sunset over the bay" />`
|
|
23
|
+
**Why:** Without alt the image is invisible to assistive tech; pass an empty alt only for decorative images
|
|
24
|
+
|
|
25
|
+
## Related components
|
|
26
|
+
|
|
27
|
+
- **Avatar** (alternative): Use Avatar for identity thumbnails with an initials fallback
|
|
28
|
+
- **AspectRatio** (alternative): Use AspectRatio for a ratio box that does not own image load behavior
|
|
29
|
+
|
|
30
|
+
## Accessibility rationale
|
|
31
|
+
|
|
32
|
+
role="img" with alt names the image; on error it shows a fallback image or neutral box so layout survives; the blur-up and zoom transitions are disabled under prefers-reduced-motion
|
|
33
|
+
|
|
34
|
+
## Props
|
|
35
|
+
|
|
36
|
+
| Name | Type | Required | Default | Description |
|
|
37
|
+
| --------------- | ------------------------------------------ | -------- | ------- | ---------------------------------------------------------------------- |
|
|
38
|
+
| `src` | `string` | No | — | Image source URL. |
|
|
39
|
+
| `alt` | `string` | No | — | Alternative text describing the image. |
|
|
40
|
+
| `fallbackSrc` | `string` | No | — | Image shown if src fails to load |
|
|
41
|
+
| `width` | `string \| number` | No | — | Width of the component. |
|
|
42
|
+
| `height` | `string \| number` | No | — | Height of the component. |
|
|
43
|
+
| `radius` | `'none' \| 'sm' \| 'md' \| 'lg' \| 'full'` | No | md | Corner radius of the image ('none' \| 'sm' \| 'md' \| 'lg' \| 'full'). |
|
|
44
|
+
| `zoom` | `boolean` | No | false | When true, zooms the image on hover. |
|
|
45
|
+
| `removeWrapper` | `boolean` | No | false | Render a bare <img> with no wrapper, placeholder, or zoom |
|
|
46
|
+
| `isBlurred` | `boolean` | No | false | When true, renders a blurred backdrop behind the image. |
|
|
47
|
+
|
|
48
|
+
## Tokens
|
|
49
|
+
|
|
50
|
+
- `--cascivo-radius-none`
|
|
51
|
+
- `--cascivo-radius-sm`
|
|
52
|
+
- `--cascivo-radius-md`
|
|
53
|
+
- `--cascivo-radius-lg`
|
|
54
|
+
- `--cascivo-radius-full`
|
|
55
|
+
- `--cascivo-color-bg-subtle`
|
|
56
|
+
- `--cascivo-color-border`
|
|
57
|
+
- `--cascivo-space-12`
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
### Basic
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
<Image src="/photo.jpg" alt="A photo" width={320} height={240} />
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### With fallback
|
|
68
|
+
|
|
69
|
+
```jsx
|
|
70
|
+
<Image src="/broken.jpg" fallbackSrc="/placeholder.jpg" alt="A photo" />
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Blurred placeholder
|
|
74
|
+
|
|
75
|
+
```jsx
|
|
76
|
+
<Image src="/photo.jpg" alt="A photo" isBlurred />
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Hover zoom
|
|
80
|
+
|
|
81
|
+
```jsx
|
|
82
|
+
<Image src="/photo.jpg" alt="A photo" zoom />
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Boundaries
|
|
86
|
+
|
|
87
|
+
| Area | Level | Note |
|
|
88
|
+
| ----------- | -------- | ----------------------------------------------------------------- |
|
|
89
|
+
| radius | flexible | Pick the corner radius that matches the surrounding surface |
|
|
90
|
+
| token names | strict | Radius and placeholder colors must resolve to --cascivo-\* tokens |
|
|
91
|
+
|
|
92
|
+
## AI context prompt
|
|
93
|
+
|
|
94
|
+
Copy this into an LLM context bar before editing this component:
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
I am modifying the cascivo Image component (display). Image with load state, blur-up placeholder, graceful fallback, and optional zoom
|
|
98
|
+
|
|
99
|
+
Architecture constraints — follow exactly:
|
|
100
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
101
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
102
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
103
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
104
|
+
- CSS logical properties only (RTL-safe).
|
|
105
|
+
|
|
106
|
+
Image is strictly bound to these tokens — use only these, do not invent token names:
|
|
107
|
+
--cascivo-radius-none, --cascivo-radius-sm, --cascivo-radius-md, --cascivo-radius-lg, --cascivo-radius-full, --cascivo-color-bg-subtle, --cascivo-color-border, --cascivo-space-12
|
|
108
|
+
|
|
109
|
+
Accessibility: role "img", WCAG 2.2-AA. Keep it AA.
|
|
110
|
+
|
|
111
|
+
Do not change (strict): token names — Radius and placeholder colors must resolve to --cascivo-* tokens
|
|
112
|
+
Flexible: radius.
|
|
113
|
+
|
|
114
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
115
|
+
```
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Indicator
|
|
2
|
+
|
|
3
|
+
**Category:** layout
|
|
4
|
+
**Description:** Positions an overlay element (badge, dot, count) at a corner of its child
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Notification counts on icon buttons
|
|
9
|
+
- Status dots on avatars
|
|
10
|
+
|
|
11
|
+
## When NOT to use
|
|
12
|
+
|
|
13
|
+
- Inline badges within text — use Badge directly
|
|
14
|
+
- Status messages below a field — use a form hint or Alert
|
|
15
|
+
|
|
16
|
+
## Related components
|
|
17
|
+
|
|
18
|
+
- **Badge** (contained-by): Badge is the most common overlay content placed inside Indicator
|
|
19
|
+
- **Avatar** (pairs-with): Indicator is frequently used to attach a status dot to an Avatar
|
|
20
|
+
|
|
21
|
+
## Accessibility rationale
|
|
22
|
+
|
|
23
|
+
The overlay is marked aria-hidden because it is a visual affordance — the underlying control (button, avatar) carries its own accessible label. Screen-reader users should receive the count or status through the control's accessible name or a live region, not from the overlay div.
|
|
24
|
+
|
|
25
|
+
## Props
|
|
26
|
+
|
|
27
|
+
| Name | Type | Required | Default | Description |
|
|
28
|
+
| ----------- | ------------------------------------------------------------ | -------- | ------- | -------------------------------------------------------- |
|
|
29
|
+
| `children` | `React.ReactNode` | Yes | — | Content rendered inside the component. |
|
|
30
|
+
| `overlay` | `React.ReactNode` | Yes | — | The element to display at the corner (badge, dot, count) |
|
|
31
|
+
| `placement` | `'top-start' \| 'top-end' \| 'bottom-start' \| 'bottom-end'` | No | top-end | Placement relative to the trigger. |
|
|
32
|
+
| `className` | `string` | No | — | Additional CSS class names merged onto the root element. |
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
### Notification count
|
|
37
|
+
|
|
38
|
+
Notification count badge on an icon button
|
|
39
|
+
|
|
40
|
+
```jsx
|
|
41
|
+
<Indicator overlay={<Badge>3</Badge>}>
|
|
42
|
+
<Button variant="ghost">
|
|
43
|
+
<Icon name="bell" />
|
|
44
|
+
</Button>
|
|
45
|
+
</Indicator>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Online status
|
|
49
|
+
|
|
50
|
+
Online status dot on an avatar
|
|
51
|
+
|
|
52
|
+
```jsx
|
|
53
|
+
<Indicator overlay={<span className="status-dot" />} placement="bottom-end">
|
|
54
|
+
<Avatar src="/user.jpg" />
|
|
55
|
+
</Indicator>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Bottom-start placement
|
|
59
|
+
|
|
60
|
+
Indicator positioned at the bottom-start corner
|
|
61
|
+
|
|
62
|
+
```jsx
|
|
63
|
+
<Indicator overlay={<Badge variant="destructive">!</Badge>} placement="bottom-start">
|
|
64
|
+
<Card>Content</Card>
|
|
65
|
+
</Indicator>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Boundaries
|
|
69
|
+
|
|
70
|
+
| Area | Level | Note |
|
|
71
|
+
| --------- | -------- | --------------------------------------------------------------------------------------------- |
|
|
72
|
+
| placement | flexible | All four corners are supported; top-end is the most common convention for notification counts |
|
|
73
|
+
|
|
74
|
+
## AI context prompt
|
|
75
|
+
|
|
76
|
+
Copy this into an LLM context bar before editing this component:
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
I am modifying the cascivo Indicator component (layout). Positions an overlay element (badge, dot, count) at a corner of its child
|
|
80
|
+
|
|
81
|
+
Architecture constraints — follow exactly:
|
|
82
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
83
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
84
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
85
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
86
|
+
- CSS logical properties only (RTL-safe).
|
|
87
|
+
|
|
88
|
+
Indicator is strictly bound to these tokens — use only these, do not invent token names:
|
|
89
|
+
none declared
|
|
90
|
+
|
|
91
|
+
Accessibility: role "none", WCAG 2.2-AA. Keep it AA.
|
|
92
|
+
Flexible: placement.
|
|
93
|
+
|
|
94
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
95
|
+
```
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# InlineLoading
|
|
2
|
+
|
|
3
|
+
**Category:** feedback
|
|
4
|
+
**Description:** Compact inline status indicator that pairs a label with a loading, success, or error state
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Showing the progress of a single inline action — a Save button that becomes "Saving… / Saved / Failed"
|
|
9
|
+
- Communicating async status next to a control without occupying its own block or modal
|
|
10
|
+
- Reflecting a terminal success or error state that should be announced to assistive tech
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- Page- or section-level loading where layout space is reserved — use Skeleton or Spinner
|
|
15
|
+
- Persistent, multi-line messages with recovery actions — use Alert or Notification
|
|
16
|
+
- Determinate progress with a known percentage — use a progress bar
|
|
17
|
+
|
|
18
|
+
## Anti-patterns
|
|
19
|
+
|
|
20
|
+
### A single status keeps the icon, color, and announced label in sync and prevents mismatched states
|
|
21
|
+
|
|
22
|
+
**Bad:** `<Spinner /> with separate manually-managed success and error markup`
|
|
23
|
+
**Good:** `<InlineLoading status={status} /> driving icon and color from one status prop`
|
|
24
|
+
**Why:** A single status keeps the icon, color, and announced label in sync and prevents mismatched states
|
|
25
|
+
|
|
26
|
+
## Related components
|
|
27
|
+
|
|
28
|
+
- **Spinner** (contains): InlineLoading renders a Spinner for its active state and adds finished/error icons plus a label
|
|
29
|
+
- **Alert** (alternative): Use Alert for persistent messages that need a title, body, and actions rather than a terse status
|
|
30
|
+
|
|
31
|
+
## Accessibility rationale
|
|
32
|
+
|
|
33
|
+
role="status" with aria-live="polite" announces the label when the status changes; the icon is decorative (aria-hidden) so meaning is carried by the text and color is never the sole signal
|
|
34
|
+
|
|
35
|
+
## Props
|
|
36
|
+
|
|
37
|
+
| Name | Type | Required | Default | Description |
|
|
38
|
+
| -------- | -------------------------------------------------------- | -------- | ------- | ---------------------------------------------------------- |
|
|
39
|
+
| `status` | `'inactive' \| 'active' \| 'finished' \| 'error'` | Yes | — | Status state. |
|
|
40
|
+
| `label` | `ReactNode` | No | — | Text label for the control. |
|
|
41
|
+
| `labels` | `{ active?: string; finished?: string; error?: string }` | No | — | Overrides for the component’s user-visible strings (i18n). |
|
|
42
|
+
|
|
43
|
+
## Tokens
|
|
44
|
+
|
|
45
|
+
- `--cascivo-color-text`
|
|
46
|
+
- `--cascivo-color-text-muted`
|
|
47
|
+
- `--cascivo-color-success`
|
|
48
|
+
- `--cascivo-color-destructive`
|
|
49
|
+
- `--cascivo-motion-enter`
|
|
50
|
+
|
|
51
|
+
## Examples
|
|
52
|
+
|
|
53
|
+
### Active
|
|
54
|
+
|
|
55
|
+
```jsx
|
|
56
|
+
<InlineLoading status="active" />
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Finished
|
|
60
|
+
|
|
61
|
+
```jsx
|
|
62
|
+
<InlineLoading status="finished" label="Saved" />
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Error
|
|
66
|
+
|
|
67
|
+
```jsx
|
|
68
|
+
<InlineLoading status="error" label="Save failed" />
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Boundaries
|
|
72
|
+
|
|
73
|
+
| Area | Level | Note |
|
|
74
|
+
| ---------------- | -------- | ------------------------------------------------------------------------------------------------ |
|
|
75
|
+
| label | flexible | Defaults come from the i18n catalog per status; override with label or the per-status labels map |
|
|
76
|
+
| status semantics | strict | active must show a spinner, finished a success icon, error an error icon — do not repurpose |
|
|
77
|
+
|
|
78
|
+
## AI context prompt
|
|
79
|
+
|
|
80
|
+
Copy this into an LLM context bar before editing this component:
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
I am modifying the cascivo InlineLoading component (feedback). Compact inline status indicator that pairs a label with a loading, success, or error state
|
|
84
|
+
|
|
85
|
+
Architecture constraints — follow exactly:
|
|
86
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
87
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
88
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
89
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
90
|
+
- CSS logical properties only (RTL-safe).
|
|
91
|
+
|
|
92
|
+
InlineLoading is strictly bound to these tokens — use only these, do not invent token names:
|
|
93
|
+
--cascivo-color-text, --cascivo-color-text-muted, --cascivo-color-success, --cascivo-color-destructive, --cascivo-motion-enter
|
|
94
|
+
|
|
95
|
+
Accessibility: role "status", WCAG 2.2-AA. Keep it AA.
|
|
96
|
+
|
|
97
|
+
Do not change (strict): status semantics — active must show a spinner, finished a success icon, error an error icon — do not repurpose
|
|
98
|
+
Flexible: label.
|
|
99
|
+
|
|
100
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
101
|
+
```
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# InputGroup
|
|
2
|
+
|
|
3
|
+
**Category:** inputs
|
|
4
|
+
**Description:** Prefix/suffix addon wrapper for Input; InputGroupAddon renders inline icons/units inside the field border; ButtonGroup collapses adjacent button borders
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Attaching a prefix/suffix addon (protocol, currency, unit) to an Input so it reads as one field
|
|
9
|
+
- Placing a leading or trailing inline icon/unit inside the field border via InputGroupAddon
|
|
10
|
+
- Grouping adjacent buttons with collapsed shared borders via ButtonGroup
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- A standalone field with no adornment — use Input directly
|
|
15
|
+
- Conveying meaning that the user must read via an addon — decorative addons are aria-hidden
|
|
16
|
+
|
|
17
|
+
## Anti-patterns
|
|
18
|
+
|
|
19
|
+
### InputGroupAddon is aria-hidden and decorative, so screen readers never announce it
|
|
20
|
+
|
|
21
|
+
**Bad:** `<InputGroupAddon>Required</InputGroupAddon> to convey field status`
|
|
22
|
+
**Good:** `Use the Input error/hint props for meaningful text`
|
|
23
|
+
**Why:** InputGroupAddon is aria-hidden and decorative, so screen readers never announce it
|
|
24
|
+
|
|
25
|
+
## Related components
|
|
26
|
+
|
|
27
|
+
- **Input** (contains): InputGroup composes around an Input to add prefix/suffix addons
|
|
28
|
+
- **Button** (contains): ButtonGroup arranges adjacent Buttons with merged borders
|
|
29
|
+
|
|
30
|
+
## Accessibility rationale
|
|
31
|
+
|
|
32
|
+
Inline addons are marked aria-hidden because they are purely decorative units/icons, so the wrapped Input keeps its own accessible name; ButtonGroup uses role="group" to convey that its buttons form a related set.
|
|
33
|
+
|
|
34
|
+
## Props
|
|
35
|
+
|
|
36
|
+
| Name | Type | Required | Default | Description |
|
|
37
|
+
| ---------- | ----------- | -------- | ------- | ------------------------------------------------------ |
|
|
38
|
+
| `prefix` | `ReactNode` | No | — | Content rendered before the input (leading adornment). |
|
|
39
|
+
| `suffix` | `ReactNode` | No | — | Content rendered after the input (trailing adornment). |
|
|
40
|
+
| `children` | `ReactNode` | Yes | — | Content rendered inside the component. |
|
|
41
|
+
|
|
42
|
+
## Tokens
|
|
43
|
+
|
|
44
|
+
- `--cascivo-color-bg-subtle`
|
|
45
|
+
- `--cascivo-color-border`
|
|
46
|
+
- `--cascivo-color-text-subtle`
|
|
47
|
+
- `--cascivo-radius-input`
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
50
|
+
|
|
51
|
+
### With prefix
|
|
52
|
+
|
|
53
|
+
```jsx
|
|
54
|
+
<InputGroup prefix="https://">
|
|
55
|
+
<Input placeholder="example.com" />
|
|
56
|
+
</InputGroup>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### With leading icon addon
|
|
60
|
+
|
|
61
|
+
```jsx
|
|
62
|
+
<InputGroup>
|
|
63
|
+
<InputGroupAddon>
|
|
64
|
+
<svg viewBox="0 0 16 16" width="16" height="16">
|
|
65
|
+
<circle cx="6" cy="6" r="4" fill="none" stroke="currentColor" strokeWidth="1.5" />
|
|
66
|
+
<path d="M10 10l3 3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
|
|
67
|
+
</svg>
|
|
68
|
+
</InputGroupAddon>
|
|
69
|
+
<Input placeholder="Search…" aria-label="Search" />
|
|
70
|
+
</InputGroup>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### With trailing unit addon
|
|
74
|
+
|
|
75
|
+
```jsx
|
|
76
|
+
<InputGroup>
|
|
77
|
+
<Input placeholder="0.00" aria-label="Weight" />
|
|
78
|
+
<InputGroupAddon align="inline-end">kg</InputGroupAddon>
|
|
79
|
+
</InputGroup>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### ButtonGroup
|
|
83
|
+
|
|
84
|
+
```jsx
|
|
85
|
+
<ButtonGroup>
|
|
86
|
+
<Button>Left</Button>
|
|
87
|
+
<Button>Right</Button>
|
|
88
|
+
</ButtonGroup>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Boundaries
|
|
92
|
+
|
|
93
|
+
| Area | Level | Note |
|
|
94
|
+
| --------------- | -------- | ----------------------------------------------------------------------------------------- |
|
|
95
|
+
| token names | strict | Addon background, border, text, and radius must resolve to the listed --cascivo-\* tokens |
|
|
96
|
+
| addon alignment | flexible | InputGroupAddon align is inline-start (leading) or inline-end (trailing) |
|
|
97
|
+
| addon content | flexible | prefix/suffix and addon children accept arbitrary ReactNode |
|
|
98
|
+
|
|
99
|
+
## AI context prompt
|
|
100
|
+
|
|
101
|
+
Copy this into an LLM context bar before editing this component:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
I am modifying the cascivo InputGroup component (inputs). Prefix/suffix addon wrapper for Input; InputGroupAddon renders inline icons/units inside the field border; ButtonGroup collapses adjacent button borders
|
|
105
|
+
|
|
106
|
+
Architecture constraints — follow exactly:
|
|
107
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
108
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
109
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
110
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
111
|
+
- CSS logical properties only (RTL-safe).
|
|
112
|
+
|
|
113
|
+
InputGroup is strictly bound to these tokens — use only these, do not invent token names:
|
|
114
|
+
--cascivo-color-bg-subtle, --cascivo-color-border, --cascivo-color-text-subtle, --cascivo-radius-input
|
|
115
|
+
|
|
116
|
+
Accessibility: role "generic", WCAG 2.2-AA. Keep it AA.
|
|
117
|
+
|
|
118
|
+
Do not change (strict): token names — Addon background, border, text, and radius must resolve to the listed --cascivo-* tokens
|
|
119
|
+
Flexible: addon alignment, addon content.
|
|
120
|
+
|
|
121
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
122
|
+
```
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Input
|
|
2
|
+
|
|
3
|
+
**Category:** inputs
|
|
4
|
+
**Description:** Text input field with optional label, hint, and error state
|
|
5
|
+
|
|
6
|
+
## When to use
|
|
7
|
+
|
|
8
|
+
- Collecting a single line of free-form text from the user
|
|
9
|
+
- Pairing a labelled field with optional hint and validation error messaging
|
|
10
|
+
- As a field control inside a Form, wired via form.field()
|
|
11
|
+
|
|
12
|
+
## When NOT to use
|
|
13
|
+
|
|
14
|
+
- Multi-line text — use Textarea
|
|
15
|
+
- Choosing from a fixed list of options — use Select, Combobox, or MultiSelect
|
|
16
|
+
- Editing one read-only value in place — use Editable
|
|
17
|
+
|
|
18
|
+
## Anti-patterns
|
|
19
|
+
|
|
20
|
+
### Placeholder text disappears on input and is not a substitute for a persistent, programmatically associated label
|
|
21
|
+
|
|
22
|
+
**Bad:** `<Input placeholder="Email" /> with no label`
|
|
23
|
+
**Good:** `<Input label="Email" placeholder="you@example.com" />`
|
|
24
|
+
**Why:** Placeholder text disappears on input and is not a substitute for a persistent, programmatically associated label
|
|
25
|
+
|
|
26
|
+
## Related components
|
|
27
|
+
|
|
28
|
+
- **Form** (contained-by): Input is the primary field control wired into a Form store
|
|
29
|
+
- **InputGroup** (pairs-with): Wrap Input in InputGroup to add prefix/suffix addons
|
|
30
|
+
- **Textarea** (alternative): Use Textarea for multi-line input
|
|
31
|
+
|
|
32
|
+
## Accessibility rationale
|
|
33
|
+
|
|
34
|
+
The label is associated to the input via htmlFor/id, error text is linked through aria-describedby and announced with role="alert", and aria-invalid is set when an error is present so assistive tech reports the field as erroneous; visual focus state is driven by CSS, not tracked imperatively.
|
|
35
|
+
|
|
36
|
+
## Props
|
|
37
|
+
|
|
38
|
+
| Name | Type | Required | Default | Description |
|
|
39
|
+
| ------------- | ---------------------- | -------- | ------- | ------------------------------------------------------------------ |
|
|
40
|
+
| `label` | `string` | No | — | Text label for the control. |
|
|
41
|
+
| `hint` | `string` | No | — | Supplementary hint text shown with the control. |
|
|
42
|
+
| `error` | `string` | No | — | Error message shown when the value is invalid. |
|
|
43
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | No | md | Visual size of the component (e.g. 'sm', 'md', 'lg'). |
|
|
44
|
+
| `placeholder` | `string` | No | — | Placeholder text shown when the field is empty. |
|
|
45
|
+
| `disabled` | `boolean` | No | false | When true, disables the control and removes it from the tab order. |
|
|
46
|
+
|
|
47
|
+
## Tokens
|
|
48
|
+
|
|
49
|
+
- `--cascivo-color-surface`
|
|
50
|
+
- `--cascivo-color-border`
|
|
51
|
+
- `--cascivo-color-accent`
|
|
52
|
+
- `--cascivo-color-destructive`
|
|
53
|
+
- `--cascivo-radius-input`
|
|
54
|
+
- `--cascivo-focus-ring`
|
|
55
|
+
|
|
56
|
+
## Examples
|
|
57
|
+
|
|
58
|
+
### With label
|
|
59
|
+
|
|
60
|
+
```jsx
|
|
61
|
+
<Input label="Email" placeholder="you@example.com" />
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### With error
|
|
65
|
+
|
|
66
|
+
```jsx
|
|
67
|
+
<Input label="Email" error="Invalid email address" />
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Boundaries
|
|
71
|
+
|
|
72
|
+
| Area | Level | Note |
|
|
73
|
+
| ------------------------- | -------- | ----------------------------------------------------------------------------------------------------------- |
|
|
74
|
+
| token names | strict | Surface, border, accent, destructive, radius, and focus-ring must resolve to the listed --cascivo-\* tokens |
|
|
75
|
+
| label / hint / error copy | flexible | Free, within content tone guidance |
|
|
76
|
+
| size | flexible | sm \| md \| lg, defaulting to md |
|
|
77
|
+
|
|
78
|
+
## AI context prompt
|
|
79
|
+
|
|
80
|
+
Copy this into an LLM context bar before editing this component:
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
I am modifying the cascivo Input component (inputs). Text input field with optional label, hint, and error state
|
|
84
|
+
|
|
85
|
+
Architecture constraints — follow exactly:
|
|
86
|
+
- Signals only (useSignal/useComputed/useSignalEffect from @cascivo/core). Never useState/useEffect/useContext/useReducer.
|
|
87
|
+
- Style only through --cascivo-* custom properties. No Tailwind, no inline styles, no CSS-in-JS.
|
|
88
|
+
- Responsive via @container queries on the canonical scale (30rem/40rem/64rem/80rem). Do not use global viewport @media breakpoints.
|
|
89
|
+
- Visual states (hover/focus/active/disabled) via CSS pseudo-classes, not JS.
|
|
90
|
+
- CSS logical properties only (RTL-safe).
|
|
91
|
+
|
|
92
|
+
Input is strictly bound to these tokens — use only these, do not invent token names:
|
|
93
|
+
--cascivo-color-surface, --cascivo-color-border, --cascivo-color-accent, --cascivo-color-destructive, --cascivo-radius-input, --cascivo-focus-ring
|
|
94
|
+
|
|
95
|
+
Accessibility: role "textbox", WCAG 2.2-AA, keyboard: Tab/Shift+Tab. Keep it AA.
|
|
96
|
+
|
|
97
|
+
Do not change (strict): token names — Surface, border, accent, destructive, radius, and focus-ring must resolve to the listed --cascivo-* tokens
|
|
98
|
+
Flexible: label / hint / error copy, size.
|
|
99
|
+
|
|
100
|
+
Do not invent props, tokens, or global viewport media queries.
|
|
101
|
+
```
|