> Leaf UI 0.6.0 · Package: @ifhover/leaf-ui · Source: b30c3d3a8fa9c5e15d0d0522cebfbd33f60c6b06
> Browser documentation: https://ifhover.github.io/leaf-ui/v/0.6.0/en/components/card.html

> For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/v/0.6.0/en/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/v/0.6.0/en/llms-full.txt.

# Card

Group related content and actions in a container.

## Basic usage


### Project overview

Keep project details together so your team can work from the same plan.

basic.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/card/basic.tsx"
import { Card } from '@ifhover/leaf-ui';

export function CardBasic() {
  return (
    <Card title="Project overview">
      Keep project details together so your team can work from the same plan.
    </Card>
  );
}
```

Expand code

## Sizes

`size` offers small, default and large cards, adjusting padding, heading typography and heading height together. Embedded Tabs follow the card size unless overridden with `tabs.size`. Buttons, inputs and other controls inside the card use their own `size`.

These cards share the same content to compare headings, tab bars and content spacing. Each card's tabs switch independently.


### Small

Overview

Activity

Keep project details, design and development working from the same plan.

### Default

Overview

Activity

Keep project details, design and development working from the same plan.

### Large

Overview

Activity

Keep project details, design and development working from the same plan.

sizes.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/card/sizes.tsx"
import { Card, Space } from '@ifhover/leaf-ui';

export function CardSizes() {
  const items = [
    {
      key: 'overview',
      label: 'Overview',
      children: 'Keep project details, design and development working from the same plan.',
    },
    {
      key: 'activity',
      label: 'Activity',
      children: 'Updated the component guidelines and invited two teammates today.',
    },
  ];
  return (
    <Space direction="vertical" align="stretch" size="lg">
      <Card title="Small" size="sm" tabs={{ items }} />
      <Card title="Default" tabs={{ items }} />
      <Card title="Large" size="lg" tabs={{ items }} />
    </Space>
  );
}
```

Expand code

## Content sections

Use spacing to group content. Set `divided` to separate the heading, body and footer actions.


### Project overview

Group content with spacing

In progress

The heading, description and body form natural sections.

### Content sections

Enable divided to separate the heading, body and footer actions.

CancelConfirm

sections.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/card/sections.tsx"
import { Button, Card, Flex, Space, Tag } from '@ifhover/leaf-ui';

export function CardSections() {
  return (
    <Space direction="vertical" align="stretch" size="lg">
      <Card
        title="Project overview"
        description="Group content with spacing"
        extra={<Tag>In progress</Tag>}
      >
        The heading, description and body form natural sections.
      </Card>
      <Card
        divided
        title="Content sections"
        footer={
          <Flex justify="end" gap="sm" wrap>
            <Button variant="outline">Cancel</Button>
            <Button>Confirm</Button>
          </Flex>
        }
      >
        Enable divided to separate the heading, body and footer actions.
      </Card>
    </Space>
  );
}
```

Expand code

## Tabbed card

Use `tabs.items` to define labels and their content. Without a title, tabs fill the heading height with vertically centered labels, and Card's `extra` appears at their trailing edge.


Overview

Activity

View project

Keep design and development working from the same plan.

OwnerRowan LinTeam members8 people

tabs.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/card/tabs.tsx"
import { Button, Card, Descriptions, Space } from '@ifhover/leaf-ui';

export function CardTabs() {
  return (
    <Card
      extra={<Button variant="link">View project</Button>}
      tabs={{
        'aria-label': 'Project overview',
        items: [
          {
            key: 'overview',
            label: 'Overview',
            children: (
              <Space direction="vertical" align="stretch" size="md">
                <span>Keep design and development working from the same plan.</span>
                <Descriptions
                  columns={2}
                  items={[
                    { key: 'owner', label: 'Owner', children: 'Rowan Lin' },
                    { key: 'members', label: 'Team members', children: '8 people' },
                  ]}
                />
              </Space>
            ),
          },
          {
            key: 'activity',
            label: 'Activity',
            children: 'Updated the component guidelines and invited two teammates today.',
          },
        ],
      }}
    />
  );
}
```

Expand code

## Heading with tabs

With a `title` or `description`, tabs sit beneath the heading. There is no divider between the heading and tabs; the divider runs below the tab bar. Control selection with `tabs.activeKey` / `tabs.onChange`. Visited pages retain input state by default, and `divided` continues to control the footer divider and surface.


### Project settings

Manage project details and team members.

Draft

Details

Members

Billing

Project name

Contact email

Save changes

tabs-with-title.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/card/tabs-with-title.tsx"
import { Button, Card, Descriptions, Flex, Form, FormField, Input, Tag } from '@ifhover/leaf-ui';

import { useId, useState } from 'react';

export function CardTabsWithTitle() {
  const [activeKey, setActiveKey] = useState('settings');
  const [saved, setSaved] = useState(false);
  const formId = useId();
  return (
    <Card
      divided
      title="Project settings"
      description="Manage project details and team members."
      extra={<Tag>{saved ? 'Saved' : 'Draft'}</Tag>}
      tabs={{
        activeKey,
        onChange: setActiveKey,
        items: [
          {
            key: 'settings',
            label: 'Details',
            children: (
              <Form
                id={formId}
                layout="vertical"
                onChange={() => setSaved(false)}
                onSubmit={(event) => {
                  event.preventDefault();
                  setSaved(true);
                }}
              >
                <FormField label="Project name">
                  <Input name="name" defaultValue="Leaf Design System" required />
                </FormField>
                <FormField label="Contact email">
                  <Input name="email" type="email" defaultValue="team@example.com" required />
                </FormField>
              </Form>
            ),
          },
          {
            key: 'members',
            label: 'Members',
            children: (
              <Descriptions
                columns={1}
                items={[
                  { key: 'owner', label: 'Project lead', children: 'Rowan Lin' },
                  { key: 'designer', label: 'Designer', children: 'Alex Chen' },
                ]}
              />
            ),
          },
          { key: 'billing', label: 'Billing', disabled: true, children: null },
        ],
      }}
      footer={
        <Flex align="center" gap="sm" justify="end">
          <Button type="submit" form={formId} disabled={activeKey !== 'settings'}>
            Save changes
          </Button>
        </Flex>
      }
    />
  );
}
```

Expand code

## Card API

| Property      | Type                             | Default | Description                                                                               |
| ------------- | -------------------------------- | ------- | ----------------------------------------------------------------------------------------- |
| `title`       | `ReactNode`                      | —       | Card heading.                                                                             |
| `description` | `ReactNode`                      | —       | Additional description.                                                                   |
| `extra`       | `ReactNode`                      | —       | Heading actions; shown at the trailing edge of tabs without a heading.                    |
| `tabs`        | [`CardTabsProps`](#cardtabs-api) | —       | Embedded tabs; replace the heading without a title or sit beneath it.                     |
| `cover`       | `ReactNode`                      | —       | Top cover.                                                                                |
| `footer`      | `ReactNode`                      | —       | Footer content or actions.                                                                |
| `loading`     | `boolean`                        | `false` | Replace the body with a skeleton                                                          |
| `bordered`    | `boolean`                        | `true`  | Show the outer border                                                                     |
| `divided`     | `boolean`                        | `false` | Separate the heading, content and footer with subtle borders.                             |
| `size`        | `'sm' \| 'md' \| 'lg'`           | `'md'`  | Card size: padding, heading typography and height, and the default size of embedded Tabs. |

## Types

Import the exported types when defining props or building item lists.

```ts
import type { CardProps, CardTabsProps, TabItem } from '@ifhover/leaf-ui';
```

## Usage notes

Place buttons or links in extra and footer. Use an explicit button or link for actions.

`tabs` reuses Tabs configuration and interaction with top-aligned line tabs. `tabs.items[].children` provides each page; Card's `children` may hold shared content below all pages. `loading` replaces the content with skeletons while headings, tabs and actions stay available. Tabs follow the card's `size`; set `tabs.size` to override. An empty item list restores the ordinary card layout.

Use `tabs` to configure disabled tabs, icons, manual keyboard activation, retained or destroyed pages, overflow menus and add, close or reorder callbacks. `tabs.extra` always belongs to the tab bar; with a title, Card's `extra` stays alongside the heading.

## Surfaces and rich content

`description` adds supporting text beneath the title. Ordinary cards have no internal dividers by default; tabbed cards always have a divider below navigation. `divided` adds a footer divider and muted surface with the same vertical action spacing as Modal and Drawer. Customize surfaces and borders through `ConfigProvider` `components.Card`.

## CardTabs API

| Property           | Type                                                                                                        | Default            | Description                                                              |
| ------------------ | ----------------------------------------------------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------ |
| `items`            | `readonly `[`TabItem`](https://ifhover.github.io/leaf-ui/v/0.6.0/en/components/tabs.md#tabitem)`[]`         | Required           | Required. Tab labels and pages; an empty list restores an ordinary card. |
| `activeKey`        | `string`                                                                                                    | First enabled item | Controlled active tab.                                                   |
| `defaultActiveKey` | `string`                                                                                                    | First enabled item | Initially active tab.                                                    |
| `onChange`         | `(key: string) => void`                                                                                     | —                  | Called when the active tab changes.                                      |
| `size`             | `'sm' \| 'md' \| 'lg'`                                                                                      | Card's `size`      | Tab size; may be overridden independently.                               |
| `activationMode`   | `'automatic' \| 'manual'`                                                                                   | `'automatic'`      | Activate with arrow keys or with Enter / Space.                          |
| `destroyInactive`  | `boolean`                                                                                                   | `false`            | Unmount pages on leaving; visited pages are retained by default.         |
| `extra`            | `ReactNode`                                                                                                 | —                  | Trailing tab bar content.                                                |
| `onClose`          | `(key: string, event: MouseEvent<HTMLButtonElement>) => void`                                               | —                  | Request removal by the application; default switching can be prevented.  |
| `onAdd`            | `() => void`                                                                                                | —                  | Show the add button and request a new tab.                               |
| `addLabel`         | `string`                                                                                                    | Localized prompt   | Accessible name of the add button.                                       |
| `overflow`         | `boolean`                                                                                                   | `true`             | Move overflowing tabs into the more menu.                                |
| `sortable`         | `boolean`                                                                                                   | `false`            | Enable sorting alongside `onReorder`.                                    |
| `onReorder`        | `(items: `[`TabItem`](https://ifhover.github.io/leaf-ui/v/0.6.0/en/components/tabs.md#tabitem)`[]) => void` | —                  | Return the reordered original items for the application to store.        |
