Design Tokens

The fundamental visual tokens of the Gunjo design system.

トークンを使う見本

色・字の大きさ・余白・角丸・影・動きのトークンだけで1画面を組んだ例です。色の名前を差し替えるだけで意味が変わり、値は書き込みません。そのまま貼り付けて動きます。

import { Badge, Button, cn } from "@gunjo/ui";

const TONES = {
    info: "border-transparent contrast-more:border-info-border forced-colors:border-[CanvasText] bg-info-subtle text-info-subtle-foreground",
    success: "border-transparent contrast-more:border-success-border forced-colors:border-[CanvasText] bg-success-subtle text-success-subtle-foreground",
    warning: "border-transparent contrast-more:border-warning-border forced-colors:border-[CanvasText] bg-warning-subtle text-warning-subtle-foreground",
};

const NOTICES = [
    {
        id: "n1",
        tone: "info",
        title: "メンテナンスの予定",
        body: "日曜の02:00から04:00まで。",
    },
    {
        id: "n2",
        tone: "success",
        title: "バックアップが終わりました",
        body: "1,204件を書き込みました。",
    },
    {
        id: "n3",
        tone: "warning",
        title: "保存容量が残りわずか",
        body: "契約分の92パーセントを使っています。",
    },
];

const TYPE_SCALE = [
    { id: "s1", className: "text-2xl font-bold", label: "text-2xl / font-bold" },
    { id: "s2", className: "text-base font-medium", label: "text-base / font-medium" },
    { id: "s3", className: "text-sm text-muted-foreground", label: "text-sm / muted" },
];

export function TokenUsage() {
    return (
        <div className="space-y-6">
            <div className="grid gap-3 sm:grid-cols-3">
                {NOTICES.map((notice) => (
                    <div
                        key={notice.id}
                        className={cn(
                            "rounded-lg border p-4 shadow-sm",
                            "transition-colors duration-200 ease-out",
                            TONES[notice.tone as keyof typeof TONES]
                        )}
                    >
                        <p className="text-sm font-semibold">{notice.title}</p>
                        <p className="text-sm">{notice.body}</p>
                    </div>
                ))}
            </div>

            <div className="rounded-md border border-transparent contrast-more:border-border forced-colors:border-[CanvasText] bg-card p-4 text-card-foreground">
                {TYPE_SCALE.map((step) => (
                    <p key={step.id} className={step.className}>
                        {step.label}
                    </p>
                ))}
            </div>

            <div className="flex flex-wrap items-center gap-3 rounded-lg bg-muted p-4">
                <Button>同じ primary トークンを使っています</Button>
                <Badge variant="secondary">secondary</Badge>
                <span
                    className="rounded-md bg-background px-3 py-2 text-sm"
                    style={{ boxShadow: "var(--shadow-md)" }}
                >
                    変数を直接使う場合: var(--shadow-md)
                </span>
            </div>
        </div>
    );
}

設計の判断

トークンは1つの画面のために選ぶ値ではなく、繰り返し使うために先に決めておく値です。何をトークンにして、何を画面ごとの判断に残すかの考え方は、UIXHERO の「ルール化して再利用する (Design System Thinking)」にまとめています。

いつ・なぜ使うか(UIXHERO)

「いつ・なぜ使うか」の判断は、姉妹サイト UIXHERO の記事で解説しています。