@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.
- package/README.md +5 -3
- package/package.json +4 -4
- package/src/components/data/badge/index.tsx +1 -1
- package/src/components/data/calendar/calendar.tsx +2 -2
- package/src/components/data/stat/index.tsx +5 -5
- package/src/components/data/status/index.tsx +3 -3
- package/src/components/data/table/index.tsx +30 -11
- package/src/components/feedback/banner/index.tsx +8 -4
- package/src/components/forms/button/index.tsx +15 -5
- package/src/components/forms/button-download/index.tsx +2 -2
- package/src/components/forms/checkbox/index.tsx +1 -1
- package/src/components/forms/editable/index.tsx +19 -19
- package/src/components/forms/input/index.tsx +44 -9
- package/src/components/forms/otp/index.tsx +1 -1
- package/src/components/forms/setting-row/index.tsx +363 -0
- package/src/components/forms/switch/index.tsx +1 -1
- package/src/components/forms/tags-input/index.tsx +1 -1
- package/src/components/forms/textarea/index.tsx +3 -8
- package/src/components/index.ts +2 -0
- package/src/components/navigation/dropdown-menu/index.tsx +3 -1
- package/src/components/navigation/menu/menu-builder.tsx +7 -2
- package/src/components/navigation/stepper/index.tsx +1 -1
- package/src/components/navigation/tabs/index.tsx +3 -3
- package/src/components/overlay/dialog/index.tsx +8 -3
- package/src/components/overlay/sheet/index.tsx +1 -1
- package/src/components/overlay/tooltip/index.tsx +4 -1
- package/src/components/select/multi-select-pro-async.tsx +2 -2
- package/src/components/select/multi-select-pro.tsx +2 -2
- package/src/components/specialized/copy/index.tsx +2 -2
- package/src/components/specialized/item/index.tsx +1 -1
- package/src/hooks/router/README.md +4 -1
- package/src/lib/env.ts +6 -1
- package/src/styles/README.md +115 -22
- package/src/styles/base.css +18 -1
- package/src/styles/presets/index.ts +1 -0
- package/src/styles/presets/themes/dense.ts +11 -0
- package/src/styles/presets/themes/django-cfg.ts +43 -2
- package/src/styles/presets/themes/high-contrast.ts +25 -9
- package/src/styles/presets/themes/ios.ts +32 -0
- package/src/styles/presets/themes/macos.ts +36 -0
- package/src/styles/presets/themes/soft.ts +13 -0
- package/src/styles/presets/themes/windows.ts +34 -0
- package/src/styles/presets/types.ts +36 -2
- package/src/styles/theme/dark.css +48 -32
- package/src/styles/theme/light.css +21 -13
- package/src/styles/theme/tokens.css +23 -0
- package/src/styles/utilities/controls.css +12 -0
- package/src/styles/utilities/divider.css +23 -0
- package/src/styles/utilities.css +2 -0
- package/src/theme/ThemeSegmented.tsx +73 -0
- package/src/theme/index.ts +2 -0
- package/src/types/index.ts +0 -0
|
@@ -13,30 +13,42 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
.dark {
|
|
16
|
-
/*
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
--
|
|
22
|
-
--
|
|
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:
|
|
28
|
-
--secondary: hsl(
|
|
29
|
-
--secondary-foreground: hsl(
|
|
30
|
-
|
|
31
|
-
--muted
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
--accent
|
|
35
|
-
--
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
--
|
|
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
|
|
53
|
-
|
|
54
|
-
|
|
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(
|
|
58
|
-
--sidebar-accent-foreground: hsl(
|
|
59
|
-
--sidebar-border: hsl(
|
|
60
|
-
--sidebar-ring: hsl(
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
--chart-
|
|
92
|
-
--chart-
|
|
93
|
-
--chart-
|
|
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
|
-
/*
|
|
28
|
-
|
|
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%
|
|
33
|
-
|
|
34
|
-
--
|
|
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(
|
|
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(
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
--chart-
|
|
93
|
-
--chart-
|
|
94
|
-
--chart-
|
|
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
|
+
}
|
package/src/styles/utilities.css
CHANGED
|
@@ -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
|
+
}
|
package/src/theme/index.ts
CHANGED
|
@@ -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';
|
package/src/types/index.ts
DELETED
|
File without changes
|