关于 migrating-to-westpac-ui-v1
供现有 @westpac/ui 用户迁移到 v1.0 的指南,面向维护旧版应用的开发者。它整理了依赖、Tailwind CSS、设计令牌和组件 API 的破坏性变更,并说明令牌迁移工具的用法。
主要功能
- 01升级 Tailwind CSS 至 v4
- 02安装新的样式配置包
- 03运行令牌迁移 codemod
- 04更新导入路径与品牌属性
- 05调整组件 API 用法
适用场景
- 01将旧版 @westpac/ui 应用升级至 v1.0
- 02批量迁移颜色令牌
- 03修复升级后的组件调用
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ westpacgel/ gel-next --skill migrating-to-westpac-ui-v1安装后在 Claude Code 中输入/migrating-to-westpac-ui-v1确认已加载。
详细介绍
迁移到 @westpac/ui v1.0
本指南介绍如何将现有应用从 v1.0 之前的 @westpac/ui 迁移到 v1.0。对于全新安装,请改用 installing-westpac-ui 技能。
何时使用
当用户正在使用旧版本的 @westpac/ui(检查 package.json),并希望升级到 v1.0 时,请参考本指南。内容包括了解主要的破坏性变更、运行令牌 codemod、更新 Tailwind CSS 配置以及修复组件 API 变更。
v0.x 的主要变更
v1.0 引入了全新架构,将 UI 组件与样式配置分离:
@westpac/style-config是新增的必需软件包,提供:- Tailwind 令牌
- 浅色/深色主题
- CSS + W3C 设计令牌
- Tailwind CSS 从 v3 升级到 v4
- 所有颜色令牌均已重命名,以支持多品牌 + 双主题
步骤
- 将 Tailwind CSS 升级到 v4
移除现有的 tailwind.config.js,并按照 Tailwind CSS v4 升级指南 操作。如果自动升级命令无法运行,请按照该页面上的手动说明操作。
- 安装更新后的依赖项
npm i @westpac/ui @westpac/style-config tailwindcss@4 postcss tailwind-variants@~3.1.1
- 更新 CSS 导入
将现有的 Tailwind/GEL CSS 设置替换为:
@import 'tailwindcss';
@import '@westpac/style-config/tailwind';
/* Import brand themes you need: */
@import '@westpac/style-config/themes/wbc';
@import '@westpac/style-config/themes/stg';
@import '@westpac/style-config/themes/bom';
@import '@westpac/style-config/themes/bsa';
/* Brand font @font-face declarations (update paths to your font files) */
/* WBC fonts */
@font-face {
src:
url('/fonts/Westpac-Bold-v2.007.woff2') format('woff2'),
url('/fonts/Westpac-Bold-v2.007.woff') format('woff');
font-family: 'Westpac';
font-weight: 100 900;
font-style: normal;
}
/* STG fonts */
@font-face {
src:
url('/fonts/dragonbold-bold-webfont.woff2') format('woff2'),
url('/fonts/dragonbold-bold-webfont.woff') format('woff');
font-family: 'Dragon Bold';
font-weight: 100 900;
font-style: normal;
}
- 更新品牌属性
品牌属性已从 data-theme 更改为 data-brand:
之前
<html data-theme="wbc"></html>
之后
<html data-brand="wbc" data-theme="light"></html>
注意: 此版本已禁用深色模式(
data-theme="dark")。
- 更新 ESLint 配置(使用 @westpac/eslint-config 时可选)
// eslint.config.mjs
import eslintConfig from '@westpac/eslint-config/nextjs';
import { defineConfig } from 'eslint/config';
export default defineConfig([
...eslintConfig,
{
settings: {
'better-tailwindcss': {
entryPoint: 'src/globals.css',
},
},
},
]);
- 运行令牌 codemod
# Install jscodeshift if needed
npm install -g jscodeshift
# Run the codemod against your source files
npx jscodeshift --parser=tsx -t node_modules/@westpac/ui/scripts/codemods/gel-tokens-tailwind-v1.cjs <path>/**/*.tsx
变更参考
- 令牌更新
- 1.1 更新示例
- 1.2 运行令牌 codemod
- 导入路径变更
- 2.1 样式常量
- 组件 API 变更
- 3.1 Accordion
- 3.2 ButtonGroup
- 3.3 DatePicker
- 3.4 Compacta
- 3.5 Repeater
- 3.6 BottomSheet
- 3.7 Pictogram
- 已弃用的组件和 API
- 表单迁移示例
- 已移除的符号和标志
- 6.1 标志
- 6.2 符号
1. 令牌更新
所有颜色令牌均已重命名,以支持多品牌 + 双主题系统。这是最大的变更,会影响代码库中的所有自定义 Tailwind 类。
1.1 更新示例
之前
<div className="bg-white">
<div className="bg-primary rounded-full">
<AccountIcon color="white" />
</div>
<h2 className="text-text">
My title
<BankIcon color="link" className="ml-2" />
</h2>
<p className="text-text">Lorem ipsum dolor sit amet</p>
</div>
之后
<div className="bg-background-white">
<div className="bg-surface-primary rounded-full">
<AccountIcon color="mono" />
</div>
<h2 className="text-text-body">
My title
<BankIcon color="primary" className="ml-2" />
</h2>
<p className="text-text-body">Lorem ipsum dolor sit amet</p>
</div>
1.2 运行令牌 codemod
提供了 codemod,用于自动迁移令牌:
# Install jscodeshift if needed
npm install -g jscodeshift
# Run the codemod against your source files
npx jscodeshift --parser=tsx -t node_modules/@westpac/ui/scripts/codemods/gel-tokens-tailwind-v1.cjs <path>/**/*.tsx
重要说明:
--parser参数可能需要根据项目使用babel、flow、ts或tsx- 根据项目结构,可能需要多次运行 codemod
- 对于无法自动映射的类,codemod 会注入
[REPLACE_TOKEN]——请与设计师合作,将其替换为正确的令牌 - 作为临时措施,可以将未知令牌替换为相近的值或十六进制值(例如,
text-black→text-[#000])
codemod 脚本源文件:gel-tokens-tailwind-v1.cjs
2. 导入路径变更
2.1 样式常量
之前
import { BREAKPOINTS, SPACING_UNIT } from '@westpac/ui/theme-constants';
之后
import { BREAKPOINTS, SPACING_UNIT } from '@westpac/style-config/constants';
3. 组件 API 变更
3.1 Accordion — 使用 react-aria useDisclose
defaultExpandedKeys 现在使用 AccordionItem 的 id 值:
之前
<Accordion defaultExpandedKeys={['FoR']}>
<AccordionItem title="Founding of Rome">Content</AccordionItem>
</Accordion>
之后
<Accordion defaultExpandedKeys={['FoR']}>
<AccordionItem id="FoR" title="Founding of Rome">
Content
</AccordionItem>
</Accordion>
3.2 ButtonGroup — 组合式 API
之前
<ButtonGroup
value={value}
buttons={[
{ value: 'Left', label: 'Left' },
{ value: 'Middle', label: 'Middle' },
{ value: 'Right', label: 'Right' },
]}
/>
之后
<ButtonGroup selectedKeys={value}>
<ButtonGroupButton id="Left">Left</ButtonGroupButton>
<ButtonGroupButton id="Middle">Middle</ButtonGroupButton>
<ButtonGroupButton id="Right">Right</ButtonGroupButton>
</ButtonGroup>
3.3 DatePicker — 基于 react-aria
disableDates 属性已由 isDateUnavailable 函数取代:
之前
<DatePicker disableDates={['2023-10-10']} />
之后
import { DateValue } from '@internationalized/date';
const disableDates = ['2023-10-20'];
const isDateUnavailable = (date: DateValue) => disableDates.some(d => d.toString() === date.toString());
<DatePicker isDateUnavailable={isDateUnavailable} />;
3.4 Compacta — 简化的 API
从 render-prop 模式改为使用 CompactaItem 的组合式子元素:
之前
<Compacta initialCompactas={[{ id: '1234', title: { primary: 'test' } }, {}]} onAdd={() => {}} onRemove={() => {}}>
{({ id, setPrimaryTitle }) => (
<Form>
<FormGroup>
<Label htmlFor={`primary-${id}`}>Primary</Label>
<Input name={`primary-${id}`} onChange={e => setPrimaryTitle(e.target.value)} />
</FormGroup>
</Form>
)}
</Compacta>
之后
<Compacta onAdd={handleAdd}>
{items.map((item, index) => (
<CompactaItem
key={index}
title={{ primary: item.primary, secondary: item.secondary, tertiary: item.tertiary }}
onRemove={() => removeItem(index)}
>
<Field label="Primary" hintMessage="Primary title text">
<Input {...register(`items.${index}.primary`)} />
</Field>
</CompactaItem>
))}
</Compacta>
3.5 Repeater — 与 Compacta 保持一致
变更模式与 Compacta 相同——使用 RepeaterItem 子元素:
之前
<Repeater>
<FormGroup>
<FormLabel htmlFor={`input${id}`}>Label</FormLabel>
<Input name={`input${id}`} />
</FormGroup>
</Repeater>
之后
<Repeater onAdd={handleAdd}>
{items.map((item, index) => (
<RepeaterItem key={index} title={{ primary: item.primary }} onRemove={() => removeItem(index)}>
<Field label="Label">
<Input {...register(`items.${index}.label`)} />
</Field>
</RepeaterItem>
))}
</Repeater>
3.6 BottomSheet — isDismissable 默认为 false
现在与 Modal 的行为保持一致:
之前
<BottomSheet title="Title">Content</BottomSheet>
之后
<BottomSheet title="Title" isDismissable>
Content
</BottomSheet>
3.7 Pictogram — mode 属性值已重命名
之前
type PictogramMode = 'dark' | 'light' | 'duo';
<Pictogram mode="dark" />;
之后
type PictogramMode = 'base' | 'mono' | 'duo';
<Pictogram mode="base" />;
4. 已弃用的组件和 API
| 已弃用 | 替代方案 / 备注 |
|---|---|
ButtonDropdown | 已由 Dropdown 替代 |
Form、FormGroup、FormChitChat、FormSection | 已移除 — 请使用带有 className="flex flex-col gap-4" 的 <form> 和 Field 组件 |
Pagination pages={[]} | 已移除 — 请改用 totalPages={number} |
5. 表单迁移示例
之前
<Form spacing="large" onSubmit={handleSubmit}>
<FormGroup>
<InputGroup size="large" label="Given name">
<Input {...register('givenName')} />
</InputGroup>
</FormGroup>
<FormGroup>
<Field label="Comments:">
<Textarea size="large" {...register('comment')} />
</Field>
</FormGroup>
</Form>
之后
<form className="flex flex-col gap-4" onSubmit={handleSubmit}>
<Field label="Given name">
<InputGroup size="large">
<Input {...register('givenName')} />
</InputGroup>
</Field>
<Field label="Comments:">
<Textarea size="large" {...register('comment')} />
</Field>
</form>
6. 已移除的符号和徽标
以下内容已移除。如果您认为移除有误,请联系 GEL 设计团队。
6.1 徽标
- BTPanormaMultibrandLargeLogo
- BTPanormaMultibrandSmallLogo
- RedAvatarCircleLogo
- RedAvatarCircleReverseLogo
- RedAvatarLogo
6.2 符号
- GooglePlusSymbol
- MastercardAcceptedSymbol
- MastercardHorizontalSymbol
- MicrosoftStoreSymbol
- PayToBlackSymbol
- PayToDarkGreySymbol
- PayToLightGreySymbol
- PayToWhiteSymbol
- PayToWordmarkBlackSymbol
- PayToWordmarkDarkGreySymbol
- PayToWordmarkLightGreySymbol
- PayToWordmarkWhiteSymbol
- SlackSymbol
- TwitterSymbol
- VisaSymbol
- XMarkInverseSymbol
- XMarkSymbol
- YammerSymbol