Skip to content
Magma Design System
Button<mds-button>Generated from @maggioli-design-system/magma@2.3.0dist/documentation.json. Encapsulation: shadow.
Common incorrect uses of <mds-button>. 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 Put HTML in the Default Slot
The default slot accepts plain text only; nested elements are stripped or break layout. Use the label prop for text and the dedicated props/slots for everything else.
<!-- INCORRECT -->
<mds-button>
<span class="bold">Scarica</span>
<small>(PDF)</small>
</mds-button>
<!-- CORRECT -->
<mds-button label="Scarica (PDF)" icon="mi/baseline/download" variant="primary"></mds-button>
Do Not Nest <mds-button> Inside an Anchor
Wrapping the button in <a> creates nested interactive controls, breaks keyboard semantics, and fails accessibility audits. Use the href prop on the component instead - it renders the link itself.
<!-- INCORRECT -->
<a href="/login">
<mds-button label="Accedi"></mds-button>
</a>
<!-- CORRECT -->
<mds-button label="Accedi" href="/login"></mds-button>
Do Not Follow the href Yourself in a Click Listener
With href set the component already renders a link the browser follows. Assigning window.location in a click listener loads the page a second time and takes a modifier click, which the browser would open in a new tab, into the current one. Either let the browser follow the link, or cancel the click and route on the client.
// INCORRECT
button.addEventListener('click', () => {
window.location.href = button.href;
});
// CORRECT: a client-side router cancels the click and routes
button.addEventListener('click', (event) => {
if (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) return;
event.preventDefault();
router.navigate(button.href);
});
Icon-Only Buttons Without an Accessible Name
When label is empty, the component derives a title from the last segment of the icon slug (“delete”), which names the icon, not the action. Always supply an explicit aria-label (or title) for icon-only buttons, or an mds-tooltip with relation="label".
<!-- INCORRECT -->
<mds-button icon="mi/baseline/delete" variant="error" tone="text"></mds-button>
<!-- CORRECT -->
<mds-button
icon="mi/baseline/delete"
aria-label="Elimina elemento"
variant="error"
tone="text"
></mds-button>
Do Not Build the Form Data Without the Submitter
new FormData(form) leaves out the name / value of the button that submitted the form, as it does for a native submit button. Pass event.submitter to read which action was chosen; do not track the clicked button in a variable or a hidden input.
// INCORRECT: action is missing
form.addEventListener('submit', (event) => {
event.preventDefault();
const data = new FormData(form);
});
// CORRECT
form.addEventListener('submit', (event) => {
event.preventDefault();
const data = new FormData(form, event.submitter);
});
Do Not Slot <mds-icon> to Add an Icon
The component’s icon prop renders the SVG through the shared icon-set service and positions it correctly via icon-position. Slotting <mds-icon> puts it in the text-only default slot, where it is stripped or misaligned.
<!-- INCORRECT -->
<mds-button>
<mds-icon name="mi/baseline/add"></mds-icon>
Aggiungi
</mds-button>
<!-- CORRECT -->
<mds-button label="Aggiungi" icon="mi/baseline/add" variant="primary" tone="weak"></mds-button>
Do Not Use Legacy ghost or quiet Tone Values
tone="ghost" and tone="quiet" were renamed in Magma 2.0 to outline and text. The old values are no longer accepted by the typed ToneBoxVariantType and silently fall back to the default tone.
<!-- INCORRECT (Magma 1.x naming) -->
<mds-button label="Modifica" tone="ghost" variant="primary"></mds-button>
<mds-button label="Annulla" tone="quiet" variant="error"></mds-button>
<!-- CORRECT (Magma 2.x) -->
<mds-button label="Modifica" tone="outline" variant="primary"></mds-button>
<mds-button label="Annulla" tone="text" variant="error"></mds-button>
Customize via Documented Vars and Parts, Not Internal Selectors
The supported customization surface is --mds-button-* CSS custom properties plus the two documented shadow parts (icon, label). Targeting other internals via ::part(), >>>, or undocumented class names couples your code to the Shadow DOM implementation and will break on minor releases.
/* INCORRECT */
mds-button >>> .text {
font-weight: bold;
}
mds-button::part(spinner) {
color: red;
}
/* CORRECT */
mds-button {
--mds-button-color: rgb(var(--magma-accent-on-emphasis));
--mds-button-radius: var(--magma-radius-lg);
}
mds-button::part(icon) {
fill: rgb(var(--magma-warning-fg));
}