Component Patterns
Guidelines for creating consistent React components.
Component Patterns
Component Template
import { cn } from '@/lib/utils';
import { forwardRef } from 'react';
import type { HTMLAttributes } from 'react';
import styles from './Component.module.scss';
export interface ComponentProps extends HTMLAttributes<HTMLDivElement> {
variant?: 'default' | 'outlined';
size?: 'sm' | 'md' | 'lg';
}
export const Component = forwardRef<HTMLDivElement, ComponentProps>(
({ className, variant = 'default', size = 'md', children, ...props }, ref) => {
return (
<div
ref={ref}
className={cn(
styles.component,
styles[variant],
styles[size],
className
)}
{...props}
>
{children}
</div>
);
}
);
Component.displayName = 'Component';
Key Patterns
1. Forward Ref
Always use forwardRef to allow parent components to access the DOM element:
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => <button ref={ref} {...props} />
);
2. Extend HTML Props
Extend native HTML element props for full flexibility:
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'secondary';
}
3. Spread Remaining Props
Always spread remaining props to the root element:
const { variant, className, children, ...props } = props;
return <div {...props}>{children}</div>;
4. Merge ClassNames
Use cn() to merge internal styles with user-provided className:
className={cn(styles.button, styles[variant], className)}
5. Display Name
Set displayName for better debugging:
Component.displayName = 'Component';
Component Checklist
- β Uses forwardRef for DOM refs
- β Extends appropriate HTML element props
- β Uses SCSS modules for styling
- β Merges className with cn()
- β Includes JSDoc with example
- β Sets displayName
- β Has unit tests
- β Passes TypeScript strict checks