The <dsgn-card> component groups related content in a bordered or elevated
<article>. It is composed entirely from named slots — media at the top, then a
badge, a heading, an optional list of feature rows, and a footer. The badge and
heading regions are omitted when empty; the media and footer regions always
reserve their spacing, so a card with no footer still renders its top border.
Usage
<dsgn-card variant="elevated" padding="md">
<span slot="heading">Card heading</span>
<dsgn-button slot="footer" appearance="outline">Learn more</dsgn-button>
</dsgn-card>
Import the component module in your application entrypoint:
import '@ds-gn/ui/card';
Playground
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | 'elevated' | 'outlined' |
'outlined' |
Visual treatment: a shadowed surface or a bordered one. |
| padding | 'none' | 'sm' | 'md' | 'lg' |
'md' |
Internal padding. none lets media run to the card edge. |
| surface | 'light' | 'dark' |
'light' |
Semantic token surface to use. It is passed down to rendered feature rows. |
| features | CardFeature[] |
[] |
Feature rows rendered in the card body. Property-only (no attribute). |
There is no default variant and no interactive prop. For a clickable card,
put a link or a <dsgn-button> in the footer slot.
Slots
| Slot | Description |
|---|---|
media |
Card media, rendered above everything else. |
badge |
Badge content above the heading. The region is omitted when empty. |
heading |
Card heading. The region is omitted when empty. |
footer |
Card footer content. |
The card has no default slot. Unslotted children are not rendered — body content
belongs in features, and anything else belongs in one of the named slots.
Features
features is a JavaScript property, so it is set from script rather than markup.
Each entry renders a <dsgn-feature-item> with an optional bullet list:
interface CardFeature {
label: string;
variant: 'default' | 'brand' | 'accent' | 'success' | 'warning' | 'error';
icon?: SVGTemplateResult;
bullets?: string[];
}
import { check } from '@ds-gn/ui/icon/icons';
const card = document.querySelector('dsgn-card');
card.features = [
{ label: 'Unlimited projects', variant: 'success', icon: check },
{
label: 'Team access',
variant: 'brand',
bullets: ['Up to 10 seats', 'Shared token themes'],
},
];
Feature rows inherit the card’s surface, so they stay legible when the card is
placed on a dark background.
Examples
Variants
<dsgn-card variant="outlined"><span slot="heading">Outlined</span></dsgn-card>
<dsgn-card variant="elevated"><span slot="heading">Elevated</span></dsgn-card>
Media card
<dsgn-card variant="elevated" padding="none">
<dsgn-image
slot="media"
src="/preview.png"
alt="Product screenshot"
aspect="video"
></dsgn-image>
<dsgn-badge slot="badge" variant="brand">New</dsgn-badge>
<dsgn-heading slot="heading" heading-size="h3">Release preview</dsgn-heading>
</dsgn-card>
Padding
<dsgn-card padding="sm"><span slot="heading">Compact</span></dsgn-card>
<dsgn-card padding="md"><span slot="heading">Standard</span></dsgn-card>
<dsgn-card padding="lg"><span slot="heading">Spacious</span></dsgn-card>
On a dark surface
<dsgn-card surface="dark" variant="outlined">
<dsgn-heading slot="heading" surface="dark" heading-size="h3"
>Dark card</dsgn-heading
>
</dsgn-card>
Usage patterns
- Pair
padding="none"with amediaslot when the image should bleed to the card’s edges; keepmdwhen the card is text-only. - Set the same
surfaceon the card and on the components you slot into it — slotted content is styled by its own element, not by the card.