@devalok/shilp-sutra 0.37.0 → 0.38.0
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/MIGRATION.md +67 -0
- package/dist/_chunks/tiptap.js +977 -968
- package/dist/_chunks/tiptap.js.map +1 -1
- package/dist/composed/index.d.ts +0 -2
- package/dist/composed/index.d.ts.map +1 -1
- package/dist/composed/index.js +5 -6
- package/dist/composed/inline-edit.d.ts.map +1 -1
- package/dist/composed/inline-edit.js +42 -40
- package/dist/composed/inline-edit.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +0 -1
- package/dist/test-utils/conformance.d.ts +37 -0
- package/dist/test-utils/conformance.d.ts.map +1 -0
- package/dist/ui/alert.d.ts +1 -2
- package/dist/ui/alert.d.ts.map +1 -1
- package/dist/ui/alert.js +1 -27
- package/dist/ui/alert.js.map +1 -1
- package/dist/ui/banner.d.ts +3 -5
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +13 -13
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +2 -2
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/input.d.ts +1 -9
- package/dist/ui/input.d.ts.map +1 -1
- package/dist/ui/input.js +26 -27
- package/dist/ui/input.js.map +1 -1
- package/dist/ui/segmented-control.d.ts +1 -1
- package/dist/ui/segmented-control.d.ts.map +1 -1
- package/dist/ui/segmented-control.js +2 -4
- package/dist/ui/segmented-control.js.map +1 -1
- package/docs/components/_header.md +1 -1
- package/docs/components/composed/activity-feed.md +6 -0
- package/docs/components/composed/avatar-group.md +8 -0
- package/docs/components/composed/bulk-action-bar.md +6 -0
- package/docs/components/composed/command-palette.md +7 -0
- package/docs/components/composed/confirm-dialog.md +6 -0
- package/docs/components/composed/content-card.md +6 -0
- package/docs/components/composed/date-picker.md +10 -0
- package/docs/components/composed/deadline-indicator.md +7 -0
- package/docs/components/composed/emoji-picker.md +8 -0
- package/docs/components/composed/empty-state.md +8 -0
- package/docs/components/composed/error-boundary.md +7 -0
- package/docs/components/composed/file-preview.md +8 -0
- package/docs/components/composed/filter-bar.md +8 -0
- package/docs/components/composed/form-section.md +6 -0
- package/docs/components/composed/global-loading.md +6 -0
- package/docs/components/composed/inline-edit.md +8 -0
- package/docs/components/composed/loading-skeleton.md +7 -0
- package/docs/components/composed/markdown-viewer.md +9 -0
- package/docs/components/composed/master-detail.md +7 -0
- package/docs/components/composed/member-picker.md +7 -0
- package/docs/components/composed/multi-select-popover.md +11 -0
- package/docs/components/composed/page-header.md +7 -0
- package/docs/components/composed/page-skeletons.md +10 -0
- package/docs/components/composed/priority-indicator.md +7 -0
- package/docs/components/composed/rich-chat-input.md +12 -0
- package/docs/components/composed/rich-text-editor.md +9 -0
- package/docs/components/composed/schedule-view.md +8 -0
- package/docs/components/composed/simple-tooltip.md +7 -0
- package/docs/components/composed/status-badge.md +10 -0
- package/docs/components/shell/app-command-palette.md +8 -0
- package/docs/components/shell/bottom-navbar.md +12 -0
- package/docs/components/shell/command-registry.md +7 -0
- package/docs/components/shell/link-context.md +15 -0
- package/docs/components/shell/notification-center.md +10 -0
- package/docs/components/shell/notification-preferences.md +7 -0
- package/docs/components/shell/sidebar.md +11 -0
- package/docs/components/shell/top-bar.md +11 -0
- package/docs/components/ui/accordion.md +10 -0
- package/docs/components/ui/alert-dialog.md +10 -1
- package/docs/components/ui/alert.md +13 -2
- package/docs/components/ui/aspect-ratio.md +7 -0
- package/docs/components/ui/autocomplete.md +7 -0
- package/docs/components/ui/avatar.md +10 -0
- package/docs/components/ui/badge-group.md +7 -0
- package/docs/components/ui/badge-indicator.md +7 -0
- package/docs/components/ui/badge.md +12 -0
- package/docs/components/ui/banner.md +10 -1
- package/docs/components/ui/breadcrumb.md +8 -0
- package/docs/components/ui/button-group.md +24 -4
- package/docs/components/ui/button-processing.md +5 -0
- package/docs/components/ui/button.md +9 -0
- package/docs/components/ui/card.md +16 -4
- package/docs/components/ui/charts.md +9 -0
- package/docs/components/ui/chat.md +9 -0
- package/docs/components/ui/checkbox.md +15 -1
- package/docs/components/ui/chip.md +9 -0
- package/docs/components/ui/code.md +7 -0
- package/docs/components/ui/collapsible.md +9 -0
- package/docs/components/ui/color-input.md +8 -0
- package/docs/components/ui/color-swatch.md +7 -0
- package/docs/components/ui/combobox.md +16 -3
- package/docs/components/ui/container.md +11 -0
- package/docs/components/ui/context-menu.md +8 -0
- package/docs/components/ui/data-table-body.md +4 -0
- package/docs/components/ui/data-table-bulk-actions.md +4 -0
- package/docs/components/ui/data-table-card.md +4 -0
- package/docs/components/ui/data-table-context.md +4 -0
- package/docs/components/ui/data-table-header.md +4 -0
- package/docs/components/ui/data-table-pagination.md +4 -0
- package/docs/components/ui/data-table-toolbar.md +7 -0
- package/docs/components/ui/data-table.md +25 -0
- package/docs/components/ui/devalok-grain.md +8 -0
- package/docs/components/ui/dialog.md +10 -0
- package/docs/components/ui/dropdown-menu.md +10 -0
- package/docs/components/ui/file-upload.md +8 -0
- package/docs/components/ui/form.md +21 -0
- package/docs/components/ui/hover-card.md +9 -0
- package/docs/components/ui/icon-button.md +7 -0
- package/docs/components/ui/icon-context.md +7 -0
- package/docs/components/ui/icon-group.md +9 -0
- package/docs/components/ui/icon.md +7 -0
- package/docs/components/ui/input-otp.md +29 -7
- package/docs/components/ui/input.md +11 -2
- package/docs/components/ui/label.md +7 -1
- package/docs/components/ui/link.md +7 -0
- package/docs/components/ui/menubar.md +9 -0
- package/docs/components/ui/navigation-menu.md +9 -0
- package/docs/components/ui/number-input.md +10 -0
- package/docs/components/ui/pagination.md +10 -0
- package/docs/components/ui/popover.md +9 -0
- package/docs/components/ui/progress-ring.md +7 -0
- package/docs/components/ui/progress.md +7 -0
- package/docs/components/ui/radio.md +27 -2
- package/docs/components/ui/search-input.md +8 -0
- package/docs/components/ui/segmented-control.md +21 -6
- package/docs/components/ui/select.md +14 -3
- package/docs/components/ui/separator.md +7 -0
- package/docs/components/ui/sheet.md +10 -0
- package/docs/components/ui/sidebar.md +30 -0
- package/docs/components/ui/skeleton.md +7 -0
- package/docs/components/ui/slider.md +15 -1
- package/docs/components/ui/spinner.md +7 -0
- package/docs/components/ui/split-button.md +11 -0
- package/docs/components/ui/stack.md +8 -0
- package/docs/components/ui/stat-card.md +9 -0
- package/docs/components/ui/status-dot.md +9 -0
- package/docs/components/ui/stepper.md +8 -0
- package/docs/components/ui/switch.md +8 -0
- package/docs/components/ui/table.md +8 -0
- package/docs/components/ui/tabs.md +10 -2
- package/docs/components/ui/text.md +9 -4
- package/docs/components/ui/textarea.md +7 -1
- package/docs/components/ui/toast.md +9 -0
- package/docs/components/ui/toaster.md +8 -0
- package/docs/components/ui/toggle-group.md +13 -4
- package/docs/components/ui/toggle.md +10 -2
- package/docs/components/ui/tooltip.md +11 -1
- package/docs/components/ui/tree-view.md +12 -0
- package/docs/components/ui/visually-hidden.md +7 -0
- package/docs/recipes/customize-brand.md +216 -0
- package/docs/recipes/index.md +51 -0
- package/docs/recipes/install-astro.md +178 -0
- package/docs/recipes/install-next-app-router.md +230 -0
- package/docs/recipes/install-next-pages.md +123 -0
- package/docs/recipes/install-remix.md +171 -0
- package/docs/recipes/install-tanstack-start.md +143 -0
- package/docs/recipes/install-vite.md +170 -0
- package/docs/recipes/server-components.md +209 -0
- package/docs/recipes/troubleshoot.md +217 -0
- package/llms-full.txt +1133 -88
- package/llms.txt +33 -16
- package/package.json +45 -35
- package/dist/composed/responsive-overlay.d.ts +0 -23
- package/dist/composed/responsive-overlay.d.ts.map +0 -1
- package/dist/composed/responsive-overlay.js +0 -40
- package/dist/composed/responsive-overlay.js.map +0 -1
- package/dist/hooks/use-toast.d.ts +0 -17
- package/dist/hooks/use-toast.d.ts.map +0 -1
- package/dist/hooks/use-toast.js +0 -3
- package/dist/tailwind/index.cjs +0 -41
- package/dist/tailwind/index.d.ts +0 -2
- package/dist/tailwind/index.d.ts.map +0 -1
- package/dist/tailwind/index.js +0 -2
- package/dist/tailwind/preset.d.ts +0 -25
- package/dist/tailwind/preset.d.ts.map +0 -1
- package/dist/tailwind/preset.js +0 -17
- package/dist/tailwind/preset.js.map +0 -1
- package/docs/components/composed/responsive-overlay.md +0 -34
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Customize: Brand & Tokens
|
|
2
|
+
|
|
3
|
+
Override colors, radius, fonts, and spacing without forking the package. All customization happens through CSS custom properties — no JS configuration.
|
|
4
|
+
|
|
5
|
+
## How tokens layer
|
|
6
|
+
|
|
7
|
+
Shilp Sutra's tokens are organized in three tiers:
|
|
8
|
+
|
|
9
|
+
1. **Primitives** (`primitives.css`) — raw OKLCH palette values. Private. You should not need to touch these.
|
|
10
|
+
2. **Semantic** (`semantic.css`) — intent-based mappings (`--color-accent-9`, `--color-surface-2`, `--font-sans`). Public, exposed to Tailwind 4's `@theme`.
|
|
11
|
+
3. **Utility output** — Tailwind generates classes (`bg-accent-9`, `text-surface-fg`, `font-sans`) from the semantic layer.
|
|
12
|
+
|
|
13
|
+
To override a token, redefine it AFTER the design-system import. The cascade does the rest.
|
|
14
|
+
|
|
15
|
+
```css
|
|
16
|
+
@import "tailwindcss";
|
|
17
|
+
@import "@devalok/shilp-sutra/css";
|
|
18
|
+
|
|
19
|
+
@theme {
|
|
20
|
+
/* Overrides go here */
|
|
21
|
+
--color-accent-9: oklch(0.55 0.22 195);
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`@theme` is the Tailwind 4 directive that registers a CSS variable AND auto-generates the matching utility (so `bg-accent-9` picks up the override).
|
|
26
|
+
|
|
27
|
+
## Common overrides
|
|
28
|
+
|
|
29
|
+
### Change the accent color
|
|
30
|
+
|
|
31
|
+
The accent scale runs from `--color-accent-1` (lightest) to `--color-accent-12` (darkest). Step 9 is the saturated default-button background, step 11 is on-tint text.
|
|
32
|
+
|
|
33
|
+
To swap to teal:
|
|
34
|
+
|
|
35
|
+
```css
|
|
36
|
+
@theme {
|
|
37
|
+
--color-accent-1: oklch(0.985 0.005 195);
|
|
38
|
+
--color-accent-2: oklch(0.96 0.012 195);
|
|
39
|
+
--color-accent-3: oklch(0.92 0.025 195);
|
|
40
|
+
--color-accent-4: oklch(0.88 0.04 195);
|
|
41
|
+
--color-accent-5: oklch(0.82 0.07 195);
|
|
42
|
+
--color-accent-6: oklch(0.74 0.10 195);
|
|
43
|
+
--color-accent-7: oklch(0.66 0.14 195);
|
|
44
|
+
--color-accent-8: oklch(0.60 0.17 195);
|
|
45
|
+
--color-accent-9: oklch(0.54 0.22 195);
|
|
46
|
+
--color-accent-10: oklch(0.49 0.21 195);
|
|
47
|
+
--color-accent-11: oklch(0.42 0.16 195);
|
|
48
|
+
--color-accent-12: oklch(0.20 0.05 195);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.dark {
|
|
52
|
+
--color-accent-9: oklch(0.62 0.21 195);
|
|
53
|
+
/* ...override remaining steps for dark mode */
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
For a quick swap without redoing the full scale, only override step 9 (background) and step 11 (foreground). Other steps will still reference the original chroma — visually mismatched but functional.
|
|
58
|
+
|
|
59
|
+
### Change the radius scale
|
|
60
|
+
|
|
61
|
+
```css
|
|
62
|
+
@theme {
|
|
63
|
+
--radius-ds-sm: 0.25rem; /* small */
|
|
64
|
+
--radius-ds-md: 0.5rem; /* default */
|
|
65
|
+
--radius-ds-lg: 0.75rem;
|
|
66
|
+
--radius-ds-xl: 1rem;
|
|
67
|
+
--radius: 0.5rem; /* unsuffixed — generates bare `rounded` */
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
For a flat, sharp brand, set everything to `0`. For a heavily rounded brand, scale up.
|
|
72
|
+
|
|
73
|
+
### Change fonts
|
|
74
|
+
|
|
75
|
+
The design system uses three font families, each backed by a CSS variable:
|
|
76
|
+
|
|
77
|
+
- `--font-sans` — Inter (body)
|
|
78
|
+
- `--font-display` — Ranade (headings)
|
|
79
|
+
- `--font-mono` — JetBrains Mono (code)
|
|
80
|
+
|
|
81
|
+
To swap with `next/font`:
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
// app/layout.tsx (Next.js App Router)
|
|
85
|
+
import { Inter, Plus_Jakarta_Sans, JetBrains_Mono } from "next/font/google";
|
|
86
|
+
|
|
87
|
+
const fontSans = Plus_Jakarta_Sans({ subsets: ["latin"], variable: "--font-sans" });
|
|
88
|
+
const fontDisplay = Plus_Jakarta_Sans({ subsets: ["latin"], weight: "700", variable: "--font-display" });
|
|
89
|
+
const fontMono = JetBrains_Mono({ subsets: ["latin"], variable: "--font-mono" });
|
|
90
|
+
|
|
91
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
92
|
+
return (
|
|
93
|
+
<html lang="en" className={`${fontSans.variable} ${fontDisplay.variable} ${fontMono.variable}`}>
|
|
94
|
+
<body>{children}</body>
|
|
95
|
+
</html>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
For Vite/Remix/Astro/TanStack, drop the `@font-face` declarations into the global CSS and override the variables:
|
|
101
|
+
|
|
102
|
+
```css
|
|
103
|
+
@font-face {
|
|
104
|
+
font-family: "Plus Jakarta Sans";
|
|
105
|
+
src: url("/fonts/PlusJakartaSans-Variable.woff2") format("woff2");
|
|
106
|
+
font-weight: 100 900;
|
|
107
|
+
font-display: swap;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@theme {
|
|
111
|
+
--font-sans: "Plus Jakarta Sans", system-ui, sans-serif;
|
|
112
|
+
--font-display: "Plus Jakarta Sans", system-ui, sans-serif;
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Change the spacing scale
|
|
117
|
+
|
|
118
|
+
The DS spacing scale runs `--spacing-ds-00` (0) to `--spacing-ds-12` (highest). Each step roughly doubles. The Tailwind classes are `p-ds-04`, `m-ds-08`, `gap-ds-03`, etc.
|
|
119
|
+
|
|
120
|
+
```css
|
|
121
|
+
@theme {
|
|
122
|
+
--spacing-ds-00: 0;
|
|
123
|
+
--spacing-ds-01: 0.125rem;
|
|
124
|
+
--spacing-ds-02: 0.25rem;
|
|
125
|
+
--spacing-ds-03: 0.5rem;
|
|
126
|
+
--spacing-ds-04: 0.75rem;
|
|
127
|
+
--spacing-ds-05: 1rem;
|
|
128
|
+
/* etc. */
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Most consumers should not touch this. The DS scale is tuned for the typography rhythm; changing one step without re-tuning typography looks visually off.
|
|
133
|
+
|
|
134
|
+
### Change a single shadow
|
|
135
|
+
|
|
136
|
+
```css
|
|
137
|
+
@theme {
|
|
138
|
+
--shadow-raised: 0 1px 2px oklch(0 0 0 / 0.06), 0 2px 4px oklch(0 0 0 / 0.04);
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Available shadows: `--shadow-raised`, `--shadow-overlay`, `--shadow-floating`, `--shadow-brand`. Each is a multi-layer composite — overriding one without considering its layers usually produces flat-looking shadows.
|
|
143
|
+
|
|
144
|
+
## Light + dark in lockstep
|
|
145
|
+
|
|
146
|
+
Every override should consider both modes. Pattern:
|
|
147
|
+
|
|
148
|
+
```css
|
|
149
|
+
@theme {
|
|
150
|
+
--color-accent-9: oklch(0.54 0.22 195);
|
|
151
|
+
--color-accent-fg: oklch(0.99 0 0);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* Dark mode override */
|
|
155
|
+
.dark {
|
|
156
|
+
--color-accent-9: oklch(0.62 0.21 195);
|
|
157
|
+
--color-accent-fg: oklch(0.10 0 0);
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`.dark` is a regular class selector — its specificity is higher than `:root`/`@theme` body, so dark-mode overrides win when the class is active.
|
|
162
|
+
|
|
163
|
+
## Forced colors (Windows high-contrast)
|
|
164
|
+
|
|
165
|
+
If you override semantic colors, the `@media (forced-colors: active)` block in `semantic.css` continues to remap to system keywords. Your override is ignored when the user is in high-contrast mode — this is the correct behavior.
|
|
166
|
+
|
|
167
|
+
If you need a custom forced-colors mapping, override inside `@media (forced-colors: active)`:
|
|
168
|
+
|
|
169
|
+
```css
|
|
170
|
+
@media (forced-colors: active) {
|
|
171
|
+
:root {
|
|
172
|
+
--color-accent-9: Highlight;
|
|
173
|
+
--color-accent-fg: HighlightText;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Per-route theming
|
|
179
|
+
|
|
180
|
+
Apply a class on a wrapper element to scope token overrides:
|
|
181
|
+
|
|
182
|
+
```css
|
|
183
|
+
.theme-karm {
|
|
184
|
+
--color-accent-9: oklch(0.55 0.22 195);
|
|
185
|
+
}
|
|
186
|
+
.theme-karm.dark,
|
|
187
|
+
.dark .theme-karm {
|
|
188
|
+
--color-accent-9: oklch(0.62 0.21 195);
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Then:
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
<div className="theme-karm">
|
|
196
|
+
<Button>Karm-themed</Button>
|
|
197
|
+
</div>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## What you cannot override via CSS variables
|
|
201
|
+
|
|
202
|
+
- The component DOM structure (use the `asChild` pattern or wrap the component to insert)
|
|
203
|
+
- The vendored Radix primitives' behavior
|
|
204
|
+
- Animation keyframes (override the `--animate-*` references via `@theme` — but the keyframe definitions themselves are package-private)
|
|
205
|
+
|
|
206
|
+
For deeper changes, fork the source or use the `className` prop with arbitrary Tailwind utilities to layer styling on top.
|
|
207
|
+
|
|
208
|
+
## Verifying an override
|
|
209
|
+
|
|
210
|
+
Open DevTools, inspect a component, and check the Computed tab for the variable's resolved value. The cascade origin column shows where the value came from — your override should appear there, not the package's default.
|
|
211
|
+
|
|
212
|
+
If the override isn't winning, check:
|
|
213
|
+
|
|
214
|
+
1. The `@theme` override comes AFTER `@import "@devalok/shilp-sutra/css";` in source order
|
|
215
|
+
2. There's no `!important` in the package overriding you (there isn't — file an issue if you find one)
|
|
216
|
+
3. The selector specificity matches the target (`.dark` class is on a parent of the inspected element, etc.)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Recipes
|
|
2
|
+
|
|
3
|
+
Copy-paste-ready setup guides for installing and customizing **`@devalok/shilp-sutra`** in any React project.
|
|
4
|
+
|
|
5
|
+
These files are designed to be read by AI coding agents (Claude Code, Cursor, Copilot, Codex) and humans alike. Every step is concrete: file paths, exact strings, expected outcomes.
|
|
6
|
+
|
|
7
|
+
When the package is installed, recipes ship at:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
node_modules/@devalok/shilp-sutra/docs/recipes/
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Install recipes
|
|
14
|
+
|
|
15
|
+
Pick the recipe that matches your framework. Detection criteria are listed at the top of each file.
|
|
16
|
+
|
|
17
|
+
| Framework | Recipe | When to pick it |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| Next.js (App Router) | [install-next-app-router.md](./install-next-app-router.md) | `app/` directory exists; using React Server Components |
|
|
20
|
+
| Next.js (Pages Router) | [install-next-pages.md](./install-next-pages.md) | `pages/` directory is the primary router; legacy or pre-13 codebases |
|
|
21
|
+
| Vite + React | [install-vite.md](./install-vite.md) | `vite.config.*` exists; SPA or MPA |
|
|
22
|
+
| Astro | [install-astro.md](./install-astro.md) | `astro.config.*` exists |
|
|
23
|
+
| Remix | [install-remix.md](./install-remix.md) | `remix.config.*` or Remix v2 with Vite |
|
|
24
|
+
| TanStack Start | [install-tanstack-start.md](./install-tanstack-start.md) | `app.config.*` with `@tanstack/start` |
|
|
25
|
+
|
|
26
|
+
If the framework is not listed, start with [install-vite.md](./install-vite.md) and adapt — most React+Tailwind setups follow the same shape.
|
|
27
|
+
|
|
28
|
+
## Customization recipes
|
|
29
|
+
|
|
30
|
+
| Recipe | What it covers |
|
|
31
|
+
|---|---|
|
|
32
|
+
| [customize-brand.md](./customize-brand.md) | Token override cookbook — change colors, radius, fonts, spacing scale, dark-mode mapping |
|
|
33
|
+
| [server-components.md](./server-components.md) | Per-component RSC-safety matrix; correct import patterns for Server Components |
|
|
34
|
+
|
|
35
|
+
## Diagnostics
|
|
36
|
+
|
|
37
|
+
| Recipe | What it covers |
|
|
38
|
+
|---|---|
|
|
39
|
+
| [troubleshoot.md](./troubleshoot.md) | Decision tree for the eight most common breakages: Tailwind not detecting tokens, framer-motion duplicates, missing `transpilePackages`, wrong CSS import order, dark mode not toggling, RSC import errors, font 404s, hydration mismatches |
|
|
40
|
+
|
|
41
|
+
## What every recipe assumes
|
|
42
|
+
|
|
43
|
+
- React `^18 || ^19`
|
|
44
|
+
- Node `>= 18.18` (no `engines.node` declared by us, but Tailwind 4 + Vite 5+ require it)
|
|
45
|
+
- A bundler that supports CSS imports from `node_modules` (every modern React framework does)
|
|
46
|
+
|
|
47
|
+
## What every recipe excludes
|
|
48
|
+
|
|
49
|
+
- Database/auth/state-management setup — out of scope. Shilp Sutra is presentation-only.
|
|
50
|
+
- IDE configuration — your call.
|
|
51
|
+
- Testing setup — see [packages/core/CONTRIBUTING.md](../../CONTRIBUTING.md) if contributing to the design system itself.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Install: Astro
|
|
2
|
+
|
|
3
|
+
> Setup recipe for adding `@devalok/shilp-sutra` to an Astro project with React islands.
|
|
4
|
+
|
|
5
|
+
## 1. Detect
|
|
6
|
+
|
|
7
|
+
You are in this recipe if:
|
|
8
|
+
|
|
9
|
+
- `astro.config.{ts,mjs,js}` exists at the project root
|
|
10
|
+
- `package.json` lists `"astro"`
|
|
11
|
+
- React is integrated via `@astrojs/react`
|
|
12
|
+
|
|
13
|
+
If `@astrojs/react` is not installed, install it first:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm astro add react
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 2. Install dependencies
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm add @devalok/shilp-sutra framer-motion
|
|
23
|
+
pnpm add -D tailwindcss@^4 @tailwindcss/vite
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Add only if rendering `<Toaster />`:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pnpm add sonner
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 3. Wire Tailwind 4 in `astro.config`
|
|
33
|
+
|
|
34
|
+
Astro has its own `@astrojs/tailwind` integration, but for Tailwind 4 use the Vite plugin directly (Astro 4.5+ supports this):
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
// astro.config.ts
|
|
38
|
+
import { defineConfig } from "astro/config";
|
|
39
|
+
import react from "@astrojs/react";
|
|
40
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
41
|
+
|
|
42
|
+
export default defineConfig({
|
|
43
|
+
integrations: [react()],
|
|
44
|
+
vite: {
|
|
45
|
+
plugins: [tailwindcss()],
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Do **not** also enable `@astrojs/tailwind` — that integration is Tailwind 3 only and will conflict.
|
|
51
|
+
|
|
52
|
+
## 4. Wire tokens
|
|
53
|
+
|
|
54
|
+
Create `src/styles/globals.css`:
|
|
55
|
+
|
|
56
|
+
```css
|
|
57
|
+
@import "tailwindcss";
|
|
58
|
+
@import "@devalok/shilp-sutra/css";
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Import it from a layout component (e.g., `src/layouts/BaseLayout.astro`):
|
|
62
|
+
|
|
63
|
+
```astro
|
|
64
|
+
---
|
|
65
|
+
import "../styles/globals.css";
|
|
66
|
+
const { title = "App" } = Astro.props;
|
|
67
|
+
---
|
|
68
|
+
<!doctype html>
|
|
69
|
+
<html lang="en" class="">
|
|
70
|
+
<head>
|
|
71
|
+
<meta charset="utf-8" />
|
|
72
|
+
<meta name="viewport" content="width=device-width" />
|
|
73
|
+
<title>{title}</title>
|
|
74
|
+
</head>
|
|
75
|
+
<body>
|
|
76
|
+
<slot />
|
|
77
|
+
</body>
|
|
78
|
+
</html>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 5. Theme toggle
|
|
82
|
+
|
|
83
|
+
Add the bootstrap script to `<head>` of `BaseLayout.astro` (before stylesheet imports):
|
|
84
|
+
|
|
85
|
+
```astro
|
|
86
|
+
---
|
|
87
|
+
import "../styles/globals.css";
|
|
88
|
+
---
|
|
89
|
+
<!doctype html>
|
|
90
|
+
<html lang="en">
|
|
91
|
+
<head>
|
|
92
|
+
<script is:inline>
|
|
93
|
+
try {
|
|
94
|
+
var stored = localStorage.getItem("theme");
|
|
95
|
+
var prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
96
|
+
if (stored === "dark" || (!stored && prefersDark))
|
|
97
|
+
document.documentElement.classList.add("dark");
|
|
98
|
+
} catch (e) {}
|
|
99
|
+
</script>
|
|
100
|
+
<!-- ... -->
|
|
101
|
+
</head>
|
|
102
|
+
<body><slot /></body>
|
|
103
|
+
</html>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`is:inline` keeps it out of bundling, so it runs before any other JS.
|
|
107
|
+
|
|
108
|
+
For runtime toggling inside React islands, use the same `useColorMode` hook shown in [install-vite.md § 5](./install-vite.md#5-theme-toggle-no-next-themes-here).
|
|
109
|
+
|
|
110
|
+
## 6. Use components in islands
|
|
111
|
+
|
|
112
|
+
Shilp Sutra components are **client-only** (they use React hooks). Mount them in islands with a `client:*` directive:
|
|
113
|
+
|
|
114
|
+
```astro
|
|
115
|
+
---
|
|
116
|
+
import { Button } from "@devalok/shilp-sutra/ui/button";
|
|
117
|
+
---
|
|
118
|
+
<Button client:load>Hello</Button>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Static / non-interactive primitives (Text, Stack, Container, Code, VisuallyHidden) work without `client:*` because they render to static markup. Per-component imports are still required.
|
|
122
|
+
|
|
123
|
+
## 7. Toaster (optional)
|
|
124
|
+
|
|
125
|
+
Mount once in a top-level island. The simplest approach is a small React wrapper component:
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
// src/components/AppToaster.tsx
|
|
129
|
+
"use client";
|
|
130
|
+
import { Toaster } from "@devalok/shilp-sutra/ui/toaster";
|
|
131
|
+
export default function AppToaster() {
|
|
132
|
+
return <Toaster />;
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
```astro
|
|
137
|
+
---
|
|
138
|
+
import AppToaster from "../components/AppToaster";
|
|
139
|
+
---
|
|
140
|
+
<AppToaster client:load />
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## 8. Verify
|
|
144
|
+
|
|
145
|
+
Create `src/pages/index.astro`:
|
|
146
|
+
|
|
147
|
+
```astro
|
|
148
|
+
---
|
|
149
|
+
import BaseLayout from "../layouts/BaseLayout.astro";
|
|
150
|
+
import { Button } from "@devalok/shilp-sutra/ui/button";
|
|
151
|
+
import { Stack } from "@devalok/shilp-sutra/ui/stack";
|
|
152
|
+
import { Text } from "@devalok/shilp-sutra/ui/text";
|
|
153
|
+
---
|
|
154
|
+
<BaseLayout title="Home">
|
|
155
|
+
<Stack className="p-ds-08" gap="ds-04">
|
|
156
|
+
<Text variant="heading-2xl">Hello, Shilp Sutra</Text>
|
|
157
|
+
<Stack direction="row" gap="ds-03">
|
|
158
|
+
<Button client:load>Primary</Button>
|
|
159
|
+
<Button client:load variant="soft">Soft</Button>
|
|
160
|
+
</Stack>
|
|
161
|
+
</Stack>
|
|
162
|
+
</BaseLayout>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Run `pnpm dev` and open the URL.
|
|
166
|
+
|
|
167
|
+
## 9. Astro-specific gotchas
|
|
168
|
+
|
|
169
|
+
- **No `transpilePackages` equivalent — and you do not need one.** Astro's Vite uses native ESM and resolves `@devalok/shilp-sutra` from `node_modules` directly.
|
|
170
|
+
- **Component must be inside a `client:*` island to be interactive.** A button without `client:load` will render but not respond to clicks.
|
|
171
|
+
- **Server-side islands (`server:defer`)** — fine, but RSC import rules apply (per-component imports only). See [server-components.md](./server-components.md).
|
|
172
|
+
- **`@astrojs/tailwind` and `@tailwindcss/vite` conflict.** Pick one. For Tailwind 4 use the Vite plugin.
|
|
173
|
+
|
|
174
|
+
## 10. What NOT to do
|
|
175
|
+
|
|
176
|
+
- ❌ Use `@astrojs/tailwind` (Tailwind 3 only).
|
|
177
|
+
- ❌ Add `tailwind.config.{ts,js}` — Tailwind 4 is CSS-first.
|
|
178
|
+
- ❌ Import shilp-sutra components into a `.astro` file expecting interactivity without `client:*`.
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# Install: Next.js (App Router)
|
|
2
|
+
|
|
3
|
+
> Setup recipe for adding `@devalok/shilp-sutra` to a Next.js 13+ App Router project.
|
|
4
|
+
|
|
5
|
+
## 1. Detect the framework
|
|
6
|
+
|
|
7
|
+
You are in this recipe if **all** of these are true:
|
|
8
|
+
|
|
9
|
+
- `package.json` lists `"next"` at version `^13.0.0` or higher
|
|
10
|
+
- An `app/` directory exists at the project root or under `src/`
|
|
11
|
+
- An `app/layout.tsx` (or `.jsx`) file exists
|
|
12
|
+
- No `pages/` directory at the project root, OR `pages/` exists but only contains `_app.{js,tsx}` and `_document.{js,tsx}` (legacy artifacts)
|
|
13
|
+
|
|
14
|
+
If `pages/` is the primary router, use [install-next-pages.md](./install-next-pages.md).
|
|
15
|
+
|
|
16
|
+
## 2. Install dependencies
|
|
17
|
+
|
|
18
|
+
Pick the package manager that matches the project's lockfile.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# pnpm (lockfile: pnpm-lock.yaml)
|
|
22
|
+
pnpm add @devalok/shilp-sutra framer-motion next-themes
|
|
23
|
+
pnpm add -D tailwindcss@^4 @tailwindcss/postcss
|
|
24
|
+
|
|
25
|
+
# npm (lockfile: package-lock.json)
|
|
26
|
+
npm install @devalok/shilp-sutra framer-motion next-themes
|
|
27
|
+
npm install -D tailwindcss@^4 @tailwindcss/postcss
|
|
28
|
+
|
|
29
|
+
# yarn (lockfile: yarn.lock)
|
|
30
|
+
yarn add @devalok/shilp-sutra framer-motion next-themes
|
|
31
|
+
yarn add -D tailwindcss@^4 @tailwindcss/postcss
|
|
32
|
+
|
|
33
|
+
# bun (lockfile: bun.lockb)
|
|
34
|
+
bun add @devalok/shilp-sutra framer-motion next-themes
|
|
35
|
+
bun add -d tailwindcss@^4 @tailwindcss/postcss
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Add only if you will render `<Toaster />`:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pnpm add sonner
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Add brand assets package if you need Devalok or Karm logos:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pnpm add @devalok/shilp-sutra-brand
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 3. Configure PostCSS
|
|
51
|
+
|
|
52
|
+
Create or update `postcss.config.mjs` at the project root:
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
export default {
|
|
56
|
+
plugins: {
|
|
57
|
+
"@tailwindcss/postcss": {},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If a `postcss.config.{js,cjs,json}` already exists, merge the plugin in. Do not delete the existing file.
|
|
63
|
+
|
|
64
|
+
## 4. Wire Tailwind 4 + design tokens
|
|
65
|
+
|
|
66
|
+
Locate the global CSS file. Common paths in priority order:
|
|
67
|
+
|
|
68
|
+
- `app/globals.css`
|
|
69
|
+
- `src/app/globals.css`
|
|
70
|
+
- `app/global.css`
|
|
71
|
+
|
|
72
|
+
If none exists, create `app/globals.css`. Set the file contents to (or merge into):
|
|
73
|
+
|
|
74
|
+
```css
|
|
75
|
+
@import "tailwindcss";
|
|
76
|
+
@import "@devalok/shilp-sutra/css";
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Order matters.** `tailwindcss` MUST come first. The shilp-sutra `/css` entry registers `@theme` blocks that the Tailwind import must process.
|
|
80
|
+
|
|
81
|
+
If the project has its own theme overrides, place them AFTER both imports:
|
|
82
|
+
|
|
83
|
+
```css
|
|
84
|
+
@import "tailwindcss";
|
|
85
|
+
@import "@devalok/shilp-sutra/css";
|
|
86
|
+
|
|
87
|
+
@theme {
|
|
88
|
+
--color-brand: oklch(0.65 0.2 280);
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Import the CSS file once from `app/layout.tsx` (it should already be imported in a fresh `create-next-app` project):
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
import "./globals.css";
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 5. Configure `transpilePackages`
|
|
99
|
+
|
|
100
|
+
Edit `next.config.{ts,js,mjs}`. Add the `transpilePackages` field:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import type { NextConfig } from "next";
|
|
104
|
+
|
|
105
|
+
const nextConfig: NextConfig = {
|
|
106
|
+
transpilePackages: ["@devalok/shilp-sutra", "@devalok/shilp-sutra-brand"],
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export default nextConfig;
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
If a `transpilePackages` array already exists, append to it. Do not replace.
|
|
113
|
+
|
|
114
|
+
Without `transpilePackages`, Next will refuse to load our pre-built `dist/*.js` because it ships native ESM that does not match Next's CJS-leaning loader for `node_modules`.
|
|
115
|
+
|
|
116
|
+
## 6. Scaffold the Providers wrapper
|
|
117
|
+
|
|
118
|
+
Create `app/providers.tsx`:
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
"use client";
|
|
122
|
+
|
|
123
|
+
import type { ReactNode } from "react";
|
|
124
|
+
import { ThemeProvider } from "next-themes";
|
|
125
|
+
import { Toaster } from "@devalok/shilp-sutra/ui/toaster";
|
|
126
|
+
|
|
127
|
+
export function Providers({ children }: { children: ReactNode }) {
|
|
128
|
+
return (
|
|
129
|
+
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
|
130
|
+
{children}
|
|
131
|
+
<Toaster />
|
|
132
|
+
</ThemeProvider>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`next-themes` is already in the install list from § 2 — no extra install step needed here. If `<Toaster />` is not used:
|
|
138
|
+
|
|
139
|
+
- Drop the `Toaster` import and its JSX usage
|
|
140
|
+
- Skip installing `sonner`
|
|
141
|
+
|
|
142
|
+
Mount `<Providers>` from `app/layout.tsx`:
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
import "./globals.css";
|
|
146
|
+
import { Providers } from "./providers";
|
|
147
|
+
|
|
148
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
149
|
+
return (
|
|
150
|
+
<html lang="en" suppressHydrationWarning>
|
|
151
|
+
<body>
|
|
152
|
+
<Providers>{children}</Providers>
|
|
153
|
+
</body>
|
|
154
|
+
</html>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`suppressHydrationWarning` on `<html>` is required because `next-themes` writes the `class` attribute before React hydrates. Without it, every page logs a hydration warning.
|
|
160
|
+
|
|
161
|
+
## 7. Verify the install
|
|
162
|
+
|
|
163
|
+
Replace the contents of `app/page.tsx`:
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
import { Button } from "@devalok/shilp-sutra/ui/button";
|
|
167
|
+
import { Stack } from "@devalok/shilp-sutra/ui/stack";
|
|
168
|
+
import { Text } from "@devalok/shilp-sutra/ui/text";
|
|
169
|
+
|
|
170
|
+
export default function Home() {
|
|
171
|
+
return (
|
|
172
|
+
<Stack className="p-ds-08" gap="ds-04">
|
|
173
|
+
<Text variant="heading-2xl">Hello, Shilp Sutra</Text>
|
|
174
|
+
<Stack direction="row" gap="ds-03">
|
|
175
|
+
<Button>Primary</Button>
|
|
176
|
+
<Button variant="soft">Soft</Button>
|
|
177
|
+
<Button variant="outline">Outline</Button>
|
|
178
|
+
</Stack>
|
|
179
|
+
</Stack>
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Run the dev server:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
pnpm dev
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Open `http://localhost:3000`. You should see:
|
|
191
|
+
|
|
192
|
+
- The heading rendered in **Ranade** (display font), the buttons in **Inter** (body font)
|
|
193
|
+
- The primary button on a saturated accent background, the soft button with a tinted background and no border, the outline button with a border and transparent background
|
|
194
|
+
- No hydration warning in the browser console
|
|
195
|
+
- No 404 for fonts (fonts are bundled inside the package; `next/font` is not required)
|
|
196
|
+
|
|
197
|
+
If anything is off, see [troubleshoot.md](./troubleshoot.md).
|
|
198
|
+
|
|
199
|
+
## 8. Common gotchas
|
|
200
|
+
|
|
201
|
+
- **CSS import order.** `tailwindcss` BEFORE `@devalok/shilp-sutra/css`. Reversing the order silently produces a build with no design-system utilities.
|
|
202
|
+
- **Multiple `framer-motion` copies.** Run `pnpm why framer-motion`. If it shows more than one resolved version, contexts (`MotionConfig`, `LayoutGroup`, `AnimatePresence`) silently break. Fix:
|
|
203
|
+
```jsonc
|
|
204
|
+
// package.json
|
|
205
|
+
{
|
|
206
|
+
"pnpm": {
|
|
207
|
+
"overrides": {
|
|
208
|
+
"framer-motion": "^12"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
For npm/yarn/bun equivalents, see [troubleshoot.md](./troubleshoot.md).
|
|
214
|
+
- **Server Component imports.** Use per-component imports (`@devalok/shilp-sutra/ui/text`) inside Server Components. The barrel import `@devalok/shilp-sutra/ui` pulls client-only code and breaks RSC. See [server-components.md](./server-components.md).
|
|
215
|
+
- **`p-3` vs `p-ds-03`.** Our spacing namespace is `--spacing-ds-*` to avoid collision with consumer numeric spacing. Use `p-ds-04`, not `p-4`.
|
|
216
|
+
- **Bare `shadow` is dead.** Tailwind 4 has no `--shadow-DEFAULT`. Use `shadow-raised`, `shadow-overlay`, or `shadow-floating`.
|
|
217
|
+
|
|
218
|
+
## 9. What you should NOT do
|
|
219
|
+
|
|
220
|
+
- ❌ Create `tailwind.config.ts` with `presets: [shilpSutra]` — the JS preset was removed in 0.38.
|
|
221
|
+
- ❌ Add `@plugin "@devalok/shilp-sutra/tailwind"` — also removed.
|
|
222
|
+
- ❌ Wrap the whole app in `<MotionConfig reducedMotion="...">` unless the user explicitly asks for a global motion override; Shilp Sutra components already respect `prefers-reduced-motion`.
|
|
223
|
+
- ❌ Import from `@devalok/shilp-sutra/tailwind` — the export was removed in 0.38.
|
|
224
|
+
- ❌ Run `pnpm add @radix-ui/react-*` — Radix is vendored; no @radix-ui runtime deps are required.
|
|
225
|
+
|
|
226
|
+
## 10. Optional next steps
|
|
227
|
+
|
|
228
|
+
- **Brand customization** — swap accent color, radius scale, or fonts: see [customize-brand.md](./customize-brand.md).
|
|
229
|
+
- **App shell** — add a sidebar + topbar layout: read `llms-full.txt` sections for `AppSidebar` and `TopBar`.
|
|
230
|
+
- **Server-safe components** — push as much rendering as possible into Server Components: see [server-components.md](./server-components.md).
|