jpskill.com
📦 その他 コミュニティ

web-ui-radix-ui

Radix UIは、デザインされていない、アクセシビリティに配慮したUIの基本要素を提供し、開発者が柔軟にカスタマイズして、使いやすく高品質なウェブインターフェースを構築するSkill。

📜 元の英語説明(参考)

Unstyled accessible UI primitives

🇯🇵 日本人クリエイター向け解説

一言でいうと

Radix UIは、デザインされていない、アクセシビリティに配慮したUIの基本要素を提供し、開発者が柔軟にカスタマイズして、使いやすく高品質なウェブインターフェースを構築するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o web-ui-radix-ui.zip https://jpskill.com/download/10320.zip && unzip -o web-ui-radix-ui.zip && rm web-ui-radix-ui.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10320.zip -OutFile "$d\web-ui-radix-ui.zip"; Expand-Archive "$d\web-ui-radix-ui.zip" -DestinationPath $d -Force; ri "$d\web-ui-radix-ui.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して web-ui-radix-ui.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → web-ui-radix-ui フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Radix UI Primitives

クイックガイド: Radix UI は、デザインシステムを構築するための、スタイルを持たない、アクセシブルなプリミティブを提供します。複合コンポーネントパターン(Root、Trigger、Content)、ポリモーフィズムのための asChild、アニメーションのための data-state 属性を使用してください。動作とアクセシビリティに焦点を当て、スタイリングの決定はスタイリングソリューションに委ねてください。現在: v1.4.x (2025年5月) - 新しいプレビュープリミティブによる完全な React 19 および RSC 互換性。


<critical_requirements>

重要: この Skill を使用する前に

すべてのコードは CLAUDE.md のプロジェクト規約に従う必要があります (kebab-case、名前付きエクスポート、インポート順序、import type、名前付き定数)

(オーバーレイコンポーネントには、複合コンポーネントの構成要素 - Root、Trigger、Portal、Content、Close - を必ず使用してください)

(カスタムコンポーネントで asChild を使用する場合は、forwardRef を使用し、すべての props を展開する必要があります - ref が通常の prop である React 19+ を使用する場合を除く)

(CSS のスタッキングコンテキストと親のオーバーフロー制約を回避するために、オーバーレイには必ず Portal を使用してください)

(Title/Description コンポーネントまたは ARIA 属性を介して、アクセシブルなラベルを必ず提供してください - Dialog は Title がない場合、コンソールにエラーを記録します)

</critical_requirements>


自動検出: Radix UI, radix-ui, @radix-ui, Dialog, Dropdown, DropdownMenu, Select, Popover, Tooltip, Accordion, Tabs, AlertDialog, asChild, Slot, Portal, data-state, OneTimePasswordField, PasswordToggleField, unstable_Form, Form.Field, Form.Message

使用する場合:

  • アクセシブルなオーバーレイコンポーネント(ダイアログ、ポップオーバー、ドロップダウン、ツールチップ)を構築する場合
  • 複数の連携する部分を持つ複合コンポーネント API を作成する場合
  • キーボードナビゲーションとフォーカスマネジメントを実装する場合
  • asChild パターンを介してポリモーフィックなコンポーネントが必要な場合

使用しない場合:

  • スタイル済みのコンポーネントが必要な場合(Radix 上に構築されたコンポーネントライブラリを使用してください)
  • 複雑なインタラクションのないシンプルなコンポーネントの場合(プレーンな HTML を使用してください)
  • React 以外のプロジェクトの場合(Radix プリミティブは React 固有です)

パッケージのインストール:

# 推奨: 統合されたツリーシェイカブルなパッケージ (バージョンの競合を防ぎます)
npm i radix-ui

# 代替: 個別のパッケージ
npm i @radix-ui/react-dialog @radix-ui/react-dropdown-menu

詳細なリソース:

  • コアコードの例 (Dialog, asChild, Slot) については、examples/core.md を参照してください。
  • オーバーレイパターン (AlertDialog, 制御された Dialog) については、examples/overlays.md を参照してください。
  • メニューパターン (DropdownMenu, サブメニュー) については、examples/menus.md を参照してください。
  • アニメーションパターン (data-state, CSS keyframes) については、examples/animation.md を参照してください。
  • フォームパターン (Select) については、examples/forms.md を参照してください。
  • ナビゲーションパターン (Accordion, Tabs) については、examples/navigation.md を参照してください。
  • プレビューコンポーネント (OneTimePasswordField, PasswordToggleField) については、examples/preview.md を参照してください。
  • 意思決定フレームワークとアンチパターンについては、reference.md を参照してください。

<philosophy>

Philosophy

Radix UI Primitives は、視覚的なデザインを強制することなく、動作とアクセシビリティの基盤を提供します。各プリミティブは以下を処理します。

  • アクセシビリティ: ARIA 属性、ロール、キーボードナビゲーション、フォーカスマネジメント
  • 動作: 開閉状態、ディスミスパターン、衝突検出
  • 構成: 連携システムとして動作する複合コンポーネント

Radix はスタイリングに依存しません: スタイリングソリューションを使用して、className prop を介してスタイルを適用します。プリミティブは、状態ベースのスタイリングのために data-state 属性を公開します。

複合コンポーネントモデル: 各プリミティブは、コンテキストを共有する複数の部分(Root、Trigger、Content など)で構成されています。これにより、連携した動作を維持しながら、柔軟な構成が可能になります。

React 19 & RSC サポート (v1.4.3): React 19 および React Server Components との完全な互換性。強化されたキーボード処理により、ブラウザのホットキーの干渉を回避します。

</philosophy>


<patterns>

コアパターン

パターン 1: 複合コンポーネントの構成要素

Radix プリミティブは、複数の部分が共有コンテキストを通じて連携する複合コンポーネントパターンを使用します。

オーバーレイコンポーネントの標準構造

import { Dialog } from "radix-ui";

// Root はコンテキストと状態管理を提供します
// Trigger はダイアログを開きます
// Portal は React ツリーの外にコンテンツをレンダリングします
// Overlay はページを覆います
// Content はダイアログ本体を含みます
// Close はダイアログを閉じます
// Title と Description はアクセシビリティを提供します

<Dialog.Root>
  <Dialog.Trigger>Open</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay className={className} />
    <Dialog.Content className={className}>
      <Dialog.Title>Dialog Title</Dialog.Title>
      <Dialog.Description>Accessible description</Dialog.Description>
      {/* Dialog content */}
      <Dialog.Close>Close</Dialog.Close>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

この構造の理由: Root は状態とコンテキストを管理し、Portal は CSS のスタッキングコンテキストをエスケープし、Overlay は視覚的な背景を提供し、Title/Description はスクリーンリーダーのアクセシビリティを保証します。


パターン 2: 制御された状態 vs 制御されていない状態

Radix プリミティブは、制御された状態と制御されていない状態の両方のパターンをサポートしています。

制御されていない状態 (Radix が状態を管理)

// Radix に内部状態の管理を任せる - 基本的なユースケースではよりシンプル
<Dialog.Root defaultOpen={false}>
  <Dialog.Trigger>Open</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Content>
      {/* Content */}
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

使用する場合: 外部状態の要件がないシンプルなダイアログ

制御された状態 (ユーザーが状態を管理)


import { useState } from "react";
import { Dialog } from "radix-ui";

function ControlledDialog() {
  const [open, setOpen] = useState(false);

  const handleSave = async () => {
    await saveData();
    setOpen(false); // 非同期操作後にプログラムで閉じる
  };

  return (
    <Dialog.Root open={open} onOpenChange={setOpen}>
      <Dialog.Trigger>Open</Dialog.Trigger>
      <Dialog.Portal>


(原文がここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Radix UI Primitives

Quick Guide: Radix UI provides unstyled, accessible primitives for building design systems. Use compound component patterns (Root, Trigger, Content), asChild for polymorphism, and data-state attributes for animations. Focus on behavior and accessibility - defer styling decisions to your styling solution. Current: v1.4.x (May 2025) - Full React 19 and RSC compatibility with new preview primitives.


<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST use compound component anatomy - Root, Trigger, Portal, Content, Close - for overlay components)

(You MUST use forwardRef and spread all props when using asChild with custom components - unless using React 19+ where ref is a regular prop)

(You MUST use Portal for overlays to escape CSS stacking contexts and parent overflow constraints)

(You MUST provide accessible labels via Title/Description components or ARIA attributes - Dialog logs console errors for missing Title)

</critical_requirements>


Auto-detection: Radix UI, radix-ui, @radix-ui, Dialog, Dropdown, DropdownMenu, Select, Popover, Tooltip, Accordion, Tabs, AlertDialog, asChild, Slot, Portal, data-state, OneTimePasswordField, PasswordToggleField, unstable_Form, Form.Field, Form.Message

When to use:

  • Building accessible overlay components (dialogs, popovers, dropdowns, tooltips)
  • Creating compound component APIs with multiple coordinated parts
  • Implementing keyboard navigation and focus management
  • Needing polymorphic components via asChild pattern

When NOT to use:

  • Pre-styled components desired (use a component library built on Radix)
  • Simple components without complex interactions (use plain HTML)
  • Non-React projects (Radix primitives are React-specific)

Package Installation:

# Recommended: Unified tree-shakeable package (prevents version conflicts)
npm i radix-ui

# Alternative: Individual packages
npm i @radix-ui/react-dialog @radix-ui/react-dropdown-menu

Detailed Resources:


<philosophy>

Philosophy

Radix UI Primitives provide behavioral and accessibility foundations without imposing visual design. Each primitive handles:

  • Accessibility: ARIA attributes, roles, keyboard navigation, focus management
  • Behavior: Open/close state, dismissal patterns, collision detection
  • Composition: Compound components that work together as coordinated systems

Radix is styling-agnostic: Apply styles via className prop using your styling solution. The primitives expose data-state attributes for state-based styling.

Compound Component Model: Each primitive consists of multiple parts (Root, Trigger, Content, etc.) that share context. This enables flexible composition while maintaining coordinated behavior.

React 19 & RSC Support (v1.4.3): Full compatibility with React 19 and React Server Components. Enhanced keyboard handling avoids browser hotkey interference.

</philosophy>


<patterns>

Core Patterns

Pattern 1: Compound Component Anatomy

Radix primitives use a compound component pattern where multiple parts work together through shared context.

Standard Structure for Overlay Components

import { Dialog } from "radix-ui";

// Root provides context and state management
// Trigger opens the dialog
// Portal renders content outside React tree
// Overlay covers the page
// Content contains the dialog body
// Close dismisses the dialog
// Title and Description provide accessibility

<Dialog.Root>
  <Dialog.Trigger>Open</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay className={className} />
    <Dialog.Content className={className}>
      <Dialog.Title>Dialog Title</Dialog.Title>
      <Dialog.Description>Accessible description</Dialog.Description>
      {/* Dialog content */}
      <Dialog.Close>Close</Dialog.Close>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

Why this structure: Root manages state and context, Portal escapes CSS stacking contexts, Overlay provides visual backdrop, Title/Description ensure screen reader accessibility


Pattern 2: Controlled vs Uncontrolled State

Radix primitives support both controlled and uncontrolled state patterns.

Uncontrolled (Radix Manages State)

// Let Radix manage internal state - simpler for basic use cases
<Dialog.Root defaultOpen={false}>
  <Dialog.Trigger>Open</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Content>
      {/* Content */}
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

When to use: Simple dialogs without external state requirements

Controlled (You Manage State)

import { useState } from "react";
import { Dialog } from "radix-ui";

function ControlledDialog() {
  const [open, setOpen] = useState(false);

  const handleSave = async () => {
    await saveData();
    setOpen(false); // Programmatically close after async operation
  };

  return (
    <Dialog.Root open={open} onOpenChange={setOpen}>
      <Dialog.Trigger>Open</Dialog.Trigger>
      <Dialog.Portal>
        <Dialog.Content>
          <Dialog.Title>Edit Profile</Dialog.Title>
          <button onClick={handleSave}>Save</button>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  );
}

When to use: Programmatic control needed (close after async, open from external trigger, sync with URL state)


Pattern 3: asChild for Polymorphism

The asChild prop enables Radix to merge behavior onto your custom components or different element types.

Changing Element Type

import { Tooltip } from "radix-ui";

// Tooltip trigger defaults to button, but you may want a link
<Tooltip.Root>
  <Tooltip.Trigger asChild>
    <a href="/docs">Documentation</a>
  </Tooltip.Trigger>
  <Tooltip.Portal>
    <Tooltip.Content>View the docs</Tooltip.Content>
  </Tooltip.Portal>
</Tooltip.Root>

Why good: Radix passes all required props and event handlers to the anchor, maintaining accessibility

With Custom Components

import { forwardRef } from "react";
import { Dialog } from "radix-ui";

// Custom component MUST use forwardRef and spread props
const CustomButton = forwardRef<HTMLButtonElement, React.ComponentProps<"button">>(
  ({ className, ...props }, ref) => {
    return <button ref={ref} className={className} {...props} />;
  }
);
CustomButton.displayName = "CustomButton";

// Use with asChild
<Dialog.Trigger asChild>
  <CustomButton className="custom-class">Open Dialog</CustomButton>
</Dialog.Trigger>

Why this works: forwardRef allows Radix to attach refs for positioning/focus, spreading props passes event handlers and ARIA attributes


Pattern 4: Building Custom asChild Components with Slot

Use the Slot utility to build your own components with asChild support.

import { forwardRef } from "react";
import { Slot } from "radix-ui";

export type ButtonProps = React.ComponentProps<"button"> & {
  asChild?: boolean;
};

export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  ({ asChild = false, className, ...props }, ref) => {
    const Comp = asChild ? Slot : "button";
    return <Comp ref={ref} className={className} {...props} />;
  }
);
Button.displayName = "Button";

// Usage - renders as button
<Button>Click me</Button>

// Usage with asChild - renders as anchor
<Button asChild>
  <a href="/page">Navigate</a>
</Button>

Why good: Slot merges all props onto the child element, eliminating wrapper elements while preserving behavior


Pattern 5: Portal Usage for Overlays

Portal renders content outside the React component tree to escape CSS stacking contexts.

import { Popover } from "radix-ui";

<Popover.Root>
  <Popover.Trigger>Toggle Popover</Popover.Trigger>
  <Popover.Portal>
    {/* Rendered in document.body, escaping parent overflow:hidden */}
    <Popover.Content className={className}>
      <Popover.Arrow />
      Popover content
    </Popover.Content>
  </Popover.Portal>
</Popover.Root>

When to use: All overlay components (dialogs, popovers, tooltips, dropdown menus)

Custom Portal Container

import { useRef } from "react";
import { Dialog } from "radix-ui";

function DialogWithCustomContainer() {
  const containerRef = useRef<HTMLDivElement>(null);

  return (
    <>
      <div ref={containerRef} />
      <Dialog.Root>
        <Dialog.Trigger>Open</Dialog.Trigger>
        <Dialog.Portal container={containerRef.current}>
          <Dialog.Content>Content in custom container</Dialog.Content>
        </Dialog.Portal>
      </Dialog.Root>
    </>
  );
}

When to use: Micro-frontends, iframes, or specific DOM hierarchy requirements


Pattern 6: Animation with data-state Attributes

Radix primitives expose data-state attributes for CSS-based animations. The unmount is suspended while exit animations complete. Use CSS @keyframes (not transition) -- Radix detects animation end events.

/* CSS keyframes — Radix suspends unmount until animation completes */
.dialog-overlay[data-state="open"] {
  animation: fadeIn 150ms ease-out;
}
.dialog-overlay[data-state="closed"] {
  animation: fadeOut 150ms ease-in;
}

Critical: CSS transition does NOT delay unmount -- only @keyframes animation works for exit animations.

JavaScript Animation Libraries

For complex orchestrated animations, use forceMount on Portal, Overlay, and Content to prevent Radix from unmounting during exit animations. Wrap with your animation library's presence detection.

// Key pattern: controlled state + forceMount + conditional rendering
<Dialog.Root open={open} onOpenChange={setOpen}>
  {open && (
    <Dialog.Portal forceMount>
      <Dialog.Overlay asChild forceMount>{/* animated overlay */}</Dialog.Overlay>
      <Dialog.Content asChild forceMount>{/* animated content */}</Dialog.Content>
    </Dialog.Portal>
  )}
</Dialog.Root>

See examples/animation.md for complete CSS keyframe and accordion height animation examples.


Pattern 7: Focus Management

Radix handles focus automatically for accessible interactions.

Default Behavior

// Focus automatically trapped in modal dialogs
// Focus returns to trigger on close
<Dialog.Root>
  <Dialog.Trigger>Open</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Content>
      {/* Focus trapped here until closed */}
      <input autoFocus /> {/* Receives focus on open */}
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

Custom Focus Control

import { useRef } from "react";
import { AlertDialog } from "radix-ui";

function AlertDialogWithCustomFocus() {
  const cancelRef = useRef<HTMLButtonElement>(null);

  return (
    <AlertDialog.Root>
      <AlertDialog.Trigger>Delete</AlertDialog.Trigger>
      <AlertDialog.Portal>
        <AlertDialog.Content
          onOpenAutoFocus={(e) => {
            e.preventDefault();
            cancelRef.current?.focus(); // Focus cancel instead of first element
          }}
        >
          <AlertDialog.Title>Confirm Delete</AlertDialog.Title>
          <AlertDialog.Cancel ref={cancelRef}>Cancel</AlertDialog.Cancel>
          <AlertDialog.Action>Delete</AlertDialog.Action>
        </AlertDialog.Content>
      </AlertDialog.Portal>
    </AlertDialog.Root>
  );
}

Why custom focus: Destructive dialogs should focus the safe action (Cancel) by default


Pattern 8: Accessible Labels

Radix provides Title and Description components for screen reader accessibility.

import { Dialog } from "radix-ui";

<Dialog.Root>
  <Dialog.Trigger>Settings</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Content
      aria-describedby={undefined} // Remove if no description
    >
      {/* Title is announced when dialog opens */}
      <Dialog.Title>Account Settings</Dialog.Title>

      {/* Description provides additional context */}
      <Dialog.Description>
        Manage your account preferences and security settings.
      </Dialog.Description>

      {/* Or visually hide but keep accessible */}
      <VisuallyHidden asChild>
        <Dialog.Description>
          This description is read by screen readers but not visible.
        </Dialog.Description>
      </VisuallyHidden>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

Why mandatory: Screen readers announce Title when dialog opens, Description provides context for the interaction

</patterns>


<integration>

Integration Guide

Radix is behavior-only: Components are unstyled. Apply styles via className prop using your styling solution.

Works with:

  • Slot utility: Build custom asChild components with the Slot component from radix-ui
  • Any CSS solution: Styles applied via className prop
  • Animation libraries: Use forceMount for JavaScript animation control

Common Component Pairs:

Primitive Use Case
Dialog Modal dialogs, forms, confirmations
AlertDialog Destructive confirmations requiring explicit action
DropdownMenu Navigation menus, action menus
Select Form selects with custom styling
Popover Non-modal floating content
Tooltip Contextual information on hover/focus
Accordion Expandable content sections
Tabs Tabbed interfaces
Progress Progress bars (supports value={undefined} for indeterminate)

Preview Components (Unstable API):

Primitive Use Case Import Prefix Version
OneTimePasswordField OTP input with keyboard nav, paste, autofill unstable_ 0.1.8
PasswordToggleField Password visibility toggle with focus management unstable_ 0.1.3
Form Form validation with constraint API unstable_ 0.1.8

Note: Preview components use unstable_ prefix. APIs may change before stable release.

</integration>


<red_flags>

RED FLAGS

High Priority Issues:

  • Missing forwardRef on custom asChild components -- Radix cannot attach refs for positioning and focus management
  • Not spreading props on asChild components -- ARIA attributes and event handlers are lost
  • Missing Portal for overlays -- content clipped by parent overflow: hidden or z-index issues
  • Missing Title/Description on dialogs -- screen readers have no context (Dialog logs console errors)
  • Using Dialog for destructive confirmations -- use AlertDialog (prevents accidental dismissal)

Gotchas & Edge Cases:

  • CSS transition does NOT delay unmount -- only @keyframes animation works for exit
  • data-state changes to "closed" before exit animation starts
  • AlertDialog requires Cancel or Action to close (no click-outside dismiss by design)
  • React 19: forwardRef wrapper no longer needed -- ref is a regular prop
  • Prefer unified radix-ui package over individual @radix-ui/* packages to prevent version conflicts

See reference.md for full anti-pattern examples with code and decision frameworks.

</red_flags>


<critical_reminders>

CRITICAL REMINDERS

All code must follow project conventions in CLAUDE.md

(You MUST use compound component anatomy - Root, Trigger, Portal, Content, Close - for overlay components)

(You MUST use forwardRef and spread all props when using asChild with custom components - unless using React 19+ where ref is a regular prop)

(You MUST use Portal for overlays to escape CSS stacking contexts and parent overflow constraints)

(You MUST provide accessible labels via Title/Description components or ARIA attributes - Dialog logs console errors for missing Title)

Failure to follow these rules will break accessibility, focus management, and proper DOM rendering.

</critical_reminders>