React Components
Quick reference for building UI components with Atomic Design, shadcn/ui, and Radix UI. Each section summarizes the key rules — reference files provide full examples and edge cases.
Atomic Design
Five-level component hierarchy: Atoms → Molecules → Organisms → Templates → Pages.
Classification Quick Reference
Level Breaks Down Further? Fetches Data? Business Logic? Reusable?
Atom No No No Yes
Molecule Into atoms No Minimal Yes
Organism Into molecules Maybe Yes Usually
Template Into organisms No No Yes
Page Into templates Yes Orchestration No
Examples
-
Atoms: Button, Input, Label, Avatar, Badge, Spinner, Separator
-
Molecules: FormField (Label + Input + Error), SearchInput (Input + Button)
-
Organisms: Header, SignUpForm, AppointmentCard, DoctorSearchResults
-
Templates: MainLayout (Header + Sidebar + Content), AuthLayout
-
Pages: DashboardPage, DoctorProfilePage (fetch data, wire to template)
Naming
-
Component files: PascalCase — Button.tsx , FormField.tsx
-
Directories: PascalCase — Button/ , FormField/
-
Tests: Button/tests/Button.test.tsx
-
Barrel exports per level: atoms/index.ts
See references/atomic-design.md for classification decision table, naming conventions, barrel exports, and anti-patterns.
Shared vs App-Specific Components
Placement Rules
components/web/src/ → Shared across apps (@drzum/ui) ├── atoms/ → @drzum/ui/atoms ├── molecules/ → @drzum/ui/molecules ├── organisms/ → @drzum/ui/organisms ├── templates/ → @drzum/ui/templates └── chad-cn/ → Raw shadcn/ui copies
patient/src/components/ → Patient app only ├── atoms/ ├── molecules/ ├── organisms/ └── templates/
Decision flow:
-
Used by 2+ apps? → components/web/ (shared)
-
Used by 1 app? → {app}/src/components/ (app-specific)
-
Is a page? → {app}/src/pages/
-
Might become shared? → Start in the app, move later when needed
Import Convention
// ✅ Shared components import { Button, Input } from "@drzum/ui/atoms"; import { FormField } from "@drzum/ui/molecules";
// ✅ App-specific components import { AppointmentCard } from "@/components/organisms/AppointmentCard";
shadcn/ui
Copy-and-own component collection. Not a dependency — source code lives in your project.
Adding Components
pnpm dlx shadcn@latest add button input dialog
Customization
Modify the source directly — you own the code:
// Add a custom variant const buttonVariants = cva("...", { variants: { variant: { default: "bg-primary text-primary-foreground hover:bg-primary/90", success: "bg-green-600 text-white hover:bg-green-700", // Custom }, }, });
Theming
shadcn/ui uses CSS variables. Change your theme by updating variables in @theme :
@theme { --color-primary: #16a34a; --color-primary-foreground: #ffffff; --color-destructive: #dc2626; }
Extending for Domain Use
Wrap shadcn components with domain-specific behavior:
function LoadingButton({ isLoading, children, ...props }: LoadingButtonProps) { return ( <Button disabled={isLoading} {...props}> {isLoading && <Loader2 className="mr-2 size-4 animate-spin" />} {isLoading ? "Cargando..." : children} </Button> ); }
See references/shadcn-ui.md for setup, configuration, form patterns with React Hook Form, and monorepo placement.
Radix UI
Accessible, unstyled primitives that shadcn/ui builds on. Key concepts:
The asChild Pattern
// Merges Radix behavior onto YOUR component <Dialog.Trigger asChild> <Button variant="outline">Abrir</Button> </Dialog.Trigger>
Always use asChild when passing your own styled component as a Radix slot.
Data Attributes for Styling
Radix exposes state via data attributes — use them for Tailwind styling:
<Tabs.Trigger className="text-muted-foreground data-[state=active]:border-b-2 data-[state=active]:border-primary data-[state=active]:text-foreground"
Tab </Tabs.Trigger>
Common: data-[state=open] , data-[state=active] , data-[state=checked] , data-[disabled]
Common Primitives
Primitive Use For Key Behavior
Dialog Modals, confirmations Focus trap, Escape to close
DropdownMenu Context menus Arrow key navigation, type-ahead
Tabs Tabbed content Arrow keys between triggers
Select Selection from options Keyboard navigation, type-ahead
Tooltip Hover information Delay, accessible labels
Accordion Collapsible sections Single or multiple open
Accessibility Checklist
-
Always include Dialog.Title (use VisuallyHidden if not visible)
-
Use asChild to avoid nesting <button> inside <button>
-
Provide aria-label for icon-only triggers
-
Test with keyboard: Tab, Escape, arrow keys, Enter/Space
See references/radix-ui.md for Dialog, Dropdown, Tabs, Select, Tooltip examples and anti-patterns.
Responsive Design
Mobile-first: base styles are mobile, breakpoints add larger-screen overrides.
Breakpoints
Prefix Min Width Target
(none) 0px Mobile (base)
sm:
640px Large phones
md:
768px Tablets
lg:
1024px Laptops
xl:
1280px Desktops
Common Patterns
{/* Stack → Row /} <div className="flex flex-col gap-4 sm:flex-row">{/ ... */}</div>
{/* Responsive grid /} <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">{/ ... */}</div>
{/* Show/hide */} <nav className="hidden lg:block">{desktopNav}</nav> <button className="lg:hidden">{hamburger}</button>
Touch Targets
Minimum 44x44px for interactive elements on mobile. Use h-11 (44px) as minimum button height.
Rules
-
Start mobile — Write base styles for the smallest screen
-
Add up — Use sm: , md: , lg: to progressively enhance
-
Prefer CSS breakpoints — Use useMediaQuery only when component trees differ, not just layout
-
Test on real devices — Don't rely only on browser DevTools resize
See references/responsive-design.md for responsive tables, container queries, touch targets, and testing patterns.
Form Element Styling
When styling form elements, follow the project's design system:
-
Focus ring: focus-visible:border-primary focus-visible:ring-2 focus-visible:ring-primary/30 — green glow effect
-
Default borders: border-border — light, subtle
-
Error state: border-destructive focus-visible:ring-destructive/30
-
Disabled: disabled:cursor-not-allowed disabled:opacity-50
Reference .molcajete/research/ui-ideas/form-ui.png for the desired look and feel.
Reference Files
File Description
references/atomic-design.md Five-level hierarchy, classification checklists, naming, barrel exports
references/shadcn-ui.md Setup, adding components, customization, cva variants, theming
references/radix-ui.md Dialog, Dropdown, Tabs, Select, Tooltip, accessibility
references/responsive-design.md Mobile-first breakpoints, responsive patterns, touch targets, container queries