Breadcrumbs
The Breadcrumbs component provides accessible navigation hierarchy for React applications. It shows the current page location within the application structure with full keyboard navigation support and customizable appearance.
Features
- ✅ Accessible Navigation - Full WCAG 2.1 AA compliance with proper ARIA labels
- ✅ Keyboard Support - Complete keyboard navigation with Tab, Enter, and Space
- ✅ Customizable Appearance - Custom separators, icons, and styling
- ✅ Smart Truncation - Automatic ellipsis for long navigation paths
- ✅ Hook Integration - Built-in state management hook
- ✅ Responsive Design - Adapts to different screen sizes
Basic Usage
import { Breadcrumbs } from '@qwickapps/react-framework';
const breadcrumbItems = [
{ label: 'Home', href: '/' },
{ label: 'Products', href: '/products' },
{ label: 'Electronics', href: '/products/electronics' },
{ label: 'Laptop', href: '/products/electronics/laptop', current: true },
];
function Navigation() {
return <Breadcrumbs items={breadcrumbItems} />;
}
With Icons
import { Breadcrumbs } from '@qwickapps/react-framework';
import { HomeIcon, FolderIcon, FileIcon } from '@icons/react';
const breadcrumbsWithIcons = [
{
label: 'Home',
href: '/',
icon: <HomeIcon />
},
{
label: 'Documents',
href: '/documents',
icon: <FolderIcon />
},
{
label: 'Report.pdf',
href: '/documents/report.pdf',
icon: <FileIcon />,
current: true
},
];
function FileNavigation() {
return (
<Breadcrumbs
items={breadcrumbsWithIcons}
separator="→"
/>
);
}
Custom Navigation Handler
import { Breadcrumbs } from '@qwickapps/react-framework';
import { useRouter } from 'next/router';
function AppNavigation() {
const router = useRouter();
const handleNavigate = (item, index) => {
// Custom navigation logic
if (item.href) {
router.push(item.href);
}
};
return (
<Breadcrumbs
items={breadcrumbItems}
onNavigate={handleNavigate}
/>
);
}
Dynamic Breadcrumbs with Hook
import { Breadcrumbs, useBreadcrumbs } from '@qwickapps/react-framework';
function DynamicNavigation() {
const {
breadcrumbs,
addBreadcrumb,
removeBreadcrumb,
setBreadcrumbs,
clearBreadcrumbs
} = useBreadcrumbs();
const navigateToSection = (section) => {
setBreadcrumbs([
{ label: 'Home', href: '/' },
{ label: section.name, href: section.url, current: true }
]);
};
const addSubsection = (subsection) => {
addBreadcrumb({
label: subsection.name,
href: subsection.url,
current: true
});
};
return (
<div>
<Breadcrumbs items={breadcrumbs} />
<div>
<button onClick={() => addSubsection({ name: 'New Section', url: '/new' })}>
Add Level
</button>
<button onClick={() => removeBreadcrumb(breadcrumbs.length - 1)}>
Go Back
</button>
<button onClick={clearBreadcrumbs}>
Reset Navigation
</button>
</div>
</div>
);
}
Truncated Long Paths
// Long navigation paths are automatically truncated
const longPath = [
{ label: 'Home', href: '/' },
{ label: 'Level 1', href: '/level1' },
{ label: 'Level 2', href: '/level1/level2' },
{ label: 'Level 3', href: '/level1/level2/level3' },
{ label: 'Level 4', href: '/level1/level2/level3/level4' },
{ label: 'Current Page', href: '/level1/level2/level3/level4/current', current: true },
];
function TruncatedNavigation() {
return (
<Breadcrumbs
items={longPath}
maxItems={4} // Shows: Home > ... > Level 4 > Current Page
/>
);
}
Props
Breadcrumbs Component
| Prop | Type | Default | Description |
|---|---|---|---|
items | BreadcrumbItem[] | required | Array of breadcrumb items |
separator | ReactNode | '/' | Custom separator between items |
className | string | '' | Additional CSS classes |
onNavigate | (item, index) => void | - | Navigation handler (overrides href) |
maxItems | number | - | Maximum items before truncation |
showRoot | boolean | true | Whether to show the first item |
BreadcrumbItem Interface
interface BreadcrumbItem {
label: string; // Display text
href?: string; // Link destination
icon?: ReactNode; // Optional icon
current?: boolean; // Mark as current page
}
useBreadcrumbs Hook
Provides state management for dynamic breadcrumb navigation:
const {
breadcrumbs, // Current breadcrumb items
addBreadcrumb, // Add item to end
removeBreadcrumb, // Remove item by index
setBreadcrumbs, // Replace all items
clearBreadcrumbs // Remove all items
} = useBreadcrumbs();
Hook Methods
| Method | Signature | Description |
|---|---|---|
addBreadcrumb | (item: BreadcrumbItem) => void | Add new breadcrumb to the end |
removeBreadcrumb | (index: number) => void | Remove breadcrumb at index |
setBreadcrumbs | (items: BreadcrumbItem[]) => void | Replace entire breadcrumb array |
clearBreadcrumbs | () => void | Remove all breadcrumbs |
Accessibility Features
ARIA Support
role="navigation"witharia-label="Breadcrumb navigation"aria-current="page"on current page item- Proper semantic markup with ordered list
Keyboard Navigation
- Tab - Navigate between breadcrumb links
- Enter - Activate breadcrumb link
- Space - Activate breadcrumb link (alternative)
Screen Reader Support
- Announces breadcrumb navigation context
- Identifies current page location
- Properly labels interactive elements
Styling
Default Styles
Breadcrumbs includes sensible default styles:
.breadcrumbs {
display: flex;
align-items: center;
font-size: 14px;
color: #6b7280;
padding: 8px 0;
}
.breadcrumbs ol {
display: flex;
align-items: center;
list-style: none;
margin: 0;
padding: 0;
gap: 8px;
}
.breadcrumbs a {
transition: color 0.2s ease;
cursor: pointer;
border-radius: 4px;
padding: 4px;
text-decoration: none;
}
Custom Styling
<Breadcrumbs
items={items}
className="custom-breadcrumbs"
style={{
backgroundColor: '#f5f5f5',
borderRadius: '8px',
padding: '12px 16px'
}}
/>
.custom-breadcrumbs a {
color: #2563eb;
font-weight: 500;
}
.custom-breadcrumbs a:hover {
color: #1d4ed8;
background-color: #dbeafe;
}
.custom-breadcrumbs [aria-current="page"] {
color: #1f2937;
font-weight: 600;
}
Examples
E-commerce Product Navigation
function ProductBreadcrumbs({ category, subcategory, product }) {
const breadcrumbs = [
{ label: 'Home', href: '/', icon: <HomeIcon /> },
{ label: 'Products', href: '/products' },
{ label: category.name, href: `/products/${category.slug}` },
{ label: subcategory.name, href: `/products/${category.slug}/${subcategory.slug}` },
{ label: product.name, href: product.url, current: true },
];
return (
<Breadcrumbs
items={breadcrumbs}
separator="›"
onNavigate={(item) => {
// Track breadcrumb navigation
analytics.track('breadcrumb_click', { item: item.label });
}}
/>
);
}
File System Navigation
function FileBrowser({ path }) {
const pathSegments = path.split('/').filter(Boolean);
const breadcrumbs = [
{ label: 'Root', href: '/', icon: <FolderIcon /> },
...pathSegments.map((segment, index) => ({
label: segment,
href: '/' + pathSegments.slice(0, index + 1).join('/'),
icon: index === pathSegments.length - 1 ? <FileIcon /> : <FolderIcon />,
current: index === pathSegments.length - 1
}))
];
return (
<Breadcrumbs
items={breadcrumbs}
maxItems={5}
/>
);
}
Admin Dashboard Navigation
function AdminBreadcrumbs() {
const { breadcrumbs, setBreadcrumbs } = useBreadcrumbs();
const location = useLocation();
useEffect(() => {
// Update breadcrumbs based on current route
const pathSegments = location.pathname.split('/').filter(Boolean);
const newBreadcrumbs = [
{ label: 'Dashboard', href: '/admin', icon: <DashboardIcon /> },
...pathSegments.map((segment, index) => {
const href = '/admin/' + pathSegments.slice(0, index + 1).join('/');
return {
label: formatSegmentName(segment),
href,
current: index === pathSegments.length - 1
};
})
];
setBreadcrumbs(newBreadcrumbs);
}, [location.pathname, setBreadcrumbs]);
return <Breadcrumbs items={breadcrumbs} />;
}
function formatSegmentName(segment) {
return segment.charAt(0).toUpperCase() + segment.slice(1).replace('-', ' ');
}
Multi-step Form Navigation
function FormStepBreadcrumbs({ currentStep, steps }) {
const breadcrumbs = steps.map((step, index) => ({
label: step.title,
href: step.url,
current: index === currentStep,
icon: index < currentStep ? <CheckIcon /> : <StepIcon />
}));
return (
<Breadcrumbs
items={breadcrumbs}
separator="→"
onNavigate={(item, index) => {
// Only allow navigation to completed steps
if (index < currentStep) {
navigateToStep(index);
}
}}
/>
);
}
Best Practices
- Provide Context - Always include a root/home breadcrumb
- Mark Current Page - Use
current: truefor the active page - Use Semantic Icons - Choose icons that represent the content type
- Handle Long Paths - Use
maxItemsfor deep navigation hierarchies - Custom Navigation - Implement
onNavigatefor SPA routing - Consistent Separators - Use the same separator throughout your app
- Keyboard Testing - Ensure all breadcrumbs are keyboard accessible
Integration with Routing Libraries
Next.js
import { useRouter } from 'next/router';
function NextBreadcrumbs({ items }) {
const router = useRouter();
return (
<Breadcrumbs
items={items}
onNavigate={(item) => router.push(item.href)}
/>
);
}
React Router
import { useNavigate } from 'react-router-dom';
function RouterBreadcrumbs({ items }) {
const navigate = useNavigate();
return (
<Breadcrumbs
items={items}
onNavigate={(item) => navigate(item.href)}
/>
);
}