Skip to content
Frontend
Skill

/component-wrapper-architecture

Best practices for wrapping shadcn/ui components. Apply when creating 8-bit styled variants of existing shadcn/ui components.

From plugin
8bitcn-ui
2k23 skills4 hooks
Install
$ npx -y skills add theorcdev/8bitcn-ui --skill component-wrapper-architecture --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/component-wrapper-architecture

Context preview

The summary Claude sees to decide when to auto-load this skill.

Best practices for wrapping shadcn/ui components. Apply when creating 8-bit styled variants of existing shadcn/ui components.

SKILL.md

component-wrapper-architecture.SKILL.md
name: component-wrapper-architecture
description: Best practices for wrapping shadcn/ui components. Apply when creating 8-bit styled variants of existing shadcn/ui components.

Component Wrapper Architecture

8-bit components wrap shadcn/ui components rather than replacing them. This pattern maintains compatibility while adding retro styling.

Basic Wrapper Pattern

**Structure:** 1. Import base component with alias 2. Define variants using class-variance-authority 3. Export separate interface for props 4. Use ref prop (not forwardRef for React 19)

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>
  );
}

Re-exporting Base Components

For components with multiple sub-components, re-export unchanged parts:

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
};

Card Wrapper Pattern

Use outer wrapper for pixelated borders while keeping base component:

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>
  );
}

Key Principles

1. **Alias imports** - Use `as ShadcnComponent` pattern for base components 2. **Empty cva base** - Variants often start empty, relying on CSS for styling 3. **Separate prop interface** - Export `BitComponentProps` for TypeScript 4. **React 19 ref** - Use `ref?: React.Ref<T>` instead of forwardRef 5. **rounded-none** - Remove all border radius from base component 6. **Pass through props** - Forward all props including `size`, `variant`, `className` 7. **Conditional retro** - Use `font !== "normal" && "retro"` pattern

Component Examples

  • `components/ui/8bit/button.tsx` - Basic wrapper with pixel borders
  • `components/ui/8bit/card.tsx` - Card with outer wrapper
  • `components/ui/8bit/dialog.tsx` - Multi-subcomponent wrapper
Read more
Ships with8bitcn-ui

Accessible retro components that you can copy and paste into your apps.Free. Open Source. Built on shadcn/ui. Documentation · Components · Blocks · Themes · Discord

Get the whole plugin