---
title: 主题切换
group:
  title: 设计
  path: /theme
  order: 5
---
## 概述

组件库提供「一键主题切换」能力，基于运行时覆盖 **CSS 变量**（与 `@alipay/one-token-lib`、组件内 `var(--color-*)` 等命名一致）实现。应用层通过 `ThemeProvider` 与 `useTheme` 切换主题，无需修改现有组件样式代码。

## 特性

- ✅ **一键切换**：调用 `setTheme('light' | 'dark')` 即可全局生效
- ✅ **持久化**：可选 `persistKey`，将用户选择写入 localStorage
- ✅ **预设主题**：内置 `light`、`dark`，深色覆盖常用语义变量
- ✅ **自定义主题**：通过 `themes` 注册或 `setTheme(name, overrides)` 传入变量覆盖
- ✅ **与样式方案兼容**：与 antd-style、one-token、px2rem 无冲突，组件继续使用 `var(--*)` 即可

## 使用方法

### 1. 应用根节点包裹 ThemeProvider

在应用入口用 `ThemeProvider` 包裹整棵组件树，并指定默认主题与可选的持久化 key：

```tsx
import { ThemeProvider } from '@alipay/agentic-design-mobile';

function App() {
  return (
    <ThemeProvider defaultTheme="light" persistKey="my-app-theme">
      <YourApp />
    </ThemeProvider>
  );
}
```

| 属性 | 类型 | 说明 |
|------|------|------|
| `defaultTheme` | `'light' \| 'dark' \| string` | 默认主题名，未持久化时使用 |
| `persistKey` | `string` | 传入则把当前主题名写入 `localStorage`，下次进入应用自动恢复 |
| `themes` | `Record<string, ThemeTokenOverrides>` | 扩展/覆盖预设主题，见下方「自定义主题」 |

### 2. 在组件中获取与切换主题

在任意子组件中通过 `useTheme`（或 `useThemeContext`）获取当前主题与切换方法：

```tsx
import { useTheme } from '@alipay/agentic-design-mobile';

function ThemeSwitch() {
  const { theme, setTheme, isDark } = useTheme();

  return (
    <button onClick={() => setTheme(isDark ? 'light' : 'dark')}>
      {isDark ? '切换为浅色' : '切换为深色'}
    </button>
  );
}
```

返回字段说明：

| 字段 | 类型 | 说明 |
|------|------|------|
| `theme` | `ThemeName` | 当前主题名 |
| `setTheme` | `(name, overrides?) => void` | 切换主题；可传第二参数做本次覆盖 |
| `themeTokens` | `ThemeTokenOverrides` | 当前生效的变量映射（只读） |
| `isDark` | `boolean` | 是否为暗色主题（`theme === 'dark'`） |

### 3. 在组件中根据主题写样式

组件样式无需改动，继续使用 one-token 的 CSS 变量即可，主题切换会自动改变这些变量的计算值：

```tsx
import { createStyles, genStyle } from '@/style';

const useStyles = createStyles(({ css, prefixCls }) => ({
  card: genStyle(
    `${prefixCls}-card`,
    css`
      background: var(--color-gray-bg-card-white);
      color: var(--color-gray-text-default);
      border-radius: var(--radius-card-base, 12px);
    `
  ),
}));
```

若需要在逻辑中根据主题分支（例如换图、换文案），可使用 `useTheme`：

```tsx
import { useTheme } from '@alipay/agentic-design-mobile';

function Header() {
  const { isDark } = useTheme();
  return (
    <header>
      <img src={isDark ? '/logo-dark.png' : '/logo.png'} alt="logo" />
    </header>
  );
}
```

### 4. 自定义主题

**方式一：通过 Provider 的 `themes` 注册**

```tsx
<ThemeProvider
  defaultTheme="light"
  persistKey="my-app-theme"
  themes={{
    brand: {
      '--color-primary-control-fill-active': '#0066ff',
      '--color-gray-text-default': '#1a1a1a',
    },
  }}
>
  <App />
</ThemeProvider>

// 在子组件中切换
setTheme('brand');
```

**方式二：切换时传入本次覆盖**

```tsx
setTheme('dark', {
  '--color-gray-bg-card-white': '#0f0f0f',
});
```

## 内置主题

| 主题名 | 说明 |
|--------|------|
| `light` | 浅色主题。不覆盖变量，实际由 one-token 的 `lui-mobile.css` 等在 `:root` 上提供的默认值生效。 |
| `dark` | 深色主题。覆盖常用语义变量，使组件在深色背景下可读。 |

## 支持的变量（深色主题覆盖项）

自定义主题或 `setTheme(name, overrides)` 时，可覆盖以下与 one-token 一致的 CSS 变量（深色主题中已使用的变量，均可被主题系统控制）。

### 背景

| 变量名 | 说明 |
|--------|------|
| `--color-gray-bg-base` | 基础背景 |
| `--color-gray-bg-card-white` | 卡片/白底背景 |
| `--color-gray-a3` | 灰度 a3 |
| `--color-gray-bg-mask` | 遮罩背景 |

### 文字

| 变量名 | 说明 |
|--------|------|
| `--color-gray-text-default` | 默认正文色 |
| `--color-gray-text-secondary` | 次要文字色 |
| `--color-gray-text-light` | 弱化文字色 |
| `--color-text-primary` | 主文字色 |
| `--color-gray-contrast` | 对比色（如深色底上的白字） |

### 边框

| 变量名 | 说明 |
|--------|------|
| `--color-gray-border-base` | 基础边框 |
| `--color-gray-border-light` | 浅边框 |
| `--color-gray-border-dark` | 深边框 |

### 主色

| 变量名 | 说明 |
|--------|------|
| `--color-primary-bg-card-light` | 主色卡片浅底 |
| `--color-primary-control-fill-active` | 主色控件激活填充 |
| `--color-primary-text-secondary` | 主色次要文字 |
| `--color-brand-blue-text-default` | 品牌蓝默认文字 |

### 阴影

| 变量名 | 说明 |
|--------|------|
| `--shadow-control-base` | 控件基础阴影 |
| `--shadow-popover-base` | 气泡/弹出层基础阴影 |

### 状态色

| 变量名 | 说明 |
|--------|------|
| `--color-success-base` | 成功态 |
| `--color-error-base` | 错误态 |
| `--color-loading-base` | 加载态 |
| `--color-abort-base` | 中止态 |
| `--color-red-control-fill-primary` | 红色控件主填充 |
| `--color-red-text-secondary` | 红色次要文字 |

以上变量在 `dark` 主题中均有覆盖；自定义主题可按需只覆盖其中部分变量，未覆盖的将沿用当前 `:root` 上的值。
