@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.
Files changed (183) hide show
  1. package/MIGRATION.md +67 -0
  2. package/dist/_chunks/tiptap.js +977 -968
  3. package/dist/_chunks/tiptap.js.map +1 -1
  4. package/dist/composed/index.d.ts +0 -2
  5. package/dist/composed/index.d.ts.map +1 -1
  6. package/dist/composed/index.js +5 -6
  7. package/dist/composed/inline-edit.d.ts.map +1 -1
  8. package/dist/composed/inline-edit.js +42 -40
  9. package/dist/composed/inline-edit.js.map +1 -1
  10. package/dist/hooks/index.d.ts +2 -2
  11. package/dist/hooks/index.d.ts.map +1 -1
  12. package/dist/hooks/index.js +0 -1
  13. package/dist/test-utils/conformance.d.ts +37 -0
  14. package/dist/test-utils/conformance.d.ts.map +1 -0
  15. package/dist/ui/alert.d.ts +1 -2
  16. package/dist/ui/alert.d.ts.map +1 -1
  17. package/dist/ui/alert.js +1 -27
  18. package/dist/ui/alert.js.map +1 -1
  19. package/dist/ui/banner.d.ts +3 -5
  20. package/dist/ui/banner.d.ts.map +1 -1
  21. package/dist/ui/banner.js +13 -13
  22. package/dist/ui/banner.js.map +1 -1
  23. package/dist/ui/index.d.ts +1 -1
  24. package/dist/ui/index.d.ts.map +1 -1
  25. package/dist/ui/index.js +2 -2
  26. package/dist/ui/index.js.map +1 -1
  27. package/dist/ui/input.d.ts +1 -9
  28. package/dist/ui/input.d.ts.map +1 -1
  29. package/dist/ui/input.js +26 -27
  30. package/dist/ui/input.js.map +1 -1
  31. package/dist/ui/segmented-control.d.ts +1 -1
  32. package/dist/ui/segmented-control.d.ts.map +1 -1
  33. package/dist/ui/segmented-control.js +2 -4
  34. package/dist/ui/segmented-control.js.map +1 -1
  35. package/docs/components/_header.md +1 -1
  36. package/docs/components/composed/activity-feed.md +6 -0
  37. package/docs/components/composed/avatar-group.md +8 -0
  38. package/docs/components/composed/bulk-action-bar.md +6 -0
  39. package/docs/components/composed/command-palette.md +7 -0
  40. package/docs/components/composed/confirm-dialog.md +6 -0
  41. package/docs/components/composed/content-card.md +6 -0
  42. package/docs/components/composed/date-picker.md +10 -0
  43. package/docs/components/composed/deadline-indicator.md +7 -0
  44. package/docs/components/composed/emoji-picker.md +8 -0
  45. package/docs/components/composed/empty-state.md +8 -0
  46. package/docs/components/composed/error-boundary.md +7 -0
  47. package/docs/components/composed/file-preview.md +8 -0
  48. package/docs/components/composed/filter-bar.md +8 -0
  49. package/docs/components/composed/form-section.md +6 -0
  50. package/docs/components/composed/global-loading.md +6 -0
  51. package/docs/components/composed/inline-edit.md +8 -0
  52. package/docs/components/composed/loading-skeleton.md +7 -0
  53. package/docs/components/composed/markdown-viewer.md +9 -0
  54. package/docs/components/composed/master-detail.md +7 -0
  55. package/docs/components/composed/member-picker.md +7 -0
  56. package/docs/components/composed/multi-select-popover.md +11 -0
  57. package/docs/components/composed/page-header.md +7 -0
  58. package/docs/components/composed/page-skeletons.md +10 -0
  59. package/docs/components/composed/priority-indicator.md +7 -0
  60. package/docs/components/composed/rich-chat-input.md +12 -0
  61. package/docs/components/composed/rich-text-editor.md +9 -0
  62. package/docs/components/composed/schedule-view.md +8 -0
  63. package/docs/components/composed/simple-tooltip.md +7 -0
  64. package/docs/components/composed/status-badge.md +10 -0
  65. package/docs/components/shell/app-command-palette.md +8 -0
  66. package/docs/components/shell/bottom-navbar.md +12 -0
  67. package/docs/components/shell/command-registry.md +7 -0
  68. package/docs/components/shell/link-context.md +15 -0
  69. package/docs/components/shell/notification-center.md +10 -0
  70. package/docs/components/shell/notification-preferences.md +7 -0
  71. package/docs/components/shell/sidebar.md +11 -0
  72. package/docs/components/shell/top-bar.md +11 -0
  73. package/docs/components/ui/accordion.md +10 -0
  74. package/docs/components/ui/alert-dialog.md +10 -1
  75. package/docs/components/ui/alert.md +13 -2
  76. package/docs/components/ui/aspect-ratio.md +7 -0
  77. package/docs/components/ui/autocomplete.md +7 -0
  78. package/docs/components/ui/avatar.md +10 -0
  79. package/docs/components/ui/badge-group.md +7 -0
  80. package/docs/components/ui/badge-indicator.md +7 -0
  81. package/docs/components/ui/badge.md +12 -0
  82. package/docs/components/ui/banner.md +10 -1
  83. package/docs/components/ui/breadcrumb.md +8 -0
  84. package/docs/components/ui/button-group.md +24 -4
  85. package/docs/components/ui/button-processing.md +5 -0
  86. package/docs/components/ui/button.md +9 -0
  87. package/docs/components/ui/card.md +16 -4
  88. package/docs/components/ui/charts.md +9 -0
  89. package/docs/components/ui/chat.md +9 -0
  90. package/docs/components/ui/checkbox.md +15 -1
  91. package/docs/components/ui/chip.md +9 -0
  92. package/docs/components/ui/code.md +7 -0
  93. package/docs/components/ui/collapsible.md +9 -0
  94. package/docs/components/ui/color-input.md +8 -0
  95. package/docs/components/ui/color-swatch.md +7 -0
  96. package/docs/components/ui/combobox.md +16 -3
  97. package/docs/components/ui/container.md +11 -0
  98. package/docs/components/ui/context-menu.md +8 -0
  99. package/docs/components/ui/data-table-body.md +4 -0
  100. package/docs/components/ui/data-table-bulk-actions.md +4 -0
  101. package/docs/components/ui/data-table-card.md +4 -0
  102. package/docs/components/ui/data-table-context.md +4 -0
  103. package/docs/components/ui/data-table-header.md +4 -0
  104. package/docs/components/ui/data-table-pagination.md +4 -0
  105. package/docs/components/ui/data-table-toolbar.md +7 -0
  106. package/docs/components/ui/data-table.md +25 -0
  107. package/docs/components/ui/devalok-grain.md +8 -0
  108. package/docs/components/ui/dialog.md +10 -0
  109. package/docs/components/ui/dropdown-menu.md +10 -0
  110. package/docs/components/ui/file-upload.md +8 -0
  111. package/docs/components/ui/form.md +21 -0
  112. package/docs/components/ui/hover-card.md +9 -0
  113. package/docs/components/ui/icon-button.md +7 -0
  114. package/docs/components/ui/icon-context.md +7 -0
  115. package/docs/components/ui/icon-group.md +9 -0
  116. package/docs/components/ui/icon.md +7 -0
  117. package/docs/components/ui/input-otp.md +29 -7
  118. package/docs/components/ui/input.md +11 -2
  119. package/docs/components/ui/label.md +7 -1
  120. package/docs/components/ui/link.md +7 -0
  121. package/docs/components/ui/menubar.md +9 -0
  122. package/docs/components/ui/navigation-menu.md +9 -0
  123. package/docs/components/ui/number-input.md +10 -0
  124. package/docs/components/ui/pagination.md +10 -0
  125. package/docs/components/ui/popover.md +9 -0
  126. package/docs/components/ui/progress-ring.md +7 -0
  127. package/docs/components/ui/progress.md +7 -0
  128. package/docs/components/ui/radio.md +27 -2
  129. package/docs/components/ui/search-input.md +8 -0
  130. package/docs/components/ui/segmented-control.md +21 -6
  131. package/docs/components/ui/select.md +14 -3
  132. package/docs/components/ui/separator.md +7 -0
  133. package/docs/components/ui/sheet.md +10 -0
  134. package/docs/components/ui/sidebar.md +30 -0
  135. package/docs/components/ui/skeleton.md +7 -0
  136. package/docs/components/ui/slider.md +15 -1
  137. package/docs/components/ui/spinner.md +7 -0
  138. package/docs/components/ui/split-button.md +11 -0
  139. package/docs/components/ui/stack.md +8 -0
  140. package/docs/components/ui/stat-card.md +9 -0
  141. package/docs/components/ui/status-dot.md +9 -0
  142. package/docs/components/ui/stepper.md +8 -0
  143. package/docs/components/ui/switch.md +8 -0
  144. package/docs/components/ui/table.md +8 -0
  145. package/docs/components/ui/tabs.md +10 -2
  146. package/docs/components/ui/text.md +9 -4
  147. package/docs/components/ui/textarea.md +7 -1
  148. package/docs/components/ui/toast.md +9 -0
  149. package/docs/components/ui/toaster.md +8 -0
  150. package/docs/components/ui/toggle-group.md +13 -4
  151. package/docs/components/ui/toggle.md +10 -2
  152. package/docs/components/ui/tooltip.md +11 -1
  153. package/docs/components/ui/tree-view.md +12 -0
  154. package/docs/components/ui/visually-hidden.md +7 -0
  155. package/docs/recipes/customize-brand.md +216 -0
  156. package/docs/recipes/index.md +51 -0
  157. package/docs/recipes/install-astro.md +178 -0
  158. package/docs/recipes/install-next-app-router.md +230 -0
  159. package/docs/recipes/install-next-pages.md +123 -0
  160. package/docs/recipes/install-remix.md +171 -0
  161. package/docs/recipes/install-tanstack-start.md +143 -0
  162. package/docs/recipes/install-vite.md +170 -0
  163. package/docs/recipes/server-components.md +209 -0
  164. package/docs/recipes/troubleshoot.md +217 -0
  165. package/llms-full.txt +1133 -88
  166. package/llms.txt +33 -16
  167. package/package.json +45 -35
  168. package/dist/composed/responsive-overlay.d.ts +0 -23
  169. package/dist/composed/responsive-overlay.d.ts.map +0 -1
  170. package/dist/composed/responsive-overlay.js +0 -40
  171. package/dist/composed/responsive-overlay.js.map +0 -1
  172. package/dist/hooks/use-toast.d.ts +0 -17
  173. package/dist/hooks/use-toast.d.ts.map +0 -1
  174. package/dist/hooks/use-toast.js +0 -3
  175. package/dist/tailwind/index.cjs +0 -41
  176. package/dist/tailwind/index.d.ts +0 -2
  177. package/dist/tailwind/index.d.ts.map +0 -1
  178. package/dist/tailwind/index.js +0 -2
  179. package/dist/tailwind/preset.d.ts +0 -25
  180. package/dist/tailwind/preset.d.ts.map +0 -1
  181. package/dist/tailwind/preset.js +0 -17
  182. package/dist/tailwind/preset.js.map +0 -1
  183. package/docs/components/composed/responsive-overlay.md +0 -34
@@ -0,0 +1,123 @@
1
+ # Install: Next.js (Pages Router)
2
+
3
+ > Setup recipe for adding `@devalok/shilp-sutra` to a Next.js project that uses the Pages Router (`pages/_app.tsx` as the entry).
4
+
5
+ ## 1. Detect
6
+
7
+ You are in this recipe if:
8
+
9
+ - `package.json` lists `"next"` (any version `>= 12`)
10
+ - A `pages/` directory exists at the project root or under `src/` and contains `_app.{js,tsx}` (and optionally `_document.{js,tsx}`)
11
+ - `app/` directory does NOT exist, OR exists but is unused
12
+
13
+ If both `app/` and `pages/` exist, prefer [install-next-app-router.md](./install-next-app-router.md) and treat the Pages Router as legacy.
14
+
15
+ ## 2. Install
16
+
17
+ Same dependencies as the App Router recipe — see [install-next-app-router.md § 2](./install-next-app-router.md#2-install-dependencies). Replace `next-themes`'s `attribute="class"` setup with the same on Pages Router (it works identically).
18
+
19
+ ## 3. PostCSS
20
+
21
+ Same as App Router — see [§ 3](./install-next-app-router.md#3-configure-postcss).
22
+
23
+ ## 4. Wire Tailwind 4 + tokens
24
+
25
+ Common CSS entry paths in priority order:
26
+
27
+ - `styles/globals.css`
28
+ - `src/styles/globals.css`
29
+ - `pages/_app.css` (rare)
30
+
31
+ If none exists, create `styles/globals.css` with:
32
+
33
+ ```css
34
+ @import "tailwindcss";
35
+ @import "@devalok/shilp-sutra/css";
36
+ ```
37
+
38
+ Import it from `pages/_app.tsx`:
39
+
40
+ ```tsx
41
+ import "../styles/globals.css";
42
+ ```
43
+
44
+ ## 5. `transpilePackages`
45
+
46
+ Identical to App Router — see [§ 5](./install-next-app-router.md#5-configure-transpilepackages).
47
+
48
+ ## 6. Providers in `_app.tsx`
49
+
50
+ Replace or merge into `pages/_app.tsx`:
51
+
52
+ ```tsx
53
+ import "../styles/globals.css";
54
+ import type { AppProps } from "next/app";
55
+ import { ThemeProvider } from "next-themes";
56
+ import { Toaster } from "@devalok/shilp-sutra/ui/toaster";
57
+
58
+ export default function App({ Component, pageProps }: AppProps) {
59
+ return (
60
+ <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
61
+ <Component {...pageProps} />
62
+ <Toaster />
63
+ </ThemeProvider>
64
+ );
65
+ }
66
+ ```
67
+
68
+ For `next-themes` to avoid hydration warnings, add a `_document.tsx` with `suppressHydrationWarning` on the `<html>`:
69
+
70
+ ```tsx
71
+ // pages/_document.tsx
72
+ import { Html, Head, Main, NextScript } from "next/document";
73
+
74
+ export default function Document() {
75
+ return (
76
+ <Html lang="en" suppressHydrationWarning>
77
+ <Head />
78
+ <body>
79
+ <Main />
80
+ <NextScript />
81
+ </body>
82
+ </Html>
83
+ );
84
+ }
85
+ ```
86
+
87
+ ## 7. Verify
88
+
89
+ Replace `pages/index.tsx`:
90
+
91
+ ```tsx
92
+ import { Button } from "@devalok/shilp-sutra/ui/button";
93
+ import { Stack } from "@devalok/shilp-sutra/ui/stack";
94
+ import { Text } from "@devalok/shilp-sutra/ui/text";
95
+
96
+ export default function Home() {
97
+ return (
98
+ <Stack className="p-ds-08" gap="ds-04">
99
+ <Text variant="heading-2xl">Hello, Shilp Sutra</Text>
100
+ <Stack direction="row" gap="ds-03">
101
+ <Button>Primary</Button>
102
+ <Button variant="soft">Soft</Button>
103
+ </Stack>
104
+ </Stack>
105
+ );
106
+ }
107
+ ```
108
+
109
+ Run `pnpm dev` and open `http://localhost:3000`. Expected output is the same as the App Router recipe — see [§ 7](./install-next-app-router.md#7-verify-the-install).
110
+
111
+ ## 8. Pages Router specifics
112
+
113
+ - **No React Server Components.** Every component runs on the client. Per-component imports still help tree-shaking but are not required for RSC safety.
114
+ - **`getServerSideProps` / `getStaticProps`** — do not import shilp-sutra components inside these (they run server-side and won't render JSX). Components are imported and used in the page module's default export, as usual.
115
+ - **`pages/_document.tsx` runs server-only.** Do not import shilp-sutra components there.
116
+
117
+ ## 9. Gotchas
118
+
119
+ Same as App Router — see [§ 8](./install-next-app-router.md#8-common-gotchas).
120
+
121
+ ## 10. What NOT to do
122
+
123
+ Same as App Router — see [§ 9](./install-next-app-router.md#9-what-you-should-not-do).
@@ -0,0 +1,171 @@
1
+ # Install: Remix
2
+
3
+ > Setup recipe for adding `@devalok/shilp-sutra` to a Remix project (v2 with Vite).
4
+
5
+ ## 1. Detect
6
+
7
+ You are in this recipe if:
8
+
9
+ - `package.json` lists `"@remix-run/node"` and `"@remix-run/react"`
10
+ - `vite.config.{ts,js}` exists with the `vitePlugin` from `@remix-run/dev`
11
+ - `app/root.tsx` exists with `<Outlet />` inside `<Document>` shell
12
+
13
+ For React Router v7 (the spiritual successor to Remix), use the [install-vite.md](./install-vite.md) recipe — it works the same way.
14
+
15
+ ## 2. Install
16
+
17
+ ```bash
18
+ pnpm add @devalok/shilp-sutra framer-motion
19
+ pnpm add -D tailwindcss@^4 @tailwindcss/vite
20
+ ```
21
+
22
+ Optional:
23
+
24
+ ```bash
25
+ pnpm add sonner # only if rendering <Toaster />
26
+ ```
27
+
28
+ ## 3. Wire Tailwind 4 in `vite.config.ts`
29
+
30
+ ```ts
31
+ import { vitePlugin as remix } from "@remix-run/dev";
32
+ import tailwindcss from "@tailwindcss/vite";
33
+ import { defineConfig } from "vite";
34
+
35
+ export default defineConfig({
36
+ plugins: [
37
+ tailwindcss(),
38
+ remix(),
39
+ ],
40
+ });
41
+ ```
42
+
43
+ `tailwindcss()` should come before `remix()` so the design tokens are processed first.
44
+
45
+ ## 4. Wire tokens
46
+
47
+ Create `app/styles/globals.css`:
48
+
49
+ ```css
50
+ @import "tailwindcss";
51
+ @import "@devalok/shilp-sutra/css";
52
+ ```
53
+
54
+ Wire it as a Remix link export from `app/root.tsx`:
55
+
56
+ ```tsx
57
+ import type { LinksFunction } from "@remix-run/node";
58
+ import globalsCss from "./styles/globals.css?url";
59
+
60
+ export const links: LinksFunction = () => [
61
+ { rel: "stylesheet", href: globalsCss },
62
+ ];
63
+ ```
64
+
65
+ The `?url` suffix is critical — it tells Vite to emit the file as an asset URL instead of inlining the CSS contents.
66
+
67
+ ## 5. Theme toggle
68
+
69
+ Create `public/theme-bootstrap.js` (a static asset served verbatim):
70
+
71
+ ```js
72
+ (function () {
73
+ try {
74
+ var stored = localStorage.getItem("theme");
75
+ var prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
76
+ if (stored === "dark" || (!stored && prefersDark)) {
77
+ document.documentElement.classList.add("dark");
78
+ }
79
+ } catch (e) {}
80
+ })();
81
+ ```
82
+
83
+ Reference it from `app/root.tsx` so it loads before any React hydration:
84
+
85
+ ```tsx
86
+ import { Outlet, Meta, Links, Scripts, ScrollRestoration } from "@remix-run/react";
87
+
88
+ export default function App() {
89
+ return (
90
+ <html lang="en" suppressHydrationWarning>
91
+ <head>
92
+ <Meta />
93
+ <Links />
94
+ <script src="/theme-bootstrap.js" />
95
+ </head>
96
+ <body>
97
+ <Outlet />
98
+ <ScrollRestoration />
99
+ <Scripts />
100
+ </body>
101
+ </html>
102
+ );
103
+ }
104
+ ```
105
+
106
+ For runtime toggling inside React components, use `useColorMode`:
107
+
108
+ ```tsx
109
+ import { useColorMode } from "@devalok/shilp-sutra/hooks/use-color-mode";
110
+
111
+ export function ThemeToggle() {
112
+ const { mode, toggle } = useColorMode();
113
+ return (
114
+ <button onClick={toggle} aria-label="Toggle theme">
115
+ {mode === "dark" ? "☀" : "☾"}
116
+ </button>
117
+ );
118
+ }
119
+ ```
120
+
121
+ ## 6. Toaster (optional)
122
+
123
+ Mount once in `app/root.tsx` next to `<Outlet />`:
124
+
125
+ ```tsx
126
+ import { Toaster } from "@devalok/shilp-sutra/ui/toaster";
127
+
128
+ // inside <body>
129
+ <>
130
+ <Outlet />
131
+ <Toaster />
132
+ </>
133
+ ```
134
+
135
+ ## 7. Verify
136
+
137
+ Create `app/routes/_index.tsx`:
138
+
139
+ ```tsx
140
+ import { Button } from "@devalok/shilp-sutra/ui/button";
141
+ import { Stack } from "@devalok/shilp-sutra/ui/stack";
142
+ import { Text } from "@devalok/shilp-sutra/ui/text";
143
+
144
+ export default function Index() {
145
+ return (
146
+ <Stack className="p-ds-08" gap="ds-04">
147
+ <Text variant="heading-2xl">Hello, Shilp Sutra</Text>
148
+ <Stack direction="row" gap="ds-03">
149
+ <Button>Primary</Button>
150
+ <Button variant="soft">Soft</Button>
151
+ </Stack>
152
+ </Stack>
153
+ );
154
+ }
155
+ ```
156
+
157
+ Run `pnpm dev` and open the URL.
158
+
159
+ ## 8. Remix-specific gotchas
160
+
161
+ - **`?url` suffix on CSS imports.** Without it, Vite tries to inline the CSS, which breaks Tailwind processing.
162
+ - **Loaders are server-only.** Do not import shilp-sutra components inside a `loader` function — they will not render.
163
+ - **Server-rendered output.** Remix SSRs every route. The CSS-in-JS-free approach of shilp-sutra works perfectly here; no extra config needed.
164
+ - **`framer-motion` and SSR.** All shilp-sutra animations gracefully degrade for the initial server render. No special handling required.
165
+ - **CSP.** If your CSP blocks inline scripts, the `theme-bootstrap.js` static asset above already complies (no `unsafe-inline` needed).
166
+
167
+ ## 9. What NOT to do
168
+
169
+ - ❌ Add `tailwind.config.{ts,js}` — Tailwind 4 is CSS-first.
170
+ - ❌ Skip the `?url` suffix on CSS imports.
171
+ - ❌ Mount `<Toaster />` inside route components — it should live once at the root.
@@ -0,0 +1,143 @@
1
+ # Install: TanStack Start
2
+
3
+ > Setup recipe for adding `@devalok/shilp-sutra` to a TanStack Start project (the React full-stack framework built on Vinxi/Vite).
4
+
5
+ ## 1. Detect
6
+
7
+ You are in this recipe if:
8
+
9
+ - `package.json` lists `"@tanstack/start"` and `"@tanstack/react-router"`
10
+ - `app.config.{ts,js}` (Vinxi) exists at the project root
11
+ - `app/router.tsx` and `app/routes/__root.tsx` exist
12
+
13
+ ## 2. Install
14
+
15
+ ```bash
16
+ pnpm add @devalok/shilp-sutra framer-motion
17
+ pnpm add -D tailwindcss@^4 @tailwindcss/vite
18
+ ```
19
+
20
+ Optional:
21
+
22
+ ```bash
23
+ pnpm add sonner # only if rendering <Toaster />
24
+ ```
25
+
26
+ ## 3. Wire Tailwind 4 in `app.config.ts`
27
+
28
+ ```ts
29
+ import { defineConfig } from "@tanstack/start/config";
30
+ import tailwindcss from "@tailwindcss/vite";
31
+
32
+ export default defineConfig({
33
+ vite: {
34
+ plugins: [tailwindcss()],
35
+ },
36
+ });
37
+ ```
38
+
39
+ ## 4. Wire tokens
40
+
41
+ Create `app/styles/globals.css`:
42
+
43
+ ```css
44
+ @import "tailwindcss";
45
+ @import "@devalok/shilp-sutra/css";
46
+ ```
47
+
48
+ Import it from `app/routes/__root.tsx`:
49
+
50
+ ```tsx
51
+ import "../styles/globals.css";
52
+ ```
53
+
54
+ If you prefer asset-URL imports the way Remix does it, use `import css from "../styles/globals.css?url"` and add `<link rel="stylesheet" href={css} />` to the `<head>` returned by `__root.tsx`.
55
+
56
+ ## 5. Theme toggle
57
+
58
+ Create `public/theme-bootstrap.js` (a static asset served verbatim):
59
+
60
+ ```js
61
+ (function () {
62
+ try {
63
+ var stored = localStorage.getItem("theme");
64
+ var prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
65
+ if (stored === "dark" || (!stored && prefersDark)) {
66
+ document.documentElement.classList.add("dark");
67
+ }
68
+ } catch (e) {}
69
+ })();
70
+ ```
71
+
72
+ Reference it from `app/routes/__root.tsx`:
73
+
74
+ ```tsx
75
+ import { createRootRoute, Outlet } from "@tanstack/react-router";
76
+
77
+ export const Route = createRootRoute({
78
+ component: () => (
79
+ <html lang="en" suppressHydrationWarning>
80
+ <head>
81
+ <script src="/theme-bootstrap.js" />
82
+ </head>
83
+ <body>
84
+ <Outlet />
85
+ </body>
86
+ </html>
87
+ ),
88
+ });
89
+ ```
90
+
91
+ For runtime toggling, use the `useColorMode` hook — see [install-vite.md § 5](./install-vite.md#5-theme-toggle-no-next-themes-here).
92
+
93
+ ## 6. Toaster (optional)
94
+
95
+ Mount in `__root.tsx` next to `<Outlet />`:
96
+
97
+ ```tsx
98
+ import { Toaster } from "@devalok/shilp-sutra/ui/toaster";
99
+
100
+ // inside <body>
101
+ <>
102
+ <Outlet />
103
+ <Toaster />
104
+ </>
105
+ ```
106
+
107
+ ## 7. Verify
108
+
109
+ Create or replace `app/routes/index.tsx`:
110
+
111
+ ```tsx
112
+ import { createFileRoute } from "@tanstack/react-router";
113
+ import { Button } from "@devalok/shilp-sutra/ui/button";
114
+ import { Stack } from "@devalok/shilp-sutra/ui/stack";
115
+ import { Text } from "@devalok/shilp-sutra/ui/text";
116
+
117
+ export const Route = createFileRoute("/")({
118
+ component: () => (
119
+ <Stack className="p-ds-08" gap="ds-04">
120
+ <Text variant="heading-2xl">Hello, Shilp Sutra</Text>
121
+ <Stack direction="row" gap="ds-03">
122
+ <Button>Primary</Button>
123
+ <Button variant="soft">Soft</Button>
124
+ </Stack>
125
+ </Stack>
126
+ ),
127
+ });
128
+ ```
129
+
130
+ Run `pnpm dev` and open the URL.
131
+
132
+ ## 8. TanStack Start specifics
133
+
134
+ - **Server functions** (`createServerFn`) — do not import shilp-sutra components inside server functions; they run server-only.
135
+ - **Streaming SSR** is the default. All shilp-sutra components SSR cleanly because they have no client-only side effects at module top-level.
136
+ - **`framer-motion` SSR** — animations gracefully degrade on the initial render.
137
+ - **CSP.** The static `theme-bootstrap.js` asset complies with strict CSP (no inline scripts required).
138
+
139
+ ## 9. What NOT to do
140
+
141
+ - ❌ Add `tailwind.config.{ts,js}` — Tailwind 4 is CSS-first.
142
+ - ❌ Mount `<Toaster />` inside route components — it should live once at the `__root`.
143
+ - ❌ Mix `@tailwindcss/postcss` and `@tailwindcss/vite` — pick one (Vite plugin recommended for TanStack Start).
@@ -0,0 +1,170 @@
1
+ # Install: Vite + React
2
+
3
+ > Setup recipe for adding `@devalok/shilp-sutra` to a Vite + React SPA.
4
+
5
+ ## 1. Detect
6
+
7
+ You are in this recipe if:
8
+
9
+ - `vite.config.{ts,js,mjs}` exists at the project root
10
+ - `package.json` lists `"vite"` and `"react"`
11
+ - `src/main.{tsx,jsx}` is the entry that calls `createRoot(...).render(<App />)`
12
+
13
+ This recipe also covers Vite + React + React Router (any version) — the design system is router-agnostic.
14
+
15
+ If you are using Remix (which now runs on Vite), use [install-remix.md](./install-remix.md). If you are using TanStack Start, use [install-tanstack-start.md](./install-tanstack-start.md).
16
+
17
+ ## 2. Install dependencies
18
+
19
+ ```bash
20
+ # pnpm
21
+ pnpm add @devalok/shilp-sutra framer-motion
22
+ pnpm add -D tailwindcss@^4 @tailwindcss/vite
23
+
24
+ # npm
25
+ npm install @devalok/shilp-sutra framer-motion
26
+ npm install -D tailwindcss@^4 @tailwindcss/vite
27
+
28
+ # yarn
29
+ yarn add @devalok/shilp-sutra framer-motion
30
+ yarn add -D tailwindcss@^4 @tailwindcss/vite
31
+
32
+ # bun
33
+ bun add @devalok/shilp-sutra framer-motion
34
+ bun add -d tailwindcss@^4 @tailwindcss/vite
35
+ ```
36
+
37
+ Add only if rendering `<Toaster />`:
38
+
39
+ ```bash
40
+ pnpm add sonner
41
+ ```
42
+
43
+ ## 3. Wire Tailwind 4 in `vite.config.ts`
44
+
45
+ Use the official Tailwind 4 Vite plugin (faster than PostCSS for Vite):
46
+
47
+ ```ts
48
+ import { defineConfig } from "vite";
49
+ import react from "@vitejs/plugin-react";
50
+ import tailwindcss from "@tailwindcss/vite";
51
+
52
+ export default defineConfig({
53
+ plugins: [react(), tailwindcss()],
54
+ });
55
+ ```
56
+
57
+ If the project already uses PostCSS for other reasons, you can use `@tailwindcss/postcss` instead — see [install-next-app-router.md § 3](./install-next-app-router.md#3-configure-postcss). Stick with one approach; do not load both.
58
+
59
+ ## 4. Wire tokens in the global CSS
60
+
61
+ Common CSS entry paths in priority order:
62
+
63
+ - `src/index.css`
64
+ - `src/main.css`
65
+ - `src/styles/globals.css`
66
+ - `src/App.css`
67
+
68
+ If none exists, create `src/index.css`. Set or merge:
69
+
70
+ ```css
71
+ @import "tailwindcss";
72
+ @import "@devalok/shilp-sutra/css";
73
+ ```
74
+
75
+ Import it once from the entry (`src/main.tsx`):
76
+
77
+ ```tsx
78
+ import "./index.css";
79
+ ```
80
+
81
+ ## 5. Theme toggle (no `next-themes` here)
82
+
83
+ Vite has no built-in theme provider. Use the design system's `useColorMode` hook with a small bootstrap script to avoid a flash of wrong theme.
84
+
85
+ Add the bootstrap to `index.html` (in `<head>`, before any stylesheet):
86
+
87
+ ```html
88
+ <script>
89
+ (function () {
90
+ try {
91
+ var stored = localStorage.getItem("theme");
92
+ var prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
93
+ var dark = stored === "dark" || (!stored && prefersDark);
94
+ if (dark) document.documentElement.classList.add("dark");
95
+ } catch (e) {}
96
+ })();
97
+ </script>
98
+ ```
99
+
100
+ Wire the runtime hook from anywhere in the app (e.g., a header button):
101
+
102
+ ```tsx
103
+ import { useColorMode } from "@devalok/shilp-sutra/hooks/use-color-mode";
104
+
105
+ export function ThemeToggle() {
106
+ const { mode, toggle } = useColorMode();
107
+ return (
108
+ <button onClick={toggle} aria-label="Toggle theme">
109
+ {mode === "dark" ? "☀" : "☾"}
110
+ </button>
111
+ );
112
+ }
113
+ ```
114
+
115
+ ## 6. Mount Toaster (optional)
116
+
117
+ If you installed `sonner`, mount the Toaster once near the app root:
118
+
119
+ ```tsx
120
+ // src/main.tsx
121
+ import { StrictMode } from "react";
122
+ import { createRoot } from "react-dom/client";
123
+ import { Toaster } from "@devalok/shilp-sutra/ui/toaster";
124
+ import { App } from "./App";
125
+ import "./index.css";
126
+
127
+ createRoot(document.getElementById("root")!).render(
128
+ <StrictMode>
129
+ <App />
130
+ <Toaster />
131
+ </StrictMode>,
132
+ );
133
+ ```
134
+
135
+ ## 7. Verify
136
+
137
+ Replace `src/App.tsx`:
138
+
139
+ ```tsx
140
+ import { Button } from "@devalok/shilp-sutra/ui/button";
141
+ import { Stack } from "@devalok/shilp-sutra/ui/stack";
142
+ import { Text } from "@devalok/shilp-sutra/ui/text";
143
+
144
+ export function App() {
145
+ return (
146
+ <Stack className="p-ds-08" gap="ds-04">
147
+ <Text variant="heading-2xl">Hello, Shilp Sutra</Text>
148
+ <Stack direction="row" gap="ds-03">
149
+ <Button>Primary</Button>
150
+ <Button variant="soft">Soft</Button>
151
+ </Stack>
152
+ </Stack>
153
+ );
154
+ }
155
+ ```
156
+
157
+ Run `pnpm dev` and open the printed Vite URL. Expected output matches [Next App Router § 7](./install-next-app-router.md#7-verify-the-install).
158
+
159
+ ## 8. Gotchas (Vite-specific)
160
+
161
+ - **`@tailwindcss/vite` and `@tailwindcss/postcss` together.** Pick one — running both causes utilities to be processed twice and CSS bloat.
162
+ - **CSS import paths in HMR.** Vite is strict about case-sensitivity even on macOS. `@devalok/shilp-sutra/CSS` will not resolve; use the lowercase `/css`.
163
+ - **Multiple framer-motion copies.** Same fix as Next — see [install-next-app-router.md § 8](./install-next-app-router.md#8-common-gotchas).
164
+ - **Spacing utilities.** Use `p-ds-04` (not `p-4`). Tailwind composite text utilities: `text-heading-xl`, `text-body-md`, `text-code`.
165
+
166
+ ## 9. What NOT to do
167
+
168
+ - ❌ Add `@devalok/shilp-sutra/tailwind` — the export was removed in 0.38.
169
+ - ❌ Add a `tailwind.config.{ts,js}` with `presets: [shilpSutra]` — JS preset removed.
170
+ - ❌ Try to use `next-themes` here — it requires Next. Use the bootstrap script + `useColorMode` shown in § 5.