# 主题化

了解如何使用内置的主题提供器和 Material-UI 主题选项来自定义支付组件的外观。`@blocklet/payment-react` 库基于 Material-UI 构建，让您能够广泛地控制支付流程的观感。

## `PaymentThemeProvider` 概览

该库包含一个专用的 `PaymentThemeProvider`，它包裹了所有支付组件。此提供器建立了一个默认主题，该主题继承自 ArcBlock UX 主题 (`@arcblock/ux/lib/Theme`)，以确保在 ArcBlock 生态系统内的视觉一致性。它还添加了自己的自定义项，例如一个特殊的 `chip` 调色板和对各种 MUI 组件的样式覆盖。

以下是 `PaymentThemeProvider` 结构的简化示例：

```tsx src/theme/index.tsx icon=logos:react
import { createTheme, ThemeProvider } from '@mui/material/styles';
import { create as createBlockletTheme, deepmerge } from '@arcblock/ux/lib/Theme';

export function PaymentThemeProvider({ children, theme: customTheme = {} }) {
  const parentTheme = useTheme();

  const mergeTheme = useMemo(() => {
    // 从基础 blocklet 主题开始
    const blockletTheme = parentTheme.themeName === 'ArcBlock' ? parentTheme : createBlockletTheme();

    // 合并我们的自定义支付主题选项
    let paymentThemeOptions = deepmerge(blockletTheme, {
      // 自定义调色板扩展，例如，用于 chip
      palette: {
        chip: { /* ... */ },
      },
      // 自定义组件样式覆盖
      components: {
        MuiButton: { /* ... */ },
        MuiOutlinedInput: { /* ... */ },
        // ... 其他组件
      },
    });

    // 合并任何用户提供的自定义主题
    paymentThemeOptions = deepmerge(paymentThemeOptions, customTheme);

    return createTheme(paymentThemeOptions);
  }, [parentTheme, customTheme]);

  return (
    <ThemeProvider theme={mergeTheme}>
      <CssBaseline />
      {children}
    </ThemeProvider>
  );
}
```

## 自定义组件样式

从 1.14.22 版本开始，您可以通过传递 `theme` 属性轻松地为单个支付组件自定义主题。该属性接受一个 Material-UI `ThemeOptions` 对象，为您提供了两种应用自定义样式的主要方法。

### 1. 使用 `styleOverrides`

对于深度的结构性更改，您可以在支付组件的作用域内覆盖特定 Material-UI 组件的样式。这是标准的 MUI 主题化方法。

```tsx Customizing the Primary Button icon=logos:react
import { PaymentProvider, CheckoutForm } from '@blocklet/payment-react';
import { useSessionContext } from '@/hooks/session-context'; // 假设 session 上下文在此处定义

function CustomStyledCheckout() {
  const { session, connectApi } = useSessionContext();

  return (
    <PaymentProvider session={session} connect={connectApi}>
      <CheckoutForm
        id="plink_xxx"
        onChange={console.info}
        theme={{
          components: {
            MuiButton: {
              styleOverrides: {
                containedPrimary: {
                  backgroundColor: '#1DC1C7',
                  color: '#fff',
                  '&:hover': {
                    backgroundColor: 'rgb(20, 135, 139)',
                  },
                },
              },
            },
          },
        }}
      />
    </PaymentProvider>
  );
}
```

在此示例中，我们针对主 contained 按钮 (`MuiButton.styleOverrides.containedPrimary`) 并更改其背景和文本颜色。

### 2. 使用 `sx` 属性

对于快速、有针对性的 CSS 更改，您可以在 `theme` 属性中传递一个 `sx` 对象。这允许您使用 CSS 选择器来定位组件内的特定元素。

```tsx Customizing with the sx Prop icon=logos:react
import { PaymentProvider, CheckoutForm } from '@blocklet/payment-react';
import { useSessionContext } from '@/hooks/session-context';

function SxStyledCheckout() {
  const { session, connectApi } = useSessionContext();

  return (
    <PaymentProvider session={session} connect={connectApi}>
      <CheckoutForm
        id="plink_xxx"
        showCheckoutSummary={false}
        onChange={console.info}
        theme={{
          sx: {
            // 通过其特定的类名来定位提交按钮
            '.cko-submit-button': {
              backgroundColor: '#1DC1C7',
              color: '#fff',
              '&:hover': {
                backgroundColor: 'rgb(20, 135, 139)',
              },
            },
          },
        }}
      />
    </PaymentProvider>
  );
}

```

当您需要覆盖一个通过标准组件样式覆盖不易访问的样式时，此方法非常有用。

## 理解默认主题

默认主题建立在颜色、间距和排版的 CSS 变量（设计令牌）系统之上，从而在亮色和暗色模式下实现一致的样式。

### 调色板

该主题通过一个自定义的 `chip` 对象扩展了标准的 Material-UI 调色板，用于设置状态指示器的样式。您可以在您的自定义主题中覆盖这些颜色。

```ts src/theme/types.ts icon=mdi:language-typescript
declare module '@mui/material/styles' {
  interface Palette {
    chip: {
      success: { text: string; background: string; border: string; };
      default: { text: string; background: string; border: string; };
      secondary: { text: string; background: string; border: string; };
      error: { text: string; background: string; border: string; };
      warning: { text: string; background: string; border: string; };
      info: { text: string; background: string; border: string; };
    };
  }
  // ... PaletteOptions 定义
}
```

### 设计令牌（CSS 变量）

对于高级的全局自定义，您可以覆盖定义主题的 CSS 变量。这些变量为亮色模式 (`:root`) 和暗色模式 (`[data-theme='dark']`) 都进行了定义。

以下是您可以作为目标的一些关键变量：

```css src/theme/index.css icon=logos:css-3
:root {
  /* 亮色主题 */
  --backgrounds-bg-base: #ffffff;
  --backgrounds-bg-interactive: #3b82f6;
  --foregrounds-fg-base: #030712;
  --foregrounds-fg-interactive: #3b82f6;
  --stroke-border-base: #eff1f5;
  --radius-m: 0.5rem; /* 8px */
}

[data-theme='dark'] {
  /* 暗色主题 */
  --backgrounds-bg-base: #1b1b1f;
  --backgrounds-bg-interactive: #60a5fa;
  --foregrounds-fg-base: #edeef0;
  --foregrounds-fg-interactive: #60a5fa;
  --stroke-border-base: #2e3035;
  --radius-m: 0.5rem;
}
```

在您的全局样式表中覆盖这些变量，将会把更改应用到所有 `@blocklet/payment-react` 组件。

### 排版

默认的排版设置可以在 `src/theme/typography.ts` 中找到。您可以在您的自定义主题中覆盖任何这些设置，以匹配您应用程序的排版。

```ts src/theme/typography.ts icon=mdi:language-typescript
export const typography = {
  h1: {
    fontSize: '1.5rem',
    lineHeight: 1.2,
    fontWeight: 800,
  },
  body1: {
    fontSize: '0.875rem',
    lineHeight: 1.75,
  },
  // ... 其他排版设置
};
```

通过理解这些自定义层次，您可以将支付组件无缝集成到您的应用程序中，并实现一致且精致的设计。

---

接下来，探索各种可以帮助您完成数据缓存和日期格式化等任务的实用工具函数。

<x-card data-title="下一步：实用工具" data-icon="lucide:wrench" data-href="/guides/utilities" data-cta="阅读更多">
  该库提供的实用工具函数参考，包括缓存请求和日期格式化。
</x-card>