# Breadcrumbs

## Introduction

The Breadcrumbs component displays a navigation trail that helps users understand their current location within a website's hierarchy and navigate back to previous levels. It shows the path from the homepage to the current page, with each level represented as a clickable link (except for the current page). Breadcrumbs improve user experience by providing context and enabling quick navigation.

```tsx
<Breadcrumbs
  crumbs={[{
  label: 'Home',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Catalog',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Category',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Subcategory',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Product',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Product Detail',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Owner',
  type: 'text'
}]}
  collapsed
/>
```

| Field           | Description | Default |
| --------------- | ----------- | ------- |
| startCrumbCount | —           | —       |
| endCrumbCount   | —           | —       |
| collapsed       | —           | true    |
| separator       | —           | —       |
| size            | —           | —       |

## Usage

```tsx
import { Breadcrumbs } from '@ceed/ads';

function MyComponent() {
  const crumbs = [
    { label: 'Home', type: 'link', linkHref: '/' },
    { label: 'Products', type: 'link', linkHref: '/products' },
    { label: 'Electronics', type: 'link', linkHref: '/products/electronics' },
    { label: 'Laptops', type: 'text' }, // Current page (not a link)
  ];

  return <Breadcrumbs crumbs={crumbs} />;
}
```

## Examples

### Basic Breadcrumbs

A simple breadcrumb navigation with three levels.

```tsx
<Breadcrumbs
  crumbs={[{
  label: 'Home',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Products',
  type: 'link',
  linkHref: '/products'
}, {
  label: 'Electronics',
  type: 'text'
}]}
  collapsed={false}
/>
```

### Sizes

Breadcrumbs support different sizes.

```tsx
<div>
  <Breadcrumbs {...args} size="sm" />
  <Breadcrumbs {...args} size="md" />
  <Breadcrumbs {...args} size="lg" />
</div>
```

### With Custom Separator

Customize the separator between breadcrumb items.

```tsx
<div style={{
  display: 'flex',
  flexDirection: 'column',
  gap: 16
}}>
<Breadcrumbs separator="/" crumbs={[{
  label: 'Home',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Category',
  type: 'link',
  linkHref: '/category'
}, {
  label: 'Item',
  type: 'text'
}]} collapsed={false} />
<Breadcrumbs separator=">" crumbs={[{
  label: 'Home',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Category',
  type: 'link',
  linkHref: '/category'
}, {
  label: 'Item',
  type: 'text'
}]} collapsed={false} />
<Breadcrumbs separator="-" crumbs={[{
  label: 'Home',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Category',
  type: 'link',
  linkHref: '/category'
}, {
  label: 'Item',
  type: 'text'
}]} collapsed={false} />
</div>
```

### Collapsed Breadcrumbs

For deep hierarchies, breadcrumbs can be collapsed with an ellipsis.

```tsx
<Breadcrumbs
  crumbs={[{
  label: 'Home',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Catalog',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Category',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Subcategory',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Product',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Product Detail',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Owner',
  type: 'text'
}]}
  collapsed
/>
```

### Collapsed Variants

Configure how many items show at the start and end when collapsed.

```tsx
<div style={{
  display: 'flex',
  flexDirection: 'column',
  gap: 16
}}>
<div>
  <span style={{
    fontSize: 12,
    color: '#666'
  }}>startCrumbCount: 1, endCrumbCount: 2</span>
  <Breadcrumbs crumbs={[{
    label: 'Home',
    type: 'link',
    linkHref: '/'
  }, {
    label: 'Products',
    type: 'link',
    linkHref: '/products'
  }, {
    label: 'Electronics',
    type: 'link',
    linkHref: '/electronics'
  }, {
    label: 'Computers',
    type: 'link',
    linkHref: '/computers'
  }, {
    label: 'Laptops',
    type: 'text'
  }]} collapsed={true} startCrumbCount={1} endCrumbCount={2} />
</div>
<div>
  <span style={{
    fontSize: 12,
    color: '#666'
  }}>startCrumbCount: 2, endCrumbCount: 1</span>
  <Breadcrumbs crumbs={[{
    label: 'Home',
    type: 'link',
    linkHref: '/'
  }, {
    label: 'Products',
    type: 'link',
    linkHref: '/products'
  }, {
    label: 'Electronics',
    type: 'link',
    linkHref: '/electronics'
  }, {
    label: 'Computers',
    type: 'link',
    linkHref: '/computers'
  }, {
    label: 'Laptops',
    type: 'text'
  }]} collapsed={true} startCrumbCount={2} endCrumbCount={1} />
</div>
</div>
```

### Single Crumb

When there's only one item in the path.

```tsx
<Breadcrumbs
  crumbs={[{
  label: 'Home',
  type: 'text'
}]}
  collapsed
/>
```

### Expanded View

Show all breadcrumb items without collapsing.

```tsx
<Breadcrumbs
  crumbs={[{
  label: 'Home',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Catalog',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Category',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Subcategory',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Product',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Product Detail',
  type: 'link',
  linkHref: '/'
}, {
  label: 'Owner',
  type: 'text'
}]}
  collapsed={false}
/>
```

## When to Use

### ✅ Good Use Cases

- **Deep hierarchies**: Sites with 3+ levels of navigation depth
- **E-commerce sites**: Product category → subcategory → product navigation
- **Documentation sites**: Section → topic → article navigation
- **File management**: Folder → subfolder → file navigation
- **Admin dashboards**: Module → submodule → detail view
- **Content management**: Categories and nested content structures

### ❌ When Not to Use

- **Flat sites**: Single-level navigation doesn't need breadcrumbs
- **Linear flows**: For sequential processes, use Stepper instead
- **Primary navigation**: Breadcrumbs supplement, not replace, main navigation
- **Mobile-first**: Consider if space allows; may need alternative patterns
- **Dynamic content**: When paths frequently change or are user-specific

## Common Use Cases

### E-commerce Product Page

```tsx
function ProductPage({ product, category, subcategory }) {
  const crumbs = [
    { label: 'Home', type: 'link', linkHref: '/' },
    { label: 'Shop', type: 'link', linkHref: '/shop' },
    { label: category.name, type: 'link', linkHref: `/shop/${category.slug}` },
    { label: subcategory.name, type: 'link', linkHref: `/shop/${category.slug}/${subcategory.slug}` },
    { label: product.name, type: 'text' },
  ];

  return (
    <Box>
      <Breadcrumbs crumbs={crumbs} />
      <ProductDetails product={product} />
    </Box>
  );
}
```

### Documentation Page

```tsx
function DocPage({ section, topic, article }) {
  const crumbs = [
    { label: 'Docs', type: 'link', linkHref: '/docs' },
    { label: section.title, type: 'link', linkHref: `/docs/${section.slug}` },
    { label: topic.title, type: 'link', linkHref: `/docs/${section.slug}/${topic.slug}` },
    { label: article.title, type: 'text' },
  ];

  return (
    <Stack spacing={2}>
      <Breadcrumbs crumbs={crumbs} size="sm" />
      <Typography level="h1">{article.title}</Typography>
      <ArticleContent content={article.content} />
    </Stack>
  );
}
```

### File Browser

```tsx
function FileBrowser({ path }) {
  const crumbs = [
    { label: 'Root', type: 'link', linkHref: '/files' },
    ...path.map((folder, index) => ({
      label: folder.name,
      type: index === path.length - 1 ? 'text' : 'link',
      linkHref: `/files/${path.slice(0, index + 1).map(f => f.id).join('/')}`,
    })),
  ];

  return (
    <Box>
      <Breadcrumbs crumbs={crumbs} collapsed={path.length > 4} />
      <FileList folderId={path[path.length - 1].id} />
    </Box>
  );
}
```

### Admin Dashboard

```tsx
function UserDetailPage({ user }) {
  const crumbs = [
    { label: 'Dashboard', type: 'link', linkHref: '/admin' },
    { label: 'Users', type: 'link', linkHref: '/admin/users' },
    { label: user.name, type: 'text' },
  ];

  return (
    <Box>
      <Breadcrumbs crumbs={crumbs} />
      <UserProfile user={user} />
    </Box>
  );
}
```

### Dynamic Breadcrumbs from Route

```tsx
function DynamicBreadcrumbs() {
  const location = useLocation();
  const pathnames = location.pathname.split('/').filter((x) => x);

  const crumbs = [
    { label: 'Home', type: 'link', linkHref: '/' },
    ...pathnames.map((value, index) => {
      const href = `/${pathnames.slice(0, index + 1).join('/')}`;
      const isLast = index === pathnames.length - 1;

      return {
        label: formatLabel(value),
        type: isLast ? 'text' : 'link',
        linkHref: href,
      };
    }),
  ];

  return <Breadcrumbs crumbs={crumbs} />;
}
```

## Props and Customization

### Key Props

| Prop              | Type                   | Default | Description                                     |
| ----------------- | ---------------------- | ------- | ----------------------------------------------- |
| `crumbs`          | `Crumb[]`              | `[]`    | Array of breadcrumb items                       |
| `collapsed`       | `boolean`              | `true`  | Collapse middle items with ellipsis             |
| `startCrumbCount` | `number`               | `1`     | Number of items to show at start when collapsed |
| `endCrumbCount`   | `number`               | `3`     | Number of items to show at end when collapsed   |
| `separator`       | `string`               | `'/'`   | Separator between items                         |
| `size`            | `'sm' \| 'md' \| 'lg'` | `'md'`  | Size of the breadcrumbs                         |

### Crumb Type

```tsx
interface Crumb {
  label: string;            // Display text
  type: 'link' | 'text';    // Link or static text
  linkHref?: string;        // URL for link type
}
```

### Collapsed Behavior

When `collapsed` is true and there are more items than `startCrumbCount + endCrumbCount`, middle items are replaced with an ellipsis:

```tsx
// With startCrumbCount=1, endCrumbCount=2, and 6 crumbs:
// Home / ... / Category / Product

<Breadcrumbs
  crumbs={crumbs}
  collapsed={true}
  startCrumbCount={1}
  endCrumbCount={2}
/>
```

### Custom Styling

```tsx
<Breadcrumbs
  crumbs={crumbs}
  sx={{
    '& .MuiBreadcrumbs-separator': {
      mx: 1,
      color: 'neutral.400',
    },
    '& a': {
      color: 'primary.500',
      textDecoration: 'none',
      '&:hover': {
        textDecoration: 'underline',
      },
    },
  }}
/>
```

## Accessibility

Breadcrumbs include important accessibility features:

### Semantic HTML

- Uses `<nav>` element with `aria-label="breadcrumb"`
- Structured as an ordered list (`<ol>`) to indicate sequence
- Current page marked with `aria-current="page"`

### ARIA Attributes

```tsx
// Generated HTML structure
<nav aria-label="breadcrumb">
  <ol>
    <li><a href="/">Home</a></li>
    <li><a href="/products">Products</a></li>
    <li aria-current="page">Current Page</li>
  </ol>
</nav>
```

### Keyboard Navigation

- **Tab**: Navigate through breadcrumb links
- **Enter**: Activate the focused link

### Screen Reader Support

- Screen readers announce "breadcrumb navigation"
- Each link is announced with its position in the sequence
- Current page is identified as the current location

### SEO Benefits

Breadcrumbs provide:

- Clear site structure for search engines
- Enhanced search result display (rich snippets)
- Improved internal linking

## Best Practices

### ✅ Do

1. **Start with Home**: Always begin with a link to the homepage

```tsx
// ✅ Good: Starts with Home
const crumbs = [
  { label: 'Home', type: 'link', linkHref: '/' },
  { label: 'Products', type: 'link', linkHref: '/products' },
  { label: 'Laptops', type: 'text' },
];
```

2. **Make current page non-clickable**: The last item should be text, not a link

```tsx
// ✅ Good: Current page is text
{ label: 'Current Page', type: 'text' }

// ❌ Bad: Current page is a link
{ label: 'Current Page', type: 'link', linkHref: '/current' }
```

3. **Use clear, concise labels**: Keep labels short but descriptive

4. **Maintain consistency**: Use the same labels as page titles or navigation

5. **Position at top**: Place breadcrumbs near the top of the page, below the header

### ❌ Don't

1. **Don't use as primary navigation**: Breadcrumbs supplement main navigation

2. **Don't duplicate with page title**: If the current page title is visible, breadcrumbs can end with the parent

```tsx
// Consider ending at parent if title is displayed
const crumbs = [
  { label: 'Home', type: 'link', linkHref: '/' },
  { label: 'Products', type: 'link', linkHref: '/products' },
  // Omit if "Laptops" is shown as page title
];
```

3. **Don't use for flat navigation**: Sites with only one or two levels don't need breadcrumbs

4. **Don't hide on mobile carelessly**: Either show a simplified version or omit entirely

## Performance Considerations

### Memoize Crumbs

When breadcrumbs are computed from props or state, memoize them:

```tsx
const crumbs = useMemo(() => [
  { label: 'Home', type: 'link', linkHref: '/' },
  { label: category.name, type: 'link', linkHref: `/category/${category.id}` },
  { label: product.name, type: 'text' },
], [category, product]);

<Breadcrumbs crumbs={crumbs} />
```

### Use Collapsed for Deep Hierarchies

For paths with many levels, use collapsing to reduce DOM elements:

```tsx
<Breadcrumbs
  crumbs={deepHierarchy}
  collapsed={true}
  startCrumbCount={1}
  endCrumbCount={2}
/>
```

### Lazy Load for Dynamic Breadcrumbs

If breadcrumb data requires fetching, ensure it doesn't block page render:

```tsx
function Page() {
  const { data: breadcrumbData, isLoading } = useBreadcrumbPath();

  return (
    <Box>
      {!isLoading && <Breadcrumbs crumbs={breadcrumbData} />}
      <PageContent />
    </Box>
  );
}
```

Breadcrumbs are a simple but powerful navigation aid that helps users understand where they are and navigate efficiently. Use them consistently across your site to improve user experience and SEO.
