JGuang

卡片

Card · Astryx

交互预览
npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0

卡片 · Card

组织相关内容,适合摘要、设置和资源展示。

安装与前置条件

npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0

需要 React 19+,按顺序导入基础 CSS 和主题,并设置 Theme Provider。参见开始使用。

示例与使用方式

  • 卡片 · 综合展示 1:首先体验这个示例,再查看代码理解组件的组合方式。
  • 卡片 · 交互示例 2:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 卡片 · 交互示例 3:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 卡片 · 样式变化 / 样式 4:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 卡片 · 交互示例 5:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
  • 卡片 · 交互示例 6:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。

API 与上游详细参考

优先使用 0.7.1 官方中文说明;上游尚未提供中文的条目保留英文。属性名、类型及默认值保持原生 API,不把示例状态名称当成组件属性。

Card

Card is a bordered, elevated container for discrete, self-contained items: things you could reorder, remove, or interact with independently. Cards are NOT the default layout tool. Most content groups don't need a container at all; spacing and alignment create visual grouping naturally. Only reach for a Card when items need clear interaction boundaries or visual comparison in a grid.

属性类型默认值说明
widthSizeValue卡片宽度(数字 = 像素,字符串 = 按原样使用)。
heightSizeValue卡片高度(数字 = 像素,字符串 = 按原样使用)。
maxWidthSizeValue卡片最大宽度。
minHeightSizeValue卡片最小高度。
childrenReactNode在卡片内部渲染的内容。
padding0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10the theme's card padding (spacing step 4 with no theme)使用间距比例的内边距。省略时,卡片采用主题的卡片内边距,而不是某个步进值;传入步进值意味着覆盖主题,而不是复述默认值。
variant'default' | 'transparent' | 'muted' | 'blue' | 'cyan' | 'gray' | 'green' | 'orange' | 'pink' | 'purple' | 'red' | 'teal' | 'yellow''default'背景颜色变体。default 使用标准卡片背景;transparent 完全去掉背景;muted 使用弱化卡片的柔和背景。非语义变体使用对应的 --color-background-<name> 令牌。
elevation'none' | 'low' | 'med' | 'high''none'静止阴影深度。none 为扁平;low/med/high 对应阴影令牌比例。

使用建议

  • Ask "could I reorder or remove this independently?" If yes, it's a card. If no, it's just a section of the page: use a heading + Stack or Section.
  • Use cards for discrete items: a single user profile, a single notification, a single metric, a product in a grid. Each card represents one "thing" with clear interaction boundaries.
  • Spacing and alignment alone create visual grouping. Not everything needs a container; try removing the card and see if the grouping is still clear from whitespace and typography.
  • Keep padding consistent across sibling cards so they align visually in a grid or list.
  • Pair a card with Layout when you need a structured header, scrollable content, and footer with actions.
  • Let cards share a row or grid on a phone: a card shrinks to fit its track and clips content that cannot wrap at its edge. Truncate long IDs, hashes, and URLs with Text maxLines={1} (the full value shows in a tooltip), and give wide content its own scroll region: Table scrolls by itself; put code or other wide content in a ScrollableArea.
  • 避免:Default to cards for visual grouping. A heading + Stack with proper spacing creates hierarchy without adding borders everywhere. Cards should be the exception, not the default.
  • 避免:Wrap page sections in cards. "General Settings", "Notification Preferences", form groups: these are page regions, use Section or heading + stack.
  • 避免:Create identical card grids (icon + heading + text, repeated). Vary the layout or question whether cards are needed at all.
  • 避免:Nest cards inside other cards; flatten the hierarchy or use spacing and dividers instead.
  • 避免:Use color variants for status; use Banner or Badge for that. Color cards are for categorization.

Cards sharing a row on a phone, with long IDs

import {Card} from '@astryxdesign/core/Card';
import {Grid} from '@astryxdesign/core/Grid';
import {VStack} from '@astryxdesign/core/Layout';
import {Heading} from '@astryxdesign/core/Heading';
import {Text} from '@astryxdesign/core/Text';

const payouts = [
  {label: 'Payout', amount: '$1,240.00', id: 'po_1Q8ZK4X7M2N5P3R6T9V1W4YB'},
  {label: 'Refund', amount: '-$86.50', id: 're_3NfK9Lm2Qx7Vb4Tz8Rw1Hy6C'},
  {label: 'Adjustment', amount: '$12.00', id: 'adj_7Hq2Wm9Kx4Lz8Vn3Rb6Tf1PD'},
];

// Each card takes one grid track and shrinks with it, so three cards fit a
// 390px phone without widening the page. The ID cannot wrap, so it truncates
// with maxLines={1} (the full value shows in a tooltip) instead of running
// past the card edge.
function PayoutCards() {
  return (
    <Grid columns={3} gap={3}>
      {payouts.map(payout => (
        <Card key={payout.id}>
          <VStack gap={1}>
            <Heading level={3}>{payout.label}</Heading>
            <Text hasTabularNumbers>{payout.amount}</Text>
            <Text type="supporting" maxLines={1}>
              {payout.id}
            </Text>
          </VStack>
        </Card>
      ))}
    </Grid>
  );
}

主题 API

{
  "container": true,
  "targets": [
    {
      "className": "astryx-card",
      "visualProps": [
        "variant",
        "elevation"
      ]
    }
  ],
  "vars": [
    {
      "name": "--_card-radius",
      "description": "Border radius of the card",
      "default": "var(--radius-container)",
      "private": true
    },
    {
      "name": "--_card-elevation",
      "description": "Resting shadow of the card, set from the elevation prop.",
      "default": "0 0 transparent",
      "private": true
    },
    {
      "name": "--_card-ring",
      "description": "Inset ring drawn in the card box-shadow list.",
      "default": "0 0 transparent",
      "private": true
    }
  ],
  "derived": [
    {
      "property": "borderRadius",
      "vars": [
        "--_card-radius"
      ]
    },
    {
      "property": "padding",
      "expand": "container"
    }
  ]
}

组件结构

  • Container: The outer box with border, background, border-radius, and padding.
  • Content: Any children rendered inside the card. Often a stack of heading, text, and actions.