Skip to content
PorabuildHeroGPUI component library
v0.14.0 · Apache-2.0

Layout

Card

Group related content and actions on a surface.

Rust
use herogpui::components::card::{Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle};

Card on docs.rsSource at v0.14.0

Usage

Showing Usage, live: HeroGPUI compiled to WebAssembly. The canvas has no accessibility tree; each example's description and code below carry the same information.

Usage

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{ActiveTheme, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Link, icons};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Card::new()
            .w(px(400.))
            .child(
                gpui::svg()
                    .size(px(24.))
                    .path(icons::KEY)
                    .text_color(cx.colors().accent.color),
            )
            .child(
                CardHeader::new()
                    .child(CardTitle::new().child("Become an Acme Creator!"))
                    .child(
                        CardDescription::new().child(CARD_USAGE_DESCRIPTION),
                    ),
            )
            .child(
                CardFooter::new().child(
                    Link::new("card-usage-link")
                        .label("Creator Hub")
                        .href("https://example.com")
                        .icon(
                            gpui::svg()
                                .size(px(12.))
                                .path(icons::EXTERNAL_LINK)
                                .text_color(cx.colors().link),
                        ),
                ),
            )
            .into_any_element()
    ])

Also calls CARD_USAGE_DESCRIPTION (included when you copy).

Variants

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CardVariant, Size, Variant};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let card = |variant: CardVariant| {
    Card::new()
        .variant(variant)
        .w(px(260.))
        .radius(px(4.))
        .child(
            CardHeader::new()
                .child(CardTitle::new().child("Daily report"))
                .child(CardDescription::new().child("Traffic summary for the week")),
        )
        .child(CardContent::new().child("Sessions are up 12% week over week."))
        .child(
            CardFooter::new().child(
                Button::new(format!("card-{variant:?}-cta"))
                    .label("View")
                    .size(Size::Sm)
                    .variant(Variant::Tertiary),
            ),
        )
};

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(CardVariant::ALL.iter().map(|v| card(*v)))

Horizontal Layout

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{ActiveTheme, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(vec![Card::new()
        .w(px(420.))
        .child(
            CardContent::new().child(
                gpui::div()
                    .flex()
                    .items_center()
                    .gap(px(16.))
                    .child(
                        gpui::div()
                            .size(px(72.))
                            .flex_shrink_0()
                            .rounded(px(12.))
                            .bg(cx.colors().default.color),
                    )
                    .child(
                        gpui::div()
                            .flex()
                            .flex_col()
                            .gap(px(4.))
                            .child(gpui::div().child("Weekly digest"))
                            .child(
                                gpui::div()
                                    .text_size(px(12.5))
                                    .text_color(cx.colors().muted)
                                    .child("Every Monday, 9am"),
                            ),
                    ),
            ),
        )
        .into_any_element()])

With Avatar

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{ActiveTheme, Avatar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Size, extend};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(vec![Card::new()
        .w(px(200.))
        .child(
            gpui::div()
                .size(px(56.))
                .rounded(extend::soft_radius(cx))
                .bg(cx.colors().default.color),
        )
        .child(
            CardHeader::new()
                .child(CardTitle::new().child("Indie Hackers"))
                .child(CardDescription::new().child("148 members")),
        )
        .child(
            CardFooter::new()
                .child(
                    Avatar::new("card-martha").name("Martha").size(Size::Sm)
                )
                .child("By Martha"),
        )
        .into_any_element()])

With Images

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{ActiveTheme, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(vec![Card::new()
        .w(px(280.))
        .child(
            CardContent::new().child(
                gpui::div()
                    .h(px(140.))
                    .w_full()
                    .rounded(px(12.))
                    .bg(cx.colors().default.color),
            ),
        )
        .child(CardFooter::new().child("A placeholder for cover art."))
        .into_any_element()])

With Form

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, InputType, TextField};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_wrap()
    .items_center()
    .justify_center()
    .gap(px(12.))
    .children(vec![Card::new()
        .w(px(320.))
        .child(CardHeader::new().child(CardTitle::new().child("Sign in")))
        .child(
            CardContent::new().child(
                gpui::div()
                    .flex()
                    .flex_col()
                    .gap(px(12.))
                    .child(
                        TextField::new(self.demo_text("card-email", "", cx))
                            .label("Email")
                            .input_type(InputType::Email)
                            .full_width(),
                    )
                    .child(
                        TextField::new(self.demo_text(
                            "card-password",
                            "",
                            cx
                        ))
                        .label("Password")
                        .input_type(InputType::Password)
                        .full_width(),
                    ),
            ),
        )
        .child(
            CardFooter::new()
                .child(Button::new("card-signin").label("Sign in")),
        )
        .into_any_element()])

Helpers used by these examples

Plain functions over the public API, defined once here and copied with each example that calls them.

CARD_USAGE_DESCRIPTION
/// v3's Card "Usage" copy. See [`ALERT_USAGE_DESCRIPTION`].
const CARD_USAGE_DESCRIPTION: &str = concat!(
    "Visit the Acme Creator Hub to sign up today and start earning ",
    "credits from your fans and followers.",
);

Anatomy

Rust types

CardCardHeaderCardTitleCardDescriptionCardContentCardFooter

Card is assembled from these builders. The API reference lists each one.

Customization

Shared appearance belongs on ThemeBuilder::components and .recipe("name"). Typed builders change how Card looks at one call site. Every builder also carries sx for placement, width and flex: it takes GPUI's own styling methods and refines them over the component's root after the theme, so an instance override wins. Behaviour builders live in the API reference below.

Styling

Card styling
MethodValuesDescription
variant(CardVariant)CardVariant::Transparent | CardVariant::Default | CardVariant::Secondary | CardVariant::TertiarySemantic variant indicating prominence level. Transparent paints nothing — no border, no background, no shadow, the full content box — while every other level fills and carries the surface shadow.
Rust
// The one slot for caller-owned low-level styling: GPUI's
// styling methods, refined over the root element last.
.sx(|el| {
    el.bg(gpui::rgba(0xffa500ff))             // background
        .text_color(gpui::rgba(0x000000ff))   // text
        .w(gpui::px(13.))                     // size
        .h(gpui::px(12.))
})

API reference

Against HeroUI v3.2.6: 6 entries ported, 7 partial, 6 not ported. Partial rows are marked in the tables; entries not ported are listed under each table with the reason.

Builders

Card builders
BuilderValuesDefaultDescription
variant(CardVariant)CardVariant::Transparent | CardVariant::Default | CardVariant::Secondary | CardVariant::TertiaryCardVariant::DefaultSemantic variant indicating prominence level. Transparent paints nothing — no border, no background, no shadow, the full content box — while every other level fills and carries the surface shadow.
ParentElement::extendPartialAnyElement—Card content; the parts compose through ParentElement::extend and the root wraps them in the padded column with the capped container radius.
Not ported6 HeroUI entries not ported
Card builders not ported
HeroUI v3Why it is not ported
Card.className
Card.Header.classNameFor the header.
Card.Title.classNameFor the title.
Card.Description.classNameFor the description.
Card.Content.classNameFor the content.
Card.Footer.classNameFor the footer.

Parts

Card parts
PartDescription
CardComposition root and data-slot owner; the padded column at a 12px part gap with the capped container radius. `overflow-visible` upstream, so adds no clipping; the variant chooses the fill and whether the surface shadow applies.
CardHeaderHeader section container; a plain flex column, with no text style of its own.
CardTitleTitle part: 14px medium text on the foreground colour, 24px leading. Renders an h3; renders the same typography on a plain div.
CardDescriptionMuted description part: 14px text at 20px leading. Renders a p; renders the same typography on a plain div.
CardContentPartialContent column at a four-pixel gap. The upstream flex-1 is dropped: the pinned-geometry test in tests/card_deep.rs measures the card as an auto-height column hugging its parts, which flex-1 regresses.
CardFooterFooter row with centered items; the card's gap separates it from the other parts and the caller composes the row's contents.