icon

Morainev0.5.0

Card
elementscard

Card

Structured content container with optional header, body, footer, and action slots.

Import#

import { Card } from 'moraine'

Slot Structure#

Structured content container with optional header, body, and footer sections.

root
├── header (optional)
│ ├── title (optional)
│ ├── description (optional)
│ └── action (optional)
├── body (optional)
└── footer (optional)

Examples#

Default#

Create project form card from coss/ui.

function Default() {
const frameworkOptions = [
{ label: 'Vite', value: 'vite' },
{ label: 'Solid Start', value: 'solid-start' },
{ label: 'Tanstack Start', value: 'tanstack-start' },
{ label: 'Astro', value: 'astro' },
]
return (
<Card
title="Create project"
description="Deploy your new project in one-click."
footer={
<>
<Button class="w-full" type="submit">
Deploy
</Button>
<div class="text-xs text-muted-foreground m-a flex gap-1 items-center">
<Icon name="i-lucide-circle-alert" class="h-lh shrink-0 size-3" />
<p>This will take a few seconds to complete.</p>
</div>
</>
}
class="max-w-xs w-full"
classes={{ footer: 'flex flex-col gap-3' }}
>
<div class="flex flex-col gap-4">
<FormField label="Name">
<Input placeholder="Name of your project" />
</FormField>
<FormField label="Framework">
<Select options={frameworkOptions} value="vite" />
</FormField>
</div>
</Card>
)
}

Sizes#

Default and compact size presets.

function Sizes() {
return (
<div class="flex gap-2">
<Card
compact
title="Small Card"
description="Compact"
footer={<Button size="sm">Action</Button>}
class="h-fit max-w-xs"
>
<p class="text-sm opacity-85">Compact spacing for dense layouts and sidebars.</p>
</Card>
<Card
title="Default Card"
description="Default"
footer={<Button size="sm">Action</Button>}
class="h-fit max-w-xs"
>
<p class="text-sm opacity-85">Standard spacing for normal form and dashboard cards.</p>
</Card>
</div>
)
}

With Image#

Media-first card using body slot customization.

function WithImage() {
return (
<div class="max-w-sm">
<Card
classes={{ header: 'pb-6' }}
header={
<img
src="https://images.unsplash.com/photo-1604076850742-4c7221f3101b?q=80&w=1887&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
alt="Landscape by mymind on Unsplash"
class="rounded-t-2xl w-full aspect-video object-cover brightness-60 grayscale"
/>
}
footer={<Button class="w-full">Open</Button>}
>
<h3 class="font-semibold">Beautiful Landscape</h3>
<p class="text-sm text-muted-foreground mt-1">
A compact media card style adapted to the sealed Moraine Card API.
</p>
</Card>
</div>
)
}

Header Action#

Custom action area inside the header slot.

function HeaderAction() {
return (
<div class="w-lg">
<Card
title="Meeting Notes"
description="Transcript summary from the latest client sync."
action={
<Button size="sm" variant="secondary">
Transcribe
</Button>
}
footer={
<div class="flex gap-2 w-full justify-end">
<Button size="sm" variant="outline">
Dismiss
</Button>
<Button size="sm">Save</Button>
</div>
}
>
<ol class="text-sm pl-5 list-decimal opacity-85 flex flex-col gap-1.5">
<li>Dashboard redesign should prioritize mobile layouts.</li>
<li>Timeline target is six weeks with weekly milestones.</li>
<li>Next review meeting is scheduled for Tuesday morning.</li>
</ol>
</Card>
</div>
)
}

API Reference#

Attributes#

Slotroot0 attributes
Card container that frames the header, body, and footer regions.
No attribute metadata for this slot.

Props#

PropTypeDefaultDescription
actionJSX.Element
Content to render in the action slot (usually a button in the header).
childrenJSX.Element
Children of the card.
classClassValue
Class applied to the component root or trigger element.
classesCardT.Classes | undefined
compactboolean | undefinedfalse
Whether to use a compact layout.
descriptionJSX.Element
Description of the card.
footerJSX.Element
Content to render in the footer slot.
headerJSX.Element
Content to render in the header slot, overrides title/description.
refJSX.HTMLElementTags["div"] extends { ref?: infer Ref; } ? Ref : never | undefined
styleJSX.CSSProperties | undefined
stylesCardT.Styles | undefined
titleJSX.Element
Title of the card.