Item
A versatile component for displaying content with media, title, description, and actions.
A simple item with title and description.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ItemExample() -> impl IntoView { view! { <div class="flex w-full max-w-md flex-col gap-6"> <Item variant="outline"> <ItemContent> <ItemTitle>"Basic Item"</ItemTitle> <ItemDescription>"A simple item with title and description."</ItemDescription> </ItemContent> <ItemActions> <Button variant="outline" size="sm"> "Action" </Button> </ItemActions> </Item> <a href="#"> <Item variant="outline" size="sm"> <ItemMedia>{icon!(icondata::LuBadgeCheck, class="size-5")}</ItemMedia> <ItemContent class="block"> <ItemTitle>"Your profile has been verified."</ItemTitle> </ItemContent> <ItemActions>{icon!(icondata::LuChevronRight, class="size-4")}</ItemActions> </Item> </a> </div> } }
Variants
Use the variant prop to change the visual style of the item.
Standard styling with subtle background and borders.
Outlined style with clear borders and transparent background.
Subdued appearance with muted colors for secondary content.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ItemVariantsExample() -> impl IntoView { view! { <div class="flex flex-col gap-6"> <Item> <ItemContent> <ItemTitle>"Default Variant"</ItemTitle> <ItemDescription> "Standard styling with subtle background and borders." </ItemDescription> </ItemContent> <ItemActions> <Button variant="outline" size="sm"> "Open" </Button> </ItemActions> </Item> <Item variant="outline"> <ItemContent> <ItemTitle>"Outline Variant"</ItemTitle> <ItemDescription> "Outlined style with clear borders and transparent background." </ItemDescription> </ItemContent> <ItemActions> <Button variant="outline" size="sm"> "Open" </Button> </ItemActions> </Item> <Item variant="muted"> <ItemContent> <ItemTitle>"Muted Variant"</ItemTitle> <ItemDescription> "Subdued appearance with muted colors for secondary content." </ItemDescription> </ItemContent> <ItemActions> <Button variant="outline" size="sm"> "Open" </Button> </ItemActions> </Item> </div> } }
Size
Use the size prop to change the size of the item. Available sizes are default, sm, and xs.
The standard size for most use cases.
A compact size for dense layouts.
The most compact size available.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ItemSizeExample() -> impl IntoView { view! { <div class="flex w-full max-w-md flex-col gap-6"> <Item variant="outline"> <ItemMedia variant="icon">{icon!(icondata::LuInbox)}</ItemMedia> <ItemContent> <ItemTitle>"Default Size"</ItemTitle> <ItemDescription>"The standard size for most use cases."</ItemDescription> </ItemContent> </Item> <Item variant="outline" size="sm"> <ItemMedia variant="icon">{icon!(icondata::LuInbox)}</ItemMedia> <ItemContent> <ItemTitle>"Small Size"</ItemTitle> <ItemDescription>"A compact size for dense layouts."</ItemDescription> </ItemContent> </Item> <Item variant="outline" size="xs"> <ItemMedia variant="icon">{icon!(icondata::LuInbox)}</ItemMedia> <ItemContent> <ItemTitle>"Extra Small Size"</ItemTitle> <ItemDescription>"The most compact size available."</ItemDescription> </ItemContent> </Item> </div> } }
Icon
Use the ItemMedia icon variant to display an icon.
New login detected from unknown device.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ItemIconExample() -> impl IntoView { view! { <div class="flex w-full max-w-lg flex-col gap-6"> <Item variant="outline"> <ItemMedia variant="icon">{icon!(icondata::LuShieldAlert)}</ItemMedia> <ItemContent> <ItemTitle>"Security Alert"</ItemTitle> <ItemDescription>"New login detected from unknown device."</ItemDescription> </ItemContent> <ItemActions> <Button size="sm" variant="outline"> "Review" </Button> </ItemActions> </Item> </div> } }
Avatar
Last seen 5 months ago
Invite your team to collaborate on this project.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ItemAvatarExample() -> impl IntoView { view! { <div class="flex w-full max-w-lg flex-col gap-6"> <Item variant="outline"> <ItemMedia> <Avatar class="size-10"> <AvatarImage src="https://github.com/evilrabbit.png" /> <AvatarFallback>"ER"</AvatarFallback> </Avatar> </ItemMedia> <ItemContent> <ItemTitle>"Evil Rabbit"</ItemTitle> <ItemDescription>"Last seen 5 months ago"</ItemDescription> </ItemContent> <ItemActions> <Button size="icon-sm" variant="outline" class="rounded-full" aria_label="Invite" > {icon!(icondata::LuPlus)} </Button> </ItemActions> </Item> <Item variant="outline"> <ItemMedia> <div class="*:ring-(--background) flex -space-x-2 *:ring-2 *:grayscale"> <Avatar> <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" /> <AvatarFallback>"CN"</AvatarFallback> </Avatar> <Avatar> <AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" /> <AvatarFallback>"LR"</AvatarFallback> </Avatar> <Avatar> <AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" /> <AvatarFallback>"ER"</AvatarFallback> </Avatar> </div> </ItemMedia> <ItemContent> <ItemTitle>"No Team Members"</ItemTitle> <ItemDescription> "Invite your team to collaborate on this project." </ItemDescription> </ItemContent> <ItemActions> <Button size="sm" variant="outline"> "Invite" </Button> </ItemActions> </Item> </div> } }
Image
Use the ItemMedia image variant to display an icon.
use leptos::prelude::*; use singlestage::*; #[derive(Clone)] struct Song { title: String, artist: String, album: String, duration: String, } #[component] pub fn ItemImageExample() -> impl IntoView { let music = RwSignal::new(vec![ Song { title: "Midnight City Lights".to_string(), artist: "Neon Dreams".to_string(), album: "Electric Nights".to_string(), duration: "3:45".to_string(), }, Song { title: "Coffee Shop Conversations".to_string(), artist: "The Morning Brew".to_string(), album: "Urban Stories".to_string(), duration: "4:05".to_string(), }, Song { title: "Digital Rain".to_string(), artist: "Cyber Symphony".to_string(), album: "Binary Beats".to_string(), duration: "3:30".to_string(), }, ]); view! { <div class="flex w-full max-w-md flex-col gap-6"> <ItemGroup class="gap-4"> <For each=move || music.get() key=|song| song.title.clone() let(song)> { let song_title = song.title.clone(); view! { <a href="#" role="listitem"> <Item variant="outline"> <ItemMedia variant="image"> <img src=format!("https://avatar.vercel.sh/{}", song.title) alt=song.title width=32 height=32 class="object-cover grayscale" /> </ItemMedia> <ItemContent> <ItemTitle class="line-clamp-1"> {song_title} " - " <span class="text-muted-foreground">{song.album}</span> </ItemTitle> <ItemDescription>{song.artist}</ItemDescription> </ItemContent> <ItemContent class="flex-none text-center"> <ItemDescription>{song.duration}</ItemDescription> </ItemContent> </Item> </a> } } </For> </ItemGroup> </div> } }
Group
Use ItemGroup to group related items together.
shadcn@vercel.com
maxleiter@vercel.com
evilrabbit@vercel.com
use leptos::prelude::*; use singlestage::*; #[derive(Clone)] struct Person { username: String, avatar: String, email: String, } #[component] pub fn ItemGroupExample() -> impl IntoView { let people = RwSignal::new(vec![ Person { username: "shadcn".to_string(), avatar: "https://github.com/shadcn.png".to_string(), email: "shadcn@vercel.com".to_string(), }, Person { username: "maxleiter".to_string(), avatar: "https://github.com/maxleiter.png".to_string(), email: "maxleiter@vercel.com".to_string(), }, Person { username: "evilrabbit".to_string(), avatar: "https://github.com/evilrabbit.png".to_string(), email: "evilrabbit@vercel.com".to_string(), }, ]); view! { <ItemGroup class="max-w-sm"> <For each=move || people.get() key=|person| person.username.clone() let(person)> { let username = person.username.clone(); view! { <Item variant="outline"> <ItemMedia> <Avatar> <AvatarImage src=person.avatar class="grayscale" /> <AvatarFallback>{username[..2].to_uppercase()}</AvatarFallback> </Avatar> </ItemMedia> <ItemContent class="gap-1"> <ItemTitle>{person.username}</ItemTitle> <ItemDescription>{person.email}</ItemDescription> </ItemContent> <ItemActions> <Button variant="ghost" size="icon" class="rounded-full"> {icon!(icondata::LuPlus)} </Button> </ItemActions> </Item> } } </For> </ItemGroup> } }
Header
Use ItemHeader to add a header above the item content.
Everyday tasks and UI generation.
Advanced thinking or reasoning.
Open Source model for everyone.
use leptos::prelude::*; use singlestage::*; #[derive(Clone)] struct Model { name: String, description: String, image: String, credit: String, } #[component] pub fn ItemHeaderExample() -> impl IntoView { let models = RwSignal::new(vec![ Model { name: "v0-1.5-sm".to_string(), description: "Everyday tasks and UI generation.".to_string(), image: "https://images.unsplash.com/photo-1650804068570-7fb2e3dbf888?q=80&w=640&auto=format&fit=crop".to_string(), credit: "Valeria Reverdo on Unsplash".to_string(), }, Model { name: "v0-1.5-lg".to_string(), description: "Advanced thinking or reasoning.".to_string(), image: "https://images.unsplash.com/photo-1610280777472-54133d004c8c?q=80&w=640&auto=format&fit=crop".to_string(), credit: "Michael Oeser on Unsplash".to_string(), }, Model { name: "v0-2.0-mini".to_string(), description: "Open Source model for everyone.".to_string(), image: "https://images.unsplash.com/photo-1602146057681-08560aee8cde?q=80&w=640&auto=format&fit=crop".to_string(), credit: "Cherry Laithang on Unsplash".to_string(), }, ]); view! { <div class="flex w-full max-w-xl flex-col gap-6"> <ItemGroup class="grid grid-cols-3 gap-4"> <For each=move || models.get() key=|model| model.name.clone() let(model)> { let model_name = model.name.clone(); view! { <Item variant="outline"> <ItemHeader> <Tooltip> <TooltipTrigger> <img src=model.image alt=model.name width=128 height=128 class="aspect-square w-full rounded-sm object-cover" /> </TooltipTrigger> <TooltipContent> <p>{model.credit}</p> </TooltipContent> </Tooltip> </ItemHeader> <ItemContent> <ItemTitle>{model_name}</ItemTitle> <ItemDescription>{model.description}</ItemDescription> </ItemContent> </Item> } } </For> </ItemGroup> </div> } }
Link
To make an Item a link, just wrap it with an anchor and it'll automatically apply hover and focus styling.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ItemLinkExample() -> impl IntoView { view! { <div class="flex w-full max-w-md flex-col gap-4"> <a href="#"> <Item> <ItemContent> <ItemTitle>"Visit our documentation"</ItemTitle> <ItemDescription> "Learn how to get started with our components." </ItemDescription> </ItemContent> <ItemActions>{icon!(icondata::LuChevronRight, class="size-4")}</ItemActions> </Item> </a> <a href="#" target="_blank" rel="noopener noreferrer"> <Item variant="outline"> <ItemContent> <ItemTitle>"External resource"</ItemTitle> <ItemDescription> "Opens in a new tab with security attributes." </ItemDescription> </ItemContent> <ItemActions>{icon!(icondata::LuExternalLink, class="size-4")}</ItemActions> </Item> </a> </div> } }
Dropdown
use leptos::prelude::*; use singlestage::*; #[derive(Clone)] struct Person { username: String, avatar: String, email: String, } #[component] pub fn ItemDropdownExample() -> impl IntoView { let people = RwSignal::new(vec![ Person { username: "shadcn".to_string(), avatar: "https://github.com/shadcn.png".to_string(), email: "shadcn@vercel.com".to_string(), }, Person { username: "maxleiter".to_string(), avatar: "https://github.com/maxleiter.png".to_string(), email: "maxleiter@vercel.com".to_string(), }, Person { username: "evilrabbit".to_string(), avatar: "https://github.com/evilrabbit.png".to_string(), email: "evilrabbit@vercel.com".to_string(), }, ]); view! { <DropdownMenu> <DropdownMenuTrigger> <Button variant="outline">"Select" {icon!(icondata::LuChevronDown)}</Button> </DropdownMenuTrigger> <DropdownMenuContent align="center"> <For each=move || people.get() key=|person| person.username.clone() let(person)> { let username = person.username.clone(); view! { <DropdownMenuItem class="p-0"> <Item size="xs" class="w-full"> <ItemMedia> <Avatar class="size-[--spacing(6.5)]"> <AvatarImage src=person.avatar class="grayscale" /> <AvatarFallback> {username[..2].to_uppercase()} </AvatarFallback> </Avatar> </ItemMedia> <ItemContent class="gap-0"> <ItemTitle>{person.username}</ItemTitle> <ItemDescription class="leading-none"> {person.email} </ItemDescription> </ItemContent> </Item> </DropdownMenuItem> } } </For> </DropdownMenuContent> </DropdownMenu> } }
Anatomy
Import all parts and piece them together.
use leptos::prelude::*; use singlestage::*; #[component] pub fn ItemAnatomy() -> impl IntoView { view! { <ItemGroup> <Item> <ItemMedia /> <ItemHeader /> <ItemContent> <ItemTitle /> <ItemDescription /> </ItemContent> <ItemActions> <Button /> </ItemActions> <ItemFooter /> </Item> <ItemSeparator /> </ItemGroup> } }
API Reference
Item
Contains the contents of an Item.
| Name | Type | Default | Description |
|---|---|---|---|
| size | String | "" | Set the display size of the Item. Accepted values: "outline" | "muted". |
| variant | String | "" | Set the display variant of the Item. Accepted values: "outline" | "muted". |
ItemMedia
Contains media content such as an icon or image for an Item.
| Name | Type | Default | Description |
|---|---|---|---|
| variant | String | "" | Set the display variant of the ItemMedia. Accepted values: "icon" | "image". |
ItemSeparator
Visual divider to separate sections inside an Item. Accepts optional inline content.