Components

Card

A bordered surface with header, title, description, action, content, and footer slots

Installation

leptos-aria add card
Install by hand
  1. Copy the source below into src/components/ui/card.rs.
  2. Add pub mod card; to src/components/ui/mod.rs.
  3. Install what it builds on: utils.

Usage

A bordered surface that groups related content.

Source

src/components/ui/card.rs

//! A bordered surface that groups related content.
//!
//! ```rust ignore
//! use crate::components::ui::card::*;
//!
//! view! {
//!     <Card class="w-full max-w-sm">
//!         <CardHeader>
//!             <CardTitle>"Notifications"</CardTitle>
//!             <CardDescription>"You have 3 unread messages."</CardDescription>
//!         </CardHeader>
//!         <CardContent class="text-sm">"Your October invoice is ready."</CardContent>
//!         <CardFooter class="text-sm text-muted-foreground">"Sent 5 minutes ago"</CardFooter>
//!     </Card>
//! }
//! ```

use leptos::prelude::*;

use super::utils::cn;

/// Render a `div` with a `data-slot` and merged classes.
macro_rules! slot {
	($(#[$doc:meta])* $name:ident, $slot:literal, $base:expr) => {
		$(#[$doc])*
		#[component]
		pub fn $name(
			/// Classes merged over the defaults; yours win conflicts.
			#[prop(optional, into)]
			class: Signal<String>,
			children: Children,
		) -> impl IntoView {
			let class = move || class.with(|class| cn(&[$base, class]));

			view! { <div data-slot=$slot class=class>{children()}</div> }
		}
	};
}

slot!(
	/// The card surface.
	Card,
	"card",
	"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm"
);
slot!(
	/// The title, description, and optional action at the top of a card.
	CardHeader,
	"card-header",
	"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 \
	 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6"
);
slot!(
	/// The card's heading text.
	CardTitle,
	"card-title",
	"leading-none font-semibold"
);
slot!(
	/// Supporting text under the title.
	CardDescription,
	"card-description",
	"text-sm text-muted-foreground"
);
slot!(
	/// A control pinned to the header's top right.
	CardAction,
	"card-action",
	"col-start-2 row-span-2 row-start-1 self-start justify-self-end"
);
slot!(
	/// The card body.
	CardContent,
	"card-content",
	"px-6"
);
slot!(
	/// Actions at the bottom of a card.
	CardFooter,
	"card-footer",
	"flex items-center px-6 [.border-t]:pt-6"
);