---
nav:
  title: 组件
  order: 1
group:
  title: Data Display
  order: 1
title: TextCard
order: 2
category: atom
---

# TextCard 文本卡片

TextCard 是一个文本卡片组件，用于展示带图标、文本、标签和角标的信息项，常用于 Tab 项、列表项、菜单项等场景。

## 何时使用

- 需要展示简洁的文本信息项
- 作为 Tabs 标签页的项
- 作为列表中的可点击项
- 作为导航菜单项
- 需要带有图标、标签或角标的文本展示

## 基础使用

### 基础文本卡片

最简单的用法，只需传入文本内容。

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '8px' }}>
      <PisellCards.TextCard text="Tab title" />
      <PisellCards.TextCard text="Another tab" />
      <PisellCards.TextCard text="More tab" />
    </div>
  );
};
```

## 样式变体

TextCard 支持 6 种样式变体，通过 `variant` 属性控制。

### 纯文本样式（text）

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
      <PisellCards.TextCard text="Default" variant="text" />
      <PisellCards.TextCard
        text="Active"
        variant="text"
        active={{ value: true }}
      />
      <PisellCards.TextCard
        text="Disabled"
        variant="text"
        disabled={{ value: true }}
      />
    </div>
  );
};
```

### 圆角背景样式（filled）

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
      <PisellCards.TextCard text="Default" variant="filled" />
      <PisellCards.TextCard
        text="Active"
        variant="filled"
        active={{ value: true }}
      />
      <PisellCards.TextCard
        text="Disabled"
        variant="filled"
        disabled={{ value: true }}
      />
    </div>
  );
};
```

### 浅色背景样式（light）

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
      <PisellCards.TextCard text="Default" variant="light" />
      <PisellCards.TextCard
        text="Active"
        variant="light"
        active={{ value: true }}
      />
    </div>
  );
};
```

### 描边样式（outlined）

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
      <PisellCards.TextCard text="Default" variant="outlined" />
      <PisellCards.TextCard
        text="Active"
        variant="outlined"
        active={{ value: true }}
      />
    </div>
  );
};
```

### 渐变样式（gradient）

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
      <PisellCards.TextCard text="Default" variant="gradient" />
      <PisellCards.TextCard
        text="Active"
        variant="gradient"
        active={{ value: true }}
      />
    </div>
  );
};
```

### 虚线样式（dashed）

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
      <PisellCards.TextCard text="Default" variant="dashed" />
      <PisellCards.TextCard
        text="Active"
        variant="dashed"
        active={{ value: true }}
      />
    </div>
  );
};
```

## 尺寸

TextCard 支持 3 种尺寸。

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
      <PisellCards.TextCard text="Small" size="small" variant="filled" />
      <PisellCards.TextCard text="Default" size="default" variant="filled" />
      <PisellCards.TextCard text="Large" size="large" variant="filled" />
    </div>
  );
};
```

## 状态管理

### 激活状态

```tsx
import { PisellCards } from '@pisell/materials';
import { useState } from 'react';

export default () => {
  const [activeKey, setActiveKey] = useState('tab1');

  return (
    <div style={{ display: 'flex', gap: '8px' }}>
      <PisellCards.TextCard
        text="Tab 1"
        variant="filled"
        active={{ value: activeKey === 'tab1' }}
        onClick={() => setActiveKey('tab1')}
      />
      <PisellCards.TextCard
        text="Tab 2"
        variant="filled"
        active={{ value: activeKey === 'tab2' }}
        onClick={() => setActiveKey('tab2')}
      />
      <PisellCards.TextCard
        text="Tab 3"
        variant="filled"
        active={{ value: activeKey === 'tab3' }}
        onClick={() => setActiveKey('tab3')}
      />
    </div>
  );
};
```

### 禁用状态

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '8px' }}>
      <PisellCards.TextCard
        text="Disabled"
        variant="filled"
        disabled={{ value: true }}
        onClick={() => alert('不会触发')}
      />
      <PisellCards.TextCard
        text="Normal"
        variant="filled"
        onClick={() => alert('会触发')}
      />
    </div>
  );
};
```

### 加载状态

```tsx
import { PisellCards } from '@pisell/materials';
import { Spin } from 'antd';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '8px' }}>
      <PisellCards.TextCard
        text="Loading"
        variant="filled"
        loading={{
          value: true,
          extra: <Spin size="small" style={{ marginLeft: 8 }} />,
        }}
      />
    </div>
  );
};
```

## 图标

### 前置图标

```tsx
import { PisellCards } from '@pisell/materials';
import { BellOutlined } from '@ant-design/icons';

export default () => {
  return (
    <PisellCards.TextCard
      text="Password"
      variant="filled"
      prefixIcon={<BellOutlined />}
    />
  );
};
```

### 后置图标

```tsx
import { PisellCards } from '@pisell/materials';
import { DownOutlined } from '@ant-design/icons';

export default () => {
  return (
    <PisellCards.TextCard
      text="Password"
      variant="filled"
      suffixIcon={<DownOutlined />}
    />
  );
};
```

### 前后图标组合

```tsx
import { PisellCards } from '@pisell/materials';
import { BellOutlined, DownOutlined } from '@ant-design/icons';

export default () => {
  return (
    <PisellCards.TextCard
      text="Password"
      variant="filled"
      prefixIcon={<BellOutlined />}
      suffixIcon={<DownOutlined />}
    />
  );
};
```

### 图标配置

```tsx
import { PisellCards } from '@pisell/materials';
import { BellOutlined } from '@ant-design/icons';

export default () => {
  return (
    <PisellCards.TextCard
      text="Password"
      variant="filled"
      prefixIcon={<BellOutlined />}
      iconConfig={{ size: 20, color: '#ff4d4f' }}
    />
  );
};
```

## 标签

### 带标签

```tsx
import { PisellCards } from '@pisell/materials';
import { Tag } from 'antd';

export default () => {
  return (
    <PisellCards.TextCard
      text="Password"
      variant="filled"
      tag={<Tag color="blue">2</Tag>}
    />
  );
};
```

## 角标

### 红点角标

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <PisellCards.TextCard
      text="Password"
      variant="filled"
      badge={{ type: 'dot' }}
    />
  );
};
```

### 数字角标

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <PisellCards.TextCard
      text="Password"
      variant="filled"
      badge={{ type: 'number', content: 99 }}
    />
  );
};
```

### 文本角标

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <PisellCards.TextCard
      text="Password"
      variant="filled"
      badge={{ type: 'text', content: 'New' }}
    />
  );
};
```

### 角标位置和大小

角标位置通过 `offset` 控制，大小通过 `size` 控制。

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '16px', flexDirection: 'column' }}>
      <div style={{ display: 'flex', gap: '16px' }}>
        <PisellCards.TextCard
          text="Top Right (默认)"
          variant="filled"
          badge={{ type: 'number', content: 99 }}
        />
        <PisellCards.TextCard
          text="Top Left"
          variant="filled"
          badge={{ type: 'number', content: 99, offset: [-10, 0] }}
        />
        <PisellCards.TextCard
          text="Bottom Right"
          variant="filled"
          badge={{ type: 'number', content: 99, offset: [0, 10] }}
        />
        <PisellCards.TextCard
          text="Bottom Left"
          variant="filled"
          badge={{ type: 'number', content: 99, offset: [-10, 10] }}
        />
      </div>
      <div style={{ display: 'flex', gap: '16px' }}>
        <PisellCards.TextCard
          text="Small Badge"
          variant="filled"
          badge={{ type: 'number', content: 99, size: 'small' }}
        />
        <PisellCards.TextCard
          text="Default Badge"
          variant="filled"
          badge={{ type: 'number', content: 99, size: 'default' }}
        />
      </div>
    </div>
  );
};
```

### 角标显示零值

通过 `showZero` 控制数字角标是否显示零值。

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '16px' }}>
      <PisellCards.TextCard
        text="Hide Zero"
        variant="filled"
        badge={{ type: 'number', content: 0, showZero: false }}
      />
      <PisellCards.TextCard
        text="Show Zero"
        variant="filled"
        badge={{ type: 'number', content: 0, showZero: true }}
      />
    </div>
  );
};
```

## 文本配置

### 字体样式

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', gap: '16px' }}>
      <PisellCards.TextCard
        text="Custom Font"
        variant="filled"
        textConfig={{
          fontSize: 18,
          fontWeight: 'bold',
          color: '#ff4d4f',
        }}
      />
    </div>
  );
};
```

### 文本省略

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
      <PisellCards.TextCard
        text="这是一段很长很长很长很长很长很长的文本内容"
        variant="filled"
        textConfig={{ maxLines: 1, ellipsis: true }}
        style={{ width: 200 }}
      />
      <PisellCards.TextCard
        text="这是一段很长很长很长很长很长很长的文本内容，会显示两行然后省略"
        variant="filled"
        textConfig={{ maxLines: 2, ellipsis: true }}
        style={{ width: 200 }}
      />
    </div>
  );
};
```

## 宽度模式

### 自动宽度（auto）

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <PisellCards.TextCard
      text="Auto Width"
      variant="filled"
      widthMode="auto"
      maxWidth={300}
    />
  );
};
```

### 固定宽度（fixed）

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <PisellCards.TextCard
      text="Fixed Width"
      variant="filled"
      widthMode="fixed"
      width={200}
    />
  );
};
```

### 撑满容器（full）

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <div style={{ width: '100%', border: '1px dashed #ccc', padding: 16 }}>
      <PisellCards.TextCard
        text="Full Width"
        variant="filled"
        widthMode="full"
      />
    </div>
  );
};
```

## 插槽

### 前置插槽

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <PisellCards.TextCard
      text="Custom Prefix"
      variant="filled"
      prefixSlot={<div style={{ color: 'red' }}>🔥</div>}
    />
  );
};
```

### 后置插槽

```tsx
import { PisellCards } from '@pisell/materials';

export default () => {
  return (
    <PisellCards.TextCard
      text="Custom Suffix"
      variant="filled"
      suffixSlot={<div style={{ color: 'green' }}>✓</div>}
    />
  );
};
```

## 综合示例

### 完整配置

```tsx
import { PisellCards } from '@pisell/materials';
import { BellOutlined, DownOutlined } from '@ant-design/icons';
import { Tag } from 'antd';

export default () => {
  return (
    <PisellCards.TextCard
      text="Complete Example"
      variant="filled"
      size="large"
      prefixIcon={<BellOutlined />}
      suffixIcon={<DownOutlined />}
      tag={<Tag color="blue">Hot</Tag>}
      badge={{ type: 'number', content: 99 }}
      active={{ value: true }}
      onClick={() => console.log('clicked')}
    />
  );
};
```

## API

### TextCardProps

| 参数       | 说明                                   | 类型                                                                    | 默认值      |
| ---------- | -------------------------------------- | ----------------------------------------------------------------------- | ----------- |
| text       | 卡片显示的文本内容（必填）             | `ReactNode`                                                             | -           |
| variant    | 卡片样式变体                           | `'text' \| 'filled' \| 'outlined' \| 'light' \| 'gradient' \| 'dashed'` | `'text'`    |
| size       | 卡片尺寸                               | `'small' \| 'default' \| 'large'`                                       | `'default'` |
| clickable  | 是否可点击                             | `boolean`                                                               | `true`      |
| prefixIcon | 前置图标                               | `ReactNode`                                                             | -           |
| suffixIcon | 后置图标                               | `ReactNode`                                                             | -           |
| iconConfig | 图标配置                               | `IconConfig`                                                            | -           |
| tag        | 后置标签                               | `ReactNode`                                                             | -           |
| tagConfig  | 标签配置                               | `TagConfig`                                                             | -           |
| badge      | 角标配置                               | `BadgeConfig`                                                           | -           |
| prefixSlot | 前置插槽（替换前置图标）               | `ReactNode`                                                             | -           |
| suffixSlot | 后置插槽（替换后置图标和标签）         | `ReactNode`                                                             | -           |
| textConfig | 文本配置                               | `TextConfig`                                                            | -           |
| widthMode  | 宽度模式                               | `'auto' \| 'fixed' \| 'full'`                                           | `'auto'`    |
| width      | 固定宽度值（widthMode='fixed' 时有效） | `number \| string`                                                      | -           |
| maxWidth   | 最大宽度（widthMode='auto' 时有效）    | `number \| string`                                                      | `400`       |
| active     | 激活状态配置                           | `ActiveConfig`                                                          | -           |
| disabled   | 禁用状态配置                           | `DisabledConfig`                                                        | -           |
| loading    | 加载状态配置                           | `LoadingConfig`                                                         | -           |
| onClick    | 点击事件                               | `(event: MouseEvent) => void`                                           | -           |
| render     | 自定义渲染函数                         | `(props: TextCardProps) => ReactNode`                                   | -           |
| className  | 自定义样式类名                         | `string`                                                                | -           |
| style      | 自定义样式                             | `CSSProperties`                                                         | -           |

### IconConfig

| 参数  | 说明                 | 类型     | 默认值 |
| ----- | -------------------- | -------- | ------ |
| size  | 图标大小（单位：px） | `number` | -      |
| color | 图标颜色             | `string` | -      |

### TagConfig

| 参数  | 说明           | 类型            | 默认值 |
| ----- | -------------- | --------------- | ------ |
| color | 标签颜色       | `string`        | -      |
| style | 标签自定义样式 | `CSSProperties` | -      |

### BadgeConfig

| 参数     | 说明                   | 类型                  | 默认值   |
| -------- | ---------------------- | --------------------- | -------- |
| type     | 角标类型               | `'dot' \| 'number' \| 'text'` | `'dot'`  |
| content  | 角标内容（数字或文本） | `ReactNode`           | -        |
| offset   | 角标偏移量 [x, y]      | `[number, number]`    | -        |
| size     | 角标大小               | `'small' \| 'default'` | -        |
| color    | 角标颜色               | `string`              | -        |
| style    | 角标自定义样式         | `CSSProperties`       | -        |
| showZero | 是否显示零值           | `boolean`             | `false`  |

**角标位置说明**：
- 角标位置通过 `offset` 控制，不设置 `offset` 时默认在右上角
- `offset` 格式为 `[x, y]`，正数向右/下偏移，负数向左/上偏移
- 例如：`offset: [0, 0]` 为默认位置，`offset: [-10, 0]` 向左偏移，`offset: [0, 10]` 向下偏移

**角标大小说明**：
- `size: 'small'` - 小尺寸角标
- `size: 'default'` - 默认尺寸角标（不设置时使用默认尺寸）

**角标显示零值说明**：
- `showZero: true` - 当 content 为 0 时显示角标
- `showZero: false` - 当 content 为 0 时不显示角标（默认）

### TextConfig

| 参数       | 说明                 | 类型               | 默认值 |
| ---------- | -------------------- | ------------------ | ------ |
| fontSize   | 字体大小（单位：px） | `number`           | -      |
| fontWeight | 字体粗细             | `string \| number` | -      |
| color      | 文本颜色             | `string`           | -      |
| maxLines   | 最大显示行数         | `number`           | `1`    |
| ellipsis   | 是否显示省略号       | `boolean`          | `true` |

### 状态配置（ActiveConfig / DisabledConfig / LoadingConfig）

| 参数      | 说明                   | 类型                       | 默认值 |
| --------- | ---------------------- | -------------------------- | ------ |
| value     | 是否处于该状态         | `boolean`                  | -      |
| style     | 该状态下的自定义样式   | `CSSProperties`            | -      |
| className | 该状态下的自定义类名   | `string`                   | -      |
| onChange  | 状态改变回调           | `(value: boolean) => void` | -      |
| extra     | 该状态下额外的渲染内容 | `ReactNode`                | -      |

## 注意事项

1. **主题色变量**：组件使用 CSS 变量 `--theme-color` 作为主题色，可通过修改 CSS 变量自定义主题色
2. **插槽优先级**：当同时设置插槽和对应内容时，插槽优先显示
3. **状态优先级**：loading > disabled > active
4. **宽度限制**：auto 模式下最大宽度为 400px，full 模式下最小宽度为 28px
5. **点击事件**：disabled 和 loading 状态下，点击事件不会触发
