Claude
Skills
Sign in
Back

atomic-design-organisms

Included with Lifetime
$97 forever

Use when building complex organisms from molecules and atoms like headers, footers, product cards, and sidebars. Organisms are distinct UI sections.

Design

What this skill does


# Atomic Design: Organisms

Master the creation of organisms - complex, distinct sections of an interface composed of molecules and atoms. Organisms represent standalone UI sections that could exist independently.

## What Are Organisms?

Organisms are relatively complex UI components that form distinct sections of an interface. They are:

- **Composed of molecules and atoms**: May include both levels
- **Standalone sections**: Can exist independently on a page
- **Context-aware**: Often tied to specific business contexts
- **Stateful**: May manage significant internal state
- **Reusable**: Used across different templates and pages

## Common Organism Types

### Navigation Organisms

- Header (logo + navigation + user menu)
- Footer (links + social icons + legal)
- Sidebar (navigation + user info + actions)
- Breadcrumbs (full navigation path)

### Content Organisms

- Product cards (image + details + actions)
- Comment sections (comments + reply forms)
- Article previews (title + excerpt + meta)
- User profiles (avatar + bio + stats)

### Form Organisms

- Login forms (fields + actions + links)
- Registration forms (multi-step fields)
- Checkout forms (payment + shipping)
- Search with filters

### Data Display Organisms

- Data tables (header + rows + pagination)
- Dashboards (stats + charts + actions)
- Timelines (events + connectors)
- Galleries (images + navigation)

## Header Organism Example

### Complete Implementation

```typescript
// organisms/Header/Header.tsx
import React, { useState } from 'react';
import { Icon } from '@/components/atoms/Icon';
import { Button } from '@/components/atoms/Button';
import { Avatar } from '@/components/atoms/Avatar';
import { NavItem } from '@/components/molecules/NavItem';
import { SearchForm } from '@/components/molecules/SearchForm';
import styles from './Header.module.css';

export interface NavLink {
  id: string;
  label: string;
  href: string;
  icon?: string;
  badge?: number;
}

export interface User {
  id: string;
  name: string;
  email: string;
  avatar?: string;
}

export interface HeaderProps {
  /** Logo element or image */
  logo: React.ReactNode;
  /** Navigation links */
  navigation: NavLink[];
  /** Current active nav item */
  activeNavId?: string;
  /** Authenticated user */
  user?: User | null;
  /** Show search form */
  showSearch?: boolean;
  /** Search submit handler */
  onSearch?: (query: string) => void;
  /** Login click handler */
  onLogin?: () => void;
  /** Logout click handler */
  onLogout?: () => void;
  /** Profile click handler */
  onProfileClick?: () => void;
}

export const Header: React.FC<HeaderProps> = ({
  logo,
  navigation,
  activeNavId,
  user,
  showSearch = true,
  onSearch,
  onLogin,
  onLogout,
  onProfileClick,
}) => {
  const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
  const [userMenuOpen, setUserMenuOpen] = useState(false);

  return (
    <header className={styles.header}>
      <div className={styles.container}>
        {/* Logo */}
        <div className={styles.logo}>{logo}</div>

        {/* Desktop Navigation */}
        <nav className={styles.nav} aria-label="Main navigation">
          <ul className={styles.navList}>
            {navigation.map((item) => (
              <li key={item.id}>
                <NavItem
                  label={item.label}
                  href={item.href}
                  icon={item.icon}
                  badge={item.badge}
                  isActive={item.id === activeNavId}
                />
              </li>
            ))}
          </ul>
        </nav>

        {/* Search */}
        {showSearch && onSearch && (
          <div className={styles.search}>
            <SearchForm
              onSubmit={onSearch}
              placeholder="Search..."
              size="sm"
            />
          </div>
        )}

        {/* User Actions */}
        <div className={styles.actions}>
          {user ? (
            <div className={styles.userMenu}>
              <button
                className={styles.userButton}
                onClick={() => setUserMenuOpen(!userMenuOpen)}
                aria-expanded={userMenuOpen}
                aria-haspopup="true"
              >
                <Avatar
                  src={user.avatar}
                  alt={user.name}
                  initials={user.name.slice(0, 2).toUpperCase()}
                  size="sm"
                />
                <span className={styles.userName}>{user.name}</span>
                <Icon name="chevron-down" size="xs" />
              </button>

              {userMenuOpen && (
                <div className={styles.dropdown}>
                  <button onClick={onProfileClick}>
                    <Icon name="user" size="sm" />
                    Profile
                  </button>
                  <button onClick={onLogout}>
                    <Icon name="log-out" size="sm" />
                    Logout
                  </button>
                </div>
              )}
            </div>
          ) : (
            <Button variant="primary" size="sm" onClick={onLogin}>
              Login
            </Button>
          )}
        </div>

        {/* Mobile Menu Toggle */}
        <button
          className={styles.mobileToggle}
          onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
          aria-expanded={mobileMenuOpen}
          aria-label="Toggle menu"
        >
          <Icon name={mobileMenuOpen ? 'x' : 'menu'} size="md" />
        </button>
      </div>

      {/* Mobile Navigation */}
      {mobileMenuOpen && (
        <nav className={styles.mobileNav} aria-label="Mobile navigation">
          <ul>
            {navigation.map((item) => (
              <li key={item.id}>
                <NavItem
                  label={item.label}
                  href={item.href}
                  icon={item.icon}
                  badge={item.badge}
                  isActive={item.id === activeNavId}
                  onClick={() => setMobileMenuOpen(false)}
                />
              </li>
            ))}
          </ul>
        </nav>
      )}
    </header>
  );
};

Header.displayName = 'Header';
```

```css
/* organisms/Header/Header.module.css */
.header {
  position: sticky;
  top: 0;
  z-index: 100;
  background-color: var(--color-white);
  border-bottom: 1px solid var(--color-neutral-200);
}

.container {
  display: flex;
  align-items: center;
  gap: 24px;
  max-width: 1280px;
  margin: 0 auto;
  padding: 12px 24px;
}

.logo {
  flex-shrink: 0;
}

.nav {
  display: none;
  flex: 1;
}

@media (min-width: 768px) {
  .nav {
    display: block;
  }
}

.navList {
  display: flex;
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.search {
  display: none;
  width: 280px;
}

@media (min-width: 1024px) {
  .search {
    display: block;
  }
}

.actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.userMenu {
  position: relative;
}

.userButton {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  background: transparent;
  border: 1px solid var(--color-neutral-200);
  border-radius: 6px;
  cursor: pointer;
}

.userName {
  display: none;
}

@media (min-width: 640px) {
  .userName {
    display: inline;
  }
}

.dropdown {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 8px;
  min-width: 160px;
  background: var(--color-white);
  border: 1px solid var(--color-neutral-200);
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.dropdown button {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 12px 16px;
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
}

.dropdown button:hover {
  background-color: var(--color-neutral-50);
}

.mobileToggle {
  display: flex;
  padding: 8px;
  background: transparent;
  border: none;
  cursor: pointer;
}

@media (min-width: 768px) {
  .mobileToggle {
    display: none;
  }
}

.mobileNav {
  border-top: 1px 

Related in Design