- 前端
- CMS
【免费下载链接】wp-calypso
The JavaScript and API powered WordPress.com
导读
本指南围绕 wp-calypso 仓库中的@automattic/privacy-toolset包展开,它是一组以 React 组件形态封装的隐私机制工具库,用于在 Automattic 各产品(如 WordPress.com、Jetpack 生态)中统一 Cookie 同意授权与「不出售/不共享我的数据」偏好设置的交互体验。读完本文,你将掌握该包的安装与样式接入方式、CookieBanner(简单同意 + 自定义分桶同意两级视图)与DoNotSellDialog(可选退出弹窗)的完整 Props 契约与数据建模、从源码到测试的底层实现细节,以及如何在 wp-calypso monorepo 中运行其单元测试与 Storybook 开发环境。
包概览:一套组件统一隐私机制
packages/privacy-toolset/是 wp-calypso monorepo 中发布到 npm 的独立包,当前版本 2.2.0(见 package.json)。包名与描述为 "Privacy tools and components for Automattic solutions.",定位非常明确:把隐私相关交互沉淀为可复用、可配置、可主题化的 React 组件,避免各产品各自为政地重复实现 Cookie 弹窗与数据出售偏好设置。
从入口文件 src/index.ts 可以看到,包对外只导出两类能力,恰好对应两种最核心的隐私交互场景:
CookieBanner(类型CookieBannerProps):Cookie 同意授权横幅;DoNotSellDialog(类型DoNotSellDialogProps):面向「Do Not Sell / Do Not Share」合规要求的偏好设置弹窗。
包的工程形态:main指向dist/cjs/index.js,module指向dist/esm/index.js,同时通过exports字段为 Calypso 内部提供calypso:src(直接引用src/index.ts源码)入口,其余消费方则按标准import/require消费构建产物。sideEffects声明了*.css与*.scss,说明样式由组件自行引入。
安装与样式接入
1. 安装工具集
yarn add @automattic/privacy-toolset2. 引入wp-components样式表
许多组件依赖样式才能正确渲染。接入方式取决于宿主环境:
- WordPress 插件内:将
wp-components样式表声明为插件样式表的依赖项,例如在wp_enqueue_style()调用时通过 dependencies 参数指定,这样 WordPress 会保证组件样式先于插件样式加载; - 非 WordPress 项目:直接链接
node_modules/@wordpress/components/build-style/style.css文件。
这条要求的根源在于:包内部大量复用了@wordpress/components的 UI 原语(如FormToggle开关),这些原语的样式正是从wp-components样式表获得。从 package.json 的dependencies可以看到@wordpress/components: ^37.0.0,同时依赖clsx、react-modal与tslib。
3. 环境约束
包的peerDependencies声明了react: ^18.3.1 || ^19.0.0与react-dom: ^18.3.1 || ^19.0.0,即要求宿主项目提供 React 18.3+ 或 19 运行时,这是使用前需要核对的重要前提。
CookieBanner:两级视图的同意授权横幅
最小用法
import { CookieBanner } from '@automattic/privacy-toolset'; const Component = () => ( <> <CookieBanner content={ contentDefinition } onAccept={ fn } /> </> );CookieBanner只有两个 Props:
| Props | 类型 | 说明 |
|---|---|---|
content | { simpleConsent: SimpleConsentContent; customizedConsent: CustomizedConsentContent } | 两级视图的文案与分类定义 |
onAccept | ( buckets: Buckets ) => void | 用户在任意一级视图做出决定后触发的回调,参数为最终同意的分桶结果 |
从源码看两级视图切换机制
组件内部通过useState维护一个ConsentViewType枚举(Simple/Customized),初始为简单视图。用户点击「Customize」时切换到自定义视图(见 index.tsx):
const handleAcceptAll = useCallback( () => { onAccept( allBucketsTrue ); }, [ onAccept ] ); const handleDeclineNonEssentials = useCallback( () => { onAccept( essentialOnly ); }, [ onAccept ] );- 点击Accept All→
onAccept( allBucketsTrue ); - 点击Decline Non-Essential(可选按钮)→
onAccept( essentialOnly ); - 点击Customize→ 切换视图,在自定义视图中点击「Accept Selection」→
onAccept( 当前分桶状态 )。
数据模型:Buckets 分桶
三个预设分桶常量定义在 consts.ts:
export const allBucketsTrue: Buckets = { essential: true, analytics: true, advertising: true, }; export const essentialOnly: Buckets = { essential: true, analytics: false, advertising: false, }; export const defaultBuckets: Buckets = { essential: true, analytics: true, advertising: false, };Buckets由三个布尔字段组成:essential(必要)、analytics(分析)、advertising(广告)。值得注意的设计细节:默认分桶状态(defaultBuckets)是「必要 + 分析开启、广告关闭」——即既比"全接受"克制,又比"仅必要"激进,这是自定义视图的初始态。
简单视图(SimpleConsent)的文案契约
export type SimpleConsentContent = { description: LongText; // 长文案,支持 ReactNode customizeButton: ShortText; // 「Customize」按钮文案 acceptAllButton: ShortText; // 「Accept All」按钮文案 declineNonEssentialButton?: ShortText; // 可选:是否渲染「Decline Non-Essential」按钮 };从 simple-consent.tsx 源码可确认:declineNonEssentialButton是否传入会直接影响 DOM 结构——按钮区会追加cookie-banner__simple-options-non-essential类,并额外渲染一个拒绝非必要 Cookie 的按钮。因此,若合规文案中不需要"仅拒绝非必要"的快捷入口,省略该字段即可自动隐藏按钮。
自定义视图(CustomizedConsent)的文案契约
export type CustomizedConsentContent = { description: LongText; // 引导文案 categories: Record< keyof Buckets, GranularConsentContent >; // 三个分桶各自的名称与描述 acceptSelectionButton: ShortText; // 「Accept Selection」按钮文案 }; type GranularConsentContent = { name: ShortText; // 分类名,如 "Required" / "Analytics" / "Advertising" description: LongText; };自定义视图的初始开关状态取自defaultBuckets,用户切换某个分桶后通过handleChangeBucket更新状态(见 customized-consent.tsx)。其中essential分桶的开关以disabled状态渲染——必要型 Cookie 不可关闭,这是隐私合规的常见要求,也保证了Buckets.essential恒为 true 的不变量。
每个分桶的开关复用@wordpress/components的FormToggle,并带有aria-labelledby与data-testid(格式为`${name}-bucket-toggle`),后者方便测试按analytics-bucket-toggle等定位(见 granular-consent.tsx)。
content 参数的完整示例
README 明确指出:content参数的详细结构以 cookie-banner.stories.tsx 为准。其Defaultstory 给出了完整可运行的结构(含 "Accept all"、"Customize" 两级文案与三个分类),Declinestory 则演示了追加declineNonEssentialButton: 'Decline Non-Essential Cookies'的三按钮形态。实际接入时只需将 story 中的占位文案替换为真实的多语言文案即可。
DoNotSellDialog:「不出售/不共享我的数据」偏好弹窗
第二个组件面向 CCPA 等法规中的 "Do Not Sell or Share My Data" 场景,底层使用react-modal实现,对外暴露可控状态(index.tsx):
export type DoNotSellDialogProps = { content: { title: string; // 弹窗标题 longDescription: React.ReactNode; // 长说明文案 toggleLabel: string; // 开关标签 closeButton: string; // 关闭按钮文案 }; isOpen: boolean; // 受控:是否打开 onClose: () => void; // 关闭回调 isActive?: boolean; // 当前偏好是否生效 onToggleActive: ( isActive: boolean ) => void; // 切换偏好 modalProps?: Omit< ModalProps, 'className' | 'overlayClassName' | 'aria' | 'onRequestClose' | 'isOpen' | 'children' >; // 透传 react-modal 其余选项 };源码细节说明:
- 组件是完全受控的:
isOpen/isActive由父组件传入,交互结果通过onClose/onToggleActive回传,方便业务侧与持久化层(如用户偏好存储)对接; - 无障碍方面,
react-modal的aria配置了modal: true、labelledby: 'do-not-sell-title'、describedby: 'do-not-sell-description',标题与正文分别挂上对应 id; modalProps采用 Omit 类型,锁定内部必须控制的 Modal 属性,只允许透传如appElement、shouldCloseOnOverlayClick等其余配置;- 偏好开关同样是
@wordpress/components的FormToggle,配合do-not-sell__preference标签渲染。
其 Storybook 示例(do-not-sell-dialog.stories.tsx)演示了标准的受控用法:父组件用useState持有isActive,将setActive作为onToggleActive传入,并以isOpen固定为 true 展示弹窗内容。
在 wp-calypso monorepo 中开发与测试
该包在 Calypso monorepo 内开发,仓库根目录执行yarn即可拉取全部devDependencies(含@automattic/calypso-build、@automattic/calypso-storybook、@testing-library/react、storybook、typescript等)。
单元测试
yarn run test-packages -- packages/privacy-toolset yarn run test-packages:watch -- packages/privacy-toolset测试源码位于组件同级的test/目录:cookie-banner与do-not-sell-dialog各有一套基于@testing-library的用例及快照(__snapshots__/*.tsx.snap)。快照文件记录了渲染出的 DOM 结构,可作为组件输出稳定性的回归依据;测试文件(如 cookie-banner.tsx)可用来验证"点击 Accept All 触发allBucketsTrue回调""essential 开关 disabled"等行为契约。
Storybook 开发环境
yarn workspace @automattic/privacy-toolset run storybook:start该命令对应 package.json 中的storybook dev -p 26840,会以26840 端口启动本地 Storybook。两个组件均有 story 文件:Cookie Banner包含Default/Decline两个 story,Do Not Sell Dialog包含Defaultstory,是调试文案、验证布局与演示组件行为的最直接入口。
构建与发布
yarn run build:通过tsc --build ./tsconfig.json ./tsconfig-cjs.json生成 ESM/CJS/类型声明,并执行copy-assets复制样式资源;yarn run prepack:发布前先clean(清理 dist)再build;yarn run watch:TS 增量编译,便于边改边看。
总结:在自身产品中落地的要点
- 两条集成前提缺一不可:
yarn add @automattic/privacy-toolset后,务必按宿主环境接入wp-components样式表(WordPress 插件走wp_enqueue_style依赖声明,其他项目直接 linkbuild-style/style.css),并确保 React 版本满足^18.3.1 || ^19.0.0; - CookieBanner 的接入成本集中在 content 上:按
simpleConsent/customizedConsent两级结构补齐文案与三分类描述,onAccept中收到的Buckets(essential/analytics/advertising)即可映射到你的 Cookie 存储与埋点开关; - DoNotSellDialog 走完全受控模式:由业务侧管理
isOpen/isActive,通过onToggleActive持久化用户偏好,modalProps可透传react-modal的补充配置; - 迭代与验证闭环:单测(
test-packages -- packages/privacy-toolset)与 Storybook(端口 26840)覆盖了从行为契约到视觉呈现的完整开发回路,是所有接入场景的可靠参照。
- 前端
- CMS
【免费下载链接】wp-calypso
The JavaScript and API powered WordPress.com
相关推荐
wp-calypso privacy-toolset 隐私组件包:从 CHANGELOG 追溯 Cookie 同意横幅与 Do-Not-Sell 对话框的完整演进
wp calypso privacy toolset 隐私组件包:从 CHANGELOG 追溯 Cookie 同意横幅与 Do Not Sell 对话框的完整演
前端CMSwp-calypso 组件库 ListTile 实战指南:用 @automattic/components 构建统一风格列表行
wp calypso 组件库 ListTile 实战指南:用 @automattic/components 构建统一风格列表行 ListTile 是 wp ca
前端CMSwp-calypso 中的 @automattic/calypso-jest:统一 Jest 预设与资源转换实战指南
wp calypso 中的 @automattic/calypso jest:统一 Jest 预设与资源转换实战指南 本指南围绕 wp calypso 仓库中的
前端CMS
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考