@devalok/shilp-sutra 0.41.0 → 0.42.1
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/AGENTS.md +10 -0
- package/MIGRATION.md +8 -0
- package/llms-full.txt +1 -1
- package/llms.txt +4 -0
- package/make-kit/Guidelines.md +71 -0
- package/make-kit/components/badge.md +162 -0
- package/make-kit/components/button.md +125 -0
- package/make-kit/components/card.md +147 -0
- package/make-kit/components/dialog.md +167 -0
- package/make-kit/components/dropdown-menu.md +205 -0
- package/make-kit/components/form.md +189 -0
- package/make-kit/components/icon.md +152 -0
- package/make-kit/components/input.md +154 -0
- package/make-kit/components/overview.md +308 -0
- package/make-kit/components/popover.md +201 -0
- package/make-kit/components/select.md +148 -0
- package/make-kit/components/stack.md +165 -0
- package/make-kit/components/table.md +215 -0
- package/make-kit/components/tabs.md +162 -0
- package/make-kit/components/text.md +139 -0
- package/make-kit/components/toast.md +193 -0
- package/make-kit/foundations/color.md +128 -0
- package/make-kit/foundations/dark-mode.md +81 -0
- package/make-kit/foundations/icons.md +107 -0
- package/make-kit/foundations/motion.md +134 -0
- package/make-kit/foundations/radius.md +78 -0
- package/make-kit/foundations/spacing.md +110 -0
- package/make-kit/foundations/surfaces.md +121 -0
- package/make-kit/foundations/typography.md +120 -0
- package/make-kit/setup.md +130 -0
- package/package.json +5 -2
- package/skill/SKILL.md +1 -1
- package/skill/references/components-full.md +1 -1
- package/skill/references/components.md +4 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Radius
|
|
2
|
+
|
|
3
|
+
Two layers: a primitive scale and semantic role tokens. **Components reference roles. Override roles, not individual components.**
|
|
4
|
+
|
|
5
|
+
## Two-layer model
|
|
6
|
+
|
|
7
|
+
**Primitive scale** (size buckets):
|
|
8
|
+
|
|
9
|
+
| Token | Pixels |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `radius-ds-none` | 0 |
|
|
12
|
+
| `radius-ds-sm` | 2 |
|
|
13
|
+
| `radius-ds-md` | 6 |
|
|
14
|
+
| `radius-ds-lg` | 10 |
|
|
15
|
+
| `radius-ds-xl` | 16 |
|
|
16
|
+
| `radius-ds-2xl` | 24 |
|
|
17
|
+
| `radius-ds-full` | 9999 (pill) |
|
|
18
|
+
|
|
19
|
+
**Semantic roles** (mapped to scale at the default preset):
|
|
20
|
+
|
|
21
|
+
| Role | Default | Where it applies |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| `radius-control` | 6 | Button, Input, Select, IconButton, segmented item, Tab trigger. |
|
|
24
|
+
| `radius-control-inner` | 2 | Inner elements inside a control (e.g. selected segment indicator). |
|
|
25
|
+
| `radius-surface` | 10 | Cards, widgets, panels. |
|
|
26
|
+
| `radius-overlay-sm` | 6 | Tooltip, Toast. |
|
|
27
|
+
| `radius-overlay` | 10 | Popover, Dropdown, Menubar. |
|
|
28
|
+
| `radius-overlay-lg` | 16 | Dialog, Sheet. |
|
|
29
|
+
| `radius-pill` | 9999 | Badge, Switch, Radio dot, Avatar circle. Pill always wins. |
|
|
30
|
+
| `radius-bubble` | 24 | Chat bubbles. |
|
|
31
|
+
|
|
32
|
+
## How to apply
|
|
33
|
+
|
|
34
|
+
In components: never — they apply the right role automatically.
|
|
35
|
+
|
|
36
|
+
In your own elements (rare):
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
<div className="bg-surface-raised rounded-(--radius-surface) p-ds-05">…</div>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
TW4 shorthand `rounded-(--radius-surface)` is the right way. **Do not** use `rounded-ds-lg` directly — it's not a semantic role, and the pre-publish audit rejects it in `src/ui/`.
|
|
43
|
+
|
|
44
|
+
## Shape presets
|
|
45
|
+
|
|
46
|
+
The kit ships three shape presets, switchable via `[data-shape]` on `<html>`:
|
|
47
|
+
|
|
48
|
+
| Preset | Roles |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `sharp` | control 2 / control-inner 0 / surface 4 / overlay 4–6 |
|
|
51
|
+
| `slightly-rounded` (default) | control 6 / control-inner 2 / surface 10 / overlay 6–16 |
|
|
52
|
+
| `rounded` | control 10 / control-inner 4 / surface 16 / overlay 10–24 |
|
|
53
|
+
|
|
54
|
+
Toggle by setting `data-shape="rounded"` on `<html>` (or any subtree) — every component re-skins instantly. Pill shapes (Badge, Switch, Radio dot, Avatar circle) stay pill regardless of preset.
|
|
55
|
+
|
|
56
|
+
```html
|
|
57
|
+
<html data-shape="rounded">
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Custom override
|
|
61
|
+
|
|
62
|
+
Consumers can swap any role in their global CSS:
|
|
63
|
+
|
|
64
|
+
```css
|
|
65
|
+
:root {
|
|
66
|
+
--radius-control: 4px; /* sharper buttons + inputs */
|
|
67
|
+
--radius-surface: 12px; /* gentler cards */
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Override the role, not individual components. That way one declaration re-skins the whole system.
|
|
72
|
+
|
|
73
|
+
## Rules
|
|
74
|
+
|
|
75
|
+
- **Never** hand-pick a pixel radius (`rounded-[12px]`). Use a role.
|
|
76
|
+
- **Never** use `rounded-ds-*` directly in component-level code — that's the primitive scale, not the role.
|
|
77
|
+
- **Never** override `<Card>`, `<Button>` etc. radius via className. Override the role instead.
|
|
78
|
+
- **Pill shapes** are uncontested — Badge, Switch, Radio dot, Avatar circle stay pill no matter the preset.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Spacing
|
|
2
|
+
|
|
3
|
+
The kit uses a `ds-*` spacing scale (2 → 160 px) so utilities never collide with consumer values. **Default to a three-tier cadence — `ds-03` / `ds-05` / `ds-07` — not every adjacent token.**
|
|
4
|
+
|
|
5
|
+
## Three-tier cadence (the rule)
|
|
6
|
+
|
|
7
|
+
| Tier | Token | Pixels | Use |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| Related | `ds-03` | 8 | Items that read as one chunk — icon + label, label + input, badges in a row. |
|
|
10
|
+
| Grouped | `ds-05` | 16 | Sections within a card — heading group, controls group, body. |
|
|
11
|
+
| Section | `ds-07` | 32 | Distinct page sections, big breaks. |
|
|
12
|
+
|
|
13
|
+
**Do not** reach for `ds-04` (12 px) or `ds-06` (24 px) just because they exist. Three tiers create rhythm; five create noise.
|
|
14
|
+
|
|
15
|
+
If you need a *fourth* tier (e.g. between heading and body inside one group), use `ds-02` (4 px) — that's the "tight pair" tier (caption to value, hint to input).
|
|
16
|
+
|
|
17
|
+
## Full scale
|
|
18
|
+
|
|
19
|
+
| Token | Pixels | Typical use |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| `ds-01` | 2 | Hairline gap. Rare. |
|
|
22
|
+
| `ds-02` | 4 | Tight pair (caption under value, icon to text inside dense control). |
|
|
23
|
+
| `ds-02b` | 6 | Off-cadence; use sparingly. |
|
|
24
|
+
| `ds-03` | 8 | **Related** (default). |
|
|
25
|
+
| `ds-04` | 12 | Use only when 8 is too tight and 16 is too loose. |
|
|
26
|
+
| `ds-05` | 16 | **Grouped** (default). |
|
|
27
|
+
| `ds-05b` | 20 | Off-cadence; rare. |
|
|
28
|
+
| `ds-06` | 24 | Comfortable section gap; prefer `ds-07` unless 32 is too much. |
|
|
29
|
+
| `ds-06b` | 28 | Off-cadence. |
|
|
30
|
+
| `ds-07` | 32 | **Section** (default). |
|
|
31
|
+
| `ds-08` | 40 | Big section. |
|
|
32
|
+
| `ds-09` | 48 | Hero spacing. |
|
|
33
|
+
| `ds-10` | 64 | Marketing. |
|
|
34
|
+
| `ds-11+` | 80 / 96 / 160 | Marketing only. |
|
|
35
|
+
|
|
36
|
+
## How to apply
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
// Padding
|
|
40
|
+
<Card className="p-ds-05">…</Card> // inside-card spacing
|
|
41
|
+
<div className="px-ds-07 py-ds-09">…</div> // page region
|
|
42
|
+
|
|
43
|
+
// Gaps
|
|
44
|
+
<Stack gap="ds-03">…</Stack> // related items
|
|
45
|
+
<Stack gap="ds-05">…</Stack> // grouped items
|
|
46
|
+
<Stack gap="ds-07">…</Stack> // sections
|
|
47
|
+
|
|
48
|
+
// Margins (rare — prefer gap)
|
|
49
|
+
<Text className="mt-ds-02">helper</Text> // tight pair
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## `<Stack>` over flex divs
|
|
53
|
+
|
|
54
|
+
Don't write `<div className="flex flex-col gap-ds-05">`. Use `<Stack>`:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
<Stack gap="ds-05">
|
|
58
|
+
<Text variant="heading-md">Heading</Text>
|
|
59
|
+
<Text variant="body-md">Body</Text>
|
|
60
|
+
<Button>CTA</Button>
|
|
61
|
+
</Stack>
|
|
62
|
+
|
|
63
|
+
<Stack direction="row" gap="ds-03" align="center">
|
|
64
|
+
<Icon icon={IconUser} />
|
|
65
|
+
<Text>Username</Text>
|
|
66
|
+
</Stack>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`<Stack>` ships with `direction` (row | col, default col), `gap` (ds-* token), `align`, `justify`, `wrap`, `as` (polymorphic).
|
|
70
|
+
|
|
71
|
+
## Component sizing (separate from spacing)
|
|
72
|
+
|
|
73
|
+
Heights for controls use `ds-{size}` aliases:
|
|
74
|
+
|
|
75
|
+
| Token | Pixels | Component sizes |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| `ds-xs` | 24 | n/a (rare) |
|
|
78
|
+
| `ds-xs-plus` | 28 | Button/Input/Select **xs** |
|
|
79
|
+
| `ds-sm` | 32 | Button/Input/Select **sm** |
|
|
80
|
+
| `ds-md` | 40 | Button/Input/Select **md** (default) |
|
|
81
|
+
| `ds-lg` | 48 | Button/Input/Select **lg** |
|
|
82
|
+
| `ds-xl` | 56 | Button **xl** |
|
|
83
|
+
|
|
84
|
+
Apply via component `size` prop, not className.
|
|
85
|
+
|
|
86
|
+
## Page layout tokens
|
|
87
|
+
|
|
88
|
+
| Token | Use |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `--spacing-page-x` | Horizontal page padding. Responsive: 16 → 24 → 40 px. |
|
|
91
|
+
| `--spacing-section-gap` | Vertical gap between major page sections. |
|
|
92
|
+
| `--spacing-card-gap` | Vertical gap between adjacent cards. |
|
|
93
|
+
|
|
94
|
+
Apply via:
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
<main className="px-(--spacing-page-x) py-ds-09">
|
|
98
|
+
<Stack gap="(--spacing-section-gap)">
|
|
99
|
+
…
|
|
100
|
+
</Stack>
|
|
101
|
+
</main>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Rules
|
|
105
|
+
|
|
106
|
+
- **Default** to `ds-03 / ds-05 / ds-07`. Justify any deviation.
|
|
107
|
+
- **Never** use raw Tailwind spacing (`p-4`, `gap-6`). The kit's spacing is `ds-*` namespaced.
|
|
108
|
+
- **Never** mix arbitrary pixel values (`p-[14px]`). Pick a scale token.
|
|
109
|
+
- **Prefer `<Stack gap>` over `flex … gap-*`**. Cleaner semantics, polymorphic via `as`.
|
|
110
|
+
- Component sizes (xs / sm / md / lg / xl) come from the size prop, not from manual height utilities.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Surfaces & Shadows
|
|
2
|
+
|
|
3
|
+
The kit ships five semantic surface tiers and a paired shadow system. **Picking the right surface is mandatory** — the wrong one breaks elevation hierarchy and dark mode adaptation. There is a hard rule about never combining surfaces with borders.
|
|
4
|
+
|
|
5
|
+
## The five surface tiers
|
|
6
|
+
|
|
7
|
+
| Tier | Token | What sits here |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| **Base** | `surface-base` | Page background. The "back wall." |
|
|
10
|
+
| **Raised** | `surface-raised` | Cards, widgets, panels — anything that floats **on** the page. |
|
|
11
|
+
| **Sunken** | `surface-sunken` | Shell chrome (Sidebar, TopBar), board columns, segmented-control tracks. |
|
|
12
|
+
| **Overlay** | `surface-overlay` | Floating layers — Dialog, Sheet, Popover, Dropdown, Toast, Tooltip-when-light, Input field. |
|
|
13
|
+
| **Inverted** | `surface-inverted` | Tooltips, inverted badges. Pair with `text-surface-inverted-fg`. |
|
|
14
|
+
|
|
15
|
+
Each tier has hover / active variants:
|
|
16
|
+
|
|
17
|
+
- `surface-raised-hover` — hover on a raised element.
|
|
18
|
+
- `surface-raised-active` — pressed / selected raised element.
|
|
19
|
+
|
|
20
|
+
And a disabled state:
|
|
21
|
+
|
|
22
|
+
- `surface-disabled` + `text-surface-fg-disabled`.
|
|
23
|
+
|
|
24
|
+
## Decision matrix
|
|
25
|
+
|
|
26
|
+
| Building… | Surface | Shadow |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| Page / layout shell | `surface-base` | none |
|
|
29
|
+
| Sidebar / TopBar (shell) | `surface-sunken` | `shadow-raised` |
|
|
30
|
+
| Card / widget / panel | `surface-raised` | `shadow-raised` |
|
|
31
|
+
| Card on hover | `surface-raised` | `shadow-raised-hover` |
|
|
32
|
+
| Board column / well / track | `surface-sunken` | none |
|
|
33
|
+
| Popover / dropdown / menu | `surface-overlay` | `shadow-floating` |
|
|
34
|
+
| Dialog / modal / sheet | `surface-overlay` | `shadow-overlay` |
|
|
35
|
+
| Tooltip | `surface-inverted` | `shadow-floating` |
|
|
36
|
+
| Toast | `surface-overlay` | `shadow-floating` |
|
|
37
|
+
| Input (rest) | `surface-overlay` | none |
|
|
38
|
+
| Input (focus) | `surface-overlay` | `shadow-ring` |
|
|
39
|
+
| Button (solid) | accent colors | `shadow-raised` |
|
|
40
|
+
| Button (disabled) | `surface-disabled` | none |
|
|
41
|
+
| Segmented track | `surface-sunken` | `shadow-inset` |
|
|
42
|
+
| Selected item | current surface | `shadow-glow` |
|
|
43
|
+
| Backdrop (under modal) | `bg-backdrop` | none |
|
|
44
|
+
|
|
45
|
+
## Shadow tokens
|
|
46
|
+
|
|
47
|
+
| Token | When |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `shadow-raised` | Cards, panels, shell chrome at rest. |
|
|
50
|
+
| `shadow-raised-hover` | Cards on hover. Subtle lift. |
|
|
51
|
+
| `shadow-floating` | Popovers, dropdowns, menus, tooltips. |
|
|
52
|
+
| `shadow-overlay` | Dialogs, sheets. Deepest. |
|
|
53
|
+
| `shadow-brand` | Optional brand-tinted glow. Use on hero CTA. |
|
|
54
|
+
| `shadow-glow` | Selection / focus accent. |
|
|
55
|
+
| `shadow-inset` | Toggle / segmented track deboss. |
|
|
56
|
+
| `shadow-ring` | Focus ring (2px accent). |
|
|
57
|
+
| `shadow-ring-sm` | Subtle separator (1px border-color). |
|
|
58
|
+
| `shadow-kbd` | Inset for keyboard shortcut badges. |
|
|
59
|
+
| `shadow-success` / `shadow-error` / `shadow-warning` | Status glow. Use on status notifications. |
|
|
60
|
+
|
|
61
|
+
## The hard rule: never combine `border-*` with `shadow-*`
|
|
62
|
+
|
|
63
|
+
Shadow tokens include a 1-px ring layer (inset hairline + drop shadow). Adding an explicit `border-surface-border` on top creates a 2-px edge that looks broken.
|
|
64
|
+
|
|
65
|
+
❌ **Wrong:**
|
|
66
|
+
```tsx
|
|
67
|
+
<div className="bg-surface-raised border border-surface-border shadow-raised rounded-(--radius-surface)">
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
✅ **Right (shadow only):**
|
|
71
|
+
```tsx
|
|
72
|
+
<div className="bg-surface-raised shadow-raised rounded-(--radius-surface)">
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
✅ **Right (border only — when shadow is unwanted, e.g. dense lists):**
|
|
76
|
+
```tsx
|
|
77
|
+
<div className="bg-surface-raised border border-surface-border rounded-(--radius-surface)">
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`<Card>` already follows this rule. Don't override with extra border classes.
|
|
81
|
+
|
|
82
|
+
## Elevation reasoning
|
|
83
|
+
|
|
84
|
+
Surfaces describe **what kind of layer** something is, not **how high** it is. Two cards next to each other are both `raised`. A dialog over them isn't `raised-more` — it's `overlay`. A sidebar isn't `raised-but-lower` — it's `sunken`.
|
|
85
|
+
|
|
86
|
+
This means: **don't stack `raised` on `raised`**. If you'd reach for that, the inner element is probably `overlay` or wants a `surface-sunken` recess instead.
|
|
87
|
+
|
|
88
|
+
## Dark mode
|
|
89
|
+
|
|
90
|
+
In dark mode the kit lightens surfaces with elevation (so `surface-overlay` is *brighter* than `surface-base`). This is the inverse of light mode and is intentional — it's how Stripe / Linear / Material 3 model elevation in dark. Don't fight it.
|
|
91
|
+
|
|
92
|
+
## Page composition example
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
<div className="min-h-screen bg-surface-base">
|
|
96
|
+
<aside className="bg-surface-sunken"> {/* Sidebar */}
|
|
97
|
+
…
|
|
98
|
+
</aside>
|
|
99
|
+
<main className="bg-surface-base p-ds-07">
|
|
100
|
+
<Card className="bg-surface-raised shadow-raised p-ds-05"> {/* Card */}
|
|
101
|
+
…
|
|
102
|
+
<Dialog>
|
|
103
|
+
<DialogContent className="bg-surface-overlay shadow-overlay">
|
|
104
|
+
… {/* Modal */}
|
|
105
|
+
</DialogContent>
|
|
106
|
+
</Dialog>
|
|
107
|
+
</Card>
|
|
108
|
+
</main>
|
|
109
|
+
</div>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
(In practice you wouldn't write the `bg-*` / `shadow-*` directly — `<Card>`, `<DialogContent>`, `<AppSidebar>` apply them. This is just the layer model.)
|
|
113
|
+
|
|
114
|
+
## Rules
|
|
115
|
+
|
|
116
|
+
- **Card-like elements** (anything that reads as a panel on the page) → `surface-raised`, never `surface-base`.
|
|
117
|
+
- **Overlay-like elements** → `surface-overlay`, always.
|
|
118
|
+
- **Never** combine an explicit border with a shadow token.
|
|
119
|
+
- **Never** invent a sixth tier. Five is the system.
|
|
120
|
+
- **Don't** override `<Card>`, `<DialogContent>`, `<PopoverContent>` surface — they pick the right one for you.
|
|
121
|
+
- For Storybook authors and pre-publish audit: components in `src/ui/` that render as cards must NOT use `bg-surface-base`. The audit script will reject it.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Typography
|
|
2
|
+
|
|
3
|
+
The kit ships an 11-step type scale (`text-ds-xs` through `text-ds-6xl`) with paired line-heights. **Use the scale, not arbitrary pixel values.**
|
|
4
|
+
|
|
5
|
+
## Philosophy
|
|
6
|
+
|
|
7
|
+
- One scale, applied with intent. A page should land on 3–4 text sizes max — heading + body + caption.
|
|
8
|
+
- Larger headings (3xl and up) use `clamp()` to scale fluidly between mobile and desktop. Smaller sizes are fixed.
|
|
9
|
+
- Default font is Inter Variable (sans). `Ranade` Variable is the accent display face for marketing-heavy treatments. SF Mono is the monospace.
|
|
10
|
+
- Letter spacing on body sizes is tuned per-size (`body-lg: -0.01em`, `body-md: 0`, `body-sm: +0.01em`, `body-xs: +0.02em`).
|
|
11
|
+
|
|
12
|
+
## Size scale
|
|
13
|
+
|
|
14
|
+
| Token | Size | Use |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| `text-ds-xs` | 10px | Footnotes, fine print, only when space is at premium. Never for primary content. |
|
|
17
|
+
| `text-ds-sm` | 12px | Captions, table labels, helper text, badges. |
|
|
18
|
+
| `text-ds-md` | 14px | Default UI body. All input fields. Default Button label. |
|
|
19
|
+
| `text-ds-base` | 16px | Body copy in marketing / docs. Mobile input minimum. |
|
|
20
|
+
| `text-ds-lg` | 18px | Lead paragraphs, large body. |
|
|
21
|
+
| `text-ds-xl` | 20px | Small heading (h4). |
|
|
22
|
+
| `text-ds-2xl` | 24px | Section heading (h3). |
|
|
23
|
+
| `text-ds-3xl` | clamp 24→32 | Page heading (h2). Fluid. |
|
|
24
|
+
| `text-ds-4xl` | clamp 28→36 | Large page heading (h1 in product). |
|
|
25
|
+
| `text-ds-5xl` | clamp 32→48 | Marketing hero. |
|
|
26
|
+
| `text-ds-6xl` | clamp 36→60 | Marketing display. |
|
|
27
|
+
|
|
28
|
+
Pair each size with a line-height: `leading-ds-{none|tight|snug|normal|relaxed|loose}`. Default for body: `leading-ds-normal` (1.4). For headings: `leading-ds-tight` (1.15) or `leading-ds-snug` (1.25).
|
|
29
|
+
|
|
30
|
+
## Composite typography utilities
|
|
31
|
+
|
|
32
|
+
Prefer these — they bundle size + leading + weight + tracking:
|
|
33
|
+
|
|
34
|
+
| Utility | Use |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `text-heading-xl` | Page hero heading. |
|
|
37
|
+
| `text-heading-lg` | Section heading. |
|
|
38
|
+
| `text-heading-md` | Card / panel heading. |
|
|
39
|
+
| `text-heading-sm` | Sub-heading. |
|
|
40
|
+
| `text-body-lg` | Lead body. |
|
|
41
|
+
| `text-body-md` | Default body. |
|
|
42
|
+
| `text-body-sm` | Secondary body. |
|
|
43
|
+
| `text-body-xs` | Caption, footnote. |
|
|
44
|
+
| `text-code` | Inline / block code. |
|
|
45
|
+
| `text-label-plain-lg` / `-md` / `-sm` | Form labels (non-tab). |
|
|
46
|
+
|
|
47
|
+
These are what `<Text>` applies internally. When generating raw text, prefer using `<Text variant="heading-md">` (or similar) over manually composing utilities.
|
|
48
|
+
|
|
49
|
+
## Font families
|
|
50
|
+
|
|
51
|
+
| Token | Family | Use |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| `font-sans` | Inter | Default. UI body + headings. |
|
|
54
|
+
| `font-display` | Inter | Marketing headings (same family by default, separate token for theming). |
|
|
55
|
+
| `font-accent` | Ranade | Optional display accent. Only for marketing hero / brand moments. |
|
|
56
|
+
| `font-mono` | SF Mono / Fira Code | Code blocks, keyboard shortcuts, tabular data. |
|
|
57
|
+
|
|
58
|
+
## Weights
|
|
59
|
+
|
|
60
|
+
`font-weight-{light|regular|medium|semibold|bold}` = 300 / 400 / 500 / 600 / 700.
|
|
61
|
+
|
|
62
|
+
Apply via Tailwind's `font-light` / `font-medium` / `font-semibold` / `font-bold`. Default is regular (400). Headings default to `font-medium` (500). **Avoid bold (700)** for headings — the kit uses medium for refined feel. Use semibold for emphasized labels.
|
|
63
|
+
|
|
64
|
+
## Hierarchy patterns
|
|
65
|
+
|
|
66
|
+
**Card heading + body:**
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
<Card className="p-ds-05">
|
|
70
|
+
<Text variant="heading-md">Project</Text>
|
|
71
|
+
<Text variant="body-md" className="text-fg-muted mt-ds-02">
|
|
72
|
+
Sub-description with metadata.
|
|
73
|
+
</Text>
|
|
74
|
+
</Card>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Page header:**
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
<Stack gap="ds-03" className="mb-ds-07">
|
|
81
|
+
<Text variant="heading-xl">Dashboard</Text>
|
|
82
|
+
<Text variant="body-lg" className="text-fg-muted">
|
|
83
|
+
Overview of every active project.
|
|
84
|
+
</Text>
|
|
85
|
+
</Stack>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Form label + input:**
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
<FormField>
|
|
92
|
+
<Label>Email</Label>
|
|
93
|
+
<Input type="email" placeholder="you@company.com" />
|
|
94
|
+
<FormHelperText>We'll never share this.</FormHelperText>
|
|
95
|
+
</FormField>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`<Label>` already applies `text-label-plain-md`. Don't override with size utilities.
|
|
99
|
+
|
|
100
|
+
## Polymorphic `<Text>`
|
|
101
|
+
|
|
102
|
+
`<Text>` is polymorphic via `as` prop:
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<Text as="h1" variant="heading-xl">Page title</Text>
|
|
106
|
+
<Text as="p" variant="body-md">Body copy.</Text>
|
|
107
|
+
<Text as="label" htmlFor="email">Email</Text>
|
|
108
|
+
<Text as="a" href="/x">A link</Text>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The `as` prop widens accepted HTML attributes to the rendered element — `htmlFor` / `href` typecheck correctly.
|
|
112
|
+
|
|
113
|
+
## Rules
|
|
114
|
+
|
|
115
|
+
- **Never** hand-pick a pixel font-size (`text-[15px]`, `text-[18px]`). Use the scale.
|
|
116
|
+
- **Never** use `font-bold` on headings. Use `font-medium` or `font-semibold`.
|
|
117
|
+
- **Never** apply two size utilities at once (`text-ds-md text-ds-lg`). Use composite variants.
|
|
118
|
+
- **Never** use small text (`text-ds-xs`) for anything except captions and footnotes.
|
|
119
|
+
- **Prefer `<Text variant="...">` over raw `<p>` / `<span>`** when typographic semantics matter.
|
|
120
|
+
- Inputs must be at least `text-ds-md` (14px) on desktop and `16px` on mobile (the kit enforces the iOS-zoom-safe minimum automatically).
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Setup
|
|
2
|
+
|
|
3
|
+
Required to use this kit. Every generated app needs all of these.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i @devalok/shilp-sutra @tabler/icons-react framer-motion tailwindcss @tailwindcss/vite
|
|
9
|
+
# optional, only if you render toasts:
|
|
10
|
+
npm i sonner
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`framer-motion` and `tailwindcss` are **required peer dependencies.** Without them, motion contexts split and tokens don't compile.
|
|
14
|
+
|
|
15
|
+
## Vite config
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { defineConfig } from 'vite'
|
|
19
|
+
import react from '@vitejs/plugin-react'
|
|
20
|
+
import tailwindcss from '@tailwindcss/vite'
|
|
21
|
+
|
|
22
|
+
export default defineConfig({
|
|
23
|
+
plugins: [react(), tailwindcss()],
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Single CSS entry
|
|
28
|
+
|
|
29
|
+
In `src/index.css` (or your global stylesheet):
|
|
30
|
+
|
|
31
|
+
```css
|
|
32
|
+
@import "tailwindcss";
|
|
33
|
+
@import "@devalok/shilp-sutra/css";
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Import that CSS file once at the app root (`main.tsx`):
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import './index.css'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Do not add `tailwind.config.ts`.** This kit is Tailwind 4 CSS-first. There is no JS preset. All tokens come from the CSS import via `@theme` blocks.
|
|
43
|
+
|
|
44
|
+
## Provider tree
|
|
45
|
+
|
|
46
|
+
Wrap the app once at the root:
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { MotionProvider } from '@devalok/shilp-sutra/motion'
|
|
50
|
+
import { Toaster } from '@devalok/shilp-sutra/ui/toaster'
|
|
51
|
+
import { IconProvider } from '@devalok/shilp-sutra/ui/icon-context'
|
|
52
|
+
|
|
53
|
+
export default function App({ children }) {
|
|
54
|
+
return (
|
|
55
|
+
<MotionProvider reducedMotion="user">
|
|
56
|
+
<IconProvider size={16}>
|
|
57
|
+
{children}
|
|
58
|
+
<Toaster />
|
|
59
|
+
</IconProvider>
|
|
60
|
+
</MotionProvider>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- `MotionProvider` — required. `reducedMotion="user"` respects OS preference. Without this provider, motion primitives still work but reduced-motion is ignored.
|
|
66
|
+
- `IconProvider` — optional but recommended. Sets default icon size for all `<Icon>` children. Override per-call with `<Icon size={20} />`.
|
|
67
|
+
- `Toaster` — only needed if the app calls `toast(...)`. Mount exactly once.
|
|
68
|
+
|
|
69
|
+
## Dark mode toggle
|
|
70
|
+
|
|
71
|
+
Add the `.dark` class on `<html>` or `<body>` to flip the entire token system to dark. The kit ships `useColorMode()`:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
import { useColorMode } from '@devalok/shilp-sutra/hooks/use-color-mode'
|
|
75
|
+
|
|
76
|
+
function ThemeToggle() {
|
|
77
|
+
const { mode, setMode } = useColorMode() // 'light' | 'dark' | 'system'
|
|
78
|
+
return (
|
|
79
|
+
<Button onClick={() => setMode(mode === 'dark' ? 'light' : 'dark')}>
|
|
80
|
+
Toggle theme
|
|
81
|
+
</Button>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The hook persists choice to `localStorage`, syncs across tabs, and respects `prefers-color-scheme` when set to `'system'`.
|
|
87
|
+
|
|
88
|
+
## Import paths
|
|
89
|
+
|
|
90
|
+
Two valid styles:
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
// Per-component (preferred — smaller bundle, server-component safe):
|
|
94
|
+
import { Button } from '@devalok/shilp-sutra/ui/button'
|
|
95
|
+
import { Card } from '@devalok/shilp-sutra/ui/card'
|
|
96
|
+
|
|
97
|
+
// Barrel (fine for client-only apps):
|
|
98
|
+
import { Button, Card, Dialog } from '@devalok/shilp-sutra'
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
A few components are **per-component only** (their barrel was removed in v0.40 because they statically import optional peer deps). These must use the subpath:
|
|
102
|
+
|
|
103
|
+
- `Toaster`, `toast` → `@devalok/shilp-sutra/ui/toaster`, `/ui/toast`
|
|
104
|
+
- `DatePicker*` → `@devalok/shilp-sutra/composed/date-picker`
|
|
105
|
+
- `EmojiPicker*` → `@devalok/shilp-sutra/composed/emoji-picker`
|
|
106
|
+
- `FilePreview` → `@devalok/shilp-sutra/composed/file-preview`
|
|
107
|
+
- `MarkdownViewer` → `@devalok/shilp-sutra/composed/markdown-viewer`
|
|
108
|
+
- `RichTextEditor*` → `@devalok/shilp-sutra/composed/rich-text-editor`
|
|
109
|
+
- `InputOTP*` → `@devalok/shilp-sutra/ui/input-otp`
|
|
110
|
+
|
|
111
|
+
## Verify
|
|
112
|
+
|
|
113
|
+
After install, this should render without errors:
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
import { Button } from '@devalok/shilp-sutra/ui/button'
|
|
117
|
+
import { Card } from '@devalok/shilp-sutra/ui/card'
|
|
118
|
+
|
|
119
|
+
export default function Page() {
|
|
120
|
+
return (
|
|
121
|
+
<div className="min-h-screen bg-surface-base p-ds-07">
|
|
122
|
+
<Card className="max-w-md mx-auto p-ds-05">
|
|
123
|
+
<Button>Hello</Button>
|
|
124
|
+
</Card>
|
|
125
|
+
</div>
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
If `bg-surface-base` doesn't apply, the CSS import is missing or out of order. The kit's CSS must come **after** `@import "tailwindcss"`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devalok/shilp-sutra",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.1",
|
|
4
4
|
"description": "Devalok Design System — accessible React components, OKLCH design tokens, and Tailwind 4 CSS-first setup. Ships with AI-agent setup recipes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Devalok Design & Strategy Studios <shilp-sutra@devalok.in>",
|
|
@@ -793,7 +793,9 @@
|
|
|
793
793
|
"import": "./dist/ai/types.js",
|
|
794
794
|
"default": "./dist/ai/types.js"
|
|
795
795
|
},
|
|
796
|
-
"./docs/*": "./docs/components/*"
|
|
796
|
+
"./docs/*": "./docs/components/*",
|
|
797
|
+
"./make-kit": "./make-kit/Guidelines.md",
|
|
798
|
+
"./make-kit/*": "./make-kit/*"
|
|
797
799
|
},
|
|
798
800
|
"files": [
|
|
799
801
|
"dist",
|
|
@@ -801,6 +803,7 @@
|
|
|
801
803
|
"docs/recipes",
|
|
802
804
|
"docs/rollback.md",
|
|
803
805
|
"fonts",
|
|
806
|
+
"make-kit",
|
|
804
807
|
"skill",
|
|
805
808
|
"scripts/welcome.mjs",
|
|
806
809
|
"AGENTS.md",
|
package/skill/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: shilp-sutra
|
|
|
3
3
|
description: Add, configure, and use components from Devalok's shilp-sutra design system (@devalok/shilp-sutra) — a Tailwind 4 + React 19 + CVA library with 110+ accessible components, OKLCH design tokens, framer-motion animations, and per-component RSC-safe entry points. Use this skill whenever the user mentions shilp-sutra, Devalok, the @devalok npm scope, or asks to install/add/style/theme UI in any React project that already depends on the package — even if they don't name it explicitly. Use it instead of generic shadcn/ui, MUI, or Chakra knowledge when shilp-sutra is in the project. Covers Next.js (App + Pages), Vite, Astro, Remix, TanStack Start setup playbooks; component API and variant reference; brand token customization; Server Component import patterns; and a troubleshoot tree for the thirteen most common breakages.
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.42.1"
|
|
7
7
|
author: Devalok Design & Strategy Studios
|
|
8
8
|
homepage: https://github.com/devalok-design/shilp-sutra
|
|
9
9
|
npm: https://www.npmjs.com/package/@devalok/shilp-sutra
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
> All variant values and props verified from source CVA definitions.
|
|
8
8
|
>
|
|
9
9
|
> Package: @devalok/shilp-sutra
|
|
10
|
-
> Version: 0.
|
|
10
|
+
> Version: 0.42.1
|
|
11
11
|
>
|
|
12
12
|
> **If you are an AI agent reading this file top-to-bottom:** the Setup
|
|
13
13
|
> section below is authoritative. If any later per-component doc or a
|
|
@@ -43,6 +43,10 @@ Paste the snippet *after* `@import "@devalok/shilp-sutra/css";` in the global st
|
|
|
43
43
|
|
|
44
44
|
The repo URL for these files is `https://github.com/devalok-design/shilp-sutra/tree/main/packages/core/docs/recipes`. Consumer projects should also have an `AGENTS.md` at their root with the rules above pre-loaded — read that first if it exists.
|
|
45
45
|
|
|
46
|
+
## NEW (v0.42.0)
|
|
47
|
+
|
|
48
|
+
- **Figma Make kit.** 26 guideline files at `node_modules/@devalok/shilp-sutra/make-kit/` (top-level `Guidelines.md` + `setup.md`, eight `foundations/*.md`, sixteen `components/*.md`). Subpath exports `@devalok/shilp-sutra/make-kit` → `Guidelines.md`, `/make-kit/*` → individual files. Used by Figma Make to generate apps + prototypes against the DS. Setup walkthrough: https://shilp-sutra.devalok.in/figma-make. Public npm registry; cross-org sharing not supported by Figma — each consumer org self-registers. Pin to a specific npm version; no auto-update flow yet. Make kits need Organization / Enterprise Figma plan; Free + Pro can still install the package directly in React projects.
|
|
49
|
+
|
|
46
50
|
## NEW (v0.40.0)
|
|
47
51
|
|
|
48
52
|
- **OAuthButton.** Brand-aware social/login buttons. Subpath: `@devalok/shilp-sutra/ui/oauth-button`. 13 providers (`google` `apple` `github` `microsoft` `x` `linkedin` `facebook` `discord` `slack` `gitlab` `sso` `email` `passkey`). Props: `provider`, `intent` (`continue|signin|signup`), `appearance` (`brand|outline|dark`), `icon` (override default glyph), `iconOnly`, `compact` (renders just "Google" instead of "Continue with Google"; aria-label keeps long form), `lastUsed` (inline right-edge pill inside button), `helperText`. Inherits Button async/loading/sizes. Siblings: `OAuthGroup` (with `reorderLastUsedFirst` for Stripe-style ordering), `OAuthDivider`, `OAuthConnectionRow` (settings-page linked state). Default glyphs from Tabler peer dep; pass `icon` to drop in a brand's official multicolour SVG. In dark mode every brand appearance lands on the same DS surface — brand identity comes from the glyph, not the bg, so rows stay visually coherent.
|