Button
One clear action: primary, quiet, ghost or danger. A link with href, a form button without.
openvibe-shared/kitJSON
Build it
kit.button({ label: 'Go live', href: '/go', icon: 'live' }) + kit.button({ label: 'Not now', kind: 'quiet', type: 'button' }) + kit.button({ label: 'Delete', kind: 'danger', type: 'button', small: true })Props
href- any?
icon- string?
kind- string?
name- any?
type- string?
attrs- any?
label- string?
small- boolean?
value- any?
Anatomy
- containerbackground color.accent.strong; radius radius.pill; minHeight size.tap; paddingX space.lg
- labelcolor color.accent.onStrong; size type.size.body; weight type.weight.bold
- iconsize size.icon; color color.accent.onStrong
Behaviour and access
- Keyboard
- Standard focus order
- Outside tap
- Leaves it open
- Scroll
- The page still scrolls
- Reduced motion
- Remove movement; keep the state change.
- Name
- its label
- Target
- 44 × 44 on touch
- Focus
- Enter (and Space as a button)
States
- default
- hover
- pressed
- focused
- disabled
Tokens
color.accent.strongradius.pillsize.tapspace.lgcolor.accent.onStrongtype.size.bodytype.weight.boldsize.icon
Android · Jetpack Compose
Button
@Composable fun OvButton(label: String, onClick: () -> Unit, kind: OvKind = OvKind.Primary, icon: ImageVector? = null) { val c = MaterialTheme.colorScheme val colors = when (kind) { OvKind.Primary -> ButtonDefaults.buttonColors(containerColor = c.primaryContainer, contentColor = c.onPrimaryContainer) OvKind.Danger -> ButtonDefaults.buttonColors(containerColor = c.error, contentColor = c.onError) OvKind.Quiet -> ButtonDefaults.outlinedButtonColors(contentColor = c.onSurface) } val content: @Composable RowScope.() -> Unit = { if (icon != null) { Icon(icon, contentDescription = null, Modifier.size(OvScale.SizeIcon)); Spacer(Modifier.width(OvScale.SpaceSm)) } Text(label, fontWeight = FontWeight.Bold) } val m = Modifier.heightIn(min = OvScale.SizeTap) if (kind == OvKind.Quiet) OutlinedButton(onClick, m, shape = RoundedCornerShape(OvScale.RadiusPill), colors = colors, border = BorderStroke(1.dp, c.outline), content = content) else Button(onClick, m, shape = RoundedCornerShape(OvScale.RadiusPill), colors = colors, content = content) }
iOS · SwiftUI
struct OvButton: View { let label: String var kind: OvKind = .primary var icon: String? = nil let action: () -> Void var body: some View { Button(action: action) { Label { Text(label).fontWeight(.bold) } icon: { if let icon { Image(systemName: icon) } } .frame(minHeight: OvScale.sizeTap) .padding(.horizontal, OvScale.spaceLg) } .buttonStyle(.borderedProminent) .buttonBorderShape(.capsule) .tint(kind == .danger ? OvTokens.colorStatusBadBase : kind == .quiet ? Color.clear : OvTokens.colorAccentStrong) .foregroundStyle(kind == .quiet ? OvTokens.colorTextPrimary : OvTokens.colorAccentOnStrong) } }
Markup
Default
<a class="ovk-btn ovk-btn--primary" href="/go"><svg class="ovk-i" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="2.15"/><path d="M8.4 8.4a5.15 5.15 0 0 0 0 7.55M15.6 8.4a5.15 5.15 0 0 1 0 7.55M6 6a8.55 8.55 0 0 0 0 12.6M18 6a8.55 8.55 0 0 1 0 12.6"/></svg><span>Go live</span></a><button class="ovk-btn ovk-btn--quiet" type="button"><span>Not now</span></button><button class="ovk-btn ovk-btn--danger ovk-btn--small" type="button"><span>Delete</span></button>