Hacktron Design System

Card

A bordered container for a self-contained block of content.

Account
Current periodAug 1 - Aug 31
<template>  <Card title="Account">    <div class="flex flex-col gap-3">Content</div>  </Card></template>

Props

Name Type Default
titlestring-
subtitlestring-
tooltipstring-
tooltipLabelstring-
iconstring-

Slots

Name Description
header-actionsTrailing content (buttons, dropdowns, a ChartLegend) next to the title/subtitle stack. Only rendered when `title` is set. There is no raw header slot: the title/subtitle props are the only card header.
defaultBody content. Any internal layout/gap (e.g. `flex flex-col gap-3`) is the caller's own wrapper div inside this slot.
bodyExplicit name for the body region - identical to the default slot, for callers who want it spelled out next to #footer. Ignored when a default slot is also passed.
footerOptional action row at the bottom of the card.

Guidelines

Do

  • Use it as a bordered container for a self-contained block of content - a stat, an account summary, a settings panel.
  • Put internal layout/spacing (e.g. flex flex-col gap-3) on your own wrapper div inside the default slot - Card doesn't expose a way to override its own body padding per instance. Content is deliberately freeform; there's no standard label/value or stat layout to reach for.
  • Same for footer - it carries no alignment of its own, so a single action reads left-aligned by default. Wrap it in your own flex justify-end gap-2 if you want right-aligned actions (the convention modals use); that's a caller choice, not Card's default.
  • Use title/subtitle/tooltip/icon for a standard header - Card renders it for you (label-01-medium text-text-tertiary title, body-05-regular text-text-tertiary subtitle, tooltip inline with the title, icon leading the title/subtitle stack). The icon sits in its own h-5 flex items-center box, matching the title's line-height, and that box top-aligns with the title's line rather than centering across both lines - same technique as the checkbox box in checkbox.vue's card variant. Put trailing actions (dropdowns, buttons) in the header-actions slot, which gets the same h-5 treatment and also top-aligns with the title's line, not the full title+subtitle block.
  • #body is an explicit name for the default slot (the region between header and footer) - use it when spelling out all three regions reads better than an anonymous default; passing both makes the default slot win.
  • Use the footer slot for an action row at the bottom. There is no header slot: a card's header is always the title/subtitle/tooltip/icon props plus #header-actions, so headers look the same on every card and can't be restyled per call site.

Don't

  • Don't reach for :ui/class to change Card's background, border, corners, or padding - there's one fixed look, not a set of variants.
  • Don't nest a border or a second bg-surface-card inside the default slot to fake a section divider - a plain <div class="h-px bg-stroke-primary" /> is enough.

Examples

Subtitle and tooltip

subtitle sits under the title; tooltip renders inline next to it via InfoTooltip.

Findings by severity New findings introduced per day, last 7 days
Chart goes here
<template>  <Card    title="Findings by severity"    subtitle="New findings introduced per day, last 7 days"    tooltip="Counts findings at the time they were first introduced, not their current status."  >    <div class="h-20 flex items-center justify-center body-05-regular text-text-tertiary">      Chart goes here    </div>  </Card></template>

Leading icon and header actions

icon leads the title/subtitle stack; header-actions renders trailing content like a connect button.

Slack Get notified in a channel when new findings are found.
Not connected
<template>  <Card    icon="i-logos-slack-icon"    title="Slack"    subtitle="Get notified in a channel when new findings are found."  >    <template #header-actions>      <Button variant="secondary" size="sm">Connect</Button>    </template>    <span class="body-04-regular text-text-tertiary">Not connected</span>  </Card></template>

footer is a separate action row at the bottom of the card, visually separated by padding.

Danger zone

Deleting this organization removes all its data and cannot be undone.

<template>  <Card title="Danger zone">    <p class="body-04-regular text-text-tertiary">      Deleting this organization removes all its data and cannot be undone.    </p>    <template #footer>      <Button variant="destructive" size="sm">Delete organization</Button>    </template>  </Card></template>