Usamos cookies para mejorar tu experiencia en el sitio
CodeWorlds

Atomic Design w React -- Budowanie galaktyki z atomów

Atomic Design to metodologia organizacji komponentów stworzona przez Brada Frosta. Analogia kosmiczna jest idealna: zaczynamy od atomów (najmniejsze cząstki materii), łączymy je w molekuły, potem w organizmy, aż zbudujemy całe strony -- galaktyki naszej aplikacji.

5 poziomów Atomic Design

1. Atoms (Atomy) -- Najmniejsze, niepodzielne elementy

Atomy to podstawowe elementy UI, które nie mają sensu rozbijać dalej:

1// atoms/Button.jsx
2function Button({ variant = 'primary', size = 'md', children, ...props }) {
3  return (
4    <button className={`btn btn-${variant} btn-${size}`} {...props}>
5      {children}
6    </button>
7  );
8}
9
10// atoms/Input.jsx
11function Input({ label, error, ...props }) {
12  return (
13    <div className="input-group">
14      {label && <label>{label}</label>}
15      <input className={`input ${error ? 'input-error' : ''}`} {...props} />
16      {error && <span className="error-text">{error}</span>}
17    </div>
18  );
19}
20
21// atoms/Badge.jsx
22function Badge({ children, color = 'blue' }) {
23  return <span className={`badge badge-${color}`}>{children}</span>;
24}
25
26// atoms/Avatar.jsx
27function Avatar({ src, name, size = 'md' }) {
28  return (
29    <img
30      className={`avatar avatar-${size}`}
31      src={src}
32      alt={name}
33    />
34  );
35}

2. Molecules (Molekuły) -- Kombinacje atomów

Molekuły łączą kilka atomów w funkcjonalną grupę:

1// molecules/SearchBar.jsx
2function SearchBar({ onSearch }) {
3  const [query, setQuery] = useState('');
4
5  return (
6    <div className="search-bar">
7      <Input
8        placeholder="Szukaj planety..."
9        value={query}
10        onChange={(e) => setQuery(e.target.value)}
11      />
12      <Button onClick={() => onSearch(query)}>Szukaj</Button>
13    </div>
14  );
15}
16
17// molecules/UserCard.jsx
18function UserCard({ user }) {
19  return (
20    <div className="user-card">
21      <Avatar src={user.avatar} name={user.name} />
22      <div>
23        <h4>{user.name}</h4>
24        <Badge color={user.role === 'captain' ? 'gold' : 'blue'}>
25          {user.role}
26        </Badge>
27      </div>
28    </div>
29  );
30}

3. Organisms (Organizmy) -- Sekcje interfejsu

Organizmy to złożone elementy budowane z molekuł i atomów:

1// organisms/CrewPanel.jsx
2function CrewPanel({ crew, onSearch, onSelect }) {
3  const [filtered, setFiltered] = useState(crew);
4
5  const handleSearch = (query) => {
6    const results = crew.filter(m =>
7      m.name.toLowerCase().includes(query.toLowerCase())
8    );
9    setFiltered(results);
10    onSearch(query);
11  };
12
13  return (
14    <section className="crew-panel">
15      <h2>Zaloga</h2>
16      <SearchBar onSearch={handleSearch} />
17      <div className="crew-grid">
18        {filtered.map(member => (
19          <UserCard
20            key={member.id}
21            user={member}
22            onClick={() => onSelect(member)}
23          />
24        ))}
25      </div>
26    </section>
27  );
28}

4. Templates -- Szkielety stron

Templates definiują układ strony bez konkretnych danych:

1// templates/DashboardTemplate.jsx
2function DashboardTemplate({ header, sidebar, main, footer }) {
3  return (
4    <div className="dashboard-layout">
5      <header className="dash-header">{header}</header>
6      <div className="dash-body">
7        <aside className="dash-sidebar">{sidebar}</aside>
8        <main className="dash-main">{main}</main>
9      </div>
10      <footer className="dash-footer">{footer}</footer>
11    </div>
12  );
13}

5. Pages -- Gotowe strony z danymi

Pages łączą template z konkretnymi danymi:

1// pages/MissionDashboard.jsx
2function MissionDashboard() {
3  const { data: crew } = useFetch('/api/crew');
4  const { data: missions } = useFetch('/api/missions');
5
6  return (
7    <DashboardTemplate
8      header={<NavigationBar />}
9      sidebar={<CrewPanel crew={crew} />}
10      main={<MissionMap missions={missions} />}
11      footer={<StatusBar />}
12    />
13  );
14}

Struktura folderów

1src/
2  components/
3    atoms/
4      Button.jsx
5      Input.jsx
6      Badge.jsx
7    molecules/
8      SearchBar.jsx
9      UserCard.jsx
10    organisms/
11      CrewPanel.jsx
12      NavigationBar.jsx
13    templates/
14      DashboardTemplate.jsx
15    pages/
16      MissionDashboard.jsx

Kiedy Atomic Design się sprawdza?

Atomic Design najlepiej działa w dużych projektach z wieloma stronami i komponentami. Jeśli budujesz prostą aplikację z kilkoma widokami, pełna hierarchia pięciu poziomów może być przesadą. W takim przypadku wystarczy prosty podział na

components/
i
pages/
.

Jednak w projektach na skalę kosmicznej stacji -- z dziesiątkami ekranów, formularzami, dashboardami -- Atomic Design przynosi ogromne korzyści:

  • Ponowne użycie -- raz zbudowany atom
    Button
    jest używany w dziesiątkach miejsc
  • Spójność -- wszystkie przyciski w aplikacji wyglądają tak samo
  • Łatwość testowania -- atomy testuje się w izolacji, bez zależności
  • Onboarding -- nowy programista szybko rozumie, gdzie szukać komponentów

Zasady kciuka

  • Atom -- jeden element HTML lub najprostszy komponent (Button, Input, Badge, Icon)
  • Molekuła -- 2-3 atomy połączone w jedną funkcję (SearchBar = Input + Button)
  • Organizm -- sekcja strony z logiką biznesową (CrewPanel z wyszukiwaniem i listą)
  • Template -- układ strony bez danych (sloty na header, sidebar, main)
  • Page -- template wypełniony konkretnymi danymi z API

Jeśli nie jesteś pewien, na którym poziomie umieścić komponent, zadaj sobie pytanie: "Czy ten komponent ma sens sam w sobie, czy potrzebuje kontekstu?" Atom działa wszędzie. Molekuła potrzebuje atomów. Organizm potrzebuje molekuł i logiki biznesowej.

Ir a CodeWorlds