# Card

A surface with a header, a body and a footer — six exported parts, and none of them an affordance.

```slint
import { Card, CardHeader, CardContent, CardFooter } from "@glint/components/card.slint";
import { Button, ButtonVariant } from "@glint/components/button.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 300px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;

            VerticalLayout {
                width: 420px;

                Card {
                    CardHeader {
                        title: "Create project";
                        description: "Deploy your new project in one-click.";
                    }

                    CardContent {
                        Text {
                            text: "Your framework will be automatically detected and configured.";
                            color: Tokens.color-muted-foreground;
                            font-size: Tokens.typography-body-sm-size;
                        }
                    }

                    CardFooter {
                        Button {
                            text: "Cancel";
                            variant: ButtonVariant.ghost;
                        }

                        Button {
                            text: "Deploy";
                        }
                    }
                }
            }
        }
    }
}
```

## Usage

```slint
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "@glint/components/card.slint";
import { Button } from "@glint/components/button.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component AppWindow inherits Window {
    width: 560px;
    height: 300px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        Card {
            CardHeader {
                title: "Notifications";
                description: "Choose what notifications you receive.";
            }

            CardContent {
                Text {
                    text: "Configure push, email, and SMS alert channels.";
                    color: Tokens.color-foreground;
                }
            }

            CardFooter {
                Button { text: "Save preferences"; }
            }
        }
    }
}
```

`Card` serves as a surface container. Its companion helpers (`CardHeader`, `CardTitle`, `CardDescription`, `CardContent`, `CardFooter`) establish clean information hierarchy.

## Examples

### Variants

Cards support `CardVariant.solid`, `CardVariant.glass`, `CardVariant.glass-interactive`, and `CardVariant.raised`.

```slint
import { Card, CardVariant, CardHeader, CardContent } from "@glint/components/card.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 320px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;
            spacing: 16px;

            VerticalLayout {
                width: 220px;
                spacing: 16px;

                Card {
                    variant: CardVariant.solid;
                    CardHeader { title: "Solid"; description: "Standard card surface"; }
                }

                Card {
                    variant: CardVariant.glass;
                    CardHeader { title: "Glass"; description: "Translucent backdrop"; }
                }
            }

            VerticalLayout {
                width: 220px;
                spacing: 16px;

                Card {
                    variant: CardVariant.glass-interactive;
                    CardHeader { title: "Interactive"; description: "Responds to hover"; }
                }

                Card {
                    variant: CardVariant.raised;
                    CardHeader { title: "Raised"; description: "Elevated elevation shadow"; }
                }
            }
        }
    }
}
```

### Sizes

Use `size: CardSize.sm` for compact lists or sidebars, and `size: CardSize.default` for full content sections.

```slint
import { Card, CardSize, CardHeader, CardContent } from "@glint/components/card.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 260px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;
            spacing: 16px;

            VerticalLayout {
                width: 220px;

                Card {
                    size: CardSize.sm;

                    CardHeader {
                        title: "Compact card";
                        description: "Reduced padding and gaps.";
                    }
                }
            }

            VerticalLayout {
                width: 240px;

                Card {
                    size: CardSize.default;

                    CardHeader {
                        title: "Default card";
                        description: "Standard spacious layout.";
                    }
                }
            }
        }
    }
}
```

### Padding overrides

Override internal container padding using `card-padding: CardPadding.none`, `CardPadding.sm`, `CardPadding.md`, or `CardPadding.lg`.

```slint
import { Card, CardPadding, CardHeader, CardContent } from "@glint/components/card.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 300px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;
            spacing: 16px;

            VerticalLayout {
                width: 220px;

                Card {
                    card-padding: CardPadding.sm;
                    CardHeader { title: "Small padding"; }
                }
            }

            VerticalLayout {
                width: 220px;

                Card {
                    card-padding: CardPadding.lg;
                    CardHeader { title: "Large padding"; }
                }
            }
        }
    }
}
```

### Radius overrides

Customize corner roundness with `card-radius: CardRadius.md`, `CardRadius.lg`, `CardRadius.xl`, or `CardRadius.xxl`.

```slint
import { Card, CardRadius, CardHeader } from "@glint/components/card.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 300px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;
            spacing: 16px;

            VerticalLayout {
                width: 220px;

                Card {
                    card-radius: CardRadius.md;
                    CardHeader { title: "Medium radius"; }
                }
            }

            VerticalLayout {
                width: 220px;

                Card {
                    card-radius: CardRadius.xxl;
                    CardHeader { title: "2XL radius"; }
                }
            }
        }
    }
}
```

### Title and description type

`CardTitle` is a [Heading](/docs/components/typography) and `CardDescription` is a `Body`, so both take the type ladder’s own knobs: `tone` picks the color role on either, `level` steps the heading, and `size` steps the description.

```slint
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@glint/components/card.slint";
import { BodySize, TypographyTone } from "@glint/components/typography.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 300px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;

            VerticalLayout {
                width: 340px;

                Card {
                    CardHeader {
                        CardTitle {
                            text: "Payment failed";
                            level: 3;
                            tone: TypographyTone.danger;
                        }

                        CardDescription {
                            text: "We could not charge the card ending 4242.";
                            size: BodySize.sm;
                            tone: TypographyTone.muted;
                        }
                    }

                    CardContent {
                        Text {
                            text: "Update the card to keep the workspace active.";
                            color: Tokens.color-foreground;
                            font-size: Tokens.typography-body-sm-size;
                            wrap: word-wrap;
                        }
                    }
                }
            }
        }
    }
}
```

## API Reference

### Properties

| Property       | Type             | Default             | Description                                                                                                                                                                                                                                                                                                              |
| -------------- | ---------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `variant`      | `in CardVariant` | `CardVariant.solid` | Surface treatment — solid, glass, glass-interactive, raised.                                                                                                                                                                                                                                                             |
| `size`         | `in CardSize`    | `CardSize.default`  | Density — the padding around the content and the gap between its sections, together. A compact card is one word (ADR-0022).                                                                                                                                                                                              |
| `card-padding` | `in CardPadding` | `CardPadding.auto`  | Padding override — auto (follow `size`), none, sm, md, lg. Reach for `none` when the content draws to the border: a full-bleed strip of media or a table, which is not a density choice at all.                                                                                                                          |
| `card-radius`  | `in CardRadius`  | `CardRadius.xl`     | Corner radius override — md, lg, xl, xxl.                                                                                                                                                                                                                                                                                |
| `hovered`      | `out bool`       | no default          | Read-only hover signal — driven by the internal TouchArea below. Consumers can read it (e.g. to drive header chip styling) but never set it.                                                                                                                                                                             |
| `padding-l`    | `out length`     | no default          | Both lengths come off `size`, and `card-padding` overrides one of them (none/sm/md/lg → 0/12/16/24). The column below applies both. They stay published for content that has to draw to the card's edge — a strip of media, a full-bleed table — and therefore needs to know what it is escaping (MessageBubble's rule). |
| `gap-l`        | `out length`     | no default          | Resolved gap between header / content / footer in px; outbound.                                                                                                                                                                                                                                                          |

### Enums

| Enum          | Values                                          |
| ------------- | ----------------------------------------------- |
| `CardVariant` | `solid`, `glass`, `glass-interactive`, `raised` |
| `CardSize`    | `sm`, `default`                                 |
| `CardPadding` | `auto`, `none`, `sm`, `md`, `lg`                |
| `CardRadius`  | `md`, `lg`, `xl`, `xxl`                         |

### CardHeader

The top band: the title and description stack on the left, and the trailing place is kept for the control that acts on the card — the `@children` slot. A header written without one pays nothing for it.

### Properties

| Property      | Type        | Default    | Description                           |
| ------------- | ----------- | ---------- | ------------------------------------- |
| `title`       | `in string` | no default | Heading of the card.                  |
| `description` | `in string` | no default | Line under the title; empty hides it. |

### CardTitle

The header’s own heading style, exported for a title that is not inside a `CardHeader`. `level` is a step on the type ladder rather than an outline level — see [Typography](/docs/components/typography#usage).

### Properties

| Property | Type                | Default                  | Description                                                                                                           |
| -------- | ------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `level`  | `in int`            | `1`                      | Which step, 1 (largest) through 5 (smallest). Out-of-range levels take the smallest step rather than drawing nothing. |
| `tone`   | `in TypographyTone` | `TypographyTone.default` | Colour role — `default`, `muted`, `subtle`.                                                                           |

### Enums

| Enum             | Values                                           |
| ---------------- | ------------------------------------------------ |
| `TypographyTone` | `default`, `muted`, `subtle`, `accent`, `danger` |

### CardDescription

The line under the title, at the muted tone and wrapping by word.

### Properties

| Property | Type                | Default                  | Description                                             |
| -------- | ------------------- | ------------------------ | ------------------------------------------------------- |
| `size`   | `in BodySize`       | `BodySize.default`       | Which step — `lg`, `default`, `sm`, `label`, `caption`. |
| `tone`   | `in TypographyTone` | `TypographyTone.default` | Colour role — `default`, `muted`, `subtle`.             |

### Enums

| Enum             | Values                                           |
| ---------------- | ------------------------------------------------ |
| `BodySize`       | `lg`, `default`, `sm`, `label`, `caption`        |
| `TypographyTone` | `default`, `muted`, `subtle`, `accent`, `danger` |

### CardContent

The body of the card.

`CardContent` publishes no properties, callbacks or functions of its own. What a call site can set on it is the Slint `VerticalLayout` it inherits.

### CardFooter

The row of actions along the bottom, aligned to the end.

`CardFooter` publishes no properties, callbacks or functions of its own. What a call site can set on it is the Slint `HorizontalLayout` it inherits.

## Accessibility

- **The surface carries no role and takes no name.** A card is a container, and Glint gives it no node in the accessibility tree: what a screen reader reads is what you put inside it. A card that is itself one target — a whole tile that opens something — is a `Button` wrapping the content, not a `Card` with a click handler.
- **`CardTitle` is a size, not an outline level.** Its `level: 5` picks a step on the type ladder ([Typography](/docs/components/typography#usage)) and nothing more: `Heading` inherits Slint’s `Text` and declares no `accessible-role`, so no heading node reaches the tree and no reading order is built from it. A screen reader hears the title as text in the order it is laid out. Where a card opens a region a reader needs to jump to, name that region at the call site — `accessible-role: region` and `accessible-label` together, the way [ScrollArea](/docs/components/scroll-area#naming-a-scrolling-surface) documents.
- **The controls inside are the accessible part.** A `Button` in a `CardHeader` or a `CardFooter` keeps its own role, name, focus ring and default action; the card neither adds to that nor gets in its way.
