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, and this page is available as Markdown at https://ifhover.github.io/leaf-ui/v/0.6.0/en/components/card.md.
  • English
  • 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
    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>
      );
    }
    

    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

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

    Default

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

    Large

    Keep project details, design and development working from the same plan.
    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>
      );
    }
    

    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.
    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>
      );
    }
    

    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.

    Keep design and development working from the same plan.
    Owner
    Rowan Lin
    Team members
    8 people
    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.',
              },
            ],
          }}
        />
      );
    }
    

    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
    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>
          }
        />
      );
    }
    

    Card API

    PropertyTypeDefaultDescription
    titleReactNode—Card heading.
    descriptionReactNode—Additional description.
    extraReactNode—Heading actions; shown at the trailing edge of tabs without a heading.
    tabsCardTabsProps—Embedded tabs; replace the heading without a title or sit beneath it.
    coverReactNode—Top cover.
    footerReactNode—Footer content or actions.
    loadingbooleanfalseReplace the body with a skeleton
    borderedbooleantrueShow the outer border
    dividedbooleanfalseSeparate 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.

    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

    PropertyTypeDefaultDescription
    itemsreadonly TabItem[]RequiredRequired. Tab labels and pages; an empty list restores an ordinary card.
    activeKeystringFirst enabled itemControlled active tab.
    defaultActiveKeystringFirst enabled itemInitially active tab.
    onChange(key: string) => void—Called when the active tab changes.
    size'sm' | 'md' | 'lg'Card's sizeTab size; may be overridden independently.
    activationMode'automatic' | 'manual''automatic'Activate with arrow keys or with Enter / Space.
    destroyInactivebooleanfalseUnmount pages on leaving; visited pages are retained by default.
    extraReactNode—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.
    addLabelstringLocalized promptAccessible name of the add button.
    overflowbooleantrueMove overflowing tabs into the more menu.
    sortablebooleanfalseEnable sorting alongside onReorder.
    onReorder(items: TabItem[]) => void—Return the reordered original items for the application to store.