Actions

Button

A clear call to action, with bound labels, variants and keyboard focus.

Open ↗
Button interaction recorded with the Blinc headless renderer
Hybrid · dark · native recording · 2×

Usage and properties

The label can be a value, Signal or Computed. A disabled button ignores activation. Choose variants and sizes when building the component.

Use the installation guide to add blinc_cn and its component stylesheet. Create the fixture bindings once, and return the demo from your UI builder. Values marked Bound accept Signal/Computed sources where the API supports them; structural options configure the component at construction.

PropertyTypeUpdate modelThis example
labelStringBoundClick me
disabledboolBoundfalse
variantButtonVariantStructuralPrimary
sizeButtonSizeStructuralMedium
on_clickFn(&EventContext)CallbackIncrement the click count

Keyboard and interaction

:hover, :active, :disabled and :focus-visible. Tab reaches the button; Enter or Space activates it.

Customizing it

Add application CSS after the default component layer. These selectors are the restyling surface for this component:

  • .cn-button
  • .cn-button--primary
  • .cn-button--secondary
  • .cn-button--outline
  • .cn-button--ghost
  • .cn-button--link
  • .cn-button--destructive
  • .cn-button--sm
  • .cn-button--md
  • .cn-button--lg
  • .cn-button--icon

Theme and component variables: --primary, --primary-hover, --primary-active, --text-inverse, --focus-ring, --radius-default.

Built-in themes

The Live theme control installs Blinc's own theme bundles, including their colours, focus rings, corner shapes and motion tokens.

pub fn theme_bundle_for(name: &str) -> blinc_theme::ThemeBundle {
    match name {
        "restrained" => blinc_theme::RestrainedTheme::bundle(),
        "expressive" => blinc_theme::ExpressiveTheme::bundle(),
        _ => blinc_theme::HybridTheme::bundle(),
    }
    .with_css(blinc_cn::cn_styles::CN_STYLES)
}

Download the default widget and component stylesheets. Sample assets and licenses are available in the asset guide.

Documentation

From the canonical component guide.

Buttons trigger actions.

Basic Usage

use blinc::cn::prelude::*;

button("Click me")
    .on_click(|_| println!("Clicked!"))

The label takes a string or a signal, and is patched in place when it changes.

Variants

// Primary (default) - main actions
button("Save").variant(ButtonVariant::Primary)

// Secondary - alternative actions
button("Cancel").variant(ButtonVariant::Secondary)

// Destructive - dangerous actions
button("Delete").variant(ButtonVariant::Destructive)

// Outline - bordered
button("Edit").variant(ButtonVariant::Outline)

// Ghost - minimal
button("More").variant(ButtonVariant::Ghost)

// Link - looks like a link
button("Learn more").variant(ButtonVariant::Link)

Sizes

button("Small").size(ButtonSize::Small)
button("Default").size(ButtonSize::Medium)
button("Large").size(ButtonSize::Large)

// Icon only (square)
button("").size(ButtonSize::Icon).icon(icons::SETTINGS)

// A size of your own: width, height
button("Wide").size(ButtonSize::Custom(160.0, 48.0))

With Icons

use blinc::icons::icons;

button("Settings").icon(icons::SETTINGS)

// After the label
button("Next")
    .icon(icons::ARROW_RIGHT)
    .icon_position(IconPosition::End)

Disabled

disabled takes a bool or a signal, so a button can follow a state:

button("Disabled").disabled(true)
button("Save").disabled(&is_saving)

A disabled button does not click and takes the disabled look.

Styling

A button's look is stylesheet. Its fill, text colour, border and shadow, and how they change on hover, press and while disabled, are the .cn-button rules of CN_STYLES, with a transition, so a button eases between states. Each variant and size has a class to hang your own rules on:

ClassMatches
.cn-buttonevery cn button
.cn-button--primary, --secondary, --destructive, --outline, --ghost, --linkthe variant
.cn-button--sm, --md, --lg, --iconthe size
/* A brand colour for primary buttons, eased on hover. Your rules win over
   cn's whatever their specificity. */
.cn-button--primary { background: #6d28d9; }
.cn-button--primary:hover:not(:disabled) { background: #7c3aed; }
.cn-button--primary:active:not(:disabled) { background: #5b21b6; }

/* One button of your own */
.danger { background: #c0392b; transition: background-color 150ms ease; }
.danger:disabled { background: #555; color: #999; }
button("Delete").class("danger")

:hover:not(:disabled) keeps the rule off a disabled button. :active matches while the pointer is down on the button or anything inside it, as on the web. Text and icons inside take the button's color, so a rule that changes it changes them too.

.color(..) on the builder fixes the text colour in every state; a fluent value wins over cn's rules, as an inline style does on the web.

Button Groups

div()
    .flex_row()
    .gap(2.0)
    .child(button("Save").variant(ButtonVariant::Primary))
    .child(button("Cancel").variant(ButtonVariant::Outline))

gap takes 4px units, so gap(2.0) is 8px.

Examples

Icon Button

button("")
    .size(ButtonSize::Icon)
    .variant(ButtonVariant::Ghost)
    .icon(icons::X)
    .on_click(|_| close_dialog())

A Button That Follows a Signal

let saving = ctx.use_signal(false);

button("Save")
    .disabled(saving)
    .on_click(move |_| saving.set(true))

API Reference

MethodTypeDefaultDescription
variantButtonVariantPrimaryVisual style
sizeButtonSizeMediumSmall, Medium, Large, Icon or Custom(w, h)
disabledbool or signalfalseDisable interaction
icon&strnoneAn icon from blinc::icons::icons
icon_positionIconPositionStartStart or End
icon_sizef32label size + 2Icon size in px
colorColorby variantText colour in every state
on_clickFn(&EventContext)noneCalled when clicked
class, id&strnoneSelectors for your own rules

Platforms and version

The component API is available in Blinc 0.6.0. The Live example runs in a dedicated worker and requires a compatible GPU surface. Preview and Code remain available when Live cannot start. The canvas has a descriptive label; a full screen-reader DOM mirror is not provided. The gallery integration is based on revision e2e55c24e078.

Recordings and live demos use the default Hybrid theme with bundled Noto Sans. The recording uses a 560 × 320 logical viewport at twice that resolution. Live follows its container and actual display density. Source base revision · Exact build source · Artifact versions and checksums · Font license.