Crazy button
A reactive, theme-aware web component compatible with the legacy RegularBtn API.
A reactive button component with the full Buttons page feature set and reactive environment colors.
Try a button to see its action or selection.
Legacy compatibility
Keep the regular-btn tag and existing attributes. Floating buttons show their label as a tooltip; extended buttons show it inline.
<regular-btn label="Add shot" icon-text="add"></regular-btn>
<regular-btn type="extended" label="Review" icon-text="rate_review" icon-position="left" depth="outlined" size="normal" shape="box"></regular-btn>
<regular-btn type="extended" label="Buttons documentation" href="buttons.html" target="_blank" size="normal"></regular-btn>Variants
All five styles from the Buttons page, with environment colors inherited automatically.
<crazy-button type="extended" variant="filled" label="Filled" size="normal" icon-text="check" icon-position="left"></crazy-button>
<crazy-button type="extended" variant="tonal" label="Tonal" size="normal" icon-text="check" icon-position="left"></crazy-button>
<crazy-button type="extended" variant="outlined" label="Outlined" size="normal" icon-text="check" icon-position="left"></crazy-button>
<crazy-button type="extended" variant="elevated" label="Elevated" size="normal" icon-text="check" icon-position="left"></crazy-button>
<crazy-button type="extended" variant="text" label="Text" size="normal" icon-text="check" icon-position="left"></crazy-button>Toggles and icon buttons
Toggle state reflects to pressed. Native buttons support Enter and Space.
<crazy-button type="extended" variant="tonal" label="Following" toggle pressed size="normal"></crazy-button>
<crazy-button type="icon" variant="standard" icon-text="search" label="Search"></crazy-button>
<crazy-button type="icon" variant="tonal" icon-text="favorite" label="Favorite" toggle></crazy-button>
<crazy-button type="icon" variant="outlined" icon-text="arrow_back" label="Back" icon-width="narrow"></crazy-button>
<crazy-button type="icon" variant="filled" icon-text="arrow_forward" label="Forward" icon-width="wide"></crazy-button>Standard and connected groups
Use the same group containers as the Buttons page. Set data-selection="single" or "multiple" on the group.
<div class="btn-group btn-group-standard" role="group" aria-label="Review actions">
<crazy-button type="extended" variant="text" label="Cancel" size="normal"></crazy-button>
<crazy-button type="extended" variant="filled" label="Save" size="normal"></crazy-button>
</div>
<div class="btn-group btn-group-connected" data-selection="single" role="group" aria-label="View">
<crazy-button type="extended" variant="tonal" label="List" toggle pressed size="normal"></crazy-button>
<crazy-button type="extended" variant="tonal" label="Grid" toggle size="normal"></crazy-button>
<crazy-button type="extended" variant="tonal" label="Board" toggle size="normal"></crazy-button>
</div>
<div class="btn-group btn-group-connected" data-selection="multiple" role="group" aria-label="Text formatting">
<crazy-button type="icon" variant="tonal" label="Bold" icon-text="format_bold" toggle></crazy-button>
<crazy-button type="icon" variant="tonal" label="Italic" icon-text="format_italic" toggle></crazy-button>
</div>Split buttons and FAB menus
Point menu-target at a unique, existing Materialize dropdown ID. Menu items remain regular links or application actions. The component initializes and cleans up its dropdown automatically.
<crazy-button type="extended" variant="filled" label="Save" size="normal" split menu-target="save-options"></crazy-button>
<ul id="save-options" class="dropdown-content">
<li><a href="#!" data-demo-action="Saved a copy">Save a copy</a></li>
<li><a href="#!" data-demo-action="Exported">Export</a></li>
</ul>
<crazy-button type="fab" icon-text="add" label="Create" menu-target="create-options"></crazy-button>
<ul id="create-options" class="dropdown-content">
<li><a href="#!" data-demo-action="Created a shot">New shot</a></li>
<li><a href="#!" data-demo-action="Created a task">New task</a></li>
</ul>Floating action buttons
FABs use environment container colors. Choose primary, secondary, or tertiary and small, normal, or large FAB geometry.
<crazy-button type="fab" icon-text="add" label="Add" fab-size="small"></crazy-button>
<crazy-button type="fab" icon-text="edit" label="Edit" fab-color="secondary"></crazy-button>
<crazy-button type="fab" icon-text="add" label="Create" fab-color="tertiary" fab-size="large"></crazy-button>
<crazy-button type="extended-fab" icon-text="edit" icon-position="left" label="Compose"></crazy-button>Navigation rail
Use type="rail" for an icon above a visible label, matching the navigation rail example. The inner link receives href, data-view, and aria-current. The active icon pill follows the environment’s secondary container colors.
Choose a section to update its current-page indicator.
<crazy-button type="rail" href="#rail-home" data-view="Home" icon-text="home" label="Home" aria-current="page"></crazy-button>
<crazy-button type="rail" href="#develop" data-view="Develop" icon-text="code" label="Develop"></crazy-button>
<crazy-button type="rail" href="#rail-settings" data-view="Settings" icon-text="settings" label="Settings" disabled></crazy-button>Set aria-current="page" on the component for the current destination and remove it from the others when your route changes. Rail geometry is fixed at 88px wide and at least 76px high; the other button size, shape, variant, and wave options apply to the other types.
Sizes and shapes
Explicit sizes xs / sm / md / lg / xl are 32 / 40 / 56 / 96 / 136px. Legacy names small / normal / large / extra-large remain available (30 / 40 / 56 / 100px).
<crazy-button type="extended" variant="tonal" size="xs" label="XS" shape="box"></crazy-button>
<crazy-button type="extended" variant="tonal" size="sm" label="SM" shape="box"></crazy-button>
<crazy-button type="extended" variant="tonal" size="md" label="MD" shape="box"></crazy-button>
<crazy-button type="extended" variant="tonal" size="lg" label="LG" shape="box"></crazy-button>
<crazy-button type="extended" variant="tonal" size="xl" label="XL" shape="box"></crazy-button>Rounded left and right shapes
Use shape="round-left" for a rounded left edge and shape="round-right" for a rounded right edge. The rounded end uses half the button height so the opposite corners retain a visible 4px radius, including on hover, while pressed, and when selected. These physical left/right shapes are useful beside a search field.
<div class="button-demo-row">
<crazy-button type="icon" size="md" shape="round-left" variant="tonal" icon-image="images/yuna.jpg" label="Open profile" href="#api"></crazy-button>
<crazy-button type="extended" size="md" variant="outlined" label="Search active shows" icon-text="search" icon-position="left" disabled></crazy-button>
<crazy-button type="icon" size="md" shape="round-right" variant="tonal" icon-text="refresh" label="Reload active shows"></crazy-button>
</div>Image-only buttons fill the available surface and inherit its shape automatically. Omit icon-image-style to keep this behavior. Transparent areas inside the source image remain transparent; set color-primary to the image background color for a seamless filled surface. Plain expressive buttons can use btn-round-left or btn-round-right alongside btn btn-expressive.
Workspace navigation rail
An always-visible 88px rail for workspace navigation. Square icon buttons are grouped by production area; hover or focus a button for its label.
Production workspace
Home
Your production workspace: quick access to the tools you use every day.
Choose a tool from the navigation to preview its destination.
Home selected.
Markup — Crazy buttons and navigation groups
<div class="workspace-nav-preview" data-layout="rail">
<nav class="workspace-demo-navigation" aria-label="Production navigation">
<div class="workspace-demo-group" role="group" aria-label="Workspace">
<crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="1" icon-text="home" label="Home" data-redirect-name="Home" color-primary="gold" color-secondary="#211b00" aria-current="page"></crazy-button>
<crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="flat" icon-text="schedule" label="Timelog" data-redirect-name="Timelog" color-secondary="var(--md-sys-color-primary)"></crazy-button>
</div>
<div class="workspace-demo-group" role="group" aria-label="Out.">
<span>Out.</span>
<crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="1" icon-text="social_distance" label="Outsource Turnover" data-redirect-name="OutsourceTurnover" color-primary="#4fc3f7" color-secondary="#052e3c"></crazy-button>
<crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="1" icon-text="microwave" label="Brief Outsource" data-redirect-name="OutsourceBrief" color-primary="#26a69a" color-secondary="#002e29"></crazy-button>
</div>
<div class="workspace-demo-group" role="group" aria-label="Prod.">
<span>Prod.</span>
<crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="1" icon-text="schedule" label="Timelog Summary" data-redirect-name="TimelogSummary" color-primary="#ab47bc" color-secondary="#fff"></crazy-button>
</div>
<div class="workspace-demo-group" role="group" aria-label="Studio">
<span>Studio</span>
<crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="1" icon-text="stadium" label="Studio Resource" data-redirect-name="StudioResource" color-primary="#ec407a" color-secondary="#fff"></crazy-button>
<crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="1" icon-text="view_timeline" label="Crew Planning" data-redirect-name="Planning" color-primary="#ef6c00" color-secondary="#fff"></crazy-button>
</div>
<div class="workspace-demo-group" role="group" aria-label="Admin">
<span>Admin</span>
<crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="flat" icon-text="settings" label="Settings" data-redirect-name="Settings" color-secondary="var(--md-sys-color-on-surface)"></crazy-button>
</div>
</nav>
<div class="workspace-demo-content">
<p class="workspace-demo-eyebrow">Production workspace</p>
<h4 data-workspace-title>Home</h4>
<p class="workspace-demo-description" data-workspace-description>Your production workspace: quick access to the tools you use every day.</p>
<div class="workspace-demo-detail"><strong>One workspace, every department.</strong><p>Choose a tool from the navigation to preview its destination.</p></div>
<p data-crazy-button-status role="status">Home selected.</p>
</div>
</div>The section colors follow the reference; the surrounding surfaces follow the environment theme. data-redirect-name retains the original route identifiers. These examples update the preview; connect buttonaction to your application router for real navigation. Preview layout styles are shown below.
Preview layout CSS
// Documentation preview layout; all controls are kmaterialize CrazyButton instances.
.workspace-nav-preview {
border: 1px solid var(--md-sys-color-outline-variant);
border-radius: 20px;
overflow: hidden;
background: var(--md-sys-color-surface);
color: var(--md-sys-color-on-surface);
margin: 24px 0;
.workspace-demo-navigation {
background: var(--md-sys-color-surface-container, var(--md-sys-color-surface-variant));
box-shadow: none;
color: var(--md-sys-color-on-surface-variant);
height: auto;
line-height: normal;
}
.workspace-demo-group { display: flex; align-items: center; gap: 12px; }
.workspace-demo-group > span { font-size: 11px; font-weight: 600; letter-spacing: .04em; }
crazy-button { flex-shrink: 0; }
crazy-button[aria-current='page'] { outline: 2px solid var(--md-sys-color-primary); outline-offset: 4px; border-radius: 16px; }
.workspace-demo-content { min-width: 0; padding: clamp(16px, 4vw, 32px); }
.workspace-demo-eyebrow { margin: 0 0 12px; font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--md-sys-color-on-surface-variant); }
h4 { font-size: clamp(22px, 3vw, 32px); margin: 0 0 12px; }
.workspace-demo-description { font-size: 14px; line-height: 1.6; }
.workspace-demo-detail { margin-top: 24px; padding: 16px; border-radius: 12px; background: var(--md-sys-color-surface-variant); font-size: 13px; }
&[data-layout='rail'] {
display: grid;
grid-template-columns: 88px minmax(0, 1fr);
.workspace-demo-navigation { display: flex; flex-direction: column; align-items: center; gap: 24px; padding: 20px 0; }
.workspace-demo-group { flex-direction: column; }
.workspace-demo-content { border-left: 1px solid var(--md-sys-color-outline-variant); }
}
&[data-layout='toolbar'] {
.toolbar { margin: 0; border-radius: 0; padding: 16px; gap: 24px; }
.workspace-demo-group > span { writing-mode: vertical-rl; transform: rotate(180deg); }
}
}
Workspace navigation toolbar
The same workspace navigation groups arranged horizontally in Materialize’s Toolbar. Scroll the toolbar to reach every group on narrow screens.
Production workspace
Home
Your production workspace: quick access to the tools you use every day.
Choose a tool from the navigation to preview its destination.
Home selected.
Markup — Crazy buttons and navigation groups
<div class="workspace-nav-preview" data-layout="toolbar">
<div class="workspace-demo-navigation toolbar" aria-label="Production navigation" role="group">
<div class="workspace-demo-group toolbar-group" role="group" aria-label="Workspace">
<crazy-button type="floating" size="large" shape="box" depth="1" icon-text="home" label="Home" data-redirect-name="Home" color-primary="gold" color-secondary="#211b00" aria-current="page"></crazy-button>
<crazy-button type="floating" size="large" shape="box" depth="flat" icon-text="schedule" label="Timelog" data-redirect-name="Timelog" color-secondary="var(--md-sys-color-primary)"></crazy-button>
</div>
<div class="workspace-demo-group toolbar-group" role="group" aria-label="Out.">
<span>Out.</span>
<crazy-button type="floating" size="large" shape="box" depth="1" icon-text="social_distance" label="Outsource Turnover" data-redirect-name="OutsourceTurnover" color-primary="#4fc3f7" color-secondary="#052e3c"></crazy-button>
<crazy-button type="floating" size="large" shape="box" depth="1" icon-text="microwave" label="Brief Outsource" data-redirect-name="OutsourceBrief" color-primary="#26a69a" color-secondary="#002e29"></crazy-button>
</div>
<div class="workspace-demo-group toolbar-group" role="group" aria-label="Prod.">
<span>Prod.</span>
<crazy-button type="floating" size="large" shape="box" depth="1" icon-text="schedule" label="Timelog Summary" data-redirect-name="TimelogSummary" color-primary="#ab47bc" color-secondary="#fff"></crazy-button>
</div>
<div class="workspace-demo-group toolbar-group" role="group" aria-label="Studio">
<span>Studio</span>
<crazy-button type="floating" size="large" shape="box" depth="1" icon-text="stadium" label="Studio Resource" data-redirect-name="StudioResource" color-primary="#ec407a" color-secondary="#fff"></crazy-button>
<crazy-button type="floating" size="large" shape="box" depth="1" icon-text="view_timeline" label="Crew Planning" data-redirect-name="Planning" color-primary="#ef6c00" color-secondary="#fff"></crazy-button>
</div>
<div class="workspace-demo-group toolbar-group" role="group" aria-label="Admin">
<span>Admin</span>
<crazy-button type="floating" size="large" shape="box" depth="flat" icon-text="settings" label="Settings" data-redirect-name="Settings" color-secondary="var(--md-sys-color-on-surface)"></crazy-button>
</div>
</div>
<div class="workspace-demo-content">
<p class="workspace-demo-eyebrow">Production workspace</p>
<h4 data-workspace-title>Home</h4>
<p class="workspace-demo-description" data-workspace-description>Your production workspace: quick access to the tools you use every day.</p>
<div class="workspace-demo-detail"><strong>One workspace, every department.</strong><p>Choose a tool from the navigation to preview its destination.</p></div>
<p data-crazy-button-status role="status">Home selected.</p>
</div>
</div>The section colors follow the reference; the surrounding surfaces follow the environment theme. data-redirect-name retains the original route identifiers. These examples update the preview; connect buttonaction to your application router for real navigation. Preview layout styles are shown below.
Preview layout CSS
// Documentation preview layout; all controls are kmaterialize CrazyButton instances.
.workspace-nav-preview {
border: 1px solid var(--md-sys-color-outline-variant);
border-radius: 20px;
overflow: hidden;
background: var(--md-sys-color-surface);
color: var(--md-sys-color-on-surface);
margin: 24px 0;
.workspace-demo-navigation {
background: var(--md-sys-color-surface-container, var(--md-sys-color-surface-variant));
box-shadow: none;
color: var(--md-sys-color-on-surface-variant);
height: auto;
line-height: normal;
}
.workspace-demo-group { display: flex; align-items: center; gap: 12px; }
.workspace-demo-group > span { font-size: 11px; font-weight: 600; letter-spacing: .04em; }
crazy-button { flex-shrink: 0; }
crazy-button[aria-current='page'] { outline: 2px solid var(--md-sys-color-primary); outline-offset: 4px; border-radius: 16px; }
.workspace-demo-content { min-width: 0; padding: clamp(16px, 4vw, 32px); }
.workspace-demo-eyebrow { margin: 0 0 12px; font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--md-sys-color-on-surface-variant); }
h4 { font-size: clamp(22px, 3vw, 32px); margin: 0 0 12px; }
.workspace-demo-description { font-size: 14px; line-height: 1.6; }
.workspace-demo-detail { margin-top: 24px; padding: 16px; border-radius: 12px; background: var(--md-sys-color-surface-variant); font-size: 13px; }
&[data-layout='rail'] {
display: grid;
grid-template-columns: 88px minmax(0, 1fr);
.workspace-demo-navigation { display: flex; flex-direction: column; align-items: center; gap: 24px; padding: 20px 0; }
.workspace-demo-group { flex-direction: column; }
.workspace-demo-content { border-left: 1px solid var(--md-sys-color-outline-variant); }
}
&[data-layout='toolbar'] {
.toolbar { margin: 0; border-radius: 0; padding: 16px; gap: 24px; }
.workspace-demo-group > span { writing-mode: vertical-rl; transform: rotate(180deg); }
}
}
Custom cursors
Set cursor to a CSS cursor value. It applies to the inner button or link and both halves of a split button. Changing or removing the attribute updates the cursor automatically.
<crazy-button type="extended" label="Grab" cursor="grab"></crazy-button>
<crazy-button type="extended" label="Help" class="cursor-help"></crazy-button>
<crazy-button type="extended" label="Custom image"
cursor="url('/cursors/target.svg') 12 12, crosshair"></crazy-button>You can also apply a cursor utility class or an inline style="cursor: …" to the component itself. An explicit cursor attribute takes precedence over that inherited cursor. Empty or invalid values fall back to the host style, normally pointer. Disabled buttons remain inactive and ignore the attribute.
button.setAttribute('cursor', 'wait');
// Restore the inherited/default cursor:
button.removeAttribute('cursor');For image cursors, provide an image URL, optional hotspot coordinates, and a fallback keyword. The example uses a 24px SVG with its hotspot at the center.
Disabled and projected content
Disabled buttons and links cannot activate. Supplied child nodes keep their identity across updates. Labels are plain text; use child markup for rich labels.
<crazy-button type="extended" variant="filled" label="Unavailable" disabled></crazy-button>
<regular-btn type="extended" label="Disabled link" href="buttons.html" disabled></regular-btn>
<crazy-button type="extended" variant="outlined" size="normal"><strong>Review</strong> shot</crazy-button>Environment colors
Try the site theme controls or choose a local accent with the library’s ColorInput picker and select Save. Tokens inherit from the nearest environment without rerendering the component. Explicit legacy color attributes override inheritance.
<div class="input-field">
<input id="button-accent" type="color" data-color-picker="pickr" data-color-theme="nano" data-color-opacity="false" value="#6750a4">
<label for="button-accent">Local accent</label>
</div>
<div id="button-environment" style="--md-sys-color-primary: #6750a4; --md-sys-color-on-primary: white; --md-sys-color-primary-container: #eaddff; --md-sys-color-on-primary-container: #21005d; padding: 16px;">
<crazy-button type="extended" variant="filled" label="Environment action" size="normal"></crazy-button>
<crazy-button type="extended" variant="outlined" label="Supporting action" size="normal"></crazy-button>
<crazy-button type="fab" icon-text="palette" label="Environment FAB"></crazy-button>
</div>Setup and API
Load Materialize CSS and an icon font, then import CrazyButton from kmaterialize. Both custom element names register automatically in the browser. For labeled icon buttons, install the optional tippy.js peer and load its styles as shown on the Tooltips page. Do not also initialize these controls with initMaterialButtons.
import { CrazyButton, Kmcomponent } from 'kmaterialize';
const button = document.querySelector<CrazyButton>('crazy-button')!;
button.setProperty('label', 'Ready');
button.setAttribute('variant', 'filled');
await button.updateComplete;
button.addEventListener('buttonaction', (event) => {
console.log((event as CustomEvent).detail); // { action, pressed }
});Kmcomponent is the CrazyPHP Crazycomponent2 script renamed, including its property schema, typed conversion, batched rendering, light DOM projection, optional shadow root, setHtmlAndCss, postRender, and onCleanup APIs. Crazy button uses light DOM for the host environment's styles.
color-primary and color-secondary prefer Materialize palette names, including gold, blue, and red, over CSS named colors. Shades such as blue lighten-2 are supported. Use explicit hex, RGB, or CSS variables when you need a custom color. Image-only buttons fill the control and follow its selected shape.
| Attribute | Values / default |
|---|---|
| type | floating (default), extended, icon, fab, extended-fab, rail |
| depth | flat (default), outlined, 1–5; variant takes precedence over the legacy style |
| shape / size | round (default), box, square, round-left, round-right / large (default), small, normal, extra-large, xs, sm, md, lg, xl |
| wave | light (default), dark, false |
| tooltip-style | classic (default), material. Uses the optional tippy.js peer; load its styles before Materialize CSS. |
| tooltip-position | top (default), right, bottom, left. Tooltip placement for floating, icon, and FAB buttons. |
| label / icon-text / icon-class | Empty label and icon; icon-class defaults to material-icons |
| icon-image / icon-image-style / icon-position | Image URL / inline image CSS / right (default), left |
| color-primary / color-secondary | Background / foreground and outline. CSS colors, var(...) expressions, or legacy palette classes such as blue lighten-5. Class colors require the legacy Materialize colors stylesheet. |
| data-view / aria-current | Navigation view identifier / current destination (for example page). Forwarded reactively to the inner control. |
| href / target | Empty (native button) / _self (default), _blank. Links use anchors; disabled links become disabled buttons. |
| variant | filled, tonal, outlined, elevated, text, standard (unfilled icon); omitted: derive from depth |
| toggle / pressed / disabled / split | Boolean: presence, true, or 1 enables; false or 0 disables; omitted defaults to false |
| icon-width | normal (default), narrow, wide |
| fab-color / fab-size | primary (default), secondary, tertiary / normal (default), small, large |
| menu-target / menu-label | External dropdown element ID / More options (default) |
| aria-label / action | Accessible name override / buttonaction event identifier (defaults to label) |
| cursor | Any valid CSS cursor value, such as grab, wait, or url(...) 12 12, crosshair; inherits the host cursor when omitted. |
| button-type / name / value / form | button (default), submit, reset / native form button attributes |
Migration notes: regular-btn is registered only when that tag is free; load this implementation instead of the old registration. Existing attribute names and floating/extended behavior are retained. Default colors now inherit the environment instead of forcing blue lighten-5. Raw HTML in the old label attribute should be moved into child markup. Use native click listeners for activation or buttonaction for the component's action and selection state (pressed is "true", "false", or null). External dropdown items keep their own handlers.