The glyph to render (inline SVG node - e.g. <NockerlIcon .../>).
label *
string
n/a
Accessible name (REQUIRED - the only thing that names an icon-only control).
variant
NockerlIconButtonStyle
'plain'
The icon-button idiom. Defaults to plain.
accent
string
'var(--color-accent-primary)'
Circle fill for filled-circle (defaults to the cyan accent token). Pass a var(--token).
size
number
40
Touch-target dimension in px. Defaults to 40 (Compose default).
pressed
boolean
n/a
TOGGLE mode: when set, the icon button HOLDS state: renders aria-pressed and, when true, the pressed VISUAL is the selection outline (a selection-weight cyan ring plus a cyan glyph, and no fill, design-laws section 6). The primary home for icon toggles (toolbar toggles, wrap, etc.). Omit for a plain command icon 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
icon *
ImageVector
n/a
The glyph to render.
contentDescription *
String?
n/a
Accessible name. Use null only when a sibling label already names the action.
onClick *
() -> Unit
n/a
Invoked on tap. No-op while enabled = false.
modifier
Modifier
Modifier
Outer modifier (placement, weight).
style
NockerlIconButtonStyle
PLAIN
Idiom: PLAIN (transparent, control radius) · FILLED_CIRCLE (solid accent circle for send/stop).
enabled
Boolean
true
When false, the button is dimmed (alpha 0.38) and non-interactive.
accent
Color
engineCloud
Circle fill for FILLED_CIRCLE (defaults to the engine-cloud cyan); ignored for PLAIN.
tint
Color
onCanvas
Glyph color for PLAIN; ignored for the circle (which contrast-picks against accent).
size
Dp
40.dp
Touch-target dimension. Use 48.dp for the send/stop circle.
iconSize
Dp
20.dp
Rendered glyph size.
The published NockerlIconButton is a self-contained View that takes an Image + a
REQUIRED accessible name. Both idioms ship (.plain / .filledCircle). State (isEnabled,
pressed) flows from the SwiftUI environment; honor .disabled(_:) for the dimmed state.
Parameter
Type
Default
Description
image *
Image
n/a
The glyph (the leading unlabeled argument), e.g. Image(systemName: "paperplane.fill"). Rendered in a 40pt visual box inside a ≥44pt hit frame.
label *
String
n/a
Required, non-empty accessible name. An icon-only control has no visible text. Whitespace is trimmed; a blank value asserts in debug builds.
style
NockerlIconButtonStyle
.plain
Idiom: .plain (transparent, NockerlRadius.control) · .filledCircle (solid accentPrimary circle for the send/stop slot).
density
NockerlControlDensity
.comfortable
The rhythm tier (foundations/density): .comfortable = 40pt visual in a ≥44pt layout frame · .compact = a 32pt visual that IS the layout footprint (dense rows keep their height) while the 44pt hit target extends invisibly via expanded touch bounds (law §13 preserved). Space compact neighbors ≥12pt apart so hit zones don’t overlap.
tint
NockerlIconButtonTint
.neutral
The .plain glyph tint: .neutral (on-card) · .destructive (status-red; delete/remove reads via color + glyph, never a screaming fill) · .custom(Color). .filledCircle ignores it (accent-locked send/stop slot).
init(systemName:label:…)
convenience
n/a
SF Symbol shorthand: NockerlIconButton(systemName: "trash", label: "Delete", tint: .destructive) { … }.
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 both idioms and the a11y contract. The earlier drift
is resolved:
Both idioms ship. Swift has .plainand.filledCircle (the send/stop slot),
matching Compose/web, no longer plain-only.
Control radius is tokenized. The .plain idiom consumes NockerlRadius.control
(12pt); .filledCircle uses the pill radius. The hardcoded 10pt is gone.
Hit target meets the minimum. Swift renders a 40pt visual inside a ≥44pt hit frame
(Apple HIG), matching Compose’s 40dp default. The old 24×22pt frame is gone.
Accessible name is required. Swift’s label is now a required, non-empty argument that
asserts in debug, matching Compose’s contentDescription / web’s label. No more unnamed
default.
Remaining, minor differences:
Sizing knob: Compose/web expose an explicit size (and Compose iconSize); Swift’s
visual is fixed at 40pt (the shared control height). Disabled state is honored via
.disabled(_:) on Swift rather than an enabled parameter.