ホーム / Skills / Web・UIデザイン / UI Styling(shadcn/ui + Tailwind)
Web・UIデザイン

UI Styling(shadcn/ui + Tailwind)

claudekitMITSkill の言語: 英語
ライセンス確認済みスクリプトを含む中リスク
デモ実行記録 · claude-sonnet-5-5 · 2026年10月
Using the ui-styling skill, build a responsive "Account settings" card with shadcn/ui and Tailwind that has a dark-mode toggle and a notifications switch. Show the component code and explain the key utility classes.
Skill: ui-styling

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-auto centers it. The styles are mobile-first, so the unprefixed classes apply to phones and sm:/lg: layer on top.
  • p-4 sm:p-6: tighter padding on phones, roomier from 640px up. pt-0 sm:pt-0 stops CardContent'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-4 keeps 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 .dark redefines. The card therefore re-themes without any dark: prefixes. Reach for dark: only for one-off overrides.
  • rounded-md p-2: a small tinted square behind each icon.
  • size-4: shorthand for w-4 h-4 on 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 htmlFor matches its Switch id, so clicking the text toggles the switch. Radix's Switch supplies role="switch", aria-checked, Space-key toggling and focus rings.
  • resolvedTheme follows the OS preference when the theme is system. The first toggle then pins an explicit light or dark.
  • The notifications state is local. Replace setNotifications with 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.

できること

shadcn/ui(Radix UI + Tailwind CSS)のスタックで UI を作る方法をモデルに教えます。コンポーネントの導入、フォーム・ダイアログ・テーブル・ナビゲーションの組み立て、モバイルファーストのレスポンシブレイアウト、ダークモードとテーマ、Tailwind のカスタマイズ(@theme ディレクティブ、独自ユーティリティ、レイヤー)。キャンバスを使ったポスターやビジュアルデザインの考え方をまとめた参考ファイルもあります。

動き方

  1. SKILL.md にスタックの概要、クイックスタート(npx shadcn@latest init、add)、よくあるパターン、参考ファイルへのリンクがあります。
  2. モデルは必要に応じて該当の参考ファイル(コンポーネント一覧、テーマ、アクセシビリティ、Tailwind ユーティリティ、レスポンシブ、カスタマイズ、キャンバスデザイン)を開きます。
  3. 任意のヘルパースクリプトが 2 つあります。npx 経由で shadcn コンポーネントを追加するものと、独自の色やフォントを含む tailwind.config.js を生成するものです。

向いている場面

React、Next.js、Vite、Remix、Astro の UI 構築や刷新、アクセシブルなコンポーネントの追加、ダークモードとデザイントークンの実装。

補足とリスク

Python のヘルパースクリプトが 2 つ含まれます。`shadcn_add.py` は指定したプロジェクトディレクトリで `npx shadcn@<バージョン> add ...` を実行します。npm からのダウンロード(ネットワーク接続)が発生し、コンポーネントファイルがプロジェクトに書き込まれます。既存のコンポーネントは `--overwrite` を付けない限り再インストールされず、`--dry-run` での確認もできます。`tailwind_config_gen.py` は Tailwind の設定ファイルを書き出し、他の `tailwind.config.*` が既にある場合は `--force` を付けない限り作成・置換を拒否します。実行前に作業内容をコミットし、生成されたファイルは差分を確認してから残してください。アカウントやキーは不要です。このサイトの掲載版には、同梱のキャンバス用フォントファイル(任意のキャンバスデザインでは手元のフォントを使うことになります)とテストファイルを含めていません。