Skip to content

Card

Flexible card component for displaying grouped content with various layouts.

import { Card } from 'asterui'

Basic Card

Simple card with title and content.

Card Title

Card content goes here. This is a basic card with a title.

import { Card } from 'asterui'

function App() {
  return (
      <Card title="Card Title" style={{ width: '20rem' }}>
        <p>Card content goes here. This is a basic card with a title.</p>
      </Card>
    )
}

export default App

Bordered

Card with a solid border instead of shadow.

Card Title

A card with a solid border instead of a shadow.

import { Card } from 'asterui'

function App() {
  return (
      <Card variant="border" title="Card Title" style={{ width: '20rem' }}>
        <p>A card with a solid border instead of a shadow.</p>
      </Card>
    )
}

export default App

With Cover Image

Card with a cover image above the content.

Cover

Card with Cover

Cards can have cover images that appear above the content.

import { Card } from 'asterui'

function App() {
  return (
      <Card
        cover={<img src="https://picsum.photos/seed/card1/400/200" alt="Cover" />}
        title="Card with Cover"
        style={{ width: '20rem' }}
      >
        <p>Cards can have cover images that appear above the content.</p>
      </Card>
    )
}

export default App

With Actions

Card with action buttons at the bottom.

Cover

Card with Actions

Action buttons appear at the bottom of the card.

import { Card, Button } from 'asterui'

function App() {
  return (
      <Card
        cover={<img src="https://picsum.photos/seed/card2/400/200" alt="Cover" />}
        title="Card with Actions"
        style={{ width: '20rem' }}
        actions={
          <>
            <Button variant="ghost" size="sm">Cancel</Button>
            <Button color="primary" size="sm">Buy Now</Button>
          </>
        }
      >
        <p>Action buttons appear at the bottom of the card.</p>
      </Card>
    )
}

export default App

Variants

Different card style variants: shadow, border, dash, borderless.

Shadow

Shadow style

Border

Solid border

Dash

Dashed border

Borderless

No border
import { Card, Space } from 'asterui'

function App() {
  return (
      <Space direction="horizontal" wrap size="md">
        <Card title="Shadow" variant="shadow" style={{ width: '14rem' }}>
          Shadow style
        </Card>
        <Card title="Border" variant="border" style={{ width: '14rem' }}>
          Solid border
        </Card>
        <Card title="Dash" variant="dash" style={{ width: '14rem' }}>
          Dashed border
        </Card>
        <Card title="Borderless" variant="borderless" style={{ width: '14rem' }}>
          No border
        </Card>
      </Space>
    )
}

export default App

Sizes

Card sizes from xs to lg with varying padding.

Extra Small

Compact content

Small

Small card content

Medium

Medium card content

Large

Large card content

import { Card, Space } from 'asterui'

function App() {
  return (
      <Space direction="horizontal" wrap size="md" align="start">
        <Card title="Extra Small" size="xs" style={{ width: '12rem' }}>
          <p>Compact content</p>
        </Card>
        <Card title="Small" size="sm" style={{ width: '14rem' }}>
          <p>Small card content</p>
        </Card>
        <Card title="Medium" size="md" style={{ width: '16rem' }}>
          <p>Medium card content</p>
        </Card>
        <Card title="Large" size="lg" style={{ width: '18rem' }}>
          <p>Large card content</p>
        </Card>
      </Space>
    )
}

export default App

Extra Content

Add extra content in the card header with the extra prop.

Card Title

Use the extra prop to add content in the top-right corner.

import { Card } from 'asterui'

function App() {
  return (
      <Card
        title="Card Title"
        extra={<a href="#" className="link link-primary text-sm">More</a>}
        style={{ width: '20rem' }}
      >
        <p>Use the extra prop to add content in the top-right corner.</p>
      </Card>
    )
}

export default App

Meta Layout

Built-in avatar, title, and description layout.

avatar

John Doe

Software Engineer

Use avatar, title, and description for a meta layout.

import { Card, Avatar } from 'asterui'

function App() {
  return (
      <Card
        avatar={<Avatar src="/avatar-2.webp" />}
        title="John Doe"
        description="Software Engineer"
        style={{ width: '20rem' }}
      >
        <p className="mt-4">Use avatar, title, and description for a meta layout.</p>
      </Card>
    )
}

export default App

Card.Meta Component

Standalone meta component for flexible positioning.

avatar
Jane Smith
Product Designer

Card.Meta can be used anywhere inside the card body.

import { Card, Avatar } from 'asterui'

function App() {
  return (
      <Card style={{ width: '20rem' }}>
        <Card.Meta
          avatar={<Avatar src="/avatar-1.webp" />}
          title="Jane Smith"
          description="Product Designer"
        />
        <p className="mt-4">Card.Meta can be used anywhere inside the card body.</p>
      </Card>
    )
}

export default App

Hoverable

Card with hover shadow effect.

Cover

Hoverable Card

Hover over this card to see the shadow effect.

import { Card } from 'asterui'

function App() {
  return (
      <Card
        hoverable
        cover={<img src="https://picsum.photos/seed/card3/400/200" alt="Cover" />}
        title="Hoverable Card"
        style={{ width: '20rem' }}
      >
        <p>Hover over this card to see the shadow effect.</p>
      </Card>
    )
}

export default App

Loading State

Skeleton loading state while content loads.

import { Card, Button, Space, Avatar } from 'asterui'
import { useState } from 'react'

function App() {
  const [loading, setLoading] = useState(true)
  
  return (
      <Space direction="vertical" size="md">
        <Button size="sm" onClick={() => setLoading(!loading)}>
          Toggle Loading
        </Button>
        <Card
          loading={loading}
          avatar={<Avatar />}
          title="Card Title"
          description="Card description"
          style={{ width: '20rem' }}
          actions={
            <>
              <Button variant="ghost" size="sm">Action</Button>
              <Button color="primary" size="sm">Submit</Button>
            </>
          }
        >
          <p className="mt-4">Card content that appears when not loading.</p>
        </Card>
      </Space>
    )
}

export default App

Image Full

Content overlays on the cover image.

Cover

Image Full

Content overlays on top of the image with dark gradient.

import { Card, Button } from 'asterui'

function App() {
  return (
      <Card
        imageFull
        cover={<img src="https://picsum.photos/seed/card4/400/250" alt="Cover" />}
        title="Image Full"
        style={{ width: '20rem' }}
        actions={<Button color="primary" size="sm">Learn More</Button>}
      >
        <p>Content overlays on top of the image with dark gradient.</p>
      </Card>
    )
}

export default App

Side Layout

Horizontal layout with image on the side.

Cover

Side Layout

The cover image appears on the side instead of the top.

import { Card, Button } from 'asterui'

function App() {
  return (
      <Card
        side
        cover={<img src="https://picsum.photos/seed/card5/200/200" alt="Cover" className="max-w-[200px]" />}
        title="Side Layout"
        style={{ width: '28rem' }}
        actions={<Button color="primary" size="sm">Details</Button>}
      >
        <p>The cover image appears on the side instead of the top.</p>
      </Card>
    )
}

export default App

Inner Card

Nested cards with subtle background distinction.

Outer Card

This is the outer card content.

Inner Card

Inner cards have a subtle background distinction.

import { Card } from 'asterui'

function App() {
  return (
      <Card title="Outer Card" style={{ width: '24rem' }}>
        <p className="mb-4">This is the outer card content.</p>
        <Card type="inner" title="Inner Card">
          <p>Inner cards have a subtle background distinction.</p>
        </Card>
      </Card>
    )
}

export default App

With Tabs

Card with tabbed content navigation.

Article content here...

import { Card } from 'asterui'
import { useState } from 'react'

function App() {
  const [activeKey, setActiveKey] = useState('tab1')
  
  return (
      <Card
        tabList={[
          { key: 'tab1', label: 'Article' },
          { key: 'tab2', label: 'App' },
          { key: 'tab3', label: 'Project' },
        ]}
        activeTabKey={activeKey}
        onTabChange={setActiveKey}
        style={{ width: '24rem' }}
      >
        {activeKey === 'tab1' && <p>Article content here...</p>}
        {activeKey === 'tab2' && <p>App content here...</p>}
        {activeKey === 'tab3' && <p>Project content here...</p>}
      </Card>
    )
}

export default App

Card Grid

Grid layout inside cards with hoverable cells.

Card Grid

Grid Item 1
Grid Item 2
Grid Item 3
Grid Item 4
import { Card } from 'asterui'

function App() {
  return (
      <Card title="Card Grid" style={{ width: '28rem' }}>
        <div className="grid grid-cols-2 -mx-6 -mb-6">
          <Card.Grid hoverable>Grid Item 1</Card.Grid>
          <Card.Grid hoverable>Grid Item 2</Card.Grid>
          <Card.Grid hoverable>Grid Item 3</Card.Grid>
          <Card.Grid hoverable>Grid Item 4</Card.Grid>
        </div>
      </Card>
    )
}

export default App
PropertyDescriptionTypeDefault
titleCard titleReactNode-
extraContent in top-right of headerReactNode-
coverCover image elementReactNode-
actionsAction buttons at bottomReactNode-
sizeCard size'xs' | 'sm' | 'md' | 'lg' | 'xl'-
variantCard style variant'shadow' | 'border' | 'dash' | 'borderless''shadow'
typeInner card style for nesting'inner'-
sideHorizontal layout with side imagebooleanfalse
imageFullContent overlays on cover imagebooleanfalse
actionsJustifyActions alignment'start' | 'center' | 'end''end'
loadingShow skeleton loading statebooleanfalse
hoverableAdd hover shadow effectbooleanfalse
avatarAvatar for meta layoutReactNode-
descriptionDescription for meta layoutReactNode-
tabListTab items for card tabsCardTabItem[]-
activeTabKeyActive tab key (controlled)string-
defaultActiveTabKeyDefault active tab keystring-
onTabChangeTab change callback(key: string) => void-
tabBarExtraContentExtra content beside tabsReactNode-
childrenCard body contentReactNode-
classNameAdditional CSS classesstring-
bodyClassNameAdditional CSS classes for the card-body elementstring-
styleInline stylesCSSProperties-
PropertyDescriptionTypeDefault
avatarAvatar or icon elementReactNode-
titleTitle contentReactNode-
descriptionDescription contentReactNode-
PropertyDescriptionTypeDefault
hoverableAdd hover effectbooleanfalse
childrenGrid cell contentReactNode-
PropertyDescriptionTypeDefault
keyUnique tab identifierstring-
labelTab label contentReactNode-
disabledDisable the tabbooleanfalse
  • Card structure uses semantic HTML
  • Tab navigation uses proper ARIA roles and states
  • Loading state provides visual feedback
  • Focus states are visible for interactive elements