Shows a spinner, holds the button width, blocks re-click.
leadingIcon
ReactNode
n/a
Optional leading glyph (icon slot).
trailingIcon
ReactNode
n/a
Optional trailing glyph (icon slot AFTER the label), e.g. a chevron / arrow.
loadingText
string
n/a
Label shown WHILE loading (e.g. "Saving…"); falls back to text.
type
'button' | 'submit' | 'reset'
'button'
Native button type: submit/reset for real forms (default button).
fullWidth
boolean
false
Stretch to the container width (e.g. a full-width CTA / sheet action).
ariaLabel
string
n/a
Accessible name override (when the label alone is ambiguous).
pressed
boolean
n/a
TOGGLE mode: when set, the button HOLDS state: it renders aria-pressed and, when true, the pressed VISUAL is the selection outline (a selection-weight cyan border plus cyan ink, and no fill, design-laws section 6), NOT a separate control. Omit it for a plain command button.
Also accepts the native <button> attributes (e.g. onClick, disabled, id, aria-*, data-*), forwarded straight through, plus a forwarded ref.
Parameter
Type
Default
Description
text *
String
n/a
Visible label. Rendered with NockerlControlTextStyle.
onClick *
() -> Unit
n/a
Invoked on click. No-op while enabled = false.
modifier
Modifier
Modifier
External modifier. Pass Modifier.fillMaxWidth() for a block button.
When false, the button is dimmed (alpha) and non-interactive.
contentPadding
PaddingValues
horizontal 18.dp, vertical 11.dp
Inner padding around the content row.
maxLines
Int
Int.MAX_VALUE
Label lines before ellipsis. Pass 1 for a width-capped, single-line button.
leadingContent
(@Composable -> Unit)?
null
Optional content (typically an Icon) before the label; receives the variant content color via LocalContentColor.
The published NockerlButton is a self-contained View: NockerlButton(_ text:, variant:, action:).
The label is auto-uppercased (buttons are the only uppercase in the type system). State
(isEnabled, isPressed) flows from the SwiftUI environment. Honor .disabled(_:) for the
dimmed, non-interactive state; there are no explicit state parameters.
Parameter
Type
Default
Description
text *
String
n/a
The label (the leading unlabeled argument). Rendered uppercased, weight .light, tracked −0.03em.
variant
NockerlButtonVariant
.primary
Fill ladder: .primary · .secondary · .tertiary · .ghost · .destructive. Primary is a vertical cyan catch-light gradient; tertiary is the outlined cyan step; all share NockerlRadius.control (12pt).
action *
() -> Void
n/a
The trailing closure, invoked on tap.
Cross-platform parity (published packages)
The published Compose (com.dizyx.nockerl.design.components) and Swift
(NockerlDesign) packages now share one API, and the earlier drift is resolved:
Full ladder on both. Swift ships all five variants (.primary … .destructive),
including .tertiary. The old “4 vs 5” gap is closed.
Control radius is tokenized. Swift consumes NockerlRadius.control (12pt) for the
fill, border, and hit shape; the hardcoded 10pt is gone.
Remaining, intentional expression differences:
Primary fill: Swift paints a vertical catch-light gradient
(accentPrimaryHi → accentPrimary) and Compose a solidaccentPrimary. Both are
static fills (no tween). Web mirrors the subtle vertical catch-light. This is a deliberate
per-platform expression, not a token drift.
Sizing: web exposes size (sm/md/lg); Compose uses contentPadding; Swift is a fixed
content padding + 40pt min height. Same visual weight, different knob per platform.