Button

Buttons trigger actions.

Basic Usage

#![allow(unused)]
fn main() {
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

#![allow(unused)]
fn main() {
// 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

#![allow(unused)]
fn main() {
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

#![allow(unused)]
fn main() {
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:

#![allow(unused)]
fn main() {
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; }
#![allow(unused)]
fn main() {
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

#![allow(unused)]
fn main() {
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

#![allow(unused)]
fn main() {
button("")
    .size(ButtonSize::Icon)
    .variant(ButtonVariant::Ghost)
    .icon(icons::X)
    .on_click(|_| close_dialog())
}

A Button That Follows a Signal

#![allow(unused)]
fn main() {
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