
ui-ux-pro-max-skill 中的 shadcn/ui 无障碍模式实战从 Radix 原语到 WCAG 测试闭环【免费下载链接】ui-ux-pro-max-skillAn AI skill that provides design intelligence for building professional UI/UX across multiple platforms.项目地址: https://gitcode.com/gh_mirrors/ui/ui-ux-pro-max-skill本文基于 ui-ux-pro-max-skill 仓库中ui-styling技能的可访问性参考文档系统讲解 shadcn/ui 组件体系的无障碍实现模式Radix UI 原语如何提供键盘导航与屏幕阅读器支持、表单如何正确关联标签与错误信息、以及颜色对比度、焦点指示、减弱动效等 WCAG 要求的落地写法。读完后你可以直接按文档中的代码模式编写 Dialog、表单、Tabs 等可访问组件并套用仓库内的测试清单与 axe-core 自动化方案完成验收。该文档位于 shadcn-accessibility.md是 ui-styling 技能入口 SKILL.md 的三篇核心参考之一另两篇是组件目录与主题定制并被 Accessibility Patterns 章节明确引用用于指导 AI Agent 在生成 React shadcn/ui 界面时遵循 ARIA 模式、键盘导航与屏幕阅读器支持。仓库中还存在一份与之完全一致的同步副本 cli/assets/skills/ui-styling/references/shadcn-accessibility.md供 CLI 发布资产使用。基础Radix UI 原语文档开篇指出一个核心前提shadcn/ui 构建在 Radix UI 原语之上这些原语是无样式的、遵循 WAI-ARIA 设计模式的可访问组件。这一设计决策为开发者带来了五项开箱即得的能力内建的键盘导航屏幕阅读器播报焦点管理自动应用的 ARIA 属性针对无障碍标准的测试验证。这意味着在 shadcn/ui 生态中编写无障碍界面时大部分 ARIA 属性如aria-expanded、aria-controls、role等由原语层自动处理开发者只需关注语义结构与可见焦点等外层问题。ui-styling 技能的 SKILL.md 也把这一点列为组件层的核心特性Pre-built accessible components via Radix UI primitives。前置条件是完成 shadcn/ui 初始化。参考 shadcn-components.md 的安装说明npx shadcnlatest add button npx shadcnlatest add button card dialog # 批量添加 npx shadcnlatest add --all # 添加全部组件组件会安装到components/ui/目录并自动处理依赖。仓库内还附带了一个 Python 封装脚本 shadcn_add.py它先检查项目根目录是否存在components.json即 shadcn 是否初始化再读取package.json中锁定的 shadcn 版本找不到时回退到内置的2.3.0默认值最后拼装并执行npx shadcnversion add components命令。其 CLI 用法与参数如下# 添加单个组件 python shadcn_add.py button # 批量添加 python shadcn_add.py button card dialog # 添加全部组件 python shadcn_add.py --all # 覆盖已存在组件 python shadcn_add.py button --overwrite # 仅预览将执行的命令 python shadcn_add.py button card --dry-run # 列出已安装组件 python shadcn_add.py --list从 shadcn_add.py 的参数定义看--list、--all、--overwrite、--dry-run、--project-root均为可选参数脚本对未初始化组件已存在npx 缺失等失败路径都返回明确错误信息与退出码适合作为 Agent 的幂等安装手段。键盘导航焦点管理可见焦点状态。键盘用户依赖focus-visible变体区分鼠标点击与键盘聚焦。文档给出的标准写法Button classNamefocus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 Accessible Button /Button跳转链接Skip to content。这是键盘用户快速越过重复导航的关键模式a href#main-content classNamesr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:px-4 focus:py-2 Skip to content /a main idmain-content {/* Content */} /main链接平时被sr-only隐藏键盘 Tab 聚焦时才通过focus:not-sr-only显示出来。仓库数据层的 ux-guidelines.csv 中 Skip Links 条目第 45 行同样将其列为 Medium 严重性要求Allow keyboard users to skip navigation反面案例是100 次 Tab 才能到达内容。Dialog/Modal 导航Dialog 通过 Radix Dialog 原语自动实现焦点陷阱import { Dialog, DialogContent, DialogTrigger } from /components/ui/dialog Dialog DialogTriggerOpen/DialogTrigger DialogContent {/* Focus trapped here */} input / {/* Auto-focused */} ButtonAction/Button {/* Esc to close, Tab to navigate */} /DialogContent /Dialog其行为特性包括焦点被锁定在对话框内、Esc键关闭、Tab在可聚焦元素间循环、关闭后焦点自动返回触发元素。需要注意的是文档中这个最小示例只展示了焦点行为而在 ux-guidelines.csv 的 Dialog 相关条目第 13 行中Include proper dialog structure 被列为 High 严重性完整的 Dialog 必须包含DialogHeader、DialogTitle、DialogDescription缺 title 或 description 会被判为缺陷——屏幕阅读器正是依靠这两个元素来播报弹窗上下文。shadcn-components.md 的 Dialog 章节 给出的完整结构如下import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from /components/ui/dialog Dialog DialogTrigger asChild ButtonOpen/Button /DialogTrigger DialogContent DialogHeader DialogTitleAre you sure?/DialogTitle DialogDescriptionThis action cannot be undone./DialogDescription /DialogHeader /DialogContent /DialogDropdown/Menu 导航import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from /components/ui/dropdown-menu DropdownMenu DropdownMenuTriggerOpen/DropdownMenuTrigger DropdownMenuContent DropdownMenuItemProfile/DropdownMenuItem DropdownMenuItemSettings/DropdownMenuItem DropdownMenuItemLogout/DropdownMenuItem /DropdownMenuContent /DropdownMenu键盘快捷键约定按键行为Space/Enter打开菜单Arrow Up/Down在菜单项间移动Esc关闭菜单Tab关闭并将焦点移出Command Palette 导航Command 组件命令面板同样遵循完整的键盘模型import { Command } from /components/ui/command Command CommandInput placeholderSearch... / CommandList CommandGroup headingSuggestions CommandItemCalendar/CommandItem CommandItemSearch/CommandItem /CommandGroup /CommandList /Command特性输入即过滤type to filter、方向键导航、Enter选择、Esc关闭。仓库的 ux-guidelines.csv 第 22-23 行还补充了两条相关约定使用 Command 承载搜索与可搜索列表而非Input加自定义下拉以及用CommandGroup的heading为条目分组。屏幕阅读器支持语义化 HTML优先使用原生 HTML 元素而不是div 汤// Good: Semantic HTML buttonClick me/button nava href/Home/a/nav // Avoid: Div soup div onClick{handler}Click me/divux-guidelines.csv 中 Screen Reader 条目第 43 行与之一致正确内容在被朗读时应语义完整正面案例是nav、main、article等结构化标签。ARIA 标签为交互元素命名。图标按钮必须通过aria-label提供可访问名称Button aria-labelClose dialog X classNameh-4 w-4 / /Button Input aria-labelEmail address typeemail /描述元素。当可见文本不足以传达后果时用aria-describedby关联补充说明Button aria-describedbydelete-description Delete Account /Button p iddelete-description classNamesr-only This action permanently deletes your account and cannot be undone /pux-guidelines.csv第 41 行将 ARIA Labels 定为 High 严重性Add aria-label for icon-only buttons并明确反面模式是无标签的buttonIcon//button。仅屏幕阅读器可见的文本对纯图标按钮用sr-only类内嵌辅助文本比aria-label更贴近 DOM 语义Button Trash classNameh-4 w-4 / span classNamesr-onlyDelete item/span /Button // CSS for sr-only .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; }其原理是把元素压缩到 1px 并裁剪切出视口使其对视觉用户不可见但保留在可访问性树中。实时区域Live Regions动态内容变更需要主动播报。aria-livepolite会在用户空闲时插入播报aria-atomictrue保证整块区域被完整读出紧急更新如错误使用assertivediv aria-livepolite aria-atomictrue {message} /div // For urgent updates div aria-liveassertive {error} /divshadcn/ui 的 Toast 组件内部已包含 live region因此toast()发出的通知会自动播报const { toast } useToast() toast({ title: Success, description: Profile updated }) // Announced to screen readers automatically仓库数据层对错误播报的要求ux-guidelines.csv 第 44 行High 严重性是Use aria-live or rolealert for errors仅靠红色边框这类视觉指示是不及格的。表单无障碍标签与描述输入框必须有标签。Label的htmlFor与Input的id必须配对import { Label } from /components/ui/label import { Input } from /components/ui/input div Label htmlForemailEmail/Label Input idemail typeemail / /div在 Form 场景中加入描述信息import { FormDescription, FormMessage } from /components/ui/form FormItem FormLabelUsername/FormLabel FormControl Input {...field} / /FormControl FormDescription Your public display name /FormDescription FormMessage / {/* Error messages */} /FormItem错误处理校验失败时错误不仅要可见还要被屏幕阅读器关联到出错的字段。核心是三个 ARIA 属性的组合aria-invalid标记状态、aria-describedby指向错误信息节点、FormMessage携带对应idFormField control{form.control} nameemail render{({ field, fieldState }) ( FormItem FormLabelEmail/FormLabel FormControl Input {...field} aria-invalid{!!fieldState.error} aria-describedby{fieldState.error ? email-error : undefined} / /FormControl FormMessage idemail-error / /FormItem )} /SKILL.md 的 Common Patterns 章节 还给出了配套的完整表单骨架react-hook-formzodResolver做 schema 校验z.object({ email: z.string().email(), password: z.string().min(8) })再包进Form {...form}与FormField。ux-guidelines.csv第 110 行第 109 号条目High 严重性进一步给出进阶要求表单整体校验失败时应在顶部提供错误摘要error summary提交失败后将焦点移动到摘要标题并为每条错误提供指向对应字段的链接——这比仅显示 toast 更利于键盘与屏幕阅读器用户。必填字段用可见星号加sr-only文本双通道传达必填Label htmlForname Name span classNametext-destructive*/span span classNamesr-only(required)/span /Label Input idname required /视觉用户看到红色星号屏幕阅读器读到 (required)。Fieldset 与 Legend用fieldset/legend对一组相关字段进行语义分组fieldset legend classNametext-lg font-semibold mb-4 Contact Information /legend div classNamespace-y-4 FormField nameemail / FormField namephone / /div /fieldset这是 WAI-ARIA 之外的原生 HTML 分组方案屏幕阅读器会在进入该组时先朗读legend内容。组件专项模式以下五个组件的模式覆盖了自动 ARIA 属性由 Radix 原语提供这一主题的典型验证Accordionimport { Accordion } from /components/ui/accordion Accordion typesingle collapsible AccordionItem valueitem-1 AccordionTrigger {/* Includes aria-expanded, aria-controls automatically */} Is it accessible? /AccordionTrigger AccordionContent {/* Hidden when collapsed, announced when expanded */} Yes. Follows WAI-ARIA design pattern. /AccordionContent /AccordionItem /AccordionAccordionTrigger自动携带aria-expanded与aria-controlsAccordionContent在折叠时对辅助技术隐藏、展开后参与播报。Tabsimport { Tabs } from /components/ui/tabs Tabs defaultValueaccount TabsList roletablist {/* Arrow keys navigate, Space/Enter activates */} TabsTrigger valueaccountAccount/TabsTrigger TabsTrigger valuepasswordPassword/TabsTrigger /TabsList TabsContent valueaccount {/* Hidden unless selected, aria-labelledby links to trigger */} Account content /TabsContent /Tabs键盘模型为方向键在标签间移动Space/Enter激活TabsContent未选中时不进入可访问性树且通过aria-labelledby关联到对应 trigger。Selectimport { Select } from /components/ui/select Select SelectTrigger aria-labelChoose theme SelectValue placeholderTheme / /SelectTrigger SelectContent {/* Keyboard navigable, announced to screen readers */} SelectItem valuelightLight/SelectItem SelectItem valuedarkDark/SelectItem /SelectContent /Select下拉内容可键盘导航并向屏幕阅读器播报。ux-guidelines.csv 第 21 行强调 Select 的完整结构SelectTriggerSelectValueSelectContentSelectItem缺SelectValue或SelectContent属于 High 严重性缺陷。Checkbox 与 Radioimport { Checkbox } from /components/ui/checkbox import { Label } from /components/ui/label div classNameflex items-center space-x-2 Checkbox idterms aria-describedbyterms-description / Label htmlFortermsAccept terms/Label /div p idterms-description classNametext-sm text-muted-foreground You agree to our Terms of Service and Privacy Policy /p注意这里把法律含义放在可见的aria-describedby关联段落中——这比把条款塞进placeholder更稳妥。Radio Group 的标准结构RadioGroupItem配id、Label配htmlFor、defaultValue在RadioGroup上见 shadcn-components.md。Alertimport { Alert } from /components/ui/alert Alert rolealert {/* Announced immediately to screen readers */} AlertTitleError/AlertTitle AlertDescription Your session has expired /AlertDescription /Alertrolealert等价于aria-liveassertivearia-atomictrue内容一旦挂载即被立即播报适合会话过期这类紧急通知。颜色对比度文档给出的 WCAG 门槛AA正文 4.5:1大文本 3:1AAA正文 7:1大文本 4.5:1。默认写法检查// Good: High contrast p classNametext-gray-900 dark:text-gray-100Text/p // Avoid: Low contrast p classNametext-gray-400 dark:text-gray-600Hard to read/p次要文本应使用语义化的 muted foreground 变量而不是任意灰色// Use semantic muted foreground p classNametext-muted-foreground Secondary text with accessible contrast /p这与 shadcn-theming.md 的 CSS 变量体系呼应muted/muted-foreground是一组语义 token在:root与.dark下分别取值。仓库的 ux-guidelines.csv 中 Color Contrast 条目High 严重性给出了量化参照#333on white 约 7:1 合格#999on white 仅 2.8:1 不合格。同一文件还有 Color Only 条目不要用颜色单独传达信息错误状态应为红色文本 错误图标而非仅红边框。焦点指示器原则是永远提供可见焦点指示器并优先使用focus-visible:变体默认焦点环Button classNamefocus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 Button /Button自定义焦点样式a href# classNamefocus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:underline Link /a不要移除焦点样式// Avoid button classNamefocus:outline-noneBad/button // Use focus-visible instead button classNamefocus-visible:ring-2Good/button仓库的 ux-guidelines.csv 为此补充了两条 WCAG 2.2 级别的量化要求Focus Not ObscuredAAHigh 严重性——键盘焦点必须至少部分可见sticky 头部需要用scroll-padding偏移避免fixed浮层完全覆盖焦点Focus AppearanceAAAMedium——焦点指示器至少 2 CSS px 周长、与周围有 3:1 状态对比度参考写法是outline: 2px solid currentColor; outline-offset: 2px而低对比度的 1pxbox-shadow是反面案例。动效与减弱动效偏好尊重系统级prefers-reduced-motion设置。全局兜底media (prefers-reduced-motion: reduce) { * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } }组件级则用 Tailwind 的motion-reduce:变体div classNametransition-all motion-reduce:transition-none Respects user preference /divux-guidelines.csv 中 Motion Sensitivity 条目High 严重性进一步指出视差滚动、scroll-jacking 会造成眩晕感正确做法是尊重prefers-reduced-motion并直接呈现最终可读状态而不是在减弱模式下保留简化版视差。测试清单与自动化工具文档给出的验收清单14 项所有交互元素可键盘访问焦点指示器可见屏幕阅读器能正确播报所有内容表单错误被播报且已关联到字段颜色对比度满足 WCAG AA使用语义化 HTML图标按钮提供 ARIA 标签模态/对话框焦点陷阱生效下拉/Select 可键盘导航Live region 播报动态更新尊重减弱动效偏好浏览器缩放至 200% 仍可用Tab 顺序符合逻辑提供跳转导航的 Skip 链接配套工具链分两类手动/工具测试Lighthouse 无障碍审计、axe DevTools 浏览器扩展、NVDA/JAWS 屏幕阅读器、纯键盘导航测试、对比度检测工具如 WebAIM Contrast Checker。开发期自动化安装axe-core/react后仅在开发环境按固定间隔扫描渲染树npm install -D axe-core/reactimport { useEffect } from react if (process.env.NODE_ENV development) { import(axe-core/react).then((axe) { axe.default(React, ReactDOM, 1000) }) }第三个参数1000是扫描间隔毫秒。该模式把 a11y 缺陷的反馈周期从上线前审计压缩到开发时实时告警与前述的 Radix 原语 ARIA 模式构成生成即合规的闭环原语保证交互层语义本文模式保证应用层语义axe-core 在开发期兜底。与仓库其他资源的衔接本文所有组件 APIDialog、Accordion、Tabs、Select、Form 等的完整用法与变体取值见 shadcn-components.mdmuted-foreground、ring等语义颜色变量的定义与深色模式实现见 shadcn-theming.md仓库数据层的 ux-guidelines.csv 以条目 Do/Dont 严重性格式维护了 100 余条跨技术栈的 UX/无障碍准则其中 Accessibility 分类条目对比度、aria-label、键盘导航、表单标签、错误播报、Skip 链接、目标尺寸 24px、焦点不可被遮挡等可作为本文清单之外的通用扩展参考组件安装环节可通过 shadcn_add.py 的--dry-run/--list参数在改动前预演与核对确保先npx shadcnlatest init再 add的初始化顺序不被跳过脚本在未检测到components.json时会直接报错退出。综上这份参考文档的价值在于把shadcn/ui 是可访问的这一笼统结论拆成了可执行的五层模式Radix 原语交互层、键盘与焦点管理导航层、ARIA 与 live region播报层、表单语义数据层、对比度/动效/测试验收层并全部给出了可直接复制的 TSX 代码与 Tailwind 类名。【免费下载链接】ui-ux-pro-max-skillAn AI skill that provides design intelligence for building professional UI/UX across multiple platforms.项目地址: https://gitcode.com/gh_mirrors/ui/ui-ux-pro-max-skill创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考