mcpField
F
frontend-ui

frontend-ui

github.com/scientiacapitalデザイン・UI28178 回インストール3 週間前に更新
リポジトリ

frontend-ui について

React 19、Tailwind CSS v4、shadcn/ui を使った SaaS UI の構築と監査を支援するフロントエンドスキルです。Next.js と Vite に対応し、コンポーネントやワークフローに加えて、アクセシビリティ、レスポンシブ設計、パフォーマンスも扱います。

主な機能

  1. 01Next.js と Vite の React 設定
  2. 02Tailwind CSS v4 と shadcn/ui のパターン
  3. 03SaaS ダッシュボードと料金ページのレイアウト
  4. 04WCAG 2.1 AA のアクセシビリティ指針
  5. 05フォーム、データ取得、パフォーマンスの確認

活用シーン

  1. 01SaaS ダッシュボードや料金ページの構築
  2. 02キーボードとスクリーンリーダーの対応監査
  3. 03検証付きフォームやデータテーブルの作成
  4. 04フロントエンドの Core Web Vitals の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/scientiacapital/skills --skill frontend-ui

インストール後、Claude Code で/frontend-uiを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

config.json
reference/
accessibility-checklist.md
component-patterns.md
form-patterns.md
performance-optimization.md
saas-dashboard.md
saas-pricing-checkout.md
shadcn-setup.md
spa-routing.md
tailwind-v4-setup.md
vite-react-setup.md
templates/
component-with-variants.tsx
dashboard-layout.tsx
form-with-server-action.tsx
nextjs-tailwind-v4-setup.css
pricing-page.tsx
spa-app-layout.tsx
vite-react-config.ts

詳細

エンタープライズグレードのフロントエンドスキル。最高水準の SaaS UI の監査と構築に対応します。Tailwind CSS v4(CSS ファーストの設定)、shadcn/ui(2026)、React 19 を使用した Next.js 15+ App Router **または Vite SPA** を扱います。

本番環境向け SaaS:ダッシュボード、料金ページ、データテーブル、オンボーディング、ロールベースの UI を対象とし、WCAG 2.1 AA のアクセシビリティと Core Web Vitals のパフォーマンスを組み込んでいます。

<quick_start>

セットアップ:Tailwind v4 + shadcn/ui

npx create-next-app@latest my-app --typescript --tailwind --eslint --app --src-dir
cd my-app && npx shadcn@latest init
npx shadcn@latest add button card dialog table form
Tailwind v4 — CSS ファースト(tailwind.config.js なし)
/* app/globals.css */
@import "tailwindcss";
@theme inline {
  --color-background: oklch(1 0 0);
  --color-foreground: oklch(0.145 0 0);
  --color-primary: oklch(0.205 0.042 264.695);
  --color-primary-foreground: oklch(0.985 0 0);
  --radius-lg: 0.5rem;
  --radius-md: calc(var(--radius-lg) - 2px);
  --radius-sm: calc(var(--radius-lg) - 4px);
}
コンポーネントの構造(shadcn/ui 2026)
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"

const buttonVariants = cva(
  "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors",
  {
    variants: {
      variant: { default: "bg-primary text-primary-foreground", outline: "border border-input" },
      size: { default: "h-10 px-4 py-2", sm: "h-9 px-3", lg: "h-11 px-8" },
    },
    defaultVariants: { variant: "default", size: "default" },
  }
)

// React 19: ref is a regular prop — no forwardRef
// data-slot: styling hook for parent overrides
function Button({ className, variant, size, ref, ...props }:
  React.ComponentProps<"button"> & VariantProps<typeof buttonVariants>) {
  return <button ref={ref} data-slot="button"
    className={cn(buttonVariants({ variant, size, className }))} {...props} />
}
cn() ユーティリティ
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) }
Vite SPA の代替案
npm create vite@latest my-app -- --template react-ts
cd my-app && npm i -D @tailwindcss/vite && npx shadcn@latest init

Next.js との主な違い:

  • @tailwindcss/vite プラグイン(postcss ではありません)— HMR が高速で、Vite とネイティブに統合
  • VITE_ 環境変数プレフィックス(NEXT_PUBLIC_ ではありません)。import.meta.env からアクセスします
  • クライアントのみ — Server Components はありません。データ取得には React Query を使用します
  • コード分割には dynamic() の代わりに React.lazy() + <Suspense> を使用します
  • React Router v7 または TanStack Router によるルーティング(ファイルベースではありません)

Tailwind v4、shadcn/ui、コンポーネントパターン、アクセシビリティ、フォーム、パフォーマンスに関するガイダンスは、すべて Vite SPA にも同様に適用されます。実際に異なるのは、ルーティングとデータ取得のみです。

reference/vite-react-setup.md と reference/spa-routing.md を参照してください。 </quick_start>

<success_criteria> エンタープライズ SaaS フロントエンドが本番環境に対応している条件:

  • アクセシブル: WCAG 2.1 AA — キーボード操作、スクリーンリーダー、フォーカス管理、コントラスト比 4.5:1
  • 高パフォーマンス: 4G モバイルで LCP < 2.5s、INP < 200ms、CLS < 0.1
  • レスポンシブ: モバイルファースト、320px~2560px に対応し、コンポーネントにはコンテナークエリを使用
  • セキュア: XSS の脆弱性なし、CSP ヘッダー、ユーザーコンテンツをサニタイズ
  • テーマ対応: CSS によるダークモード、@theme 内のデザイントークン、一貫した余白と色
  • コンポーザブル: Server Components をデフォルトとし、クライアント境界をリーフコンポーネントに寄せる
  • 型安全: TypeScript の strict モード、すべてのフォームで Zod によるバリデーション、any を使用しない </success_criteria>

<core_principles>

  1. サーバーファースト — Server Components をデフォルトにします。インタラクティブ性が必要な場合にのみ "use client" を追加します。クライアント境界はリーフコンポーネントに寄せます。
  2. デフォルトでアクセシブル — まずセマンティック HTML(<nav>、<main>、<article>)を使用します。ネイティブのセマンティクスでは不十分な場合にのみ ARIA を使用します。
  3. 設定よりコンポジション — 小さく、合成可能なコンポーネントを使用します。複雑な UI には Compound パターンを使用します。境界で Context を使用します。
  4. 段階的な情報開示 — まず重要な情報を示します。必要に応じて複雑さを明らかにし、認知負荷を軽減します。
  5. モバイルファースト — 最小画面向けに設計し、より大きな画面に向けて拡張します。コンポーネントにはコンテナークエリを使用します。タッチターゲットは 44px 以上にします。
  6. デザイントークン — すべての視覚的な値を CSS @theme に定義します。ハードコードは避けます。知覚的な均一性には OKLCH を使用します。
  7. エンドツーエンドの型安全性 — Zod スキーマをクライアントとサーバーで共有します。手動で定義したインターフェースより React.ComponentProps<> を使用します。 </core_principles>

<tailwind_v4>

Tailwind CSS v4 — v3 からの主な変更点

  • tailwind.config.js なし — すべての設定は CSS の @theme ディレクティブで行います
  • @import "tailwindcss" — @tailwind base/components/utilities に代わるものです
  • OKLCH カラー — hex/HSL に代わる、知覚的に均一なカラーです
  • コンテナークエリを標準搭載 — @container、@md:、@lg: プレフィックス
  • @source — CSS ネイティブのファイルスキャン(content 配列に代わるものです)
  • CSS サイズを 70% 縮小 — 未使用のスタイルを自動的に除去します
  • @theme inline — shadcn/ui ブリッジ。ユーティリティを生成せずにトークンを使用できます
@theme {
  --color-brand-500: oklch(0.55 0.15 250);
  --font-sans: "Inter", system-ui, sans-serif;
  --breakpoint-xs: 475px;
  --animate-slide-in: slide-in 0.2s ease-out;
}
// Container queries — component-level responsive
<div className="@container">
  <div className="grid grid-cols-1 @md:grid-cols-2 @lg:grid-cols-3 gap-4">
    {items.map(item => <Card key={item.id} {...item} />)}
  </div>
</div>

移行: npx @tailwindcss/upgrade — reference/tailwind-v4-setup.md を参照してください。 </tailwind_v4>

<shadcn_ui>

shadcn/ui 2026

  • @theme inline — トークンを Tailwind v4 に橋渡しします
  • data-slot — 属性ベースのスタイル設定フック(className のオーバーライドに代わるものです)
  • forwardRef なし — React 19 では ref をプロパティとして渡します
  • tw-animate-css — v4 との互換性のため、tailwindcss-animate に代わるものです
  • Radix または Base UI — プリミティブライブラリを選択します
// data-slot: parent can target child styles
function Card({ className, ref, ...props }: React.ComponentProps<"div">) {
  return <div ref={ref} data-slot="card" className={cn("rounded-xl border bg-card", className)} {...props} />
}

// Style from parent:
<div className="[&_[data-slot=card]]:shadow-lg">
  <Card>...</Card>
</div>

ダークモード: .dark クラスによる CSS カスタムプロパティの切り替え。reference/shadcn-setup.md を参照してください。 </shadcn_ui>

<component_architecture>

サーバーコンポーネントとクライアントコンポーネント

サーバーコンポーネント(デフォルト)クライアントコンポーネント("use client")
非同期データフェッチ、DB アクセスuseState、useEffect、イベントハンドラー
JS バンドルゼロ、シークレットへのアクセスブラウザー API、サードパーティのクライアントライブラリ

ルール: "use client" は可能な限り最小のリーフに押し下げます。

// Server page with client island
export default async function DashboardPage() {
  const metrics = await getMetrics()
  return (
    <main>
      <KPICards data={metrics} />       {/* Server-rendered */}
      <RevenueChart data={metrics} />   {/* Client island */}
    </main>
  )
}
主要なパターン
  • 複合コンポーネント — <Table>/<TableRow>/<TableCell> の名前空間による合成
  • cva バリアント — class-variance-authority による型安全なスタイルバリアント
  • React.ComponentProps — 手動のインターフェースを置き換え、ref を通常のプロパティとして扱います
  • data-slot — 親子間のオーバーライドのための外部スタイリングフック
  • ポリモーフィック(asChild) — 異なる要素としてレンダリングするための Slot パターン
  • SPA コード分割 — React.lazy() + <Suspense> が Next.js の dynamic() を置き換えます

完全な例については reference/component-patterns.md を参照してください。 </component_architecture>

<saas_patterns>

エンタープライズ SaaS パターン

ダッシュボード: サイドバー + ヘッダー + メイン
<div className="flex h-screen">
  <Sidebar className="w-64 hidden lg:flex" />
  <div className="flex-1 flex flex-col">
    <Header />  {/* Search, user menu, notifications */}
    <main className="flex-1 overflow-auto p-6">
      <KPIGrid metrics={metrics} />
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mt-6">
        <RevenueChart data={revenue} />
        <ActivityFeed items={activities} />
      </div>
    </main>
  </div>
</div>
料金プラン(3 層のコンバージョン)

アンカー(低) | コンバージョンターゲット(ハイライト、「Most Popular」) | エンタープライズ(カスタム)

月額/年額の切り替え、機能比較表、社会的証明。templates/pricing-page.tsx を参照してください。

データテーブル — ソート/フィルター/ページネーションには shadcn Table + TanStack Table
状態の三種 — すべてのデータコンポーネントには次が必要です: ローディング(Skeleton) | エラー(再試行アクション) | 空(ガイダンス)
ロールベース UI — 条件付きレンダリングのための hasPermission(user, "scope") ガード

reference/saas-dashboard.md と reference/saas-pricing-checkout.md を参照してください。 </saas_patterns>

## WCAG 2.1 AA

セマンティック HTML を最優先 — <header>、<nav>、<main>、<article>、<section>、<footer>

パターン実装
キーボードナビゲーションTab/Shift+Tab、メニュー/タブ内の矢印キー、Escape で閉じる
フォーカス管理ダイアログ内でのトラップ、閉じる際の復元、スキップリンク
ARIA ライブリージョン動的コンテンツには aria-live="polite"
フォームエラーaria-invalid、aria-describedby、role="alert"
ローディング状態ローディング中のボタンに aria-busy={true}
コントラストテキスト 4.5:1、UI コンポーネント 3:1(OKLCH の明度チャンネル)
// Skip link
<a href="#main-content" className="sr-only focus:not-sr-only focus:absolute focus:z-50">
  Skip to main content
</a>

コンポーネントごとの ARIA パターンについては reference/accessibility-checklist.md を参照してください。

<state_management>

状態の決定ツリー

状態の種類解決策例
URL 状態nuqs / useSearchParamsフィルター、ページネーション、タブ
サーバーデータReact Query / SWRAPI データ、ユーザープロフィール
ローカル UIuseStateフォーム入力、トグル
親子間の共有状態のリフトアップ / Contextアコーディオングループ
複雑な横断的関心事Zustandカート、ウィザード、通知

URL 状態を優先 — 共有可能で、ブックマーク可能で、リフレッシュ後も保持されます。 </state_management>

<data_fetching>

データフェッチ

パターン使用場面方法
サーバーコンポーネントデフォルトasync function Page() { const data = await db.query() }
Suspense ストリーミング遅いデータ<Suspense fallback={<Skeleton/>}><SlowComponent/></Suspense>
サーバーアクションミューテーション"use server" + revalidatePath()
React QueryクライアントのリアルタイムuseQuery({ queryKey, queryFn, refetchInterval })
React Query(SPA)クライアントのみのアプリローダー付きの useQuery({ queryKey, queryFn }) — サーバーコンポーネントを置き換えます
</data_fetching>
## フォーム: RHF + Zod + shadcn Form + サーバーアクション
  1. 共有 Zod スキーマ — クライアント検証とサーバーアクションの唯一の信頼できる情報源
  2. React Hook Form — zodResolver を使った useForm、mode: "onBlur"
  3. shadcn Form — <Form>/<FormField>/<FormItem>/<FormLabel>/<FormMessage>
  4. サーバーアクション — サーバー上で safeParse、フィールドエラーを返し、revalidatePath
const schema = z.object({
  name: z.string().min(2),
  email: z.string().email(),
})

reference/form-patterns.md と templates/form-with-server-action.tsx を参照してください。

## Core Web Vitals
指標目標すぐにできる改善
LCP < 2.5sメインコンテンツが表示されるnext/image with priority, next/font
INP < 200ms操作にすばやく応答するdynamic() で大きなコンポーネントをコード分割する
CLS < 0.1レイアウトシフトがない画像/フォント用のスペースを確保する、スケルトンローダー

Tailwind v4 は CSS を自動的に 70% 小さくします。reference/performance-optimization.md を参照してください。

| トピック | 参照ファイル | 読み込むタイミング | |-------|----------------|--------------| | Tailwind v4 のセットアップ | `reference/tailwind-v4-setup.md` | 新規プロジェクト、v3 からの移行 | | shadcn/ui のセットアップ | `reference/shadcn-setup.md` | コンポーネントライブラリのセットアップ | | コンポーネントのパターン | `reference/component-patterns.md` | カスタムコンポーネントの構築 | | SaaS ダッシュボード | `reference/saas-dashboard.md` | ダッシュボードのレイアウト、KPI カード | | 料金設定とチェックアウト | `reference/saas-pricing-checkout.md` | 料金ページ、Stripe UI | | アクセシビリティ | `reference/accessibility-checklist.md` | WCAG 監査、ARIA パターン | | フォームのパターン | `reference/form-patterns.md` | 複数ステップのフォーム、ファイルアップロード | | パフォーマンス | `reference/performance-optimization.md` | Core Web Vitals、Lighthouse | | Vite + React のセットアップ | `reference/vite-react-setup.md` | 新規 Vite SPA プロジェクト | | SPA のルーティング | `reference/spa-routing.md` | React Router、TanStack Router | ## エンタープライズ SaaS のリリース前監査
アクセシビリティ
  • すべてのインタラクティブ要素でキーボード操作が可能
  • スクリーンリーダーがコンテンツの意味を適切に読み上げる
  • フォーカスインジケーターが見える、スキップリンクがある
  • 色のコントラスト >= 4.5:1(テキスト)、>= 3:1(UI)
パフォーマンス
  • LCP < 2.5s、INP < 200ms、CLS < 0.1
  • 画像には next/image、フォントには next/font を使用
  • 大きなコンポーネントを dynamic() でコード分割
レスポンシブ対応
  • 320px〜2560px で動作し、タッチターゲットは >= 44px
  • 再利用可能なコンポーネントにはコンテナークエリを使用
セキュリティ
  • サニタイズせずに生の HTML を注入しない
  • CSP ヘッダー、クライアントとサーバーの両方で Zod による検証
UX
  • すべてのデータ表示にローディング/エラー/空の状態を用意
  • データ変更にはトースト、破壊的な操作には確認を用意

結果サイドカーの出力

最後のステップとして、~/.claude/skill-analytics/last-outcome-frontend-ui.json に書き込みます。

{"ts":"[UTC ISO8601]","skill":"frontend-ui","version":"1.0.0","variant":"default",
 "status":"[success|partial|error]","runtime_ms":[estimated ms from start],
 "metrics":{"components_built":[n],"pages_created":[n],"a11y_checks_passed":[bool]},
 "error":null,"session_id":"[YYYY-MM-DD]"}

一部のステージが失敗しても結果が生成された場合は、ステータスに "partial" を使用してください。出力が生成されなかった場合に限り、"error" を使用してください。

コメント