Simple Navbar
A logo, an inline link row and a CTA, collapsing to a hamburger menu below the md breakpoint.
6 फ्रेमवर्कमध्यम
A slide-in drawer with a real focus trap, Escape to close, scroll lock and focus restoration.
<!--
A drawer is a modal, and a modal that only *looks* modal is the classic
half-built one: the page behind it still takes Tab, so a keyboard user walks
straight out of the open drawer into links they cannot see. Three things fix
that, and all three are required -
1. role="dialog" aria-modal="true", so it is announced as a dialog.
2. A focus trap: Tab off the last item wraps to the first, Shift+Tab off the
first wraps to the last.
3. Escape closes it and focus returns to the button that opened it, so the
user is put back where they were rather than at the top of the document.
Scroll lock is the fourth: without overflow:hidden on <body> the page behind
scrolls under your finger while the drawer sits still.
-->
<header class="navdrawer">
<div class="navdrawer__bar">
<a class="navdrawer__brand" href="/">Adysre</a>
<button
class="navdrawer__toggle"
type="button"
aria-expanded="false"
aria-controls="navdrawer-panel"
aria-label="Open main menu"
>
<svg class="navdrawer__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true" focusable="false">
<path d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<div class="navdrawer__overlay" hidden></div>
<div class="navdrawer__panel" id="navdrawer-panel" role="dialog" aria-modal="true" aria-label="Main menu" hidden>
<div class="navdrawer__panel-head">
<span class="navdrawer__panel-title">Menu</span>
<button class="navdrawer__close" type="button" aria-label="Close main menu">
<svg class="navdrawer__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true" focusable="false">
<path d="M6 6l12 12M18 6L6 18" />
</svg>
</button>
</div>
<nav aria-label="Main">
<ul class="navdrawer__links">
<li><a class="navdrawer__link" href="/product" aria-current="page">Product</a></li>
<li><a class="navdrawer__link" href="/pricing">Pricing</a></li>
<li><a class="navdrawer__link" href="/docs">Docs</a></li>
</ul>
</nav>
<a class="navdrawer__cta" href="/signup">Get started</a>
</div>
</header>
<script>
document.querySelectorAll('.navdrawer').forEach(function (root) {
var toggle = root.querySelector('.navdrawer__toggle');
var close = root.querySelector('.navdrawer__close');
var overlay = root.querySelector('.navdrawer__overlay');
var panel = root.querySelector('.navdrawer__panel');
function focusables() {
return Array.prototype.slice.call(
panel.querySelectorAll('a[href], button:not([disabled])')
);
}
function setOpen(open) {
panel.hidden = !open;
overlay.hidden = !open;
toggle.setAttribute('aria-expanded', String(open));
// Scroll lock: without this the page scrolls behind the open drawer.
document.body.style.overflow = open ? 'hidden' : '';
if (open) {
var first = focusables()[0];
if (first) first.focus();
} else {
toggle.focus();
}
}
toggle.addEventListener('click', function () {
setOpen(true);
});
close.addEventListener('click', function () {
setOpen(false);
});
overlay.addEventListener('click', function () {
setOpen(false);
});
document.addEventListener('keydown', function (event) {
if (panel.hidden) return;
if (event.key === 'Escape') {
setOpen(false);
return;
}
if (event.key !== 'Tab') return;
// The trap. Tab past the last item wraps to the first; Shift+Tab before
// the first wraps to the last.
var items = focusables();
if (items.length === 0) return;
var first = items[0];
var last = items[items.length - 1];
if (event.shiftKey && document.activeElement === first) {
event.preventDefault();
last.focus();
} else if (!event.shiftKey && document.activeElement === last) {
event.preventDefault();
first.focus();
}
});
});
</script>| Prop | टाइप | डिफ़ॉल्ट | विवरण |
|---|---|---|---|
ariaLabel | string | 'Open main menu' | बटन का एक्सेसिबल नाम। सिर्फ़ आइकन वाले बटन के लिए ज़रूरी है। |
ctaLabel | string | 'Get started' | कॉल-टू-एक्शन बटन का टेक्स्ट। |
ctaHref | string | '/signup' | कॉल-टू-एक्शन लिंक का डेस्टिनेशन। |
className | string | - | रूट एलिमेंट पर मर्ज होने वाली अतिरिक्त क्लासेज़। |
A drawer is a modal, and a modal that only *looks* modal is the classic half-built one: the page behind it still takes Tab, so a keyboard user walks straight out of the open drawer into links they cannot see. Four things fix it and all four are here - `role="dialog" aria-modal="true"`; a focus trap that wraps Tab off the last item back to the first and Shift+Tab off the first to the last; Escape closing it with focus returned to the button that opened it, not dumped at the top of the document; and `overflow: hidden` on `<body>` so the page does not scroll under your finger while the drawer sits still. The slide animation is decoration and sits behind `motion-safe:` - someone who asked for less motion still gets the drawer, it simply arrives. The `focusables()` selector covers links and buttons; widen it if you add inputs.