UNPKG

@casoon/dragonfly

Version:

Modular, lightweight CSS framework and design system for modern web projects. Optimized for Astro JS, LightningCSS and Container Queries with @layer-based architecture and comprehensive accessibility.

540 lines (458 loc) 13.8 kB
/** * Breadcrumb Navigation Components * * Flexible breadcrumb system with multiple layout types and utility classes. * Uses CSS Nesting and Container Queries for modern responsive design. * * @layer: components * * Breadcrumb Types: * - .breadcrumbs: Base breadcrumb navigation * - .breadcrumbs-simple: Basic breadcrumb with separators * - .breadcrumbs-pills: Pill-style breadcrumbs * - .breadcrumbs-arrows: Arrow-style separators * - .breadcrumbs-slash: Slash separators * * Utility Classes: * - .compact: Reduced spacing * - .large: Increased spacing * - .center: Center alignment * - .theme-dark: Dark theme * - .truncated: Manual truncation * - .keep-all: Prevent auto-truncation on mobile * * BEM Classes (for compatibility): * - .list: Breadcrumb list * - .item: Breadcrumb item * - .link: Breadcrumb link * - .current: Current page * - .separator: Separator element * * Container Queries: * - Responsive text sizing * - Mobile truncation * - Automatic layout adjustments * * Accessibility: * - Use nav element with aria-label="Breadcrumb" * - Use ordered list (ol) for the breadcrumb items * - Current page should have aria-current="page" */ /* Note: header-tokens.css was removed - tokens are now defined inline */ @layer components { /* Breadcrumb tokens */ :root { /* Breadcrumb spacing */ --breadcrumb-padding: var(--space-3) 0; --breadcrumb-gap: var(--space-2); --breadcrumb-item-padding: var(--space-1) var(--space-2); /* Breadcrumb colors */ --breadcrumb-color: var(--color-neutral-600); --breadcrumb-link-color: var(--color-primary-600, #2563eb); --breadcrumb-link-hover: var(--color-primary-700, #1d4ed8); --breadcrumb-current-color: var(--color-neutral-900, #111827); --breadcrumb-separator-color: var(--color-neutral-400, #9ca3af); /* Breadcrumb typography */ --breadcrumb-font-size: var(--text-sm, 0.875rem); --breadcrumb-font-weight: var(--font-medium, 500); --breadcrumb-line-height: 1.5; /* Breadcrumb responsive breakpoints */ --breadcrumb-mobile-breakpoint: 768px; } /* Base breadcrumb container */ .breadcrumbs { align-items: center; color: var(--breadcrumb-color); container-type: inline-size; display: flex; font-size: var(--breadcrumb-font-size); font-weight: var(--breadcrumb-font-weight); line-height: var(--breadcrumb-line-height, 1.5); margin: var(--space-2) 0; padding: var(--breadcrumb-padding); /* Breadcrumb list (both ol/ul and BEM class) */ & ol, & ul, & .list { align-items: center; display: flex; flex-wrap: wrap; gap: var(--breadcrumb-gap); list-style: none; margin: 0; padding: 0; & li, & .item { align-items: center; display: flex; gap: var(--breadcrumb-gap); position: relative; &:not(:last-child)::after { color: var(--breadcrumb-separator-color); content: "/"; font-size: 0.875em; } &:last-child { color: var(--breadcrumb-current-color); font-weight: var(--font-semibold, 600); } } } /* BEM separator element */ & .separator { align-items: center; color: var(--breadcrumb-separator-color); display: inline-flex; margin: 0 var(--breadcrumb-gap); &::before { content: "/"; font-size: 0.85em; } } /* Breadcrumb links */ & a, & .link { color: var(--breadcrumb-link-color); padding: var(--breadcrumb-item-padding); text-decoration: none; transition: color 0.2s ease; &:hover, &:focus { color: var(--breadcrumb-link-hover); text-decoration: underline; } &:focus { outline: 2px solid var(--breadcrumb-link-color); outline-offset: 2px; } &[aria-current="page"] { color: var(--breadcrumb-current-color); cursor: default; font-weight: var(--font-semibold, 600); pointer-events: none; } } /* BEM current page element */ & .current { color: var(--breadcrumb-current-color); font-weight: var(--font-semibold, 600); } /* Home icon support */ & .home-icon { align-items: center; display: flex; & svg, & img { height: 1em; width: 1em; } } /* Manual truncation */ &.truncated { & ol li, & ul li, & .item { display: none; &:first-child, &:nth-last-child(2), &:last-child { display: flex; } } & ol li:nth-last-child(2)::before, & ul li:nth-last-child(2)::before, & .item:nth-last-child(2)::before { color: var(--breadcrumb-separator-color); content: "..."; margin: 0 var(--breadcrumb-gap); } } /* Utility modifiers */ &.compact { padding: var(--space-2) 0; & ol, & ul, & .list { gap: var(--space-1); } & a, & .link { padding: var(--space-1); } } &.large { font-size: var(--text-base); padding: var(--space-4) 0; & ol, & ul, & .list { gap: var(--space-3); } & a, & .link { padding: var(--space-2) var(--space-3); } } &.center { justify-content: center; text-align: center; & ol, & ul, & .list { justify-content: center; } } /* Container query responsive adjustments */ @container (width <= 768px) { font-size: var(--text-xs, 0.75rem); & ol, & ul, & .list { gap: var(--space-1); & li, & .item { gap: var(--space-1); &:not(:last-child)::after { font-size: 0.75em; } } } & a, & .link { padding: var(--space-1); } /* Auto-truncate on mobile (unless keep-all is set) */ &:not(.keep-all) { & ol li:not(:first-child, :last-child), & ul li:not(:first-child, :last-child), & .item:not(:first-child, :last-child) { display: none; } & ol li:first-child + li:not(:last-child), & ul li:first-child + li:not(:last-child), & .item:first-child + .item:not(:last-child) { display: flex; } & ol li:first-child + li::before, & ul li:first-child + li::before, & .item:first-child + .item::before { color: var(--breadcrumb-separator-color); content: "..."; margin: 0 var(--breadcrumb-gap); } } } @container (width <= 480px) { &:not(.keep-all) { & ol, & ul, & .list { & li:not(:first-child, :last-child), & .item:not(:first-child, :last-child) { display: none; } & li:nth-last-child(2)::before, & .item:nth-last-child(2)::before { content: "..."; margin-right: var(--space-1); } } } } } /* Breadcrumb Type: Simple (alias for base) */ .breadcrumbs-simple { /* Inherits all styles from base .breadcrumbs */ } /* Inherits all styles from base .breadcrumbs */ /* Breadcrumb Type: Pills */ .breadcrumbs-pills { & a, & .link { background-color: var(--color-neutral-100, #f3f4f6); border-radius: var(--radius-full, 9999px); &:hover, &:focus { background-color: var(--color-neutral-200, #e5e7eb); } &[aria-current="page"] { background-color: var(--color-primary-100, #dbeafe); } } & ol li:not(:last-child)::after, & ul li:not(:last-child)::after, & .separator::before { display: none; } } /* Breadcrumb Type: Arrows */ .breadcrumbs-arrows { & ol, & ul, & .list { gap: 0; & li, & .item { background-color: var(--color-neutral-100, #f3f4f6); gap: 0; position: relative; &:not(:first-child) { margin-left: -8px; padding-left: 6px; &::before { border-bottom: 2%0px solid transparent; border-left: 8px solid var(--color-neutral-100, #f3f4f6); border-top: 2%0px solid transparent; content: ""; height: 0%; left: 0%; position: absolute; top: 50%; transform: translateY(-50%); width: 0%; z-index: 1; } } &:not(:last-child)::after { border-bottom: 2%0px solid transparent; border-left: 8px solid var(--color-neutral-100, #f3f4f6); border-top: 2%0px solid transparent; content: ""; height: 0%; position: absolute; right: -8px; top: 50%; transform: translateY(-50%); width: 0%; z-index: 2; } &:last-child { background-color: var(--color-primary-100, #dbeafe); &::before { border-left-color: var(--color-primary-100, #dbeafe); } } } } & a, & .link { padding: var(--space-2) var(--space-4); } } /* Breadcrumb Type: Slash */ .breadcrumbs-slash { & ol li:not(:last-child)::after, & ul li:not(:last-child)::after, & .separator::before { content: "/"; font-size: 1em; font-weight: normal; } } /* Theme variants */ .breadcrumbs { &.theme-dark { --breadcrumb-color: var(--color-neutral-300, #d1d5db); --breadcrumb-link-color: var(--color-primary-400); --breadcrumb-link-hover: var(--color-primary-300); --breadcrumb-current-color: var(--color-neutral-100, #f3f4f6); --breadcrumb-separator-color: var(--color-neutral-500, #6b7280); &.breadcrumbs-pills a, &.breadcrumbs-pills .link { background-color: var(--color-neutral-800, #1f2937); &:hover, &:focus { background-color: var(--color-neutral-700, #374151); } &[aria-current="page"] { background-color: var(--color-primary-900); } } &.breadcrumbs-arrows { & ol li, & ul li, & .item { background-color: var(--color-neutral-800, #1f2937); &:not(:first-child)::before { border-left-color: var(--color-neutral-800, #1f2937); } &:not(:last-child)::after { border-left-color: var(--color-neutral-800, #1f2937); } &:last-child { background-color: var(--color-primary-900); &::before { border-left-color: var(--color-primary-900); } } } } } } /* Fallback media queries for browsers without container query support */ @supports not (container-type: inline-size) { @media (max-width: 768px) { .breadcrumbs { font-size: var(--text-xs, 0.75rem); & ol, & ul, & .list { gap: var(--space-1); & li, & .item { gap: var(--space-1); &:not(:last-child)::after { font-size: 0.75em; } } } & a, & .link { padding: var(--space-1); } /* Auto-truncate on mobile (unless keep-all is set) */ &:not(.keep-all) { & ol li:not(:first-child, :last-child), & ul li:not(:first-child, :last-child), & .item:not(:first-child, :last-child) { display: none; } & ol li:first-child + li:not(:last-child), & ul li:first-child + li:not(:last-child), & .item:first-child + .item:not(:last-child) { display: flex; } & ol li:first-child + li::before, & ul li:first-child + li::before, & .item:first-child + .item::before { color: var(--breadcrumb-separator-color); content: "..."; margin: 0 var(--breadcrumb-gap); } } } } @media (width <= 480px) { .breadcrumbs:not(.keep-all) { & ol, & ul, & .list { & li:not(:first-child, :last-child), & .item:not(:first-child, :last-child) { display: none; } & li:nth-last-child(2)::before, & .item:nth-last-child(2)::before { content: "..."; margin-right: var(--space-1); } } } } } /* Print styles */ @media print { .breadcrumbs { color: black; & a, & .link { color: black; text-decoration: underline; } & ol li:not(:last-child)::after, & ul li:not(:last-child)::after, & .separator::before { color: black; } } } /* High contrast mode */ @media (prefers-contrast: more) { .breadcrumbs { & a, & .link { border: 1px solid transparent; } &.breadcrumbs-pills a, &.breadcrumbs-pills .link, &.breadcrumbs-arrows li, &.breadcrumbs-arrows .item { border: 2px solid; } } } /* Reduced motion */ @media (prefers-reduced-motion: reduce) { .breadcrumbs { & a, & .link { transition: none; } } } }