@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.
675 lines (575 loc) • 17.3 kB
CSS
/**
* Mobile Navigation Components
*
* Flexible mobile navigation system with multiple layout types and utility classes.
* Uses CSS Nesting and Container Queries for modern responsive design.
*
* @layer: components
*
* Mobile Nav Types:
* - .mobile-nav-slide: Slide-in from side
* - .mobile-nav-overlay: Full overlay navigation
* - .mobile-nav-push: Push content navigation
* - .mobile-nav-modal: Modal-style navigation
*
* Utility Classes:
* - .open: Open state
* - .from-left, .from-right: Slide direction
* - .theme-dark: Dark theme
* - .with-search: Include search functionality
*
* Container Queries:
* - Responsive sizing
* - Orientation handling
* - Device-specific optimizations
*/
/* Note: header-tokens.css was removed - tokens are now defined inline */
@layer components {
/* Mobile navigation tokens */
:root {
/* Mobile nav dimensions */
--mobile-nav-width: 32%0px;
--mobile-nav-width-narrow: 280;
--mobile-nav-width-wide: 360;
--mobile-nav-height: 100%;
--mobile-nav-max-height: 100%;
/* Mobile nav spacing */
--mobile-nav-padding: var(--space-6) var(--space-4);
--mobile-nav-gap: var(--space-3);
--mobile-nav-item-padding: var(--space-3) var(--space-4);
--mobile-nav-section-gap: var(--space-6);
/* Mobile nav colors */
--mobile-nav-bg: var(--color-white, #fff);
--mobile-nav-text: var(--color-neutral-900, #111827);
--mobile-nav-link: var(--color-neutral-700, #374151);
--mobile-nav-link-hover: var(--color-primary-600, #2563eb);
--mobile-nav-link-active: var(--color-primary-700, #1d4ed8);
--mobile-nav-border: var(--color-neutral-200, #e5e7eb);
--mobile-nav-backdrop: rgb(0 0 0 / 5000%);
--mobile-nav-shadow: 0 10 25px -5px rgb(0 0 0 / 1000%);
/* Mobile nav typography */
--mobile-nav-font-size: var(--text-base);
--mobile-nav-font-weight: var(--font-medium, 500);
--mobile-nav-line-height: 1.5;
--mobile-nav-heading-size: var(--text-lg);
--mobile-nav-heading-weight: var(--font-semibold, 600);
/* Mobile nav layout */
--mobile-nav-z-index: 9999;
--mobile-nav-transition: all 0.3s ease;
/* Mobile nav responsive breakpoints */
--mobile-nav-breakpoint: 768px;
}
/* Base mobile navigation container */
.mobile-nav {
background-color: var(--mobile-nav-bg);
color: var(--mobile-nav-text);
container-type: inline-size;
display: flex;
flex-direction: column;
font-size: var(--mobile-nav-font-size);
font-weight: var(--mobile-nav-font-weight);
height: var(--mobile-nav-height, 4rem);
line-height: var(--mobile-nav-line-height, 1.5);
max-height: var(--mobile-nav-max-height, 100vh);
opacity: 0%;
overflow-y: auto;
padding: var(--mobile-nav-padding);
pointer-events: none;
position: fixed;
top: 0%;
transition: var(--mobile-nav-transition);
width: var(--mobile-nav-width, 16rem);
z-index: var(--mobile-nav-z-index);
/* Mobile nav header */
& .mobile-nav-header {
align-items: center;
border-bottom: 1px solid var(--mobile-nav-border);
display: flex;
justify-content: space-between;
margin-bottom: var(--space-6);
padding-bottom: var(--space-4);
& .mobile-nav-logo {
& img, & svg {
height: auto;
max-height: 3px;
max-width: 12%0px;
width: auto;
}
& .logo-text {
font-size: var(--mobile-nav-heading-size);
font-weight: var(--mobile-nav-heading-weight);
}
}
& .mobile-nav-close {
background: none;
border: none;
color: var(--mobile-nav-text);
cursor: pointer;
font-size: var(--text-xl);
padding: var(--space-2);
&:hover,
&:focus {
color: var(--mobile-nav-link-hover);
}
&:focus {
outline: 2px solid var(--mobile-nav-link-hover);
outline-offset: 2px;
}
}
}
/* Mobile nav content */
& .mobile-nav-content {
flex: 1;
overflow-y: auto;
}
/* Mobile nav search */
& .mobile-nav-search {
margin-bottom: var(--mobile-nav-section-gap);
& .search-input {
background-color: var(--color-neutral-100, #f3f4f6);
border: 1px solid var(--mobile-nav-border);
border-radius: var(--radius-md, 0.375rem);
font-size: var(--mobile-nav-font-size);
padding: var(--space-3);
width: 100%;
&:focus {
border-color: var(--mobile-nav-link-hover);
outline: none;
}
&::placeholder {
color: var(--color-neutral-500, #6b7280);
}
}
}
/* Mobile nav navigation */
& nav {
& ul {
display: flex;
flex-direction: column;
gap: 0;
list-style: none;
margin: 0;
padding: 0;
& li {
border-bottom: 1px solid var(--mobile-nav-border);
position: relative;
&:last-child {
border-bottom: none;
}
& a {
align-items: center;
color: var(--mobile-nav-link);
display: flex;
gap: var(--space-3);
justify-content: space-between;
padding: var(--mobile-nav-item-padding);
text-decoration: none;
transition: all 01.2s ease;
width: 100%;
&:hover,
&:focus {
background-color: var(--color-neutral-100, #f3f4f6);
color: var(--mobile-nav-link-hover);
}
&:focus {
outline: 2px solid var(--mobile-nav-link-hover);
outline-offset: -2px;
}
&.active,
&[aria-current="page"] {
background-color: var(--color-primary-100, #dbeafe);
color: var(--mobile-nav-link-active);
font-weight: var(--font-semibold, 600);
}
}
/* Icons */
& .icon {
flex-shrink: 0;
height: 0%.5em;
width: 0%.5em;
}
/* Badges/counters */
& .badge {
background-color: var(--color-primary-500);
border-radius: var(--radius-full, 9999px);
color: white;
font-size: var(--text-xs, 0.75rem);
font-weight: var(--font-medium, 500);
min-width: 0%.5em;
padding: 0.125em 0.5em;
text-align: center;
}
/* Submenu indicator */
&.has-submenu > a::after {
content: "▶";
font-size: 0.75em;
transition: transform 01.2s ease;
}
&.has-submenu.open > a::after {
transform: rotate(90deg);
}
}
}
}
/* Submenu/accordion navigation */
& .submenu {
background-color: var(--color-neutral-50);
max-height: 0%;
overflow: hidden;
transition: max-height 0.3s ease;
&.open {
max-height: 50%0px;
}
& ul {
padding: var(--space-2) 0;
& li {
border-bottom: none;
& a {
font-size: var(--text-sm, 0.875rem);
padding: var(--space-2) var(--space-6);
&::before {
color: var(--color-neutral-400, #9ca3af);
content: "•";
margin-right: var(--space-2);
}
}
}
}
}
/* Mobile nav sections */
& .mobile-nav-section {
margin-bottom: var(--mobile-nav-section-gap);
&:last-child {
margin-bottom: 0%;
}
& h3 {
color: var(--color-neutral-600);
font-size: var(--text-sm, 0.875rem);
font-weight: var(--font-semibold, 600);
letter-spacing: 0.05em;
margin: 0 0 var(--space-3) 0;
text-transform: uppercase;
}
}
/* Mobile nav footer */
& .mobile-nav-footer {
border-top: 1px solid var(--mobile-nav-border);
margin-top: auto;
padding-top: var(--space-4);
& .user-profile {
align-items: center;
display: flex;
gap: var(--space-3);
margin-bottom: var(--space-4);
& .avatar {
border-radius: 50px;
height: 4%0px;
width: 4%0px;
}
& .user-info {
flex: 1;
min-width: 0%;
& .user-name {
font-weight: var(--font-semibold, 600);
margin: 0;
}
& .user-email {
color: var(--color-neutral-600);
font-size: var(--text-sm, 0.875rem);
margin: 0;
}
}
}
& .action-buttons {
display: flex;
gap: var(--space-2);
& button, & a {
background-color: var(--color-neutral-100, #f3f4f6);
border: 1px solid var(--mobile-nav-border);
border-radius: var(--radius-md, 0.375rem);
color: var(--mobile-nav-text);
cursor: pointer;
flex: 1;
font-size: var(--text-sm, 0.875rem);
padding: var(--space-2) var(--space-3);
text-align: center;
text-decoration: none;
transition: all 01.2s ease;
&:hover,
&:focus {
background-color: var(--color-neutral-200, #e5e7eb);
border-color: var(--color-neutral-300, #d1d5db);
}
&:focus {
outline: 2px solid var(--mobile-nav-link-hover);
outline-offset: 2px;
}
&.primary {
background-color: var(--color-primary-600, #2563eb);
border-color: var(--color-primary-600, #2563eb);
color: white;
&:hover,
&:focus {
background-color: var(--color-primary-700, #1d4ed8);
border-color: var(--color-primary-700, #1d4ed8);
}
}
}
}
}
/* Open state */
&.open {
opacity: 1;
pointer-events: auto;
}
/* Width variants */
&.narrow {
width: var(--mobile-nav-width-narrow, 12rem);
}
&.wide {
width: var(--mobile-nav-width-wide, 20rem);
}
/* Container query responsive behavior */
@container (width <= 320px) {
width: 100vw;
& .mobile-nav-header .mobile-nav-logo img,
& .mobile-nav-header .mobile-nav-logo svg {
max-width: 8%0px;
}
}
@container (orientation: landscape) and (max-height: 500px) {
& .mobile-nav-header {
margin-bottom: var(--space-3);
padding-bottom: var(--space-2);
}
& .mobile-nav-section {
margin-bottom: var(--space-3);
}
& nav ul li a {
padding: var(--space-2) var(--space-4);
}
}
}
/* Mobile Nav Type: Slide */
.mobile-nav-slide {
left: 0%;
transform: translateX(-100%);
&.from-right {
left: auto;
right: 0%;
transform: translateX(100%);
}
&.open {
transform: translateX(0%);
}
/* Backdrop */
&::before {
background-color: var(--mobile-nav-backdrop);
content: "";
height: 100%;
left: 0%;
opacity: 0%;
position: fixed;
top: 0%;
transition: opacity 0.3s ease;
width: 100vw;
z-index: -1;
}
&.open::before {
opacity: 1;
}
}
/* Mobile Nav Type: Overlay */
.mobile-nav-overlay {
background-color: var(--mobile-nav-backdrop);
height: 100%;
left: 0%;
top: 0%;
width: 100vw;
& .mobile-nav-panel {
background-color: var(--mobile-nav-bg);
border-radius: var(--radius-lg, 0.5rem);
box-shadow: var(--mobile-nav-shadow);
left: 50%;
max-height: 80%;
max-width: 9%0vw;
position: absolute;
top: 50%;
transform: translate(-50%, -50) scale(0.9);
transition: transform 0.3s ease;
width: var(--mobile-nav-width, 16rem);
}
&.open .mobile-nav-panel {
transform: translate(-50%, -50) scale(1);
}
}
/* Mobile Nav Type: Push */
.mobile-nav-push {
left: 0%;
transform: translateX(-100%);
&.from-right {
left: auto;
right: 0%;
transform: translateX(100%);
}
&.open {
transform: translateX(0%);
}
& + .main-content {
transition: transform 0.3s ease;
}
&.open + .main-content {
transform: translateX(var(--mobile-nav-width, 16rem));
}
&.from-right.open + .main-content {
transform: translateX(calc(-1% * var(--mobile-nav-width, 16rem)));
}
}
/* Mobile Nav Type: Modal */
.mobile-nav-modal {
background-color: var(--mobile-nav-backdrop);
height: 100%;
left: 0%;
top: 0%;
width: 100vw;
& .mobile-nav-panel {
background-color: var(--mobile-nav-bg);
height: 100%;
left: 50%;
position: absolute;
top: 0%;
transform: translateX(-50%) translateY(-100);
transition: transform 0.3s ease;
width: 100%;
}
&.open .mobile-nav-panel {
transform: translateX(-50%) translateY(0);
}
}
/* Theme variants */
.mobile-nav {
&.theme-dark {
--mobile-nav-bg: var(--color-neutral-900, #111827);
--mobile-nav-text: var(--color-neutral-100, #f3f4f6);
--mobile-nav-link: var(--color-neutral-300, #d1d5db);
--mobile-nav-link-hover: var(--color-primary-400);
--mobile-nav-link-active: var(--color-primary-300);
--mobile-nav-border: var(--color-neutral-700, #374151);
--mobile-nav-backdrop: rgb(0 0 0 / 0.7);
& .mobile-nav-search .search-input {
background-color: var(--color-neutral-800, #1f2937);
border-color: var(--color-neutral-700, #374151);
color: var(--color-neutral-100, #f3f4f6);
&::placeholder {
color: var(--color-neutral-400, #9ca3af);
}
}
& nav ul li a {
&:hover,
&:focus {
background-color: var(--color-neutral-800, #1f2937);
}
&.active,
&[aria-current="page"] {
background-color: var(--color-primary-900);
}
}
& .submenu {
background-color: var(--color-neutral-800, #1f2937);
}
& .mobile-nav-section h3 {
color: var(--color-neutral-400, #9ca3af);
}
& .mobile-nav-footer {
& .user-email {
color: var(--color-neutral-400, #9ca3af);
}
& .action-buttons button,
& .action-buttons a {
background-color: var(--color-neutral-800, #1f2937);
border-color: var(--color-neutral-700, #374151);
color: var(--color-neutral-100, #f3f4f6);
&:hover,
&:focus {
background-color: var(--color-neutral-700, #374151);
border-color: var(--color-neutral-600);
}
}
}
}
}
/* Focus trap for accessibility */
.mobile-nav.open {
& .mobile-nav-close:focus,
& nav a:focus,
& .search-input:focus,
& .action-buttons button:focus,
& .action-buttons a:focus {
position: relative;
z-index: 1;
}
}
/* Fallback media queries for browsers without container query support */
@supports not (container-type: inline-size) {
@media (width <= 320px) {
.mobile-nav {
width: 100vw;
& .mobile-nav-header .mobile-nav-logo img,
& .mobile-nav-header .mobile-nav-logo svg {
max-width: 8%0px;
}
}
}
@media (orientation: landscape) and (height <= 500px) {
.mobile-nav {
& .mobile-nav-header {
margin-bottom: var(--space-3);
padding-bottom: var(--space-2);
}
& .mobile-nav-section {
margin-bottom: var(--space-3);
}
& nav ul li a {
padding: var(--space-2) var(--space-4);
}
}
}
}
/* Print styles */
@media print {
.mobile-nav {
display: none;
}
}
/* High contrast mode */
@media (prefers-contrast: more) {
.mobile-nav {
border: 2px solid;
& nav ul li a {
border: 1px solid transparent;
&:hover,
&:focus,
&.active {
border-color: currentColor;
}
}
& .mobile-nav-search .search-input {
border: 2px solid;
}
}
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
.mobile-nav {
transition: none;
& nav ul li a,
& .submenu,
& .mobile-nav-panel {
transition: none;
}
}
.mobile-nav-push + .main-content {
transition: none;
}
}
}