atomic-design
Installation
SKILL.md
When to Use
- Creating new UI components
- Deciding where a component belongs
- Building reusable component libraries
- Structuring the presentation layer
- Reviewing component architecture
Atomic Design Hierarchy
┌─────────────────────────────────────────────────────────┐
│ PAGES │
│ Complete screens/views │
├─────────────────────────────────────────────────────────┤
│ TEMPLATES │
│ Page layouts without real data │
├─────────────────────────────────────────────────────────┤
│ ORGANISMS │
│ Complex components (forms, headers) │
├─────────────────────────────────────────────────────────┤
│ MOLECULES │
│ Simple groups of atoms (input + label) │
├─────────────────────────────────────────────────────────┤
│ ATOMS │
│ Basic building blocks (button, text, icon) │
└─────────────────────────────────────────────────────────┘
Component Levels
Atoms
Smallest building blocks. Cannot be broken down further.
// atoms/Button.jsx
export function Button({ label, onPress, variant = 'primary', disabled }) {
return (
<TouchableOpacity
style={[styles.button, styles[variant], disabled && styles.disabled]}
onPress={onPress}
disabled={disabled}
accessible={true}
accessibilityRole="button"
accessibilityLabel={label}
>
<Text style={styles.label}>{label}</Text>
</TouchableOpacity>
);
}
// atoms/Icon.jsx
export function Icon({ name, size = 24, color = '#000' }) {
return <IconComponent name={name} size={size} color={color} />;
}
// atoms/Text.jsx
export function Typography({ variant = 'body', children, ...props }) {
return <Text style={[styles.base, styles[variant]]} {...props}>{children}</Text>;
}
// atoms/Spacer.jsx
export function Spacer({ size = 'md' }) {
const sizes = { sm: 8, md: 16, lg: 24, xl: 32 };
return <View style={{ height: sizes[size] }} />;
}
Examples: Button, Text, Icon, Input, Image, Spacer, Divider, Badge
Molecules
Simple groups of atoms functioning together.
// molecules/IconButton.jsx
import { Button } from '../atoms/Button';
import { Icon } from '../atoms/Icon';
export function IconButton({ icon, label, onPress }) {
return (
<TouchableOpacity onPress={onPress} style={styles.container}>
<Icon name={icon} />
<Text style={styles.label}>{label}</Text>
</TouchableOpacity>
);
}
// molecules/InputField.jsx
import { Typography } from '../atoms/Typography';
import { TextInput } from '../atoms/TextInput';
export function InputField({ label, error, ...inputProps }) {
return (
<View>
<Typography variant="label">{label}</Typography>
<TextInput {...inputProps} hasError={!!error} />
{error && <Typography variant="error">{error}</Typography>}
</View>
);
}
// molecules/StatusIndicator.jsx
export function StatusIndicator({ status, message }) {
return (
<View style={styles.container}>
<Icon name={statusIcons[status]} color={statusColors[status]} />
<Typography>{message}</Typography>
</View>
);
}
Examples: Search input, Navigation link, Card header, List item, Form field
Organisms
Complex components composed of molecules and atoms.
// organisms/VoiceCommandPanel.jsx
import { StatusIndicator } from '../molecules/StatusIndicator';
import { IconButton } from '../molecules/IconButton';
import { Typography } from '../atoms/Typography';
export function VoiceCommandPanel({
isListening,
lastCommand,
onActivate,
onDeactivate
}) {
return (
<View style={styles.panel}>
<Typography variant="heading">Comandos de Voz</Typography>
<StatusIndicator
status={isListening ? 'active' : 'idle'}
message={isListening ? 'Escuchando...' : 'Di "Iris" para activar'}
/>
{lastCommand && (
<View style={styles.lastCommand}>
<Typography variant="label">Último comando:</Typography>
<Typography>{lastCommand}</Typography>
</View>
)}
<IconButton
icon={isListening ? 'mic-off' : 'mic'}
label={isListening ? 'Detener' : 'Activar'}
onPress={isListening ? onDeactivate : onActivate}
/>
</View>
);
}
// organisms/CameraPreview.jsx
export function CameraPreview({ onCapture, isAnalyzing }) {
return (
<View style={styles.container}>
<CameraView style={styles.camera} />
<View style={styles.overlay}>
{isAnalyzing && <LoadingIndicator message="Analizando..." />}
<CaptureButton onPress={onCapture} disabled={isAnalyzing} />
</View>
</View>
);
}
// organisms/DescriptionCard.jsx
export function DescriptionCard({ description, timestamp, onRepeat }) {
return (
<Card>
<CardHeader>
<Typography variant="label">Descripción</Typography>
<Typography variant="caption">{formatTime(timestamp)}</Typography>
</CardHeader>
<CardBody>
<Typography>{description}</Typography>
</CardBody>
<CardFooter>
<IconButton icon="repeat" label="Repetir" onPress={onRepeat} />
</CardFooter>
</Card>
);
}
Examples: Header, Navigation bar, Form, Card, Modal, List with items
Templates
Page-level layouts. Define structure, receive content via props/children.
// templates/MainLayout.jsx
import { SafeAreaView } from 'react-native-safe-area-context';
export function MainLayout({ header, content, footer }) {
return (
<SafeAreaView style={styles.container}>
<View style={styles.header}>{header}</View>
<View style={styles.content}>{content}</View>
{footer && <View style={styles.footer}>{footer}</View>}
</SafeAreaView>
);
}
// templates/CameraLayout.jsx
export function CameraLayout({ camera, overlay, controls }) {
return (
<View style={styles.fullScreen}>
<View style={styles.cameraContainer}>{camera}</View>
<View style={styles.overlay}>{overlay}</View>
<View style={styles.controls}>{controls}</View>
</View>
);
}
Examples: Dashboard layout, Auth layout, Camera layout, Settings layout
Pages (Screens)
Complete screens with real data and business logic.
// pages/HomeScreen.jsx
import { MainLayout } from '../templates/MainLayout';
import { VoiceCommandPanel } from '../organisms/VoiceCommandPanel';
import { CameraPreview } from '../organisms/CameraPreview';
import { DescriptionCard } from '../organisms/DescriptionCard';
import { useVoiceCommands } from '../../voice/presentation/hooks/useVoiceCommands';
import { useVisionAnalysis } from '../../vision/presentation/hooks/useVisionAnalysis';
export function HomeScreen() {
const { isListening, lastCommand, startListening, stopListening } = useVoiceCommands();
const { description, isAnalyzing, analyzeScene, repeatLast } = useVisionAnalysis();
return (
<MainLayout
header={
<VoiceCommandPanel
isListening={isListening}
lastCommand={lastCommand}
onActivate={startListening}
onDeactivate={stopListening}
/>
}
content={
<CameraPreview
onCapture={analyzeScene}
isAnalyzing={isAnalyzing}
/>
}
footer={
description && (
<DescriptionCard
description={description}
onRepeat={repeatLast}
/>
)
}
/>
);
}
Folder Structure
src/
├── shared/
│ └── presentation/
│ └── components/
│ ├── atoms/
│ │ ├── Button.jsx
│ │ ├── Icon.jsx
│ │ ├── Typography.jsx
│ │ └── index.js
│ ├── molecules/
│ │ ├── IconButton.jsx
│ │ ├── InputField.jsx
│ │ └── index.js
│ ├── organisms/
│ │ ├── Header.jsx
│ │ └── index.js
│ └── templates/
│ ├── MainLayout.jsx
│ └── index.js
│
├── voice/
│ └── presentation/
│ └── components/
│ ├── molecules/
│ │ └── VoiceStatus.jsx
│ └── organisms/
│ └── VoiceCommandPanel.jsx
│
└── vision/
└── presentation/
└── components/
└── organisms/
├── CameraPreview.jsx
└── DescriptionCard.jsx
Decision Tree
Is it a basic HTML/RN element wrapper?
→ ATOM (Button, Text, Input, Icon)
Is it a simple combination of 2-3 atoms?
→ MOLECULE (IconButton, InputField, Avatar + Name)
Is it a complex, self-contained UI section?
→ ORGANISM (Header, Form, Card, Modal)
Is it a page structure without specific content?
→ TEMPLATE (MainLayout, AuthLayout)
Is it a complete screen with data and logic?
→ PAGE/SCREEN (HomeScreen, SettingsScreen)
Rules
| Rule | Reason |
|---|---|
| Atoms have no business logic | Pure presentation only |
| Molecules combine atoms only | Keep them simple |
| Organisms can have local state | Complex enough to need it |
| Templates receive children/slots | Flexible layouts |
| Pages connect to hooks/state | Only place with data fetching |
| Each level imports only from below | Clear dependency direction |
Index Files
// atoms/index.js - Export all atoms
export { Button } from './Button';
export { Icon } from './Icon';
export { Typography } from './Typography';
export { Spacer } from './Spacer';
// Usage
import { Button, Icon, Typography } from '@/shared/presentation/components/atoms';
Accessibility at Each Level
| Level | Accessibility Requirement |
|---|---|
| Atoms | accessibilityRole, base labels |
| Molecules | accessibilityLabel combining context |
| Organisms | accessibilityHint for complex actions |
| Pages | Focus management, screen reader announcements |
// Atom: basic role
<TouchableOpacity accessibilityRole="button">
// Molecule: contextual label
<InputField accessibilityLabel={`Campo de ${label}`}>
// Organism: action hint
<VoiceCommandPanel accessibilityHint="Activa comandos de voz diciendo Iris">
Related skills