@djangocfg/ui-core 2.1.426 → 2.1.428

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 (52) hide show
  1. package/README.md +5 -3
  2. package/package.json +4 -4
  3. package/src/components/data/badge/index.tsx +1 -1
  4. package/src/components/data/calendar/calendar.tsx +2 -2
  5. package/src/components/data/stat/index.tsx +5 -5
  6. package/src/components/data/status/index.tsx +3 -3
  7. package/src/components/data/table/index.tsx +30 -11
  8. package/src/components/feedback/banner/index.tsx +8 -4
  9. package/src/components/forms/button/index.tsx +15 -5
  10. package/src/components/forms/button-download/index.tsx +2 -2
  11. package/src/components/forms/checkbox/index.tsx +1 -1
  12. package/src/components/forms/editable/index.tsx +19 -19
  13. package/src/components/forms/input/index.tsx +44 -9
  14. package/src/components/forms/otp/index.tsx +1 -1
  15. package/src/components/forms/setting-row/index.tsx +363 -0
  16. package/src/components/forms/switch/index.tsx +1 -1
  17. package/src/components/forms/tags-input/index.tsx +1 -1
  18. package/src/components/forms/textarea/index.tsx +3 -8
  19. package/src/components/index.ts +2 -0
  20. package/src/components/navigation/dropdown-menu/index.tsx +3 -1
  21. package/src/components/navigation/menu/menu-builder.tsx +7 -2
  22. package/src/components/navigation/stepper/index.tsx +1 -1
  23. package/src/components/navigation/tabs/index.tsx +3 -3
  24. package/src/components/overlay/dialog/index.tsx +8 -3
  25. package/src/components/overlay/sheet/index.tsx +1 -1
  26. package/src/components/overlay/tooltip/index.tsx +4 -1
  27. package/src/components/select/multi-select-pro-async.tsx +2 -2
  28. package/src/components/select/multi-select-pro.tsx +2 -2
  29. package/src/components/specialized/copy/index.tsx +2 -2
  30. package/src/components/specialized/item/index.tsx +1 -1
  31. package/src/hooks/router/README.md +4 -1
  32. package/src/lib/env.ts +6 -1
  33. package/src/styles/README.md +115 -22
  34. package/src/styles/base.css +18 -1
  35. package/src/styles/presets/index.ts +1 -0
  36. package/src/styles/presets/themes/dense.ts +11 -0
  37. package/src/styles/presets/themes/django-cfg.ts +43 -2
  38. package/src/styles/presets/themes/high-contrast.ts +25 -9
  39. package/src/styles/presets/themes/ios.ts +32 -0
  40. package/src/styles/presets/themes/macos.ts +36 -0
  41. package/src/styles/presets/themes/soft.ts +13 -0
  42. package/src/styles/presets/themes/windows.ts +34 -0
  43. package/src/styles/presets/types.ts +36 -2
  44. package/src/styles/theme/dark.css +48 -32
  45. package/src/styles/theme/light.css +21 -13
  46. package/src/styles/theme/tokens.css +23 -0
  47. package/src/styles/utilities/controls.css +12 -0
  48. package/src/styles/utilities/divider.css +23 -0
  49. package/src/styles/utilities.css +2 -0
  50. package/src/theme/ThemeSegmented.tsx +73 -0
  51. package/src/theme/index.ts +2 -0
  52. package/src/types/index.ts +0 -0
@@ -13,30 +13,42 @@
13
13
  */
14
14
 
15
15
  .dark {
16
- /* Base colors - True black background with subtle grays */
17
- --background: hsl(0 0% 4%);
18
- --foreground: hsl(0 0% 98%);
19
- --card: hsl(0 0% 8%);
20
- --card-foreground: hsl(0 0% 98%);
21
- --popover: hsl(0 0% 12%);
22
- --popover-foreground: hsl(0 0% 98%);
16
+ /* Warm-gray surface ladder mapped from Claude's dark theme (hue ~48–60, a
17
+ * faint warm tint instead of pure neutral). The VISIBLE page background is
18
+ * Claude's bg-100 (~14.5%) — NOT near-black; card/popover lift above it so
19
+ * panels and menus read as raised. muted recesses below the page.
20
+ * page ≈ bg-100 card ≈ bg-000(18.4%) popover ≈ slightly above card */
21
+ --background: hsl(60 2.7% 14.5%);
22
+ --foreground: hsl(48 33% 97%);
23
+ --card: hsl(60 2.1% 18.4%);
24
+ --card-foreground: hsl(48 33% 97%);
25
+ --popover: hsl(48 2.5% 21%);
26
+ --popover-foreground: hsl(48 33% 97%);
23
27
  /* Exact brand: #00d9ff (same HSL as :root light primary) */
24
28
  --primary: hsl(189 100% 50%);
25
29
  /* Dark label on bright cyan — stronger contrast than white on #00d9ff */
26
30
  --primary-foreground: hsl(0 0% 9%);
27
- /* Secondary: dark elevated surface + light label (matches typical shadcn dark “secondary” role) */
28
- --secondary: hsl(0 0% 16%);
29
- --secondary-foreground: hsl(0 0% 96%);
30
- --muted: hsl(0 0% 10%);
31
- --muted-foreground: hsl(0 0% 60%);
32
- /* Cyan-tinted elevated surface */
33
- --accent: hsl(189 18% 17%);
34
- --accent-foreground: hsl(0 0% 98%);
35
- --destructive: hsl(0 84% 60%);
31
+ /* Secondary: elevated warm-gray control surface + light label */
32
+ --secondary: hsl(60 2.1% 18.4%);
33
+ --secondary-foreground: hsl(48 33% 97%);
34
+ /* Recessed surface — below the page (Claude bg-200), for input rest / chips. */
35
+ --muted: hsl(30 3.3% 11.8%);
36
+ --muted-foreground: hsl(48 5% 59%);
37
+ /* Hover/active surface (rails, menus, tabs) — a quiet warm lift above the page. */
38
+ --accent: hsl(48 3% 24%);
39
+ --accent-foreground: hsl(48 33% 97%);
40
+ --destructive: hsl(0 67% 60%);
36
41
  --destructive-foreground: hsl(0 0% 98%);
37
- --border: hsl(0 0% 15%);
38
- --input: hsl(0 0% 15%);
39
- --ring: hsl(189 100% 50%);
42
+ /* Soft warm border Claude draws hairlines from a light border at low
43
+ * contrast, so a mid warm-gray keeps lines visible but never harsh. */
44
+ --border: hsl(48 3% 28%);
45
+ /* Input surface — a notch above card so fields read as raised controls. */
46
+ --input: hsl(48 2.5% 24%);
47
+ /* Divider — hairline; slightly softer than --border so rows don't read as a
48
+ * hard rule (Claude menus/rows). */
49
+ --divider: hsl(48 3% 24%);
50
+ /* Focus ring — blue (system-accent feel), independent of the cyan brand. */
51
+ --ring: hsl(217 91% 60%);
40
52
  --shadow-card: none;
41
53
 
42
54
  /* Code surface — see light.css for the rationale. On dark we want
@@ -49,15 +61,17 @@
49
61
  --code-border: hsl(0 0% 18%);
50
62
  --code-inline: hsl(0 0% 14%);
51
63
  --code-inline-foreground: hsl(0 0% 92%);
52
- /* Sidebar Dark Theme - Darker black sidebar */
53
- --sidebar-background: hsl(0 0% 0%);
54
- --sidebar-foreground: hsl(0 0% 98%);
64
+ /* Sidebar same warm-gray family as the page (Claude has NO black sidebar
65
+ * block; rail and page share one tone). A hair darker than --background for
66
+ * subtle separation, not a hard black slab. */
67
+ --sidebar-background: hsl(30 3% 11.8%);
68
+ --sidebar-foreground: hsl(48 33% 97%);
55
69
  --sidebar-primary: hsl(189 100% 50%);
56
70
  --sidebar-primary-foreground: hsl(0 0% 9%);
57
- --sidebar-accent: hsl(189 14% 12%);
58
- --sidebar-accent-foreground: hsl(0 0% 98%);
59
- --sidebar-border: hsl(0 0% 15%);
60
- --sidebar-ring: hsl(189 100% 50%);
71
+ --sidebar-accent: hsl(48 3% 24%);
72
+ --sidebar-accent-foreground: hsl(48 33% 97%);
73
+ --sidebar-border: hsl(48 3% 28%);
74
+ --sidebar-ring: hsl(217 91% 60%);
61
75
  /* ── Status surfaces (dark) ──────────────────────────────────────
62
76
  * Dark variants: dim backgrounds (~8-12% lightness) so banners
63
77
  * don't blow out against the near-black page. Foreground raised
@@ -85,10 +99,12 @@
85
99
  /* Surface gradient dark */
86
100
  --surface-gradient: linear-gradient(to bottom, var(--background), color-mix(in oklab, var(--background) 80%, transparent));
87
101
 
88
- /* Chart colors — chart-1 aligned with brand */
89
- --chart-1: 189 100% 50%;
90
- --chart-2: 142 76% 36%;
91
- --chart-3: 262 83% 58%;
92
- --chart-4: 26 90% 57%;
93
- --chart-5: 346 77% 50%;
102
+ /* Chart colors — chart-1 aligned with brand.
103
+ * Fully-wrapped hsl() like every other token (consume via `bg-chart-N` or
104
+ * `var(--chart-N)`, never `hsl(var(--chart-N))`). */
105
+ --chart-1: hsl(189 100% 50%);
106
+ --chart-2: hsl(142 76% 36%);
107
+ --chart-3: hsl(262 83% 58%);
108
+ --chart-4: hsl(26 90% 57%);
109
+ --chart-5: hsl(346 77% 50%);
94
110
  }
@@ -24,14 +24,20 @@
24
24
  --secondary-foreground: hsl(0 0% 98%);
25
25
  --muted: hsl(0 0% 96%);
26
26
  --muted-foreground: hsl(0 0% 45%);
27
- /* Subtle cyan-tinted hover surface (not gray-only) */
28
- --accent: hsl(192 18% 94%);
27
+ /* Neutral hover/active surface quiet gray lift, no hue tint
28
+ * (Claude/macOS settings convention). */
29
+ --accent: hsl(0 0% 94%);
29
30
  --accent-foreground: hsl(0 0% 9%);
30
31
  --destructive: hsl(0 84% 60%);
31
32
  --destructive-foreground: hsl(0 0% 98%);
32
- --border: hsl(0 0% 90%);
33
- --input: hsl(0 0% 90%);
34
- --ring: hsl(192 90% 35%);
33
+ --border: hsl(0 0% 87%);
34
+ /* Input surface — faint gray fill so fields are visible on white cards. */
35
+ --input: hsl(0 0% 97%);
36
+ /* Divider — hairline between rows; slightly darker than --border so it reads
37
+ * on white cards. */
38
+ --divider: hsl(0 0% 88%);
39
+ /* Focus ring — blue (system-accent feel), independent of the cyan brand. */
40
+ --ring: hsl(217 91% 55%);
35
41
  --shadow-card: 0 1px 3px 0 rgb(0 0 0 / 0.06), 0 1px 2px -1px rgb(0 0 0 / 0.04);
36
42
 
37
43
  /* Code surface — used by markdown code fences, terminal blocks,
@@ -54,10 +60,10 @@
54
60
  --sidebar-foreground: hsl(0 0% 9%);
55
61
  --sidebar-primary: hsl(192 90% 35%);
56
62
  --sidebar-primary-foreground: hsl(0 0% 100%);
57
- --sidebar-accent: hsl(189 16% 95%);
63
+ --sidebar-accent: hsl(0 0% 95%);
58
64
  --sidebar-accent-foreground: hsl(0 0% 9%);
59
65
  --sidebar-border: hsl(0 0% 90%);
60
- --sidebar-ring: hsl(192 90% 35%);
66
+ --sidebar-ring: hsl(217 91% 55%);
61
67
  /* ── Status surfaces ─────────────────────────────────────────────
62
68
  * Each status has 4 tokens: icon/accent color, page background,
63
69
  * readable foreground text, and border ring.
@@ -86,10 +92,12 @@
86
92
  /* Surface gradient */
87
93
  --surface-gradient: linear-gradient(to bottom, var(--background), color-mix(in oklab, var(--background) 80%, transparent));
88
94
 
89
- /* Chart colors — chart-1 aligned with brand hue */
90
- --chart-1: 192 90% 35%;
91
- --chart-2: 142 76% 36%;
92
- --chart-3: 262 83% 58%;
93
- --chart-4: 26 90% 57%;
94
- --chart-5: 346 77% 50%;
95
+ /* Chart colors — chart-1 aligned with brand hue.
96
+ * Fully-wrapped hsl() like every other token (consume via `bg-chart-N` or
97
+ * `var(--chart-N)`, never `hsl(var(--chart-N))`). */
98
+ --chart-1: hsl(192 90% 35%);
99
+ --chart-2: hsl(142 76% 36%);
100
+ --chart-3: hsl(262 83% 58%);
101
+ --chart-4: hsl(26 90% 57%);
102
+ --chart-5: hsl(346 77% 50%);
95
103
  }
@@ -44,6 +44,7 @@
44
44
  --color-destructive-foreground: var(--destructive-foreground);
45
45
  --color-border: var(--border);
46
46
  --color-input: var(--input);
47
+ --color-divider: var(--divider);
47
48
  --color-ring: var(--ring);
48
49
 
49
50
  /* Status surfaces */
@@ -82,6 +83,28 @@
82
83
  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
83
84
  --color-sidebar-border: var(--sidebar-border);
84
85
  --color-sidebar-ring: var(--sidebar-ring);
86
+
87
+ /* Charts — categorical series. `--chart-N` are fully-wrapped colors in
88
+ * light/dark/preset, so this is a plain reference (NOT `hsl(var(...))`).
89
+ * Backs the `bg-chart-1` / `text-chart-2` / `border-chart-3` utilities and
90
+ * their opacity modifiers (`bg-chart-1/40`). For Recharts/shadcn `color:`
91
+ * props pass `var(--chart-N)` directly. */
92
+ --color-chart-1: var(--chart-1);
93
+ --color-chart-2: var(--chart-2);
94
+ --color-chart-3: var(--chart-3);
95
+ --color-chart-4: var(--chart-4);
96
+ --color-chart-5: var(--chart-5);
97
+
98
+ /* Typography — `font-sans` / `font-mono` utilities read `--font-sans` /
99
+ * `--font-mono` directly (those live in base.css, retinted per preset), so
100
+ * no binding is needed for them. Tailwind's text scale reads `--text-*`,
101
+ * which we bridge to the preset-overridable `--font-size-*` tokens so
102
+ * `text-xs…text-xl` follow the active preset instead of Tailwind defaults. */
103
+ --text-xs: var(--font-size-xs);
104
+ --text-sm: var(--font-size-sm);
105
+ --text-base: var(--font-size-base);
106
+ --text-lg: var(--font-size-lg);
107
+ --text-xl: var(--font-size-xl);
85
108
  }
86
109
 
87
110
  @theme {
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Control utilities
3
+ *
4
+ * Shared corner radius for interactive controls (nav items, inputs, search,
5
+ * value chips) via the `--radius-control` token, so they round consistently
6
+ * and stay themeable per preset. Plain CSS class — compiles regardless of the
7
+ * Tailwind content scan.
8
+ */
9
+
10
+ .rounded-control {
11
+ border-radius: var(--radius-control);
12
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Divider utilities
3
+ *
4
+ * Hairline separators that use the dedicated `--divider` token (lighter than
5
+ * `--border` on elevated surfaces, so rows inside cards/dialogs stay visible).
6
+ *
7
+ * Plain CSS classes — NOT JIT-scanned Tailwind utilities — so they compile
8
+ * regardless of which package's source files the Tailwind content scan covers.
9
+ * Use these for settings rows, list items, and any inset divider.
10
+ */
11
+
12
+ .divider-b {
13
+ border-bottom: 1px solid var(--divider);
14
+ }
15
+
16
+ .divider-t {
17
+ border-top: 1px solid var(--divider);
18
+ }
19
+
20
+ /* Suppress the divider on the last child in a list of `.divider-b` rows. */
21
+ .divider-b:last-child {
22
+ border-bottom: 0;
23
+ }
@@ -7,6 +7,8 @@
7
7
  */
8
8
 
9
9
  @import './utilities/display.css';
10
+ @import './utilities/divider.css';
11
+ @import './utilities/controls.css';
10
12
  @import './utilities/step.css';
11
13
  @import './utilities/animations.css';
12
14
  @import './utilities/glass.css';
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * ThemeSegmented — a 3-way System / Light / Dark segmented control
5
+ * (Claude / macOS settings style), as opposed to the binary `ThemeToggle`.
6
+ *
7
+ * Reads/writes the full theme via `useThemeContext` (`theme` + `setTheme`,
8
+ * which support `'system'`). Must be used within ThemeProvider. SSR-safe:
9
+ * renders a stable placeholder until mounted to avoid hydration mismatch.
10
+ */
11
+
12
+ import { Monitor, Moon, Sun } from 'lucide-react';
13
+ import { useEffect, useState } from 'react';
14
+
15
+ import { cn } from '../lib/utils';
16
+ import { useThemeContext, type Theme } from './ThemeProvider';
17
+
18
+ export interface ThemeSegmentedProps {
19
+ className?: string;
20
+ /** Compact paddings for tight rows. */
21
+ size?: 'default' | 'compact';
22
+ }
23
+
24
+ const OPTIONS: Array<{ value: Theme; icon: React.ComponentType<{ className?: string }>; label: string }> = [
25
+ { value: 'system', icon: Monitor, label: 'System' },
26
+ { value: 'light', icon: Sun, label: 'Light' },
27
+ { value: 'dark', icon: Moon, label: 'Dark' },
28
+ ];
29
+
30
+ export function ThemeSegmented({ className, size = 'default' }: ThemeSegmentedProps) {
31
+ const { theme, setTheme } = useThemeContext();
32
+ const [mounted, setMounted] = useState(false);
33
+ useEffect(() => setMounted(true), []);
34
+
35
+ const active: Theme = mounted ? (theme ?? 'system') : 'system';
36
+ const btn = size === 'compact' ? 'h-7 w-7' : 'h-8 w-8';
37
+ const icon = size === 'compact' ? 'size-3.5' : 'size-4';
38
+
39
+ return (
40
+ <div
41
+ role="radiogroup"
42
+ aria-label="Theme"
43
+ className={cn(
44
+ 'rounded-control inline-flex items-center gap-0.5 border border-border bg-muted p-0.5',
45
+ className,
46
+ )}
47
+ >
48
+ {OPTIONS.map(({ value, icon: Icon, label }) => {
49
+ const selected = active === value;
50
+ return (
51
+ <button
52
+ key={value}
53
+ type="button"
54
+ role="radio"
55
+ aria-checked={selected}
56
+ aria-label={label}
57
+ title={label}
58
+ onClick={() => setTheme(value)}
59
+ className={cn(
60
+ 'inline-flex items-center justify-center rounded-[calc(var(--radius-control)-0.25rem)] transition-colors',
61
+ btn,
62
+ selected
63
+ ? 'bg-background text-foreground shadow-sm'
64
+ : 'text-muted-foreground hover:text-foreground',
65
+ )}
66
+ >
67
+ <Icon className={icon} />
68
+ </button>
69
+ );
70
+ })}
71
+ </div>
72
+ );
73
+ }
@@ -4,6 +4,8 @@ export { ThemeProvider, useThemeContext } from './ThemeProvider';
4
4
  export type { Theme, ThemeProviderProps } from './ThemeProvider';
5
5
  export { ThemeToggle } from './ThemeToggle';
6
6
  export type { ThemeToggleProps, ThemeLockBehavior } from './ThemeToggle';
7
+ export { ThemeSegmented } from './ThemeSegmented';
8
+ export type { ThemeSegmentedProps } from './ThemeSegmented';
7
9
  export { ForceTheme } from './ForceTheme';
8
10
  export { ThemeOverride, resolveForcedTheme } from './ThemeOverride';
9
11
  export type { ThemeOverrideRule, ThemeOverrideProps, ForcedTheme } from './ThemeOverride';
File without changes