mcpField
R
react-component-generator

react-component-generator

github.com/onewave-ai開発393322 回インストール1 週間前に更新
リポジトリ

react-component-generator について

React コンポーネントを生成するためのスキルです。クライアントとサーバーの実装パターン、フォーム、アクセシビリティを扱い、構造化された指針を求める開発者向けです。

主な機能

  1. 01クライアント・サーバーコンポーネントのパターン
  2. 02TypeScript の props インターフェース
  3. 03React Hook Form と Zod のフォームテンプレート
  4. 04アクセシビリティチェックリスト

活用シーン

  1. 01型付き React コンポーネントの雛形作成
  2. 02バリデーション付きフォームの構築
  3. 03キーボード操作とスクリーンリーダー対応の確認

インストール

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

$npx skills add https://github.com/onewave-ai/claude-skills --skill react-component-generator

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

詳細

React コンポーネントジェネレーター

手順

React コンポーネントを作成する際は、次の手順に従ってください。

  1. コンポーネントの種類を決定する:クライアントコンポーネントまたはサーバーコンポーネント
  2. TypeScript で props インターフェースを定義する
  3. ベストプラクティスに従って実装する
  4. アクセシビリティ属性を追加する

テンプレート

クライアントコンポーネント
'use client';

import { useState, useCallback } from 'react';
import { cn } from '@/lib/utils';

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: 'primary' | 'secondary' | 'ghost';
  size?: 'sm' | 'md' | 'lg';
  isLoading?: boolean;
  children: React.ReactNode;
}

export function Button({
  variant = 'primary',
  size = 'md',
  isLoading = false,
  children,
  className,
  disabled,
  ...props
}: ButtonProps) {
  const baseStyles = 'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2';

  const variants = {
    primary: 'bg-blue-600 text-white hover:bg-blue-700',
    secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
    ghost: 'hover:bg-gray-100',
  };

  const sizes = {
    sm: 'h-8 px-3 text-sm',
    md: 'h-10 px-4',
    lg: 'h-12 px-6 text-lg',
  };

  return (
    <button
      className={cn(baseStyles, variants[variant], sizes[size], className)}
      disabled={disabled || isLoading}
      aria-busy={isLoading}
      {...props}
    >
      {isLoading ? <span className="animate-spin mr-2">⏳</span> : null}
      {children}
    </button>
  );
}
サーバーコンポーネント
import { db } from '@/lib/db';

interface UserListProps {
  limit?: number;
}

export async function UserList({ limit = 10 }: UserListProps) {
  const users = await db.user.findMany({ take: limit });

  if (users.length === 0) {
    return <p className="text-gray-500">No users found.</p>;
  }

  return (
    <ul role="list" className="divide-y">
      {users.map((user) => (
        <li key={user.id} className="py-4">
          <span>{user.name}</span>
        </li>
      ))}
    </ul>
  );
}
React Hook Form を使ったフォームコンポーネント
'use client';

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';

const schema = z.object({
  email: z.string().email('Invalid email'),
  password: z.string().min(8, 'Min 8 characters'),
});

type FormData = z.infer<typeof schema>;

export function LoginForm({ onSubmit }: { onSubmit: (data: FormData) => void }) {
  const {
    register,
    handleSubmit,
    formState: { errors, isSubmitting },
  } = useForm<FormData>({
    resolver: zodResolver(schema),
  });

  return (
    <form onSubmit={handleSubmit(onSubmit)} noValidate>
      <div>
        <label htmlFor="email">Email</label>
        <input
          id="email"
          type="email"
          aria-invalid={!!errors.email}
          aria-describedby={errors.email ? 'email-error' : undefined}
          {...register('email')}
        />
        {errors.email && (
          <p id="email-error" role="alert">{errors.email.message}</p>
        )}
      </div>
      <button type="submit" disabled={isSubmitting}>
        {isSubmitting ? 'Loading...' : 'Submit'}
      </button>
    </form>
  );
}

アクセシビリティチェックリスト

  • セマンティック HTML 要素を使用する
  • アイコンのみのボタンには aria-label を追加する
  • 必要に応じて role 属性を含める
  • キーボード操作が機能することを確認する
  • フォームのエラーには aria-invalid と aria-describedby を追加する
  • 読み込み状態には aria-busy を使用する

コメント