Use Cases

Radix UI with Claude Code

Learn about radix ui using Claude Code. Practical tips and code examples included.

Radix UIでアクセシブルなUIを構築する

Radix UIはアクセシビリティに優れたヘッドレスUIコンポーネントライブラリです。スタイルを持たないため、自由にデザインを適用でき、WAI-ARIAパターンに準拠したインタラクションが自動で実装されます。Claude Codeはコンポーネントの組み立てからスタイリングまで一貫してサポートします。

ダイアログ(モーダル)の実装

Claude Codeにアクセシブルなモーダルを依頼しましょう。

> Radix UIのDialogで確認モーダルを作って。
> Tailwind CSSでスタイリング、アニメーション付きで。
import * as Dialog from "@radix-ui/react-dialog";

interface ConfirmDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  title: string;
  description: string;
  onConfirm: () => void;
  confirmLabel?: string;
  variant?: "danger" | "default";
}

function ConfirmDialog({
  open,
  onOpenChange,
  title,
  description,
  onConfirm,
  confirmLabel = "確認",
  variant = "default",
}: ConfirmDialogProps) {
  return (
    <Dialog.Root open={open} onOpenChange={onOpenChange}>
      <Dialog.Portal>
        <Dialog.Overlay className="fixed inset-0 bg-black/50 data-[state=open]:animate-fadeIn" />
        <Dialog.Content className="fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 bg-white rounded-lg p-6 w-full max-w-md shadow-xl data-[state=open]:animate-slideUp">
          <Dialog.Title className="text-lg font-semibold">
            {title}
          </Dialog.Title>
          <Dialog.Description className="mt-2 text-gray-600">
            {description}
          </Dialog.Description>

          <div className="mt-6 flex justify-end gap-3">
            <Dialog.Close asChild>
              <button className="px-4 py-2 rounded bg-gray-100 hover:bg-gray-200">
                キャンセル
              </button>
            </Dialog.Close>
            <button
              onClick={() => {
                onConfirm();
                onOpenChange(false);
              }}
              className={`px-4 py-2 rounded text-white ${
                variant === "danger"
                  ? "bg-red-500 hover:bg-red-600"
                  : "bg-blue-500 hover:bg-blue-600"
              }`}
            >
              {confirmLabel}
            </button>
          </div>

          <Dialog.Close asChild>
            <button
              className="absolute top-4 right-4 text-gray-400 hover:text-gray-600"
              aria-label="Close"
            >

            </button>
          </Dialog.Close>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  );
}

ドロップダウンメニュー

キーボードナビゲーション完備のドロップダウンです。

import * as DropdownMenu from "@radix-ui/react-dropdown-menu";

function UserMenu({ user }: { user: User }) {
  return (
    <DropdownMenu.Root>
      <DropdownMenu.Trigger asChild>
        <button className="flex items-center gap-2 p-2 rounded-full hover:bg-gray-100">
          <img
            src={user.avatar}
            alt={user.name}
            className="w-8 h-8 rounded-full"
          />
          <span>{user.name}</span>
        </button>
      </DropdownMenu.Trigger>

      <DropdownMenu.Portal>
        <DropdownMenu.Content
          className="min-w-[200px] bg-white rounded-lg shadow-lg border p-1"
          sideOffset={5}
          align="end"
        >
          <DropdownMenu.Label className="px-3 py-2 text-sm text-gray-500">
            {user.email}
          </DropdownMenu.Label>
          <DropdownMenu.Separator className="h-px bg-gray-200 my-1" />

          <DropdownMenu.Item className="px-3 py-2 text-sm rounded cursor-pointer hover:bg-blue-50 hover:text-blue-600 outline-none">
            プロフィール
          </DropdownMenu.Item>
          <DropdownMenu.Item className="px-3 py-2 text-sm rounded cursor-pointer hover:bg-blue-50 hover:text-blue-600 outline-none">
            設定
          </DropdownMenu.Item>

          <DropdownMenu.Sub>
            <DropdownMenu.SubTrigger className="px-3 py-2 text-sm rounded cursor-pointer hover:bg-blue-50 outline-none flex justify-between">
              テーマ
              <span>▸</span>
            </DropdownMenu.SubTrigger>
            <DropdownMenu.Portal>
              <DropdownMenu.SubContent className="min-w-[150px] bg-white rounded-lg shadow-lg border p-1">
                <DropdownMenu.RadioGroup value="light">
                  <DropdownMenu.RadioItem value="light" className="px-3 py-2 text-sm rounded hover:bg-blue-50 outline-none">
                    ライト
                  </DropdownMenu.RadioItem>
                  <DropdownMenu.RadioItem value="dark" className="px-3 py-2 text-sm rounded hover:bg-blue-50 outline-none">
                    ダーク
                  </DropdownMenu.RadioItem>
                  <DropdownMenu.RadioItem value="system" className="px-3 py-2 text-sm rounded hover:bg-blue-50 outline-none">
                    システム
                  </DropdownMenu.RadioItem>
                </DropdownMenu.RadioGroup>
              </DropdownMenu.SubContent>
            </DropdownMenu.Portal>
          </DropdownMenu.Sub>

          <DropdownMenu.Separator className="h-px bg-gray-200 my-1" />
          <DropdownMenu.Item className="px-3 py-2 text-sm rounded cursor-pointer hover:bg-red-50 text-red-600 outline-none">
            ログアウト
          </DropdownMenu.Item>
        </DropdownMenu.Content>
      </DropdownMenu.Portal>
    </DropdownMenu.Root>
  );
}

タブコンポーネント

import * as Tabs from "@radix-ui/react-tabs";

function SettingsTabs() {
  return (
    <Tabs.Root defaultValue="general" className="w-full">
      <Tabs.List className="flex border-b" aria-label="設定">
        {["general", "security", "notifications"].map((tab) => (
          <Tabs.Trigger
            key={tab}
            value={tab}
            className="px-4 py-2 text-sm border-b-2 border-transparent data-[state=active]:border-blue-500 data-[state=active]:text-blue-600 hover:text-gray-700"
          >
            {tab === "general" && "一般"}
            {tab === "security" && "security"}
            {tab === "notifications" && "通知"}
          </Tabs.Trigger>
        ))}
      </Tabs.List>

      <Tabs.Content value="general" className="p-4">
        <h3 className="text-lg font-medium">一般設定</h3>
        {/* 一般設定のフォーム */}
      </Tabs.Content>
      <Tabs.Content value="security" className="p-4">
        <h3 className="text-lg font-medium">セキュリティ設定</h3>
        {/* セキュリティ設定のフォーム */}
      </Tabs.Content>
      <Tabs.Content value="notifications" className="p-4">
        <h3 className="text-lg font-medium">通知設定</h3>
        {/* 通知設定のフォーム */}
      </Tabs.Content>
    </Tabs.Root>
  );
}

ツールチップとポップオーバー

import * as Tooltip from "@radix-ui/react-tooltip";

function IconButton({ icon, label }: { icon: React.ReactNode; label: string }) {
  return (
    <Tooltip.Provider delayDuration={300}>
      <Tooltip.Root>
        <Tooltip.Trigger asChild>
          <button className="p-2 rounded hover:bg-gray-100" aria-label={label}>
            {icon}
          </button>
        </Tooltip.Trigger>
        <Tooltip.Portal>
          <Tooltip.Content
            className="bg-gray-900 text-white text-xs px-3 py-1.5 rounded shadow-lg"
            sideOffset={5}
          >
            {label}
            <Tooltip.Arrow className="fill-gray-900" />
          </Tooltip.Content>
        </Tooltip.Portal>
      </Tooltip.Root>
    </Tooltip.Provider>
  );
}

Zusammenfassung

Radix UIはアクセシビリティを犠牲にすることなく、自由度の高いUIを構築できる優れたライブラリです。Claude Codeを使えば、各コンポーネントの組み立てとスタイリングを素早く実装できます。

Radix UIをベースにしたUI構築はshadcn/ui活用ガイドを、アニメーションの追加はFramer Motionアニメーション実装を、アクセシビリティの全般的な対応はアクセシビリティ実装ガイドを参照してください。Radix UI公式ドキュメントも確認しておきましょう。

#Claude Code #Radix UI #React #accessibility #UIコンポーネント