ProComponents, templates & AI tooling
HeroUI
27.7k

Card

Card 从 HeroUI v2 到 v3 的迁移指南。

完整的 API 参考、样式指南与高级示例请参阅 v3 Card 文档。本指南只关注从 HeroUI v2 的迁移。

结构变化

在 v2 中,Card 使用独立导出的子组件:CardHeaderCardBodyCardFooter

import { Card, CardHeader, CardBody, CardFooter } from "@heroui/react";

export default function App() {
  return (
    <Card>
      <CardHeader>Header</CardHeader>
      <CardBody>Body</CardBody>
      <CardFooter>Footer</CardFooter>
    </Card>
  );
}

在 v3 中,Card 使用复合组件模式,子部件以 Card.* 形式显式组合:

import { Card } from "@heroui/react";

export default function App() {
  return (
    <Card>
      <Card.Header>
        <Card.Title>Title</Card.Title>
        <Card.Description>Description</Card.Description>
      </Card.Header>
      <Card.Content>Body content</Card.Content>
      <Card.Footer>Footer</Card.Footer>
    </Card>
  );
}

关键变化

1. 组件结构

v2: 独立组件:CardHeaderCardBodyCardFooter
v3: 复合组件:Card.HeaderCard.TitleCard.DescriptionCard.ContentCard.Footer

2. 组件命名变化

v2 组件v3 组件说明
CardHeaderCard.Header功能等价
CardBodyCard.Content已重命名
CardFooterCard.Footer功能等价
Card.Title新增:用于标题区标题
Card.Description新增:用于标题区描述

3. Prop 变更

v2 propv3 位置说明
shadow已移除(例如使用 Tailwind shadow-smshadow-md
radius已移除(例如使用 Tailwind rounded-lg
fullWidth已移除(例如使用 Tailwind w-full
isHoverable已移除(请使用 Tailwind 的 hover class)
isPressable请在 Card 内使用 buttona 包裹可点击区域
isBlurredisFooterBlurred已移除(例如使用 Tailwind backdrop-blur-*
isDisabled已移除(请使用条件渲染处理)
disableAnimationdisableRipple已移除
allowTextSelectionOnPress已移除(不再适用)
classNames在各子部件上使用 className

4. 变体

v2:variant prop(主要通过 shadow / radius 控制观感)
v3: 提供 variant prop:transparentdefaultsecondarytertiary

迁移示例

Card 结构

{/* Basic structure */}
<Card>
  <CardHeader>Header</CardHeader>
  <CardBody>Body content</CardBody>
  <CardFooter>Footer</CardFooter>
</Card>

{/* With title and description */}
<Card>
  <CardHeader className="pb-0 pt-2 px-4 flex-col items-start">
    <p className="text-tiny uppercase font-bold">Daily Mix</p>
    <small className="text-default-500">12 Tracks</small>
    <h4 className="font-bold text-large">Frontend Radio</h4>
  </CardHeader>
  <CardBody>Content</CardBody>
</Card>
{/* 基础结构 */}
<Card>
  <Card.Header>
    <Card.Title>Header</Card.Title>
  </Card.Header>
  <Card.Content>Body content</Card.Content>
  <Card.Footer>Footer</Card.Footer>
</Card>

{/* 标题 + 描述 */}
<Card>
  <Card.Header>
    <Card.Title>Frontend Radio</Card.Title>
    <Card.Description>Daily Mix • 12 Tracks</Card.Description>
  </Card.Header>
  <Card.Content>Content</Card.Content>
</Card>

可点击的 Card

<Card 
  isPressable 
  shadow="sm" 
  onPress={() => console.log("pressed")}
>
  <CardBody>Clickable card</CardBody>
</Card>
<Card className="shadow-sm">
  <button
    type="button"
    className="w-full cursor-pointer text-left"
    onClick={() => console.log("pressed")}
  >
    <Card.Content>Clickable card</Card.Content>
  </button>
</Card>

带图片的 Card

<Card className="py-4">
  <CardHeader className="pb-0 pt-2 px-4 flex-col items-start">
    <h4 className="font-bold text-large">Frontend Radio</h4>
  </CardHeader>
  <CardBody className="overflow-visible py-2">
    <Image
      alt="Card background"
      className="object-cover rounded-xl"
      src="https://example.com/image.jpg"
      width={270}
    />
  </CardBody>
</Card>
<Card className="py-4">
  <Card.Header>
    <Card.Title>Frontend Radio</Card.Title>
  </Card.Header>
  <Card.Content className="overflow-visible py-2">
    <img
      alt="Card background"
      className="object-cover rounded-xl w-full"
      src="https://example.com/image.jpg"
    />
  </Card.Content>
</Card>
import { Card, CardFooter, Image, Button } from "@heroui/react";

<Card isFooterBlurred className="border-none" radius="lg">
  <Image
    alt="Woman listing to music"
    className="object-cover"
    height={200}
    src="https://example.com/image.jpg"
    width={200}
  />
  <CardFooter className="justify-between before:bg-white/10 border-white/20 border-1 overflow-hidden py-1 absolute before:rounded-xl rounded-large bottom-1 w-[calc(100%_-_8px)] shadow-small ml-1 z-10">
    <p className="text-tiny text-white/80">Available soon.</p>
    <Button className="text-tiny text-white bg-black/20" size="sm">
      Notify me
    </Button>
  </CardFooter>
</Card>
import { Card, Button } from "@heroui/react";

<Card className="border-none rounded-lg relative overflow-hidden">
  <img
    alt="Woman listing to music"
    className="object-cover w-full h-[200px]"
    src="https://example.com/image.jpg"
  />
  <Card.Footer className="justify-between backdrop-blur-md bg-white/10 border-white/20 border overflow-hidden py-1 absolute rounded-lg bottom-1 w-[calc(100%_-_8px)] shadow-sm ml-1 z-10">
    <p className="text-tiny text-white/80">Available soon.</p>
    <Button className="text-tiny text-white bg-black/20" size="sm">
      Notify me
    </Button>
  </Card.Footer>
</Card>

Card 变体

{/* v2 doesn't have variants, uses shadow/radius */}
<Card shadow="md" radius="lg">
  <CardBody>Content</CardBody>
</Card>
<Card variant="default">
  <Card.Content>Content</Card.Content>
</Card>
<Card variant="secondary">
  <Card.Content>Content</Card.Content>
</Card>

样式变化

v2:classNames prop

<Card 
  classNames={{
    base: "custom-base",
    header: "custom-header",
    body: "custom-body",
    footer: "custom-footer"
  }}
/>

v3:直接使用 className prop

<Card className="custom-base">
  <Card.Header className="custom-header">
    <Card.Title>Title</Card.Title>
  </Card.Header>
  <Card.Content className="custom-body">
    Content
  </Card.Content>
  <Card.Footer className="custom-footer">
    Footer
  </Card.Footer>
</Card>

组件组成

v3 的 Card 结构如下:

Card (Root)
  ├── Card.Header (optional)
  │   ├── Card.Title (optional)
  │   └── Card.Description (optional)
  ├── Card.Content (optional)
  └── Card.Footer (optional)

总结

  1. 组件结构:请使用复合组件,而不是 v2 的独立导出子组件。
  2. CardBodyCard.Content:组件已重命名。
  3. 新增子组件Card.TitleCard.Description,用于结构化标题区。
  4. 大量样式 prop 已移除:请改用 Tailwind CSS class。
  5. 可点击 Card:不要用 isPressable,改为在 Card 内使用 button 或链接。
  6. 模糊效果:请使用 Tailwind backdrop-blur-* class,而不是相关 prop。
  7. 变体:新增用于表达语义层级 / 视觉强调度的变体体系。
  8. classNames 已移除:在各子部件上使用 className prop。

本页目录