Skip to content

Commit f9d5538

Browse files
abdoutclaude
andcommitted
feat: replace CardsDemo with shadcn/ui RootComponents grid
- Add shadcn/ui v4 primitives: field, button-group, input-group, empty, spinner, item - Create 16 interactive demo components matching shadcn/ui homepage - Update globals.css with exact shadcn/ui theme variables and utilities - Add selection colors, destructive-foreground, and 3xl/4xl breakpoints - Update container-wrapper, section-soft utilities to match shadcn exactly Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 8ccab0f commit f9d5538

29 files changed

Lines changed: 2156 additions & 53 deletions

.source/index.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/app/globals.css

Lines changed: 77 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -20,51 +20,61 @@
2020

2121
@custom-variant dark (&:is(.dark *));
2222

23+
@custom-variant fixed (&:is(.layout-fixed *));
24+
2325
@theme inline {
24-
--color-background: var(--background);
25-
--color-foreground: var(--foreground);
26+
--breakpoint-3xl: 1600px;
27+
--breakpoint-4xl: 2000px;
2628
--font-sans: var(--font-sans);
2729
--font-mono: var(--font-mono);
2830
--font-rubik: var(--font-rubik);
29-
--color-sidebar-ring: var(--sidebar-ring);
30-
--color-sidebar-border: var(--sidebar-border);
31-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
32-
--color-sidebar-accent: var(--sidebar-accent);
33-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
34-
--color-sidebar-primary: var(--sidebar-primary);
35-
--color-sidebar-foreground: var(--sidebar-foreground);
36-
--color-sidebar: var(--sidebar);
37-
--color-chart-5: var(--chart-5);
38-
--color-chart-4: var(--chart-4);
39-
--color-chart-3: var(--chart-3);
40-
--color-chart-2: var(--chart-2);
41-
--color-chart-1: var(--chart-1);
42-
--color-ring: var(--ring);
43-
--color-input: var(--input);
44-
--color-border: var(--border);
45-
--color-destructive: var(--destructive);
46-
--color-accent-foreground: var(--accent-foreground);
47-
--color-accent: var(--accent);
48-
--color-muted-foreground: var(--muted-foreground);
49-
--color-muted: var(--muted);
50-
--color-secondary-foreground: var(--secondary-foreground);
51-
--color-secondary: var(--secondary);
52-
--color-primary-foreground: var(--primary-foreground);
53-
--color-primary: var(--primary);
54-
--color-popover-foreground: var(--popover-foreground);
55-
--color-popover: var(--popover);
56-
--color-card-foreground: var(--card-foreground);
31+
--radius-sm: calc(var(--radius) - 4px);
32+
--radius-md: calc(var(--radius) - 2px);
33+
--radius-lg: var(--radius);
34+
--radius-xl: calc(var(--radius) + 4px);
35+
--radius-2xl: calc(var(--radius) + 8px);
36+
--radius-3xl: calc(var(--radius) + 12px);
37+
--radius-4xl: calc(var(--radius) + 16px);
38+
--color-background: var(--background);
39+
--color-foreground: var(--foreground);
5740
--color-card: var(--card);
41+
--color-card-foreground: var(--card-foreground);
42+
--color-popover: var(--popover);
43+
--color-popover-foreground: var(--popover-foreground);
44+
--color-primary: var(--primary);
45+
--color-primary-foreground: var(--primary-foreground);
46+
--color-secondary: var(--secondary);
47+
--color-secondary-foreground: var(--secondary-foreground);
48+
--color-muted: var(--muted);
49+
--color-muted-foreground: var(--muted-foreground);
50+
--color-accent: var(--accent);
51+
--color-accent-foreground: var(--accent-foreground);
52+
--color-destructive: var(--destructive);
53+
--color-destructive-foreground: var(--destructive-foreground);
54+
--color-border: var(--border);
55+
--color-input: var(--input);
56+
--color-ring: var(--ring);
57+
--color-chart-1: var(--chart-1);
58+
--color-chart-2: var(--chart-2);
59+
--color-chart-3: var(--chart-3);
60+
--color-chart-4: var(--chart-4);
61+
--color-chart-5: var(--chart-5);
62+
--color-sidebar: var(--sidebar);
63+
--color-sidebar-foreground: var(--sidebar-foreground);
64+
--color-sidebar-primary: var(--sidebar-primary);
65+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
66+
--color-sidebar-accent: var(--sidebar-accent);
67+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
68+
--color-sidebar-border: var(--sidebar-border);
69+
--color-sidebar-ring: var(--sidebar-ring);
5870
--color-surface: var(--surface);
5971
--color-surface-foreground: var(--surface-foreground);
6072
--color-code: var(--code);
6173
--color-code-foreground: var(--code-foreground);
6274
--color-code-highlight: var(--code-highlight);
6375
--color-code-number: var(--code-number);
64-
--radius-sm: calc(var(--radius) - 4px);
65-
--radius-md: calc(var(--radius) - 2px);
66-
--radius-lg: var(--radius);
67-
--radius-xl: calc(var(--radius) + 4px);
76+
--color-selection: var(--selection);
77+
--color-selection-foreground: var(--selection-foreground);
6878
}
6979

7080
:root {
@@ -107,6 +117,9 @@
107117
--code-foreground: var(--surface-foreground);
108118
--code-highlight: oklch(0.96 0 0);
109119
--code-number: oklch(0.56 0 0);
120+
--destructive-foreground: oklch(0.97 0.01 17);
121+
--selection: oklch(0.145 0 0);
122+
--selection-foreground: oklch(1 0 0);
110123
}
111124

112125
.dark {
@@ -122,9 +135,10 @@
122135
--secondary-foreground: oklch(0.985 0 0);
123136
--muted: oklch(0.269 0 0);
124137
--muted-foreground: oklch(0.708 0 0);
125-
--accent: oklch(0.269 0 0);
138+
--accent: oklch(0.371 0 0);
126139
--accent-foreground: oklch(0.985 0 0);
127140
--destructive: oklch(0.704 0.191 22.216);
141+
--destructive-foreground: oklch(0.58 0.22 27);
128142
--border: oklch(1 0 0 / 10%);
129143
--input: oklch(1 0 0 / 15%);
130144
--ring: oklch(0.556 0 0);
@@ -140,19 +154,24 @@
140154
--sidebar-accent: oklch(0.269 0 0);
141155
--sidebar-accent-foreground: oklch(0.985 0 0);
142156
--sidebar-border: oklch(1 0 0 / 10%);
143-
--sidebar-ring: oklch(0.556 0 0);
157+
--sidebar-ring: oklch(0.439 0 0);
144158
--surface: oklch(0.2 0 0);
145159
--surface-foreground: oklch(0.708 0 0);
146160
--code: var(--surface);
147161
--code-foreground: var(--surface-foreground);
148162
--code-highlight: oklch(0.27 0 0);
149163
--code-number: oklch(0.72 0 0);
164+
--selection: oklch(0.922 0 0);
165+
--selection-foreground: oklch(0.205 0 0);
150166
}
151167

152168
@layer base {
153169
* {
154170
@apply border-border outline-ring/50;
155171
}
172+
::selection {
173+
@apply bg-selection text-selection-foreground;
174+
}
156175
html {
157176
@apply bg-background text-foreground;
158177
height: -webkit-fill-available;
@@ -380,30 +399,24 @@
380399
}
381400

382401
/* v4 utilities - shadcn/ui style */
383-
@utility extend-touch-target {
384-
@media (pointer: coarse) {
385-
@apply relative touch-manipulation after:absolute after:-inset-2;
386-
}
387-
}
388-
389402
@utility border-grid {
390403
@apply border-border/50 dark:border-border;
391404
}
392405

393406
@utility section-soft {
394-
@apply from-background to-surface/40 dark:bg-background bg-gradient-to-b;
407+
@apply from-background to-surface/40 dark:bg-background 3xl:fixed:bg-none bg-gradient-to-b;
395408
}
396409

397410
@utility theme-container {
398411
@apply font-sans;
399412
}
400413

401414
@utility container-wrapper {
402-
@apply mx-auto w-full px-2;
415+
@apply 3xl:fixed:max-w-[calc(var(--breakpoint-2xl)+2rem)] mx-auto w-full px-2;
403416
}
404417

405418
@utility container {
406-
@apply mx-auto max-w-[1400px] px-4 lg:px-8;
419+
@apply 3xl:max-w-screen-2xl mx-auto max-w-[1400px] px-4 lg:px-8;
407420
}
408421

409422
@utility no-scrollbar {
@@ -414,3 +427,22 @@
414427
display: none;
415428
}
416429
}
430+
431+
@utility border-ghost {
432+
@apply after:border-border relative after:absolute after:inset-0 after:border after:mix-blend-darken dark:after:mix-blend-lighten;
433+
}
434+
435+
@utility step {
436+
counter-increment: step;
437+
438+
&:before {
439+
@apply border-background bg-muted mr-2 inline-flex size-6 items-center justify-center rounded-full text-center -indent-px font-mono text-sm font-medium md:absolute md:mt-[-4px] md:ml-[-50px] md:size-9 md:border-4;
440+
content: counter(step);
441+
}
442+
}
443+
444+
@utility extend-touch-target {
445+
@media (pointer: coarse) {
446+
@apply relative touch-manipulation after:absolute after:-inset-2;
447+
}
448+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import { Button } from "@/components/ui/button"
5+
import {
6+
Field,
7+
FieldDescription,
8+
FieldGroup,
9+
FieldLabel,
10+
FieldTitle,
11+
} from "@/components/ui/field"
12+
import { Input } from "@/components/ui/input"
13+
import { Label } from "@/components/ui/label"
14+
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
15+
import { Switch } from "@/components/ui/switch"
16+
import { MinusIcon, PlusIcon } from "lucide-react"
17+
18+
export function AppearanceSettings() {
19+
const [gpuCount, setGpuCount] = React.useState(8)
20+
21+
const handleGpuChange = (e: React.ChangeEvent<HTMLInputElement>) => {
22+
const value = parseInt(e.target.value, 10)
23+
if (!isNaN(value) && value >= 1 && value <= 99) {
24+
setGpuCount(value)
25+
}
26+
}
27+
28+
const handleGpuIncrement = (increment: number) => {
29+
setGpuCount((prev) => Math.min(99, Math.max(1, prev + increment)))
30+
}
31+
32+
return (
33+
<FieldGroup>
34+
<Field>
35+
<FieldTitle>Compute Environment</FieldTitle>
36+
<FieldDescription>
37+
Choose the environment for your compute resources.
38+
</FieldDescription>
39+
<RadioGroup defaultValue="kubernetes" className="mt-2 gap-3">
40+
<div className="flex items-start gap-2">
41+
<RadioGroupItem value="kubernetes" id="kubernetes" />
42+
<div className="grid gap-0.5">
43+
<Label htmlFor="kubernetes" className="font-medium">
44+
Kubernetes
45+
</Label>
46+
<p className="text-muted-foreground text-sm">
47+
Container orchestration platform.
48+
</p>
49+
</div>
50+
</div>
51+
<div className="flex items-start gap-2">
52+
<RadioGroupItem value="vm" id="vm" />
53+
<div className="grid gap-0.5">
54+
<Label htmlFor="vm" className="font-medium">
55+
Virtual Machine
56+
</Label>
57+
<p className="text-muted-foreground text-sm">
58+
Traditional VM-based infrastructure.
59+
</p>
60+
</div>
61+
</div>
62+
</RadioGroup>
63+
</Field>
64+
<Field>
65+
<FieldTitle>GPU Configuration</FieldTitle>
66+
<FieldDescription>
67+
Set the number of GPUs for your workload.
68+
</FieldDescription>
69+
<div className="mt-2 flex items-center gap-2">
70+
<Button
71+
variant="outline"
72+
size="icon-sm"
73+
onClick={() => handleGpuIncrement(-1)}
74+
disabled={gpuCount <= 1}
75+
aria-label="Decrease GPU count"
76+
>
77+
<MinusIcon />
78+
</Button>
79+
<Input
80+
type="number"
81+
value={gpuCount}
82+
onChange={handleGpuChange}
83+
className="w-16 text-center"
84+
min={1}
85+
max={99}
86+
/>
87+
<Button
88+
variant="outline"
89+
size="icon-sm"
90+
onClick={() => handleGpuIncrement(1)}
91+
disabled={gpuCount >= 99}
92+
aria-label="Increase GPU count"
93+
>
94+
<PlusIcon />
95+
</Button>
96+
</div>
97+
</Field>
98+
<Field orientation="horizontal">
99+
<FieldLabel htmlFor="wallpaper-tinting" className="flex-1">
100+
<FieldTitle>Wallpaper Tinting</FieldTitle>
101+
<FieldDescription>
102+
Allow wallpaper tinting in windows.
103+
</FieldDescription>
104+
</FieldLabel>
105+
<Switch id="wallpaper-tinting" />
106+
</Field>
107+
</FieldGroup>
108+
)
109+
}

0 commit comments

Comments
 (0)