UI Builder
You are an expert at building modern user interfaces.
Activation
This skill activates when the user needs help with:
- UI component design
- Responsive layouts
- CSS/Tailwind styling
- Accessibility (a11y)
- Design system implementation
Process
1. Component Library Structure
// Button component with variants
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "primary" | "secondary" | "ghost" | "danger";
size?: "sm" | "md" | "lg";
loading?: boolean;
icon?: React.ReactNode;
}
export function Button({
variant = "primary",
size = "md",
loading = false,
icon,
children,
className,
disabled,
...props
}: ButtonProps) {
const variants = {
primary: "bg-blue-600 text-white hover:bg-blue-700",
secondary: "bg-gray-200 text-gray-900 hover:bg-gray-300",
ghost: "bg-transparent hover:bg-gray-100",
danger: "bg-red-600 text-white hover:bg-red-700",
};
const sizes = {
sm: "px-3 py-1.5 text-sm",
md: "px-4 py-2 text-base",
lg: "px-6 py-3 text-lg",
};
return (
<button
className={cn(
"inline-flex items-center justify-center rounded-md font-medium transition-colors",
"focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500",
"disabled:opacity-50 disabled:pointer-events-none",
variants[variant],
sizes[size],
className
)}
disabled={disabled || loading}
{...props}
>
{loading && <Spinner className="mr-2 h-4 w-4" />}
{icon && !loading && <span className="mr-2">{icon}</span>}
{children}
</button>
);
}
2. Responsive Layout
// Responsive grid
function ProductGrid({ products }: { products: Product[] }) {
return (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 p-4">
{products.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
// Container component
function Container({ children, className }: { children: ReactNode; className?: string }) {
return (
<div className={cn("mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8", className)}>
{children}
</div>
);
}
// Responsive navigation
function Navigation() {
const [isOpen, setIsOpen] = useState(false);
return (
<nav className="bg-white shadow">
<Container className="flex items-center justify-between h-16">
<Logo />
{/* Desktop menu */}
<div className="hidden md:flex items-center space-x-8">
<NavLink href="/products">Products</NavLink>
<NavLink href="/about">About</NavLink>
<Button size="sm">Sign In</Button>
</div>
{/* Mobile menu button */}
<button
className="md:hidden p-2"
=> setIsOpen(!isOpen)}
aria-expanded={isOpen}
>
<MenuIcon />
</button>
</Container>
{/* Mobile menu */}
{isOpen && (
<div className="md:hidden border-t">
<div className="px-4 py-2 space-y-2">
<MobileNavLink href="/products">Products</MobileNavLink>
<MobileNavLink href="/about">About</MobileNavLink>
</div>
</div>
)}
</nav>
);
}
3. Form Components
// Input with label and error
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
label: string;
error?: string;
hint?: string;
}
export function Input({ label, error, hint, id, className, ...props }: InputProps) {
const inputId = id || label.toLowerCase().replace(/\s+/g, "-");
return (
<div className="space-y-1">
<label htmlFor={inputId} className="block text-sm font-medium text-gray-700">
{label}
{props.required && <span className="text-red-500 ml-1">*</span>}
</label>
<input
id={inputId}
className={cn(
"block w-full rounded-md border px-3 py-2 shadow-sm",
"focus:border-blue-500 focus:ring-blue-500",
error ? "border-red-500" : "border-gray-300",
className
)}
aria-describedby={error ? `${inputId}-error` : hint ? `${inputId}-hint` : undefined}
aria-invalid={error ? "true" : undefined}
{...props}
/>
{hint && !error && (
<p id={`${inputId}-hint`} className="text-sm text-gray-500">{hint}</p>
)}
{error && (
<p id={`${inputId}-error`} className="text-sm text-red-600" role="alert">{error}</p>
)}
</div>
);
}
// Select component
interface SelectProps {
label: string;
options: { value: string; label: string }[];
value: string;
onChange: (value: string) => void;
error?: string;
}
export function Select({ label, options, value, onChange, error }: SelectProps) {
return (
<div className="space-y-1">
<label className="block text-sm font-medium text-gray-700">{label}</label>
<select
value={value}
=> onChange(e.target.value)}
className={cn(
"block w-full rounded-md border px-3 py-2",
error ? "border-red-500" : "border-gray-300"
)}
>
{options.map((opt) => (
<option key={opt.value} value={opt.value}>{opt.label}</option>
))}
</select>
{error && <p className="text-sm text-red-600">{error}</p>}
</div>
);
}
4. Modal/Dialog
import { Dialog, Transition } from "@headlessui/react";
interface ModalProps {
isOpen: boolean;
onClose: () => void;
title: string;
children: ReactNode;
}
export function Modal({ isOpen, onClose, title, children }: ModalProps) {
return (
<Transition show={isOpen} as={Fragment}>
<Dialog className="relative z-50">
{/* Backdrop */}
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black/25" aria-hidden="true" />
</Transition.Child>
{/* Modal */}
<div className="fixed inset-0 flex items-center justify-center p-4">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="w-full max-w-md rounded-lg bg-white p-6 shadow-xl">
<Dialog.Title className="text-lg font-medium">{title}</Dialog.Title>
<div className="mt-4">{children}</div>
</Dialog.Panel>
</Transition.Child>
</div>
</Dialog>
</Transition>
);
}
5. Accessibility Checklist
## A11y Requirements
- [ ] All interactive elements keyboard accessible
- [ ] Focus states visible
- [ ] Color contrast 4.5:1 minimum
- [ ] Images have alt text
- [ ] Form inputs have labels
- [ ] Error messages associated with inputs
- [ ] ARIA attributes where needed
- [ ] Skip links for navigation
- [ ] Semantic HTML elements
- [ ] Screen reader tested
Output Format
Provide:
- Component code with styling
- Responsive breakpoints
- Accessibility attributes
- Animation/transitions
- Usage examples