Skip to content
Magma Design System
Header<mds-header>Generated from @maggioli-design-system/magma@2.3.0dist/documentation.json. Encapsulation: shadow.
Common incorrect uses of <mds-header>. Each entry pairs the wrong form with the right one and a one-line reason. System-wide rules (boolean-as-string, shadow piercing, Tailwind color utilities, raw native event listening) live in agents/anti-patterns.md - they apply here too but are not repeated.
Do Not Place <mds-header-bar> Outside <mds-header>
<mds-header-bar> is a compound child; it must be a direct slot child of <mds-header>, which relays breakpoint and appearance state down to it. Using the bar standalone breaks that communication: its hamburger has no menu to open, and appearance and auto-hide do not apply.
<!-- INCORRECT -->
<mds-header-bar>
<mds-img src="/logo.svg" alt="Logo"></mds-img>
</mds-header-bar>
<!-- CORRECT -->
<mds-header>
<mds-header-bar>
<mds-img src="/logo.svg" alt="Logo"></mds-img>
</mds-header-bar>
</mds-header>
Do Not Drive Scroll Appearance with JavaScript When appearance-set Is Available
Manually toggling appearance on a scroll listener duplicates what appearance-set already handles declaratively, and once appearance-set is also set the component’s own scroll handler rewrites appearance on every scroll.
<!-- INCORRECT -->
<mds-header id="hdr" appearance="inline">
<mds-header-bar>...</mds-header-bar>
</mds-header>
<script>
window.addEventListener('scroll', () => {
document.getElementById('hdr').appearance = window.scrollY > 300 ? 'stripe' : 'inline';
});
</script>
<!-- CORRECT -->
<mds-header appearance-set="inline, stripe 300" appearance="inline">
<mds-header-bar>...</mds-header-bar>
</mds-header>
Do Not Omit the menu Slot When Providing a Hamburger-Only Nav
If no [slot="menu"] child is present there is no modal to open, but the bar still shows the hamburger icon on the viewports set by menu, and pressing it does nothing. Always provide menu content when you want the mobile toggle to be visible, or set menu="none".
<!-- INCORRECT: the hamburger icon shows but opens nothing -->
<mds-header menu="mobile">
<mds-header-bar>
<mds-img src="/logo.svg" alt="Logo"></mds-img>
<mds-button slot="nav" label="Accedi" variant="dark" tone="outline"></mds-button>
</mds-header-bar>
</mds-header>
<!-- CORRECT -->
<mds-header menu="mobile">
<mds-header-bar>
<mds-img src="/logo.svg" alt="Logo"></mds-img>
<mds-button slot="nav" label="Accedi" variant="dark" tone="outline"></mds-button>
</mds-header-bar>
<div slot="menu">
<mds-button label="Accedi" variant="dark" tone="outline"></mds-button>
</div>
</mds-header>
Do Not Listen to Native scroll Events to Detect Auto-Hide State
The component already emits mdsHeaderVisibilityChange when the bar flips between hidden and visible. Attaching a second scroll listener couples your code to the same threshold logic and risks running out of sync.
<!-- INCORRECT -->
<mds-header auto-hide="300" id="hdr">
<mds-header-bar>...</mds-header-bar>
</mds-header>
<script>
window.addEventListener('scroll', () => {
const hidden = window.scrollY > 300;
document.body.classList.toggle('header-hidden', hidden);
});
</script>
<!-- CORRECT -->
<mds-header auto-hide="300" id="hdr">
<mds-header-bar>...</mds-header-bar>
</mds-header>
<script>
document.getElementById('hdr').addEventListener('mdsHeaderVisibilityChange', (e) => {
document.body.classList.toggle('header-hidden', e.detail.visibility === 'hidden');
});
</script>
Do Not Pierce Shadow DOM to Style the Internal Modal
The side-modal container is exposed as ::part(menu) and its stacking is controllable via --mds-header-z-index. Do not use >>>, /deep/, or undocumented internal selectors.
/* INCORRECT */
mds-header >>> .menu mds-modal {
background: red;
}
/* CORRECT */
mds-header {
--mds-header-z-index: 500;
}
mds-header::part(menu) {
/* documented part - safe to target */
}