@alexgorbatchev/shadcn 0.0.54 → 0.0.55

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/README.md CHANGED
@@ -198,10 +198,15 @@ An independent production Vite consumer installed from the archive verifies RTL
198
198
  | `ThemeProvider.defaultTheme` | `"light" \| "dark" \| "system"` | `"system"` | Initial preference when storage has no saved value. |
199
199
  | `ThemeProvider.storageKey` | `string` | `"shadcn-alexgorbatchev-theme"` | Local storage key for the preference. |
200
200
  | `ThemeProvider.forcedTheme` | `"light" \| "dark"` | unset | Overrides the displayed palette without changing the saved preference. |
201
+ | `ThemeProvider.preset` | `"devhost" \| "shadcn"` | `"devhost"` | Document-wide design preset, independent of color mode and density. |
201
202
  | `DensityProvider.density` | `"compact" \| "comfortable"` | `"comfortable"` | Density for descendants and their portals. |
202
203
  | Component `density` | `"compact" \| "comfortable"` | inherited | Local override on styled components that expose the prop. |
203
204
 
204
- `useTheme()` returns `theme`, `resolvedTheme`, and `setTheme`. Call `setTheme("light")`, `setTheme("dark")`, or `setTheme("system")` from a component inside the provider.
205
+ `useTheme()` returns `theme`, `resolvedTheme`, `setTheme`, and `preset`. Call `setTheme("light")`, `setTheme("dark")`, or `setTheme("system")` from a component inside the provider.
206
+
207
+ Use `<ThemeProvider preset="shadcn" defaultTheme="system">` for the [default shadcn Neutral palette](https://ui.shadcn.com/docs/theming), system sans-serif text, and its rounded corner scale. The default `devhost` preset uses the package's monospace design and sharp corners. Both presets support light, dark, and system modes, including portaled content. Code retains the monospace font. Density, component composition, and package-specific status colors remain independent of the preset.
208
+
209
+ The preset is controlled by the prop; changing it updates the document without changing the saved color-mode preference. Persist that prop in your application if needed. Storybook exposes the same choice in its **Design** toolbar. For a page styled before React mounts, set `data-theme-preset="shadcn"` and `data-theme="light"` or `"dark"` on `<html>` to match the provider. The existing `theme.css` import and `@source` setup cover both presets.
205
210
 
206
211
  Override tokens after the theme imports. This example uses the existing success palette as the primary accent:
207
212
 
@@ -14,6 +14,8 @@ Questionnaire adapts the official registry's fifteen styled parts around `@shadc
14
14
 
15
15
  ## shadcn/ui
16
16
 
17
+ The `shadcn` design preset in `src/theme.css` adapts the default Neutral light/dark palette and radius scale from https://ui.shadcn.com/docs/theming, retrieved on 2026-10-31. It preserves the package's independent density and status tokens and uses document data attributes for selection. The upstream MIT notice below covers these tokens.
18
+
17
19
  Questionnaire's NativeChoiceKeyboard and ItemArrowNavigation Storybook interactions adapt the native choice-navigation and contextual horizontal-arrow browser tests from `packages/react/src/questionnaire/questionnaire.browser.test.tsx` at upstream commit `3d98900e9b73c45f035f8109e9d41ba6a51685e7` (https://github.com/shadcn-ui/ui). Local changes use this package's styled compositions, Storybook's play context and accessible queries, and assert unanswered-item guards, focus, selection and submitted answers. The upstream MIT notice below covers these adaptations.
18
20
 
19
21
  Sidebar adapts the official provider and styled parts, preserving custom render/ref contracts, keyboard toggling within each provider, consumer-owned persistence, and native mobile Sheet behavior. Local changes support density, cancelled toggle events, observation without controlled state, inert offcanvas panels, configured mobile widths, and centered icons with accessible collapsed labels. Separator uses Base UI's current orientation attributes, and Tooltip preserves native state callbacks.
@@ -1111,13 +1111,15 @@ function StoredThemeProvider({
1111
1111
  children,
1112
1112
  defaultTheme = "system",
1113
1113
  storageKey = "shadcn-alexgorbatchev-theme",
1114
- forcedTheme
1114
+ forcedTheme,
1115
+ preset = "devhost"
1115
1116
  }) {
1116
1117
  const { isDarkMode, ternaryDarkMode, setTernaryDarkMode } = useTernaryDarkMode({
1117
1118
  defaultValue: defaultTheme,
1118
1119
  localStorageKey: storageKey
1119
1120
  });
1120
1121
  return /* @__PURE__ */ jsx12(ThemePalette, {
1122
+ preset,
1121
1123
  theme: forcedTheme ?? ternaryDarkMode,
1122
1124
  resolvedTheme: forcedTheme ?? (isDarkMode ? "dark" : "light"),
1123
1125
  setTheme: setTernaryDarkMode,
@@ -1128,13 +1130,15 @@ function ThemePalette({
1128
1130
  children,
1129
1131
  theme,
1130
1132
  resolvedTheme,
1131
- setTheme
1133
+ setTheme,
1134
+ preset
1132
1135
  }) {
1133
1136
  useIsomorphicLayoutEffect(() => {
1134
1137
  document.documentElement.dataset.theme = resolvedTheme;
1138
+ document.documentElement.dataset.themePreset = preset;
1135
1139
  document.documentElement.style.colorScheme = resolvedTheme;
1136
- }, [resolvedTheme]);
1137
- const value = useMemo(() => ({ theme, resolvedTheme, setTheme }), [theme, resolvedTheme, setTheme]);
1140
+ }, [resolvedTheme, preset]);
1141
+ const value = useMemo(() => ({ theme, resolvedTheme, setTheme, preset }), [theme, resolvedTheme, setTheme, preset]);
1138
1142
  return /* @__PURE__ */ jsxs8(ThemeContext.Provider, {
1139
1143
  value,
1140
1144
  children: [
@@ -1147,7 +1151,8 @@ function ThemePalette({
1147
1151
  function ControlledThemeProvider({
1148
1152
  children,
1149
1153
  controlledTheme,
1150
- forcedTheme
1154
+ forcedTheme,
1155
+ preset = "devhost"
1151
1156
  }) {
1152
1157
  const isDark = useMediaQuery("(prefers-color-scheme: dark)");
1153
1158
  const { theme, setTheme } = controlledTheme;
@@ -1156,6 +1161,7 @@ function ControlledThemeProvider({
1156
1161
  theme: forcedTheme ?? theme,
1157
1162
  resolvedTheme,
1158
1163
  setTheme,
1164
+ preset,
1159
1165
  children
1160
1166
  });
1161
1167
  }
@@ -1,7 +1,8 @@
1
1
  import { type ReactElement, type ReactNode } from "react";
2
- import type { IThemeContextValue, ResolvedTheme, ThemeMode } from "../theme/types.js";
2
+ import type { IThemeContextValue, ResolvedTheme, ThemeMode, ThemePreset } from "../theme/types.js";
3
3
  export interface IThemeProviderProps {
4
4
  children: ReactNode;
5
+ preset?: ThemePreset;
5
6
  defaultTheme?: ThemeMode;
6
7
  storageKey?: string;
7
8
  forcedTheme?: ResolvedTheme;
@@ -31,7 +31,7 @@ import {
31
31
  DrawerHeader2,
32
32
  DrawerTitle2,
33
33
  DrawerDescription2
34
- } from "../../chunk-d5pabsj2.js";
34
+ } from "../../chunk-aye7r5mq.js";
35
35
  import {
36
36
  MenuPopup,
37
37
  MenuItem2,
package/dist/index.d.ts CHANGED
@@ -47,7 +47,7 @@ export { ScrollGuard } from "./components/ScrollGuard.js";
47
47
  export type { IScrollGuardProps } from "./components/ScrollGuard.js";
48
48
  export type { IThemeProviderProps } from "./components/ThemeProvider.js";
49
49
  export { useTheme } from "./hooks/useTheme.js";
50
- export type { ThemeMode, ResolvedTheme, IThemeContextValue } from "./theme/types.js";
50
+ export type { ThemeMode, ResolvedTheme, ThemePreset, IThemeContextValue } from "./theme/types.js";
51
51
  export { useComboboxAnchor } from "./hooks/useComboboxAnchor.js";
52
52
  export { cn } from "./utils/cn.js";
53
53
  export { Toggle, toggleVariants } from "./components/Toggle.js";
package/dist/index.js CHANGED
@@ -171,7 +171,7 @@ import {
171
171
  StatusTracker2,
172
172
  DashboardLayout2,
173
173
  BillingUsage2
174
- } from "./chunk-d5pabsj2.js";
174
+ } from "./chunk-aye7r5mq.js";
175
175
  import {
176
176
  Tabs2,
177
177
  tabsListVariants2,
package/dist/prototype.js CHANGED
@@ -2051,7 +2051,7 @@ var program = new Command;
2051
2051
  // package.json
2052
2052
  var package_default = {
2053
2053
  name: "@alexgorbatchev/shadcn",
2054
- version: "0.0.54",
2054
+ version: "0.0.55",
2055
2055
  description: "Sharp, monospace React components with compact and comfortable densities.",
2056
2056
  license: "MIT",
2057
2057
  repository: {
@@ -1,7 +1,9 @@
1
1
  import type { TernaryDarkMode } from "usehooks-ts";
2
2
  export type ThemeMode = TernaryDarkMode;
3
3
  export type ResolvedTheme = "light" | "dark";
4
+ export type ThemePreset = "devhost" | "shadcn";
4
5
  export interface IThemeContextValue {
6
+ preset: ThemePreset;
5
7
  theme: ThemeMode;
6
8
  resolvedTheme: ResolvedTheme;
7
9
  setTheme: (theme: ThemeMode) => void;
package/dist/theme.css CHANGED
@@ -46,16 +46,16 @@
46
46
  --color-sidebar-border: var(--sidebar-border, var(--border));
47
47
  --color-sidebar-ring: var(--sidebar-ring, var(--ring));
48
48
  --font-sans: var(--ag-font);
49
- --font-mono: var(--ag-font);
49
+ --font-mono: var(--ag-font-mono);
50
50
  --text-xs: var(--ag-text-xs);
51
51
  --text-sm: var(--ag-control-text);
52
52
  --text-base: var(--ag-text);
53
53
  --text-lg: var(--ag-heading);
54
- --radius-xs: 2px;
55
- --radius-sm: 2px;
56
- --radius-md: 4px;
57
- --radius-lg: 4px;
58
- --radius-xl: 4px;
54
+ --radius-xs: var(--ag-radius-xs);
55
+ --radius-sm: var(--ag-radius-sm);
56
+ --radius-md: var(--ag-radius-md);
57
+ --radius-lg: var(--radius);
58
+ --radius-xl: var(--ag-radius-xl);
59
59
  --spacing-control: var(--ag-control-h);
60
60
  --spacing-control-xs: calc(var(--ag-control-h) - 4px);
61
61
  --spacing-control-sm: calc(var(--ag-control-h) - 2px);
@@ -74,7 +74,13 @@
74
74
  @layer base {
75
75
  :root {
76
76
  --ag-font: "JetBrains Mono Variable", "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
77
+ --ag-font-mono:
78
+ "JetBrains Mono Variable", "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
77
79
  --radius: 4px;
80
+ --ag-radius-xs: 2px;
81
+ --ag-radius-sm: 2px;
82
+ --ag-radius-md: 4px;
83
+ --ag-radius-xl: 4px;
78
84
  --ag-text-xs: 11px;
79
85
  --ag-control-text: 12px;
80
86
  --ag-text: 14px;
@@ -205,6 +211,93 @@
205
211
  --ag-shadow: 0 6px 22px rgb(0 0 0 / 0.3);
206
212
  }
207
213
 
214
+ [data-theme-preset="shadcn"] {
215
+ --ag-font:
216
+ ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
217
+ --radius: 0.625rem;
218
+ --ag-radius-xs: calc(var(--radius) * 0.4);
219
+ --ag-radius-sm: calc(var(--radius) * 0.6);
220
+ --ag-radius-md: calc(var(--radius) * 0.8);
221
+ --ag-radius-xl: calc(var(--radius) * 1.4);
222
+ --faint-foreground: var(--muted-foreground);
223
+ --destructive-soft: color-mix(in oklab, var(--destructive) 15%, transparent);
224
+ --frame-edge: var(--border);
225
+ --frame-halo: transparent;
226
+ --terminal-background: var(--background);
227
+ --ag-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
228
+ }
229
+
230
+ [data-theme-preset="shadcn"],
231
+ [data-theme-preset="shadcn"][data-theme="dark"] {
232
+ --background: oklch(0.145 0 0);
233
+ --foreground: oklch(0.985 0 0);
234
+ --card: oklch(0.205 0 0);
235
+ --card-foreground: oklch(0.985 0 0);
236
+ --popover: oklch(0.205 0 0);
237
+ --popover-foreground: oklch(0.985 0 0);
238
+ --primary: oklch(0.922 0 0);
239
+ --primary-foreground: oklch(0.205 0 0);
240
+ --secondary: oklch(0.269 0 0);
241
+ --secondary-foreground: oklch(0.985 0 0);
242
+ --muted: oklch(0.269 0 0);
243
+ --muted-foreground: oklch(0.708 0 0);
244
+ --accent: oklch(0.269 0 0);
245
+ --accent-foreground: oklch(0.985 0 0);
246
+ --destructive: oklch(0.704 0.191 22.216);
247
+ --destructive-foreground: oklch(0.145 0 0);
248
+ --border: oklch(1 0 0 / 10%);
249
+ --input: oklch(1 0 0 / 15%);
250
+ --ring: oklch(0.556 0 0);
251
+ --chart-1: oklch(0.488 0.243 264.376);
252
+ --chart-2: oklch(0.696 0.17 162.48);
253
+ --chart-3: oklch(0.769 0.188 70.08);
254
+ --chart-4: oklch(0.627 0.265 303.9);
255
+ --chart-5: oklch(0.645 0.246 16.439);
256
+ --sidebar: oklch(0.205 0 0);
257
+ --sidebar-foreground: oklch(0.985 0 0);
258
+ --sidebar-primary: oklch(0.488 0.243 264.376);
259
+ --sidebar-primary-foreground: oklch(0.985 0 0);
260
+ --sidebar-accent: oklch(0.269 0 0);
261
+ --sidebar-accent-foreground: oklch(0.985 0 0);
262
+ --sidebar-border: oklch(1 0 0 / 10%);
263
+ --sidebar-ring: oklch(0.556 0 0);
264
+ }
265
+
266
+ [data-theme-preset="shadcn"][data-theme="light"] {
267
+ --background: oklch(1 0 0);
268
+ --foreground: oklch(0.145 0 0);
269
+ --card: oklch(1 0 0);
270
+ --card-foreground: oklch(0.145 0 0);
271
+ --popover: oklch(1 0 0);
272
+ --popover-foreground: oklch(0.145 0 0);
273
+ --primary: oklch(0.205 0 0);
274
+ --primary-foreground: oklch(0.985 0 0);
275
+ --secondary: oklch(0.97 0 0);
276
+ --secondary-foreground: oklch(0.205 0 0);
277
+ --muted: oklch(0.97 0 0);
278
+ --muted-foreground: oklch(0.556 0 0);
279
+ --accent: oklch(0.97 0 0);
280
+ --accent-foreground: oklch(0.205 0 0);
281
+ --destructive: oklch(0.577 0.245 27.325);
282
+ --destructive-foreground: oklch(1 0 0);
283
+ --border: oklch(0.922 0 0);
284
+ --input: oklch(0.922 0 0);
285
+ --ring: oklch(0.708 0 0);
286
+ --chart-1: oklch(0.646 0.222 41.116);
287
+ --chart-2: oklch(0.6 0.118 184.704);
288
+ --chart-3: oklch(0.398 0.07 227.392);
289
+ --chart-4: oklch(0.828 0.189 84.429);
290
+ --chart-5: oklch(0.769 0.188 70.08);
291
+ --sidebar: oklch(0.985 0 0);
292
+ --sidebar-foreground: oklch(0.145 0 0);
293
+ --sidebar-primary: oklch(0.205 0 0);
294
+ --sidebar-primary-foreground: oklch(0.985 0 0);
295
+ --sidebar-accent: oklch(0.97 0 0);
296
+ --sidebar-accent-foreground: oklch(0.205 0 0);
297
+ --sidebar-border: oklch(0.922 0 0);
298
+ --sidebar-ring: oklch(0.708 0 0);
299
+ }
300
+
208
301
  [data-density="comfortable"] {
209
302
  --ag-text-xs: 11px;
210
303
  --ag-control-text: 12px;
@@ -49,6 +49,14 @@ Storybook CSF excerpts. Default args and render apply unless overridden. Local h
49
49
  }
50
50
  ```
51
51
 
52
+ ### Shadcn
53
+
54
+ ```tsx
55
+ {
56
+ globals: { preset: "shadcn", theme: "system" }
57
+ }
58
+ ```
59
+
52
60
  ### ForcedLight
53
61
 
54
62
  ```tsx
package/llms/setup.md CHANGED
@@ -198,10 +198,15 @@ An independent production Vite consumer installed from the archive verifies RTL
198
198
  | `ThemeProvider.defaultTheme` | `"light" \| "dark" \| "system"` | `"system"` | Initial preference when storage has no saved value. |
199
199
  | `ThemeProvider.storageKey` | `string` | `"shadcn-alexgorbatchev-theme"` | Local storage key for the preference. |
200
200
  | `ThemeProvider.forcedTheme` | `"light" \| "dark"` | unset | Overrides the displayed palette without changing the saved preference. |
201
+ | `ThemeProvider.preset` | `"devhost" \| "shadcn"` | `"devhost"` | Document-wide design preset, independent of color mode and density. |
201
202
  | `DensityProvider.density` | `"compact" \| "comfortable"` | `"comfortable"` | Density for descendants and their portals. |
202
203
  | Component `density` | `"compact" \| "comfortable"` | inherited | Local override on styled components that expose the prop. |
203
204
 
204
- `useTheme()` returns `theme`, `resolvedTheme`, and `setTheme`. Call `setTheme("light")`, `setTheme("dark")`, or `setTheme("system")` from a component inside the provider.
205
+ `useTheme()` returns `theme`, `resolvedTheme`, `setTheme`, and `preset`. Call `setTheme("light")`, `setTheme("dark")`, or `setTheme("system")` from a component inside the provider.
206
+
207
+ Use `<ThemeProvider preset="shadcn" defaultTheme="system">` for the [default shadcn Neutral palette](https://ui.shadcn.com/docs/theming), system sans-serif text, and its rounded corner scale. The default `devhost` preset uses the package's monospace design and sharp corners. Both presets support light, dark, and system modes, including portaled content. Code retains the monospace font. Density, component composition, and package-specific status colors remain independent of the preset.
208
+
209
+ The preset is controlled by the prop; changing it updates the document without changing the saved color-mode preference. Persist that prop in your application if needed. Storybook exposes the same choice in its **Design** toolbar. For a page styled before React mounts, set `data-theme-preset="shadcn"` and `data-theme="light"` or `"dark"` on `<html>` to match the provider. The existing `theme.css` import and `@source` setup cover both presets.
205
210
 
206
211
  Override tokens after the theme imports. This example uses the existing success palette as the primary accent:
207
212
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexgorbatchev/shadcn",
3
- "version": "0.0.54",
3
+ "version": "0.0.55",
4
4
  "description": "Sharp, monospace React components with compact and comfortable densities.",
5
5
  "license": "MIT",
6
6
  "repository": {