Account settings card
Setup
npx shadcn@latest add card switch label separator
npm install next-themes
Wrap your app in the theme provider once (for example in app/layout.tsx). Add suppressHydrationWarning to <html>.
import { ThemeProvider } from "next-themes"
<ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>
{children}
</ThemeProvider>
components/account-settings-card.tsx
"use client"
import * as React from "react"
import { useTheme } from "next-themes"
import { Moon, Sun, Bell } from "lucide-react"
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { Label } from "@/components/ui/label"
import { Separator } from "@/components/ui/separator"
import { Switch } from "@/components/ui/switch"
export function AccountSettingsCard() {
const { resolvedTheme, setTheme } = useTheme()
const [mounted, setMounted] = React.useState(false)
const [notifications, setNotifications] = React.useState(true)
// The theme is unknown on the server, so wait for mount to avoid a hydration mismatch.
React.useEffect(() => setMounted(true), [])
const isDark = mounted && resolvedTheme === "dark"
return (
<Card className="mx-auto w-full max-w-sm shadow-sm transition-shadow hover:shadow-md sm:max-w-md lg:max-w-lg">
<CardHeader className="space-y-1 p-4 sm:p-6">
<CardTitle className="text-xl font-semibold tracking-tight sm:text-2xl">
Account settings
</CardTitle>
<CardDescription>Manage your appearance and alerts.</CardDescription>
</CardHeader>
<CardContent className="space-y-4 p-4 pt-0 sm:p-6 sm:pt-0">
<Separator />
{/* Dark mode */}
<div className="flex items-center justify-between gap-4">
<div className="flex items-start gap-3">
<div className="rounded-md bg-muted p-2 text-muted-foreground">
{isDark ? <Moon className="size-4" /> : <Sun className="size-4" />}
</div>
<div className="space-y-0.5">
<Label htmlFor="dark-mode" className="text-sm font-medium">
Dark mode
</Label>
<p className="text-sm text-muted-foreground">
Switch between light and dark themes.
</p>
</div>
</div>
<Switch
id="dark-mode"
checked={isDark}
disabled={!mounted}
onCheckedChange={(checked) => setTheme(checked ? "dark" : "light")}
/>
</div>
<Separator />
{/* Notifications */}
<div className="flex items-center justify-between gap-4">
<div className="flex items-start gap-3">
<div className="rounded-md bg-muted p-2 text-muted-foreground">
<Bell className="size-4" />
</div>
<div className="space-y-0.5">
<Label htmlFor="notifications" className="text-sm font-medium">
Notifications
</Label>
<p className="text-sm text-muted-foreground">
Get email updates about account activity.
</p>
</div>
</div>
<Switch
id="notifications"
checked={notifications}
onCheckedChange={setNotifications}
/>
</div>
</CardContent>
</Card>
)
}
Key utility classes
Responsive sizing
w-full max-w-sm sm:max-w-md lg:max-w-lg mx-auto: the card fills narrow screens, then caps its width at each breakpoint.mx-autocenters it. The styles are mobile-first, so the unprefixed classes apply to phones andsm:/lg:layer on top.p-4 sm:p-6: tighter padding on phones, roomier from 640px up.pt-0 sm:pt-0stopsCardContent's default top padding from stacking on the header's bottom padding.text-xl sm:text-2xl: the title scales up with the viewport.
Row layout
flex items-center justify-between gap-4: the label block sits on the left and the switch is pushed to the right edge.gap-4keeps long text from touching the switch.flex items-start gap-3: the icon aligns with the top of the two-line label and description.space-y-0.5/space-y-4: vertical rhythm between children, with no margins on individual elements.
Theme-aware colors
bg-muted,text-muted-foreground: these are shadcn semantic tokens backed by CSS variables, which.darkredefines. The card therefore re-themes without anydark:prefixes. Reach fordark:only for one-off overrides.rounded-md p-2: a small tinted square behind each icon.size-4: shorthand forw-4 h-4on the icons (Tailwind 3.4+).
Polish
shadow-sm hover:shadow-md transition-shadow: a subtle lift on hover, animating only the shadow.tracking-tight font-semibold: tighter, bolder heading text.
Accessibility and behavior notes
- Each
Label htmlFormatches itsSwitch id, so clicking the text toggles the switch. Radix'sSwitchsuppliesrole="switch",aria-checked, Space-key toggling and focus rings. resolvedThemefollows the OS preference when the theme issystem. The first toggle then pins an explicitlightordark.- The
notificationsstate is local. ReplacesetNotificationswith a call to your API or form action to persist it.
I haven't run this, since there's no project scaffold in the working directory. If you'd like, I can write it into a Vite or Next app here and check it in the browser.
Real run in an isolated folder with only this skill installed. Only the Skill and Read tools were enabled; the model answered from SKILL.md without opening the reference files, and no bundled script was run.
What it does
Teaches the model how to build interfaces on the shadcn/ui (Radix UI + Tailwind CSS) stack: setting up components, composing forms, dialogs, tables and navigation, writing mobile-first responsive layouts, adding dark mode and theming, and customizing Tailwind (the @theme directive, custom utilities, layers). A reference file covers a canvas-based approach to posters and visual designs.
How it works
SKILL.mdgives the stack overview, quick start (npx shadcn@latest init,add), common patterns and links to reference files.- The model opens the matching reference on demand: component catalog, theming, accessibility, Tailwind utilities, responsive design, customization or canvas design.
- Two optional helper scripts: one adds shadcn components through
npx, the other generates atailwind.config.jswith custom colors and fonts.
Good for
Building or restyling React, Next.js, Vite, Remix or Astro interfaces, adding accessible components, implementing dark mode and design tokens.
Contains two Python helper scripts. `shadcn_add.py` runs `npx shadcn@<version> add ...` in the project directory you point it at: this downloads from npm (network access) and writes component files into your project. It refuses to reinstall components that already exist unless you pass `--overwrite`, and it supports `--dry-run`. `tailwind_config_gen.py` writes a Tailwind config file and refuses to create or replace one when another `tailwind.config.*` exists unless you pass `--force`. Commit your work first and review the diff before keeping generated files. No account or key is needed. Not included in this listing: the bundled canvas font files (so the optional canvas-design approach falls back to your own fonts) and the test files.