From aai-dev-frontend
Provides patterns for React component hierarchies, composition, reusable UI elements like compound components, container/presenter, render props, and custom hooks.
npx claudepluginhub bradtaylorsf/alphaagent-teamThis skill uses the workspace's default tool permissions.
Patterns for designing maintainable, reusable component architectures in React and modern frameworks.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Guides code writing, review, and refactoring with Karpathy-inspired rules to avoid overcomplication, ensure simplicity, surgical changes, and verifiable success criteria.
Executes ctx7 CLI to fetch up-to-date library documentation, manage AI coding skills (install/search/generate/remove/suggest), and configure Context7 MCP. Useful for current API refs, skill handling, or agent setup.
Share bugs, ideas, or general feedback.
Patterns for designing maintainable, reusable component architectures in React and modern frameworks.
Each component should do one thing well.
// Bad: Component does too much
function UserDashboard() {
// Fetches data, handles auth, renders UI, manages state...
}
// Good: Separate concerns
function UserDashboard() {
return (
<DashboardLayout>
<UserHeader />
<UserStats />
<RecentActivity />
</DashboardLayout>
);
}
Build complex UIs by composing simple components.
// Compound component pattern
<Card>
<Card.Header>
<Card.Title>Settings</Card.Title>
</Card.Header>
<Card.Body>
<SettingsForm />
</Card.Body>
<Card.Footer>
<Button>Save</Button>
</Card.Footer>
</Card>
interface ButtonProps {
// Required props first
children: React.ReactNode;
// Optional with sensible defaults
variant?: 'primary' | 'secondary' | 'ghost';
size?: 'sm' | 'md' | 'lg';
// Boolean props (default false)
isLoading?: boolean;
isDisabled?: boolean;
// Event handlers
onClick?: (event: React.MouseEvent) => void;
// Spread native props
...rest: React.ButtonHTMLAttributes<HTMLButtonElement>;
}
Container (logic):
function UserListContainer() {
const { data, isLoading } = useUsers();
const handleDelete = useDeleteUser();
return (
<UserList
users={data}
isLoading={isLoading}
onDelete={handleDelete}
/>
);
}
Presenter (UI):
function UserList({ users, isLoading, onDelete }) {
if (isLoading) return <Skeleton />;
return (
<ul>
{users.map(user => (
<UserItem key={user.id} user={user} onDelete={onDelete} />
))}
</ul>
);
}
const Card = ({ children }) => (
<div className="card">{children}</div>
);
Card.Header = ({ children }) => (
<div className="card-header">{children}</div>
);
Card.Body = ({ children }) => (
<div className="card-body">{children}</div>
);
Card.Footer = ({ children }) => (
<div className="card-footer">{children}</div>
);
function MouseTracker({ render }) {
const [position, setPosition] = useState({ x: 0, y: 0 });
useEffect(() => {
const handleMove = (e) => setPosition({ x: e.clientX, y: e.clientY });
window.addEventListener('mousemove', handleMove);
return () => window.removeEventListener('mousemove', handleMove);
}, []);
return render(position);
}
// Usage
<MouseTracker render={({ x, y }) => <Tooltip x={x} y={y} />} />
function useLocalStorage<T>(key: string, initialValue: T) {
const [value, setValue] = useState<T>(() => {
const stored = localStorage.getItem(key);
return stored ? JSON.parse(stored) : initialValue;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue] as const;
}
components/
├── ui/ # Primitive UI components
│ ├── Button/
│ │ ├── Button.tsx
│ │ ├── Button.test.tsx
│ │ └── index.ts
│ └── Input/
├── features/ # Feature-specific components
│ ├── auth/
│ │ ├── LoginForm.tsx
│ │ └── SignupForm.tsx
│ └── dashboard/
├── layout/ # Layout components
│ ├── Header.tsx
│ ├── Sidebar.tsx
│ └── Footer.tsx
└── shared/ # Shared/cross-cutting
├── ErrorBoundary.tsx
└── LoadingSpinner.tsx
UserProfile.tsx)use prefix (useAuth.ts)formatDate.ts)API_ENDPOINTS.ts)// Memoize expensive components
const MemoizedList = React.memo(ExpensiveList);
// Memoize callbacks
const handleClick = useCallback(() => {
doSomething(id);
}, [id]);
// Memoize computed values
const sortedItems = useMemo(() => {
return items.sort((a, b) => a.name.localeCompare(b.name));
}, [items]);
// Lazy load routes
const Dashboard = React.lazy(() => import('./Dashboard'));
// Lazy load heavy components
const Chart = React.lazy(() => import('./Chart'));
// With Suspense
<Suspense fallback={<Skeleton />}>
<Chart data={data} />
</Suspense>
Used by:
frontend-developer agent