Skip to main content

Chip

Purpose​

Compact elements for filters, choices, entries and actions.

Signature​

pub struct Chip<Msg = crate::callback::Callback> { .. }

impl Chip {
pub fn new(label: impl Into<String>) -> Self;
}

Example​

Rendered preview of the Chip demo

From frus-examples/widgets/src/features/display/widgets/chip.rs:

//! `Chip` — a compact element for an attribute, a filter, a choice or an entry. One
//! widget; what makes it one kind or another is what it can do: be selected, carry an
//! icon, be removed, be pressed.

use frus::{Align, Chip, Column, Icons, Text, Widget, Wrap};

use crate::common::shared::{section, sections};

const TOPPINGS: [&str; 4] = ["Cheese", "Olives", "Basil", "Mushrooms"];
const SIZES: [&str; 3] = ["Small", "Medium", "Large"];

pub fn example() -> Box<dyn Widget> {
// `frus::component` turns a closure into a widget that can keep state with hooks:
// each `use_state` value survives rebuilds, and setting it rebuilds the component.
Box::new(frus::component(|cx| {
let toppings = cx.use_state(|| vec![true, false, false, false]);
let size = cx.use_state(|| 1usize);
let guests = cx.use_state(|| vec!["Ada", "Alan", "Grace"]);
let presses = cx.use_state(|| 0u32);

// Filter chips: each one toggles independently, and a checkmark shows the ones on.
let filters = TOPPINGS.iter().enumerate().fold(
Wrap::new().gap(8.0).run_gap(8.0),
|row, (i, name)| {
let toppings_handle = toppings.clone();
row.child(
Chip::new(*name)
.selected(toppings.with(|on| on[i]))
.on_press(move || toppings_handle.update(|on| on[i] = !on[i])),
)
},
);

// Choice chips: exactly one is selected. No checkmark, the fill says it.
let choices =
SIZES
.iter()
.enumerate()
.fold(Wrap::new().gap(8.0).run_gap(8.0), |row, (i, name)| {
let size_handle = size.clone();
row.child(
Chip::new(*name)
.selected(size.get() == i)
.show_checkmark(false)
.on_press(move || size_handle.set(i)),
)
});

// Input chips: entries the user added, each with a leading icon and a delete cross.
let entries =
guests
.get()
.into_iter()
.fold(Wrap::new().gap(8.0).run_gap(8.0), |row, name| {
let guests_handle = guests.clone();
row.child(Chip::new(name).leading(Icons::PERSON).on_remove(move || {
guests_handle.update(|list| list.retain(|g| *g != name))
}))
});

// Action chips: a pressable shortcut, like a small button.
let presses_handle = presses.clone();
let actions = Wrap::new()
.gap(8.0)
.run_gap(8.0)
.child(
Chip::new("Add to calendar")
.leading(Icons::EVENT)
.on_press(move || presses_handle.update(|n| *n += 1)),
)
// A disabled chip stays visible, dimmed, and ignores presses.
.child(
Chip::new("Unavailable")
.leading(Icons::BLOCK)
.enabled(false),
);

let chosen: Vec<&str> = TOPPINGS
.iter()
.zip(toppings.get())
.filter_map(|(name, on)| on.then_some(*name))
.collect();

sections(vec![
Box::new(section(
"Filter chips",
Column::new()
.cross_axis_alignment(Align::Start)
.spacing(8.0)
.child(filters)
.child(Text::new(format!("Toppings: {}", chosen.join(", ")))),
)),
Box::new(section(
"Choice chips",
Column::new()
.cross_axis_alignment(Align::Start)
.spacing(8.0)
.child(choices)
.child(Text::new(format!("Size: {}", SIZES[size.get()]))),
)),
Box::new(section(
"Input chips (removable)",
Column::new()
.cross_axis_alignment(Align::Start)
.spacing(8.0)
.child(entries)
.child(Text::new(format!("{} guests left", guests.with(Vec::len)))),
)),
Box::new(section(
"Action chips",
Column::new()
.cross_axis_alignment(Align::Start)
.spacing(8.0)
.child(actions)
.child(Text::new(format!("Pressed {} times", presses.get()))),
)),
])
}))
}

Properties​

MethodArgumentEffect
.selected()selected: boolMarks the chip selected: it fills, its label takes the colour that goes with the fill, and a checkmark appears in the leading slot unless there is an icon there already (or Chip::show_checkmark says otherwise).
.leading()icon: IconDataA leading icon — the avatar or glyph an entry chip carries.
.enabled()enabled: boolGreys the chip out and makes it inert: no press, no ink, out of the tab order, and announced to a reader as disabled rather than simply going quiet.
.on_press()message: impl Into<Msg>The message the chip emits when pressed. A chip with none is inert, which is what an attribute chip is.
.on_remove()message: impl Into<Msg>Adds a delete cross that emits message.
.show_checkmark()show: boolWhether a selected chip shows a checkmark. On by default.
.color()color: ColorThe surface under an unselected chip. Transparent by default.
.selected_color()color: ColorThe surface under a selected one.
.label_color()color: ColorThe label's colour when unselected.
.selected_label_color()color: ColorThe label's colour when selected.
.label_style()style: TextStyleThe label's type. Defaults to the theme's label_large step.
.border_color()color: ColorThe outline's colour.
.border_width()width: f32The outline's thickness; 0.0 removes it.
.radius()radius: impl Into<BorderRadius>The corner radii (uniform via f32, per corner via BorderRadius) — the shorthand for a rounded rectangle. See Chip::shape.
.shape()shape: ShapeBorderThe last of the two to be called is the one that counts: they are one property.
.padding()padding: f32The room inside the outline.
.label_padding()padding: f32The room on either side of the label.
.height()height: f32The chip's height.
.icon_size()size: f32The size of the leading icon, the checkmark and the delete cross.

Behaviour​

A compact label — an attribute, a filter or an entry.

See also​

  • Card: a themed surface that groups one piece of content: elevated, filled or outlined.
  • CircleAvatar: a circle that stands for a person: a picture, initials or an icon.
  • Badge: a small count or dot that says there is something new.
  • Icon: vector icons from the bundled set, or your own, sized and coloured.
  • The guide: Text, colour and the theme
  • API reference: Chip

Source: crates/frus-widgets/src/chip.rs @ e6fba33f5b42