All files / src/components/shared/Breadcrumbs Breadcrumbs.tsx

100% Statements 14/14
91.66% Branches 11/12
100% Functions 4/4
100% Lines 14/14

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113                                                                                                          13x   70x   70x 48x 2x 2x         70x             118x 118x 118x     118x 70x               48x                                             13x      
/**
 * Breadcrumbs Component (Story 1.17 - Deferred Navigation Feature)
 *
 * Reusable breadcrumb navigation component providing contextual navigation trails.
 * Required for organizer role, optional for other roles.
 *
 * Features:
 * - Clickable navigation links
 * - Automatic home icon on first item
 * - Support for dynamic breadcrumb items
 * - i18n support for labels
 * - Accessible with proper ARIA labels
 * - MUI NavigateNext separator
 *
 * Usage:
 * ```tsx
 * <Breadcrumbs
 *   items={[
 *     { label: 'Home', path: '/organizer/events' },
 *     { label: 'Event Detail', path: '/organizer/events/BATbern56' },
 *     { label: 'Edit' } // Current page (no path = not clickable)
 *   ]}
 * />
 * ```
 */
 
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { Breadcrumbs as MuiBreadcrumbs, Link, Typography, Box } from '@mui/material';
import { Home as HomeIcon, NavigateNext as NavigateNextIcon } from '@mui/icons-material';
 
export interface BreadcrumbItem {
  /** Display label for the breadcrumb */
  label: string;
  /** Navigation path (if undefined, item is not clickable - represents current page) */
  path?: string;
  /** Optional icon to display before label (only for first item if not provided) */
  icon?: React.ReactNode;
}
 
export interface BreadcrumbsProps {
  /** Array of breadcrumb items to display */
  items: BreadcrumbItem[];
  /** Optional aria-label for accessibility (defaults to "breadcrumb") */
  ariaLabel?: string;
  /** Optional margin bottom spacing (defaults to 3) */
  marginBottom?: number;
}
 
/**
 * Breadcrumbs component for contextual navigation.
 * Automatically adds Home icon to first item and handles navigation.
 */
export const Breadcrumbs: React.FC<BreadcrumbsProps> = React.memo(
  ({ items, ariaLabel = 'breadcrumb', marginBottom = 3 }) => {
    const navigate = useNavigate();
 
    const handleClick = React.useCallback(
      (path: string) => (event: React.MouseEvent) => {
        event.preventDefault();
        navigate(path);
      },
      [navigate]
    );
 
    return (
      <MuiBreadcrumbs
        separator={<NavigateNextIcon fontSize="small" />}
        aria-label={ariaLabel}
        sx={{ mb: marginBottom }}
      >
        {items.map((item, index) => {
          const isFirst = index === 0;
          const isLast = index === items.length - 1;
          const showHomeIcon = isFirst && !item.icon;
 
          // Current page (no path) - not clickable
          if (!item.path || isLast) {
            return (
              <Typography key={index} color="text.primary">
                {item.label}
              </Typography>
            );
          }
 
          // Clickable link
          return (
            <Link
              key={index}
              underline="hover"
              color="inherit"
              sx={{
                display: 'flex',
                alignItems: 'center',
                cursor: 'pointer',
              }}
              onClick={handleClick(item.path)}
            >
              {showHomeIcon && <HomeIcon sx={{ mr: 0.5 }} fontSize="inherit" />}
              {item.icon && <Box sx={{ mr: 0.5, display: 'flex' }}>{item.icon}</Box>}
              {item.label}
            </Link>
          );
        })}
      </MuiBreadcrumbs>
    );
  }
);
 
Breadcrumbs.displayName = 'Breadcrumbs';
 
export default Breadcrumbs;