component-wrapper-architecture について
component-wrapper-architecture は、8-bit コンポーネントを shadcn/ui のラッパーとして構築する開発スキルです。基盤コンポーネントとその props を維持しながら、レトロなスタイルを加える方法を説明します。
主な機能
- 01shadcn/ui コンポーネントのラップ
- 02class-variance-authority によるバリアント定義
- 03独立した props インターフェースの公開
- 04React 19 の ref props の使用
- 05基盤コンポーネントの props を引き継ぐ
活用シーン
- 01shadcn/ui ボタンへのピクセルスタイル追加
- 02カードをピクセル化ボーダーでラップ
- 03基盤コンポーネントによるレトロなダイアログ構築
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ theorcdev/ 8bitcn-ui --skill component-wrapper-architectureインストール後、Claude Code で/component-wrapper-architectureを入力して読み込まれたか確認します。
詳細
コンポーネントラッパーアーキテクチャ
8-bit コンポーネントは shadcn/ui コンポーネントを置き換えるのではなく、ラップします。このパターンにより、互換性を維持しながらレトロなスタイルを追加できます。
基本的なラッパーパターン
構成:
- ベースコンポーネントをエイリアス付きでインポートします
- class-variance-authority を使用してバリアントを定義します
- プロパティ用のインターフェースを個別にエクスポートします
- React 19 では forwardRef ではなく ref プロパティを使用します
import { type VariantProps, cva } from "class-variance-authority";
import { cn } from "@/lib/utils";
import { Button as ShadcnButton } from "@/components/ui/button";
import "@/components/ui/8bit/styles/retro.css";
export const buttonVariants = cva("", {
variants: {
font: {
normal: "",
retro: "retro",
},
variant: {
default: "bg-foreground",
// ...
},
},
defaultVariants: {
variant: "default",
size: "default",
},
});
export interface BitButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
ref?: React.Ref<HTMLButtonElement>;
}
function Button({ children, asChild, ...props }: BitButtonProps) {
const { variant, size, className, font } = props;
return (
<ShadcnButton
{...props}
className={cn(
"rounded-none active:translate-y-1 transition-transform",
className
)}
size={size}
variant={variant}
asChild={asChild}
>
{children}
</ShadcnButton>
);
}
ベースコンポーネントの再エクスポート
複数のサブコンポーネントを持つコンポーネントでは、変更しない部分を再エクスポートします。
import {
Dialog as ShadcnDialog,
DialogHeader as ShadcnDialogHeader,
DialogFooter as ShadcnDialogFooter,
DialogDescription as ShadcnDialogDescription,
} from "@/componentsconst Dialog = ShadcnDialog;
const DialogHeader =/ui/dialog";
ShadcnDialogHeader;
const DialogFooter = ShadcnDialogFooter;
const DialogDescription = ShadcnDialogDescription;
export {
Dialog,
DialogHeader,
DialogFooter,
DialogDescription,
// ...custom implementations
};
カードのラッパーパターン
ベースコンポーネントを維持しつつ、外側のラッパーでピクセル化された境界線を適用します。
function Card({ className, font, ...props }: BitCardProps) {
return (
<div
className={cn(
"relative border-y-6 border-foreground dark:border-ring !p-0",
className
)}
>
<ShadcnCard
{...props}
className={cn(
"rounded-none border-0 !w-full",
font !== "normal" && "retro",
className
)}
/>
{/* Pixelated side borders */}
<div
className="absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none"
aria-hidden="true"
/>
</div>
);
}
主な原則
- インポートのエイリアス - ベースコンポーネントには
as ShadcnComponentパターンを使用します - 空の cva ベース - バリアントのベースは空にし、スタイルは CSS に委ねることがよくあります
- 個別のプロパティインターフェース - TypeScript 用に
BitComponentPropsをエクスポートします - React 19 の ref - forwardRef ではなく
ref?: React.Ref<T>を使用します - rounded-none - ベースコンポーネントからすべての角丸を削除します
- プロパティの引き継ぎ -
size、variant、classNameを含むすべてのプロパティを転送します - 条件付きレトロスタイル -
font !== "normal" && "retro"パターンを使用します
コンポーネントの例
components/ui/8bit/button.tsx- ピクセル化された境界線を持つ基本的なラッパーcomponents/ui/8bit/card.tsx- 外側のラッパーを持つカードcomponents/ui/8bit/dialog.tsx- 複数のサブコンポーネントを持つラッパー
コメント
Markdown 対応