JavaScript Button
@lemonadejs/button · ✓ 24 contract checks · framework-agnostic · zero dependencies
<Button /> — a pressable action block (LemonadeJS v6)
Built on the v6 contract model: a real
<button> (native semantics, native disabled, native keyboard
activation) — or a real <a> when href is set. Three variants
(contained is the default), five colors, three sizes, an optional
material icon, and a loading state whose spinner replaces the content
while clicks are blocked. Ripple-free by design: hover/active/
focus-visible states live entirely in CSS.
Content: label for plain text, or children for anything richer —
both render inside the same button.
Example
import { html } from 'lemonadejs';
import Button from '@lemonadejs/button';
const App = (props, { state }) => {
const saving = state(false);
const status = state('Draft not saved');
const save = () => {
saving.value = true;
setTimeout(() => {
saving.value = false;
status.value = 'Saved at ' + new Date().toLocaleTimeString();
}, 1200);
};
return html`<div>
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
<${Button} label="Save changes" loading="${saving}" onclick="${save}" />
<${Button} variant="outlined" label="Preview" onclick="${() => (status.value = 'Preview opened')}" />
<${Button} variant="text" color="error" label="Discard" onclick="${() => (status.value = 'Draft discarded')}" />
<${Button} color="success" size="small" label="Publish" disabled />
</div>
<p>${status}</p>
</div>`;
};Installation
npm install @lemonadejs/button
import Button from '@lemonadejs/button';
import '@lemonadejs/button/style.css';
The icons come from Google Material Symbols. Load the font once per page:
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined">
Three deployment forms, one component:
html`<${Button} />` // by value (no registration)
setComponents({ Button }); // then <Button /> by name anywhere
createWebComponent(Button); // <lm-button> in plain HTML/any framework
Props
Every declared prop arrives as a live state — pass a value for a snapshot or a state for a two-way live wire. Attribute strings are coerced to the declared type.
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | '' | text content (children also supported) |
variant | string | '' | ” = contained |
color | string | '' | ” = primary |
size | string | '' | small |
disabled | boolean | false | blocks interaction (native on <button>) |
loading | boolean | false | spinner replaces the content; disabled while on |
fullwidth | boolean | false | stretch to the container width |
href | string | '' | renders a real <a> instead of <button> |
type | string | '' | button type: submit |
icon | string | '' | material icon name shown before the label |
aria-label | string | '' |
Events
All event names are lowercase (the platform convention — LJS-305 warns otherwise).
onclick— fires on activation (never while disabled/loading)
Styling
All classes follow the lm-button-* convention; visual variants are data-*
attributes on the root. Override freely — there is no styling engine to fight.
Contract
The machine-readable schema ships with the package:
import contract from '@lemonadejs/button/contract.json';
verify.json carries the conformance proof produced by verify(Button).
Looking for the v5 plugin? See the archived v5 documentation.