UNPKG

asafarim-navlinks

Version:

A versatile React navigation component with unlimited multi-level dropdowns, four alignment options, mobile responsiveness, and customizable styling. Perfect for modern web applications.

512 lines (437 loc) 11.7 kB
/* * ASafariM NavLinks - Modern, Minimalist Navigation Component * with Theme Support and Multi-level Dropdowns */ /* =========== Theme Variables =========== */ :root { /* Light Theme */ --nav-bg-light: #ffffff; --nav-text-light: #333333; --nav-hover-bg-light: #f5f5f5; --nav-hover-text-light: #2563eb; --nav-border-light: #e5e7eb; --nav-shadow-light: 0 2px 10px rgba(0, 0, 0, 0.1); --nav-dropdown-bg-light: #ffffff; /* Dark Theme */ --nav-bg-dark: #1e293b; --nav-text-dark: #f1f5f9; --nav-hover-bg-dark: #334155; --nav-hover-text-dark: #38bdf8; --nav-border-dark: #475569; --nav-shadow-dark: 0 2px 10px rgba(0, 0, 0, 0.3); --nav-dropdown-bg-dark: #1e293b; /* Shared Colors */ --nav-primary: #3b82f6; --nav-accent: #f43f5e; /* Spacing */ --nav-padding: 0.75rem 1rem; --nav-gap: 1rem; --nav-transition: 200ms ease-in-out; --nav-border-radius: 0.375rem; /* Z-index levels */ --nav-z-index: 50; --nav-dropdown-z-index: 100; } /* =========== Theme Modes =========== */ .lightTheme { --nav-bg: var(--nav-bg-light); --nav-text: var(--nav-text-light); --nav-hover-bg: var(--nav-hover-bg-light); --nav-hover-text: var(--nav-hover-text-light); --nav-border: var(--nav-border-light); --nav-shadow: var(--nav-shadow-light); --nav-dropdown-bg: var(--nav-dropdown-bg-light); } .darkTheme { --nav-bg: var(--nav-bg-dark); --nav-text: var(--nav-text-dark); --nav-hover-bg: var(--nav-hover-bg-dark); --nav-hover-text: var(--nav-hover-text-dark); --nav-border: var(--nav-border-dark); --nav-shadow: var(--nav-shadow-dark); --nav-dropdown-bg: var(--nav-dropdown-bg-dark); } .autoTheme { --nav-bg: var(--nav-bg-light); --nav-text: var(--nav-text-light); --nav-hover-bg: var(--nav-hover-bg-light); --nav-hover-text: var(--nav-hover-text-light); --nav-border: var(--nav-border-light); --nav-shadow: var(--nav-shadow-light); --nav-dropdown-bg: var(--nav-dropdown-bg-light); } /* Auto dark mode when system prefers dark theme */ @media (prefers-color-scheme: dark) { .autoTheme { --nav-bg: var(--nav-bg-dark); --nav-text: var(--nav-text-dark); --nav-hover-bg: var(--nav-hover-bg-dark); --nav-hover-text: var(--nav-hover-text-dark); --nav-border: var(--nav-border-dark); --nav-shadow: var(--nav-shadow-dark); --nav-dropdown-bg: var(--nav-dropdown-bg-dark); } .autoTheme.demoContext { background: linear-gradient(135deg, #2d3748 0%, #1a202c 100%); } .autoTheme.demoContext .navList li a, .autoTheme.demoContext .navList li .navButton { color: white; } .autoTheme.demoContext .dropdown { background: #2d3748; border: 1px solid rgba(255, 255, 255, 0.1); } } /* =========== Base Container =========== */ .navContainer { position: relative; width: 100%; background: var(--nav-bg); border-bottom: 1px solid var(--nav-border); box-shadow: var(--nav-shadow); z-index: var(--nav-z-index); } /* Demo mode styles */ .navContainer.demoContext { border-radius: var(--nav-border-radius); overflow: visible; } /* =========== Navigation List =========== */ .navList { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: row; align-items: center; } .navList li { list-style-type: none; position: relative; margin: 0; } /* =========== Links & Buttons =========== */ .navList li a, .navList li .navButton { display: flex; align-items: center; padding: var(--nav-padding); color: var(--nav-text); text-decoration: none; white-space: nowrap; transition: all var(--nav-transition); font-size: 0.9rem; border: none; background: transparent; cursor: pointer; font-family: inherit; } .navList li a:hover, .navList li .navButton:hover { background: var(--nav-hover-bg); color: var(--nav-hover-text); } .navList li a:focus, .navList li .navButton:focus { outline: 2px solid var(--nav-primary); outline-offset: -2px; } /* =========== Dropdowns =========== */ .dropdown { position: absolute; top: 100%; left: 0; background: var(--nav-dropdown-bg); border: 1px solid var(--nav-border); border-radius: var(--nav-border-radius); box-shadow: var(--nav-shadow); min-width: 200px; opacity: 0; visibility: hidden; transform: translateY(10px); transition: all var(--nav-transition); z-index: var(--nav-dropdown-z-index); padding: 0.25rem 0; } /* Show dropdown on hover (desktop only) */ @media (min-width: 769px) { .hasChildren:hover > .dropdown { opacity: 1; visibility: visible; transform: translateY(0); } } /* JavaScript-controlled expanded state */ .dropdown.expanded { opacity: 1; visibility: visible; transform: translateY(0) !important; } /* Nested dropdowns */ .dropdown .dropdown { top: 0; left: 100%; transform: translateX(10px); } .dropdown .hasChildren:hover > .dropdown { transform: translateX(0); } /* Arrow indicators */ .arrow { margin-left: 0.5rem; font-size: 0.65rem; opacity: 0.7; transition: transform var(--nav-transition); } .arrow.expanded, li.expanded > a .arrow, li.expanded > .navButton .arrow { transform: rotate(180deg); } /* Dropdown list styles */ .dropdown li { width: 100%; } .dropdown li a, .dropdown li .navButton { padding: 0.5rem 1rem; justify-content: space-between; border-left: 3px solid transparent; } .dropdown li a:hover, .dropdown li .navButton:hover { border-left-color: var(--nav-primary); } /* Dropdown positioning */ .rightAligned { right: 0; left: auto; } .leftAligned { left: 0; right: auto; } .topAligned { bottom: 100%; top: auto; transform: translateY(-10px); } .bottomAligned { top: 100%; bottom: auto; } /* =========== Icons & Emojis =========== */ .emoji { margin-right: 0.5rem; font-size: 1.1em; } .iconLeft { margin-right: 0.5rem; } .iconRight { margin-left: 0.5rem; } .logoIcon { margin-right: 0.5rem; } .logoCaption { font-weight: 500; } /* =========== Mobile Styles =========== */ @media (max-width: 768px) { /* Mobile Header */ .mobileHeader { display: flex; align-items: center; justify-content: space-between; padding: 0.75rem 1rem; background: var(--nav-bg); border-bottom: 1px solid var(--nav-border); } .mobileBrand { display: flex; align-items: center; } /* Hamburger Button */ .hamburger { display: flex; flex-direction: column; justify-content: space-between; width: 24px; height: 20px; background: transparent; border: none; cursor: pointer; padding: 0; z-index: 10; } .hamburgerLine { display: block; width: 100%; height: 2px; background: var(--nav-text); border-radius: 1px; transition: all 0.3s ease; } .hamburger.active .hamburgerLine:nth-child(1) { transform: translateY(9px) rotate(45deg); } .hamburger.active .hamburgerLine:nth-child(2) { opacity: 0; } .hamburger.active .hamburgerLine:nth-child(3) { transform: translateY(-9px) rotate(-45deg); } /* Mobile Menu */ .navList.mobileNav { flex-direction: column; align-items: stretch; max-height: 0; overflow: hidden; opacity: 0; transition: all 0.3s ease; } .navList.mobileOpen { max-height: 100vh; opacity: 1; } .navList.mobileNav li { width: 100%; list-style-type: none; border-bottom: 1px solid var(--nav-border); } .navList.mobileNav li:last-child { border-bottom: none; } /* Mobile Dropdowns */ .navList.mobileNav .dropdown { position: static; width: 100%; box-shadow: none; border: none; border-radius: 0; background: var(--nav-hover-bg); max-height: 0; overflow: hidden; transition: all 0.3s ease; opacity: 0; visibility: hidden; transform: none !important; padding: 0; } .navList.mobileNav .dropdown.expanded { max-height: 1000px; opacity: 1; visibility: visible; padding: 0; } .navList.mobileNav .dropdown li { border-bottom: none; } .navList.mobileNav .dropdown li a, .navList.mobileNav .dropdown li .navButton { padding-left: 2rem; } .navList.mobileNav .dropdown .dropdown li a, .navList.mobileNav .dropdown .dropdown li .navButton { padding-left: 3rem; } .navList.mobileNav .dropdown .dropdown .dropdown li a, .navList.mobileNav .dropdown .dropdown .dropdown li .navButton { padding-left: 4rem; } /* Mobile arrow indicators */ .navList.mobileNav .arrow { transition: transform 0.3s ease; } .navList.mobileNav .expanded > a .arrow, .navList.mobileNav .expanded > .navButton .arrow { transform: rotate(180deg); } } /* =========== Accessibility =========== */ .skipNav { position: absolute; top: -9999px; left: 0; background: var(--nav-primary); color: white; padding: 0.5rem 1rem; z-index: 9999; text-decoration: none; } .skipNav:focus { top: 0; } /* Demo-specific styling that respects themes */ /* Dark theme demo context */ .darkTheme.demoContext, .autoTheme.demoContext { background: linear-gradient(135deg, #2d3748 0%, #1a202c 100%); } .darkTheme.demoContext .navList li a, .darkTheme.demoContext .navList li .navButton, .autoTheme.demoContext .navList li a, .autoTheme.demoContext .navList li .navButton { color: white; font-weight: 500; } .darkTheme.demoContext .dropdown, .autoTheme.demoContext .dropdown { background: #2d3748; border: 1px solid rgba(255, 255, 255, 0.1); } .darkTheme.demoContext .navList li a:hover, .darkTheme.demoContext .navList li .navButton:hover, .autoTheme.demoContext .navList li a:hover, .autoTheme.demoContext .navList li .navButton:hover { background: rgba(255, 255, 255, 0.1); } /* Light theme demo context */ .lightTheme.demoContext { background: linear-gradient(135deg, #f0f4f8 0%, #d9e2ec 100%); border: 1px solid var(--nav-border); } .lightTheme.demoContext .navList li a, .lightTheme.demoContext .navList li .navButton { color: var(--nav-text-light); font-weight: 500; } .lightTheme.demoContext .dropdown { background: var(--nav-dropdown-bg-light); border: 1px solid var(--nav-border-light); } .lightTheme.demoContext .navList li a:hover, .lightTheme.demoContext .navList li .navButton:hover { background: var(--nav-hover-bg-light); color: var(--nav-hover-text-light); } /* Enhanced light theme styles for better visibility */ .lightTheme .navList li a, .lightTheme .navList li .navButton { color: var(--nav-text-light); } .lightTheme .dropdown { background-color: var(--nav-dropdown-bg-light); border-color: var(--nav-border-light); } .lightTheme .navList li a:hover, .lightTheme .navList li .navButton:hover { background-color: var(--nav-hover-bg-light); color: var(--nav-hover-text-light); } /* Light theme dropdown hover states */ .lightTheme .hasChildren:hover > a, .lightTheme .hasChildren:hover > .navButton { background-color: var(--nav-hover-bg-light); color: var(--nav-hover-text-light); } /* Mobile styles for light theme */ .lightTheme .mobileHeader { background: var(--nav-bg-light); border-color: var(--nav-border-light); } .lightTheme .hamburgerLine { background-color: var(--nav-text-light); }