Components / display
Card builder
A raised panel that groups related rows or content.
A builder is RenderOnce. Construct and mount it in one expression.
use gpui_kit::display::card::Card;
Reviewed in card.
Also drawn by motion-flip translation-packs reading-direction, which arranges components rather than reviewing them.
Construct
new() -> Self
Options
Chain onto the value.
id(ident: impl Into<Ident>) -> Self
name(name: impl Into<SharedString>) -> Self
variant(variant: CardVariant) -> Self
ground(ground: Surface) -> Self
header(header: CardHeader) -> Self
media(media: impl Fn(&mut Window, &mut App) -> AnyElement + 'static) -> Self
footer(footer: impl Fn(&mut Window, &mut App) -> AnyElement + 'static) -> Self
padded(padded: bool) -> Self
padding(padding: impl Into<Option<Space>>) -> Self
on_click(handler: impl Fn(&mut Window, &mut App) + 'static) -> Self
Example · card
fn card(_window: &mut Window, cx: &mut App) -> AnyElement {
let theme = cx.theme().clone();
let label = |content: &'static str| {
div()
.flex_1()
.min_w_0()
.child(crate::foundation::text(&theme, TypeScale::Label, content))
};
let caption = |content: &'static str| {
crate::foundation::text(&theme, TypeScale::Caption, content)
.text_tone(&theme, TextTone::Muted)
};
let column = |card: Card| div().flex_1().min_w_0().child(card);
stack(&theme)
.child(
Card::new()
.id("scene.card")
.header(
CardHeader::new("Workspace services")
.subtitle("Four checked a moment ago")
.action(|_window, _cx| {
Button::new("scene.card.refresh")
.label("Refresh")
.secondary()
.small()
.into_any_element()
}),
)
.child(
ListRow::new()
.id("scene.card.runtime")
.leading(StatusDot::new(Tone::Success))
.child(label("Native runtime"))
.trailing(Badge::new("Ready").success()),
)
.child(
ListRow::new()
.id("scene.card.catalog")
.leading(StatusDot::new(Tone::Warning))
.child(label("Model catalog"))
.trailing(Badge::new("Stale").warning()),
)
.child(
ListRow::new()
.id("scene.card.index")
.selected(true)
.leading(StatusDot::new(Tone::Success))
.child(label("Search index"))
.trailing(Badge::new("Ready").success()),
)
.child(
ListRow::new()
.id("scene.card.telemetry")
.disabled(true)
.leading(StatusDot::new(Tone::Neutral))
.child(label("Telemetry export"))
.trailing(Badge::new("Off")),
)
.footer(|_window, cx| {
let theme = cx.theme().clone();
div()
.row()
.w_full()
.gap(px(theme.spacing.sm))
.child(
Button::new("scene.card.restart")
.label("Restart all")
.secondary()
.small(),
)
.child(div().flex_1())
.child(
crate::foundation::text(&theme, TypeScale::Caption, "4 services")
.text_tone(&theme, TextTone::Faint),
)
.into_any_element()
}),
)
.child(
row(&theme)
.items_start()
.child(column(
Card::new()
.id("scene.card.elevated")
.variant(CardVariant::Elevated)
.padding(Space::Lg)
.child(crate::foundation::text(
&theme,
TypeScale::Strong,
"Elevated",
))
.child(caption("A shadow. One card on a page.")),
))
.child(column(
Card::new()
.id("scene.card.filled")
.variant(CardVariant::Filled)
.padding(Space::Lg)
.child(crate::foundation::text(&theme, TypeScale::Strong, "Filled"))
.child(caption("A tonal plane for a dense grid.")),
))
.child(column(
Card::new()
.id("scene.card.ghost")
.variant(CardVariant::Ghost)
.padding(Space::Lg)
.child(crate::foundation::text(&theme, TypeScale::Strong, "Ghost"))
.child(caption("Neither. Structure without a plane.")),
)),
)
.child(
row(&theme)
.items_start()
.child(column(
Card::new()
.id("scene.card.actionable")
.padding(Space::Lg)
.on_click(|_window, _cx| {})
.header(CardHeader::new("Open the run").subtitle("The whole card acts"))
.child(caption("Enter and space reach it from the keyboard.")),
))
.child(column(
// The pairing the rows above never put together, which is
// how a card with no plane came to be lifted off one.
Card::new()
.id("scene.card.actionable-ghost")
.variant(CardVariant::Ghost)
.padding(Space::Lg)
.on_click(|_window, _cx| {})
.header(CardHeader::new("Open the line").subtitle("A ghost card acts too"))
.child(caption("No plane to rise off, so the pointer gets a wash.")),
))
.child(column(
Card::new()
.id("scene.card.chosen")
.padding(Space::Lg)
.selected(true)
.header(CardHeader::new("Selected").subtitle("A stronger material wash"))
.child(caption(
"Fill carries selection without moving the content.",
)),
))
.child(column(
Card::new()
.id("scene.card.unavailable")
.padding(Space::Lg)
.disabled(true)
.on_click(|_window, _cx| {})
.header(CardHeader::new("Unavailable").subtitle("Says so, and stays read"))
.child(caption("A disabled card installs no handler at all.")),
)),
)
.into_any_element()
}