[{"data":1,"prerenderedAt":1574},["ShallowReactive",2],{"article-/topics/design/ai-assisted-design-tools-practice":3,"related-design":366,"content-query-pY2ZKYElDx":1308},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"topic":5,"author":11,"tags":12,"image":18,"imageQuery":19,"pexelsPhotoId":20,"pexelsUrl":21,"featured":6,"readingTime":22,"body":23,"_type":360,"_id":361,"_source":362,"_file":363,"_stem":364,"_extension":365},"/topics/design/ai-assisted-design-tools-practice","design",false,"","AI 辅助设计工具实践：从提效幻想走向真实可用的设计工作流","AI 设计工具的价值不在生成几张图，而在帮助团队加速探索、整理资产和减少重复劳动。本文从适用场景、风险边界和协作方式出发，讲清 AI 辅助设计工具的实践方法。","2026-04-25","HTMLPAGE 团队",[13,14,15,16,17],"AI Design Tools","Design Workflow","Productivity","Design System","Collaboration","/images/topics/design/ai-assisted-design-tools-practice.jpg","designer using ai tool interface on laptop",16094046,"https://www.pexels.com/photo/man-using-chatgpt-16094046/",14,{"type":24,"children":25,"toc":349},"root",[26,34,39,59,64,69,76,81,109,114,120,125,130,153,158,164,169,174,187,192,198,203,221,226,232,237,242,265,270,275,303,308,313,318],{"type":27,"tag":28,"props":29,"children":30},"element","p",{},[31],{"type":32,"value":33},"text","AI 辅助设计工具这两年发展很快，团队也越来越容易被它们吸引。",{"type":27,"tag":28,"props":35,"children":36},{},[37],{"type":32,"value":38},"原因很直接：",{"type":27,"tag":40,"props":41,"children":42},"ul",{},[43,49,54],{"type":27,"tag":44,"props":45,"children":46},"li",{},[47],{"type":32,"value":48},"能更快出草图",{"type":27,"tag":44,"props":50,"children":51},{},[52],{"type":32,"value":53},"能批量生成视觉变体",{"type":27,"tag":44,"props":55,"children":56},{},[57],{"type":32,"value":58},"能辅助整理组件和文案",{"type":27,"tag":28,"props":60,"children":61},{},[62],{"type":32,"value":63},"但真正落到设计工作流里，很多团队又会发现：工具是用了，效率却不一定稳定提升。",{"type":27,"tag":28,"props":65,"children":66},{},[67],{"type":32,"value":68},"问题不在 AI 没有能力，而在于团队没有明确它适合放在哪些环节。",{"type":27,"tag":70,"props":71,"children":73},"h2",{"id":72},"ai-更适合加速探索与整理不适合直接替代设计判断",[74],{"type":32,"value":75},"AI 更适合加速“探索与整理”，不适合直接替代设计判断",{"type":27,"tag":28,"props":77,"children":78},{},[79],{"type":32,"value":80},"设计工作里最适合 AI 介入的，通常不是最终定稿，而是这些环节：",{"type":27,"tag":40,"props":82,"children":83},{},[84,89,94,99,104],{"type":27,"tag":44,"props":85,"children":86},{},[87],{"type":32,"value":88},"概念发散",{"type":27,"tag":44,"props":90,"children":91},{},[92],{"type":32,"value":93},"变体生成",{"type":27,"tag":44,"props":95,"children":96},{},[97],{"type":32,"value":98},"文案整理",{"type":27,"tag":44,"props":100,"children":101},{},[102],{"type":32,"value":103},"设计资产归纳",{"type":27,"tag":44,"props":105,"children":106},{},[107],{"type":32,"value":108},"初步一致性检查",{"type":27,"tag":28,"props":110,"children":111},{},[112],{"type":32,"value":113},"AI 在这些地方能显著提效，因为它擅长快速产出候选项，但它并不天然理解品牌、业务优先级和复杂用户心智。",{"type":27,"tag":70,"props":115,"children":117},{"id":116},"把-ai-放进设计流程前先定义输入质量",[118],{"type":32,"value":119},"把 AI 放进设计流程前，先定义输入质量",{"type":27,"tag":28,"props":121,"children":122},{},[123],{"type":32,"value":124},"很多团队用 AI 设计工具效果不稳定，根因通常是输入过于随意。",{"type":27,"tag":28,"props":126,"children":127},{},[128],{"type":32,"value":129},"如果没有明确的：",{"type":27,"tag":40,"props":131,"children":132},{},[133,138,143,148],{"type":27,"tag":44,"props":134,"children":135},{},[136],{"type":32,"value":137},"场景目标",{"type":27,"tag":44,"props":139,"children":140},{},[141],{"type":32,"value":142},"品牌边界",{"type":27,"tag":44,"props":144,"children":145},{},[146],{"type":32,"value":147},"风格限制",{"type":27,"tag":44,"props":149,"children":150},{},[151],{"type":32,"value":152},"内容结构",{"type":27,"tag":28,"props":154,"children":155},{},[156],{"type":32,"value":157},"AI 往往只能生成看起来“很多”，但真正可用的不多。",{"type":27,"tag":70,"props":159,"children":161},{"id":160},"ai-生成内容必须接入人工筛选和系统约束",[162],{"type":32,"value":163},"AI 生成内容必须接入人工筛选和系统约束",{"type":27,"tag":28,"props":165,"children":166},{},[167],{"type":32,"value":168},"AI 设计工具最容易制造的问题，是局部看起来不错，但整体风格逐渐漂移。",{"type":27,"tag":28,"props":170,"children":171},{},[172],{"type":32,"value":173},"因此任何 AI 生成结果，最终都需要过两层：",{"type":27,"tag":40,"props":175,"children":176},{},[177,182],{"type":27,"tag":44,"props":178,"children":179},{},[180],{"type":32,"value":181},"人工判断：是否真的符合目标和业务场景",{"type":27,"tag":44,"props":183,"children":184},{},[185],{"type":32,"value":186},"系统约束：是否符合 tokens、组件规范和品牌规则",{"type":27,"tag":28,"props":188,"children":189},{},[190],{"type":32,"value":191},"没有这两层，AI 提效很快会变成后续返工。",{"type":27,"tag":70,"props":193,"children":195},{"id":194},"团队协作要把-ai-输出视为候选资产",[196],{"type":32,"value":197},"团队协作要把 AI 输出视为“候选资产”",{"type":27,"tag":28,"props":199,"children":200},{},[201],{"type":32,"value":202},"不少团队一引入 AI，就容易出现新的协作噪声：",{"type":27,"tag":40,"props":204,"children":205},{},[206,211,216],{"type":27,"tag":44,"props":207,"children":208},{},[209],{"type":32,"value":210},"谁都能生成一堆版本",{"type":27,"tag":44,"props":212,"children":213},{},[214],{"type":32,"value":215},"但没人知道哪个才是有效资产",{"type":27,"tag":44,"props":217,"children":218},{},[219],{"type":32,"value":220},"讨论成本反而更高",{"type":27,"tag":28,"props":222,"children":223},{},[224],{"type":32,"value":225},"更合理的方式是把 AI 输出定义成候选资产，再通过设计流程决定哪些进入正式系统。",{"type":27,"tag":70,"props":227,"children":229},{"id":228},"一个常见失败案例ai-产出越来越多系统一致性却越来越差",[230],{"type":32,"value":231},"一个常见失败案例：AI 产出越来越多，系统一致性却越来越差",{"type":27,"tag":28,"props":233,"children":234},{},[235],{"type":32,"value":236},"这种情况通常说明团队只引入了生成能力，没有引入筛选和治理能力。",{"type":27,"tag":28,"props":238,"children":239},{},[240],{"type":32,"value":241},"问题常见于：",{"type":27,"tag":40,"props":243,"children":244},{},[245,250,255,260],{"type":27,"tag":44,"props":246,"children":247},{},[248],{"type":32,"value":249},"品牌边界缺失",{"type":27,"tag":44,"props":251,"children":252},{},[253],{"type":32,"value":254},"生成内容没人归档",{"type":27,"tag":44,"props":256,"children":257},{},[258],{"type":32,"value":259},"设计系统没有承接 AI 结果",{"type":27,"tag":44,"props":261,"children":262},{},[263],{"type":32,"value":264},"评审流程没有升级",{"type":27,"tag":28,"props":266,"children":267},{},[268],{"type":32,"value":269},"AI 不是自动让设计系统更强，它只会放大现有流程的优点和缺点。",{"type":27,"tag":70,"props":271,"children":273},{"id":272},"一份可直接复用的检查清单",[274],{"type":32,"value":272},{"type":27,"tag":40,"props":276,"children":277},{},[278,283,288,293,298],{"type":27,"tag":44,"props":279,"children":280},{},[281],{"type":32,"value":282},"是否优先把 AI 用在探索、整理和低风险重复任务中",{"type":27,"tag":44,"props":284,"children":285},{},[286],{"type":32,"value":287},"输入是否明确了场景、品牌和结构边界",{"type":27,"tag":44,"props":289,"children":290},{},[291],{"type":32,"value":292},"AI 输出是否经过人工判断和系统约束双重筛选",{"type":27,"tag":44,"props":294,"children":295},{},[296],{"type":32,"value":297},"团队是否把 AI 结果视为候选资产而非直接定稿",{"type":27,"tag":44,"props":299,"children":300},{},[301],{"type":32,"value":302},"生成、评审、归档是否形成了稳定流程",{"type":27,"tag":70,"props":304,"children":306},{"id":305},"总结",[307],{"type":32,"value":305},{"type":27,"tag":28,"props":309,"children":310},{},[311],{"type":32,"value":312},"AI 辅助设计工具真正的价值，不是替代设计，而是让设计团队更快进入有效判断。只要先把输入质量、筛选机制和系统承接设计好，AI 才会从噱头变成稳定生产力。",{"type":27,"tag":28,"props":314,"children":315},{},[316],{"type":32,"value":317},"进一步阅读：",{"type":27,"tag":40,"props":319,"children":320},{},[321,331,340],{"type":27,"tag":44,"props":322,"children":323},{},[324],{"type":27,"tag":325,"props":326,"children":328},"a",{"href":327},"/topics/design/design-development-collaboration-workflow",[329],{"type":32,"value":330},"设计与开发协作流程",{"type":27,"tag":44,"props":332,"children":333},{},[334],{"type":27,"tag":325,"props":335,"children":337},{"href":336},"/topics/design/design-to-code-automation-guide",[338],{"type":32,"value":339},"设计稿到代码自动化",{"type":27,"tag":44,"props":341,"children":342},{},[343],{"type":27,"tag":325,"props":344,"children":346},{"href":345},"/topics/design/design-system-documentation-best-practices",[347],{"type":32,"value":348},"设计系统文档化最佳实践",{"title":7,"searchDepth":350,"depth":350,"links":351},3,[352,354,355,356,357,358,359],{"id":72,"depth":353,"text":75},2,{"id":116,"depth":353,"text":119},{"id":160,"depth":353,"text":163},{"id":194,"depth":353,"text":197},{"id":228,"depth":353,"text":231},{"id":272,"depth":353,"text":272},{"id":305,"depth":353,"text":305},"markdown","content:topics:design:ai-assisted-design-tools-practice.md","content","topics/design/ai-assisted-design-tools-practice.md","topics/design/ai-assisted-design-tools-practice","md",[367,727,1029],{"_path":368,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":369,"description":370,"keywords":371,"image":377,"author":11,"date":378,"readingTime":379,"topic":5,"body":380,"_type":360,"_id":724,"_source":362,"_file":725,"_stem":726,"_extension":365},"/topics/design/button-component-design","按钮组件设计详解","学习按钮样式、交互状态、无障碍性和最佳实践",[372,373,374,375,376],"按钮设计","Button Component","交互状态","UI 组件","用户体验","/images/topics/button-design.jpg","2025-12-08",18,{"type":24,"children":381,"toc":706},[382,386,391,396,403,416,422,431,437,446,450,456,467,473,482,488,497,502,511,516,527,532,541,546,559,593,604,647,652],{"type":27,"tag":70,"props":383,"children":384},{"id":369},[385],{"type":32,"value":369},{"type":27,"tag":28,"props":387,"children":388},{},[389],{"type":32,"value":390},"按钮是 UI 中最重要的交互元素。优秀的按钮设计能够指导用户行为。",{"type":27,"tag":70,"props":392,"children":394},{"id":393},"按钮类型",[395],{"type":32,"value":393},{"type":27,"tag":397,"props":398,"children":400},"h3",{"id":399},"primary-button主按钮",[401],{"type":32,"value":402},"Primary Button（主按钮）",{"type":27,"tag":404,"props":405,"children":410},"pre",{"className":406,"code":408,"language":409,"meta":7},[407],"language-css",".btn-primary {\n  background-color: #0066cc;\n  color: #ffffff;\n  padding: 12px 24px;\n  border: none;\n  border-radius: 4px;\n  font-weight: 600;\n  font-size: 16px;\n  cursor: pointer;\n  transition: all 0.2s ease;\n}\n\n.btn-primary:hover {\n  background-color: #0052a3;\n  box-shadow: 0 4px 12px rgba(0, 102, 204, 0.2);\n}\n\n.btn-primary:active {\n  background-color: #003d7a;\n  transform: scale(0.98);\n}\n\n.btn-primary:disabled {\n  background-color: #cccccc;\n  cursor: not-allowed;\n  opacity: 0.6;\n}\n","css",[411],{"type":27,"tag":412,"props":413,"children":414},"code",{"__ignoreMap":7},[415],{"type":32,"value":408},{"type":27,"tag":397,"props":417,"children":419},{"id":418},"secondary-button次按钮",[420],{"type":32,"value":421},"Secondary Button（次按钮）",{"type":27,"tag":404,"props":423,"children":426},{"className":424,"code":425,"language":409,"meta":7},[407],".btn-secondary {\n  background-color: transparent;\n  color: #0066cc;\n  border: 2px solid #0066cc;\n  padding: 10px 22px;\n  border-radius: 4px;\n  font-weight: 600;\n  cursor: pointer;\n  transition: all 0.2s;\n}\n\n.btn-secondary:hover {\n  background-color: rgba(0, 102, 204, 0.1);\n}\n\n.btn-secondary:active {\n  background-color: rgba(0, 102, 204, 0.2);\n}\n",[427],{"type":27,"tag":412,"props":428,"children":429},{"__ignoreMap":7},[430],{"type":32,"value":425},{"type":27,"tag":397,"props":432,"children":434},{"id":433},"danger-button危险按钮",[435],{"type":32,"value":436},"Danger Button（危险按钮）",{"type":27,"tag":404,"props":438,"children":441},{"className":439,"code":440,"language":409,"meta":7},[407],".btn-danger {\n  background-color: #cc0000;\n  color: #ffffff;\n  padding: 12px 24px;\n  border-radius: 4px;\n  cursor: pointer;\n  font-weight: 600;\n}\n\n.btn-danger:hover {\n  background-color: #990000;\n  box-shadow: 0 4px 12px rgba(204, 0, 0, 0.2);\n}\n",[442],{"type":27,"tag":412,"props":443,"children":444},{"__ignoreMap":7},[445],{"type":32,"value":440},{"type":27,"tag":70,"props":447,"children":448},{"id":374},[449],{"type":32,"value":374},{"type":27,"tag":397,"props":451,"children":453},{"id":452},"loading-状态",[454],{"type":32,"value":455},"Loading 状态",{"type":27,"tag":404,"props":457,"children":462},{"className":458,"code":460,"language":461,"meta":7},[459],"language-jsx","import { useState } from 'react';\n\nfunction Button({ children, onClick, loading, ...props }) {\n  const [isLoading, setIsLoading] = useState(false);\n  \n  const handleClick = async () => {\n    setIsLoading(true);\n    try {\n      await onClick();\n    } finally {\n      setIsLoading(false);\n    }\n  };\n  \n  return (\n    \u003Cbutton\n      onClick={handleClick}\n      disabled={isLoading || loading}\n      aria-busy={isLoading || loading}\n      {...props}\n    >\n      {isLoading ? (\n        \u003C>\n          \u003Cspan className=\"spinner\" aria-hidden=\"true\">\u003C/span>\n          {children}\n        \u003C/>\n      ) : (\n        children\n      )}\n    \u003C/button>\n  );\n}\n","jsx",[463],{"type":27,"tag":412,"props":464,"children":465},{"__ignoreMap":7},[466],{"type":32,"value":460},{"type":27,"tag":397,"props":468,"children":470},{"id":469},"disabled-状态",[471],{"type":32,"value":472},"Disabled 状态",{"type":27,"tag":404,"props":474,"children":477},{"className":475,"code":476,"language":409,"meta":7},[407],".btn:disabled {\n  opacity: 0.5;\n  cursor: not-allowed;\n  background-color: #cccccc;\n  color: #999999;\n}\n\n/* 禁用状态下隐藏指针光标 */\n.btn:disabled:hover {\n  box-shadow: none;\n  transform: none;\n}\n",[478],{"type":27,"tag":412,"props":479,"children":480},{"__ignoreMap":7},[481],{"type":32,"value":476},{"type":27,"tag":397,"props":483,"children":485},{"id":484},"focus-状态",[486],{"type":32,"value":487},"Focus 状态",{"type":27,"tag":404,"props":489,"children":492},{"className":490,"code":491,"language":409,"meta":7},[407],".btn:focus {\n  outline: none;\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1),\n              0 0 0 5px #0066cc;\n}\n\n/* 键盘导航焦点 */\n.btn:focus-visible {\n  outline: 2px solid #0066cc;\n  outline-offset: 2px;\n}\n",[493],{"type":27,"tag":412,"props":494,"children":495},{"__ignoreMap":7},[496],{"type":32,"value":491},{"type":27,"tag":70,"props":498,"children":500},{"id":499},"按钮大小",[501],{"type":32,"value":499},{"type":27,"tag":404,"props":503,"children":506},{"className":504,"code":505,"language":409,"meta":7},[407],"/* 小按钮 */\n.btn-sm {\n  padding: 6px 12px;\n  font-size: 12px;\n  min-height: 32px;\n  min-width: 32px;\n}\n\n/* 中等按钮（默认） */\n.btn-md {\n  padding: 12px 24px;\n  font-size: 16px;\n  min-height: 44px;\n  min-width: 44px;\n}\n\n/* 大按钮 */\n.btn-lg {\n  padding: 16px 32px;\n  font-size: 18px;\n  min-height: 56px;\n  min-width: 56px;\n}\n\n/* 全宽按钮 */\n.btn-block {\n  width: 100%;\n  display: block;\n}\n",[507],{"type":27,"tag":412,"props":508,"children":509},{"__ignoreMap":7},[510],{"type":32,"value":505},{"type":27,"tag":70,"props":512,"children":514},{"id":513},"无障碍性",[515],{"type":32,"value":513},{"type":27,"tag":404,"props":517,"children":522},{"className":518,"code":520,"language":521,"meta":7},[519],"language-html","\u003C!-- 语义正确 -->\n\u003Cbutton type=\"submit\" aria-label=\"提交表单\">\n  提交\n\u003C/button>\n\n\u003C!-- 加载状态 -->\n\u003Cbutton aria-busy=\"true\" disabled>\n  \u003Cspan aria-hidden=\"true\" class=\"spinner\">\u003C/span>\n  加载中...\n\u003C/button>\n\n\u003C!-- 图标按钮 -->\n\u003Cbutton aria-label=\"关闭\">\n  \u003Csvg aria-hidden=\"true\" width=\"24\" height=\"24\">\n    \u003Cline x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n    \u003Cline x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n  \u003C/svg>\n\u003C/button>\n\n\u003C!-- 切换按钮 -->\n\u003Cbutton aria-pressed=\"false\" aria-label=\"点赞\">\n  ♥\n\u003C/button>\n","html",[523],{"type":27,"tag":412,"props":524,"children":525},{"__ignoreMap":7},[526],{"type":32,"value":520},{"type":27,"tag":70,"props":528,"children":530},{"id":529},"完整组件示例",[531],{"type":32,"value":529},{"type":27,"tag":404,"props":533,"children":536},{"className":534,"code":535,"language":461,"meta":7},[459],"const Button = React.forwardRef((\n  {\n    children,\n    variant = 'primary',\n    size = 'md',\n    loading = false,\n    disabled = false,\n    icon,\n    className,\n    ...props\n  },\n  ref\n) => {\n  return (\n    \u003Cbutton\n      ref={ref}\n      className={`btn btn-${variant} btn-${size} ${className}`}\n      disabled={disabled || loading}\n      aria-busy={loading}\n      {...props}\n    >\n      {icon && \u003Cspan className=\"btn-icon\" aria-hidden=\"true\">{icon}\u003C/span>}\n      {loading ? (\n        \u003C>\n          \u003Cspan className=\"spinner\" aria-hidden=\"true\">\u003C/span>\n          {children}\n        \u003C/>\n      ) : (\n        children\n      )}\n    \u003C/button>\n  );\n});\n\nButton.displayName = 'Button';\n",[537],{"type":27,"tag":412,"props":538,"children":539},{"__ignoreMap":7},[540],{"type":32,"value":535},{"type":27,"tag":70,"props":542,"children":544},{"id":543},"最佳实践",[545],{"type":32,"value":543},{"type":27,"tag":28,"props":547,"children":548},{},[549,551,557],{"type":32,"value":550},"✅ ",{"type":27,"tag":552,"props":553,"children":554},"strong",{},[555],{"type":32,"value":556},"应该做的事",{"type":32,"value":558},":",{"type":27,"tag":40,"props":560,"children":561},{},[562,567,572,583,588],{"type":27,"tag":44,"props":563,"children":564},{},[565],{"type":32,"value":566},"最小触摸目标 44x44px",{"type":27,"tag":44,"props":568,"children":569},{},[570],{"type":32,"value":571},"清晰的视觉反馈",{"type":27,"tag":44,"props":573,"children":574},{},[575,577],{"type":32,"value":576},"使用语义 HTML ",{"type":27,"tag":412,"props":578,"children":580},{"className":579},[],[581],{"type":32,"value":582},"\u003Cbutton>",{"type":27,"tag":44,"props":584,"children":585},{},[586],{"type":32,"value":587},"提供加载状态反馈",{"type":27,"tag":44,"props":589,"children":590},{},[591],{"type":32,"value":592},"支持键盘导航",{"type":27,"tag":28,"props":594,"children":595},{},[596,598,603],{"type":32,"value":597},"❌ ",{"type":27,"tag":552,"props":599,"children":600},{},[601],{"type":32,"value":602},"不应该做的事",{"type":32,"value":558},{"type":27,"tag":40,"props":605,"children":606},{},[607,620,625,630,635],{"type":27,"tag":44,"props":608,"children":609},{},[610,612,618],{"type":32,"value":611},"使用 ",{"type":27,"tag":412,"props":613,"children":615},{"className":614},[],[616],{"type":32,"value":617},"\u003Cdiv>",{"type":32,"value":619}," 模拟按钮",{"type":27,"tag":44,"props":621,"children":622},{},[623],{"type":32,"value":624},"隐藏焦点指示器",{"type":27,"tag":44,"props":626,"children":627},{},[628],{"type":32,"value":629},"过多的按钮样式",{"type":27,"tag":44,"props":631,"children":632},{},[633],{"type":32,"value":634},"忽视禁用状态",{"type":27,"tag":44,"props":636,"children":637},{},[638,639,645],{"type":32,"value":611},{"type":27,"tag":412,"props":640,"children":642},{"className":641},[],[643],{"type":32,"value":644},"\u003Ca>",{"type":32,"value":646}," 代替按钮",{"type":27,"tag":70,"props":648,"children":650},{"id":649},"测试清单",[651],{"type":32,"value":649},{"type":27,"tag":40,"props":653,"children":656},{"className":654},[655],"contains-task-list",[657,670,679,688,697],{"type":27,"tag":44,"props":658,"children":661},{"className":659},[660],"task-list-item",[662,668],{"type":27,"tag":663,"props":664,"children":667},"input",{"disabled":665,"type":666},true,"checkbox",[],{"type":32,"value":669}," 在各种浏览器中测试",{"type":27,"tag":44,"props":671,"children":673},{"className":672},[660],[674,677],{"type":27,"tag":663,"props":675,"children":676},{"disabled":665,"type":666},[],{"type":32,"value":678}," 验证键盘导航",{"type":27,"tag":44,"props":680,"children":682},{"className":681},[660],[683,686],{"type":27,"tag":663,"props":684,"children":685},{"disabled":665,"type":666},[],{"type":32,"value":687}," 检查色彩对比度",{"type":27,"tag":44,"props":689,"children":691},{"className":690},[660],[692,695],{"type":27,"tag":663,"props":693,"children":694},{"disabled":665,"type":666},[],{"type":32,"value":696}," 测试触摸设备",{"type":27,"tag":44,"props":698,"children":700},{"className":699},[660],[701,704],{"type":27,"tag":663,"props":702,"children":703},{"disabled":665,"type":666},[],{"type":32,"value":705}," 屏幕阅读器兼容性",{"title":7,"searchDepth":350,"depth":350,"links":707},[708,709,714,719,720,721,722,723],{"id":369,"depth":353,"text":369},{"id":393,"depth":353,"text":393,"children":710},[711,712,713],{"id":399,"depth":350,"text":402},{"id":418,"depth":350,"text":421},{"id":433,"depth":350,"text":436},{"id":374,"depth":353,"text":374,"children":715},[716,717,718],{"id":452,"depth":350,"text":455},{"id":469,"depth":350,"text":472},{"id":484,"depth":350,"text":487},{"id":499,"depth":353,"text":499},{"id":513,"depth":353,"text":513},{"id":529,"depth":353,"text":529},{"id":543,"depth":353,"text":543},{"id":649,"depth":353,"text":649},"content:topics:design:button-component-design.md","topics/design/button-component-design.md","topics/design/button-component-design",{"_path":728,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":729,"description":730,"keywords":731,"image":736,"author":11,"date":378,"readingTime":737,"topic":5,"body":738,"_type":360,"_id":1026,"_source":362,"_file":1027,"_stem":1028,"_extension":365},"/topics/design/dark-mode-design","暗黑模式设计完整方案","学习暗黑模式实现、色彩方案、对比度管理和最佳实践",[732,733,734,735,376],"暗黑模式","Dark Mode","色彩系统","CSS 变量","/images/topics/dark-mode-design.jpg",20,{"type":24,"children":739,"toc":1009},[740,744,749,754,760,769,775,784,789,795,804,810,821,827,836,841,850,855,864,869,878,882,891,919,928,956,960],{"type":27,"tag":70,"props":741,"children":742},{"id":729},[743],{"type":32,"value":729},{"type":27,"tag":28,"props":745,"children":746},{},[747],{"type":32,"value":748},"暗黑模式已成为现代应用的标准功能。它能够减少眼睛疲劳、节省电池、改善用户体验。",{"type":27,"tag":70,"props":750,"children":752},{"id":751},"核心色彩系统",[753],{"type":32,"value":751},{"type":27,"tag":397,"props":755,"children":757},{"id":756},"light-mode-配色",[758],{"type":32,"value":759},"Light Mode 配色",{"type":27,"tag":404,"props":761,"children":764},{"className":762,"code":763,"language":409,"meta":7},[407],":root {\n  /* Light Mode */\n  --bg-primary: #ffffff;\n  --bg-secondary: #f5f5f5;\n  --bg-tertiary: #efefef;\n  \n  --text-primary: #1a1a1a;\n  --text-secondary: #666666;\n  --text-tertiary: #999999;\n  \n  --border-color: #e0e0e0;\n  --divider-color: #f0f0f0;\n}\n",[765],{"type":27,"tag":412,"props":766,"children":767},{"__ignoreMap":7},[768],{"type":32,"value":763},{"type":27,"tag":397,"props":770,"children":772},{"id":771},"dark-mode-配色",[773],{"type":32,"value":774},"Dark Mode 配色",{"type":27,"tag":404,"props":776,"children":779},{"className":777,"code":778,"language":409,"meta":7},[407],"@media (prefers-color-scheme: dark) {\n  :root {\n    /* Dark Mode */\n    --bg-primary: #1a1a1a;\n    --bg-secondary: #2d2d2d;\n    --bg-tertiary: #3a3a3a;\n    \n    --text-primary: #ffffff;\n    --text-secondary: #e0e0e0;\n    --text-tertiary: #a0a0a0;\n    \n    --border-color: #404040;\n    --divider-color: #2a2a2a;\n  }\n}\n",[780],{"type":27,"tag":412,"props":781,"children":782},{"__ignoreMap":7},[783],{"type":32,"value":778},{"type":27,"tag":70,"props":785,"children":787},{"id":786},"实现方案",[788],{"type":32,"value":786},{"type":27,"tag":397,"props":790,"children":792},{"id":791},"方案-1prefers-color-scheme",[793],{"type":32,"value":794},"方案 1：prefers-color-scheme",{"type":27,"tag":404,"props":796,"children":799},{"className":797,"code":798,"language":409,"meta":7},[407],"/* 自动跟随系统设置 */\n@media (prefers-color-scheme: light) {\n  :root {\n    --bg: #fff;\n    --text: #000;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --bg: #1a1a1a;\n    --text: #fff;\n  }\n}\n\nbody {\n  background: var(--bg);\n  color: var(--text);\n}\n",[800],{"type":27,"tag":412,"props":801,"children":802},{"__ignoreMap":7},[803],{"type":32,"value":798},{"type":27,"tag":397,"props":805,"children":807},{"id":806},"方案-2javascript-切换",[808],{"type":32,"value":809},"方案 2：JavaScript 切换",{"type":27,"tag":404,"props":811,"children":816},{"className":812,"code":814,"language":815,"meta":7},[813],"language-javascript","// 检测和切换暗黑模式\nfunction initDarkMode() {\n  const isDark = localStorage.getItem('darkMode') === 'true' ||\n                 window.matchMedia('(prefers-color-scheme: dark)').matches;\n  \n  if (isDark) {\n    document.documentElement.setAttribute('data-theme', 'dark');\n  }\n}\n\nfunction toggleDarkMode() {\n  const isDark = document.documentElement.getAttribute('data-theme') === 'dark';\n  const newTheme = isDark ? 'light' : 'dark';\n  \n  document.documentElement.setAttribute('data-theme', newTheme);\n  localStorage.setItem('darkMode', newTheme === 'dark');\n}\n\n// CSS 应用\nhtml[data-theme='light'] {\n  color-scheme: light;\n}\n\nhtml[data-theme='dark'] {\n  color-scheme: dark;\n}\n","javascript",[817],{"type":27,"tag":412,"props":818,"children":819},{"__ignoreMap":7},[820],{"type":32,"value":814},{"type":27,"tag":397,"props":822,"children":824},{"id":823},"方案-3css-variables-javascript",[825],{"type":32,"value":826},"方案 3：CSS Variables + JavaScript",{"type":27,"tag":404,"props":828,"children":831},{"className":829,"code":830,"language":815,"meta":7},[813],"const themes = {\n  light: {\n    '--bg-primary': '#ffffff',\n    '--text-primary': '#000000',\n    '--accent': '#0066cc',\n    '--border': '#e0e0e0',\n  },\n  dark: {\n    '--bg-primary': '#1a1a1a',\n    '--text-primary': '#ffffff',\n    '--accent': '#4da3ff',\n    '--border': '#404040',\n  },\n};\n\nfunction applyTheme(themeName) {\n  const theme = themes[themeName];\n  Object.entries(theme).forEach(([key, value]) => {\n    document.documentElement.style.setProperty(key, value);\n  });\n  localStorage.setItem('theme', themeName);\n}\n",[832],{"type":27,"tag":412,"props":833,"children":834},{"__ignoreMap":7},[835],{"type":32,"value":830},{"type":27,"tag":70,"props":837,"children":839},{"id":838},"对比度管理",[840],{"type":32,"value":838},{"type":27,"tag":404,"props":842,"children":845},{"className":843,"code":844,"language":409,"meta":7},[407],"/* Light Mode 对比度 */\n:root {\n  --contrast-high: #000000;     /* 21:1 */\n  --contrast-medium: #333333;   /* 12.6:1 */\n  --contrast-low: #666666;      /* 5.1:1 */\n}\n\n/* Dark Mode 对比度 */\n@media (prefers-color-scheme: dark) {\n  :root {\n    --contrast-high: #ffffff;    /* 21:1 */\n    --contrast-medium: #e0e0e0;  /* 11.6:1 */\n    --contrast-low: #a0a0a0;     /* 4.5:1 */\n  }\n}\n\n/* 应用对比度 */\n.text-primary { color: var(--contrast-high); }\n.text-secondary { color: var(--contrast-medium); }\n.text-tertiary { color: var(--contrast-low); }\n",[846],{"type":27,"tag":412,"props":847,"children":848},{"__ignoreMap":7},[849],{"type":32,"value":844},{"type":27,"tag":70,"props":851,"children":853},{"id":852},"图片和图表处理",[854],{"type":32,"value":852},{"type":27,"tag":404,"props":856,"children":859},{"className":857,"code":858,"language":521,"meta":7},[519],"\u003C!-- 针对不同主题的图片 -->\n\u003Cpicture>\n  \u003Csource \n    media=\"(prefers-color-scheme: dark)\" \n    srcset=\"chart-dark.svg\"\n  />\n  \u003Cimg src=\"chart-light.svg\" alt=\"图表\" />\n\u003C/picture>\n\n\u003C!-- SVG 颜色适配 -->\n\u003Csvg class=\"icon\">\n  \u003Ccircle cx=\"50\" cy=\"50\" r=\"40\" fill=\"currentColor\" />\n\u003C/svg>\n\n\u003Cstyle>\n  .icon {\n    color: var(--text-primary);\n  }\n\u003C/style>\n",[860],{"type":27,"tag":412,"props":861,"children":862},{"__ignoreMap":7},[863],{"type":32,"value":858},{"type":27,"tag":70,"props":865,"children":867},{"id":866},"完整示例",[868],{"type":32,"value":866},{"type":27,"tag":404,"props":870,"children":873},{"className":871,"code":872,"language":461,"meta":7},[459],"import { useState, useEffect } from 'react';\n\nfunction ThemeProvider({ children }) {\n  const [theme, setTheme] = useState('light');\n  const [mounted, setMounted] = useState(false);\n  \n  useEffect(() => {\n    setMounted(true);\n    \n    // 获取保存的主题或系统偏好\n    const savedTheme = localStorage.getItem('theme');\n    const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches \n      ? 'dark' \n      : 'light';\n    \n    const initialTheme = savedTheme || systemTheme;\n    setTheme(initialTheme);\n    document.documentElement.setAttribute('data-theme', initialTheme);\n  }, []);\n  \n  const toggleTheme = () => {\n    const newTheme = theme === 'light' ? 'dark' : 'light';\n    setTheme(newTheme);\n    localStorage.setItem('theme', newTheme);\n    document.documentElement.setAttribute('data-theme', newTheme);\n  };\n  \n  // 防止闪烁\n  if (!mounted) {\n    return null;\n  }\n  \n  return (\n    \u003CThemeContext.Provider value={{ theme, toggleTheme }}>\n      {children}\n      \u003CThemeToggle theme={theme} onChange={toggleTheme} />\n    \u003C/ThemeContext.Provider>\n  );\n}\n\nfunction ThemeToggle({ theme, onChange }) {\n  return (\n    \u003Cbutton \n      onClick={onChange}\n      aria-label={`切换到${theme === 'light' ? '暗黑' : '亮色'}模式`}\n    >\n      {theme === 'light' ? '🌙' : '☀️'}\n    \u003C/button>\n  );\n}\n",[874],{"type":27,"tag":412,"props":875,"children":876},{"__ignoreMap":7},[877],{"type":32,"value":872},{"type":27,"tag":70,"props":879,"children":880},{"id":543},[881],{"type":32,"value":543},{"type":27,"tag":28,"props":883,"children":884},{},[885,886,890],{"type":32,"value":550},{"type":27,"tag":552,"props":887,"children":888},{},[889],{"type":32,"value":556},{"type":32,"value":558},{"type":27,"tag":40,"props":892,"children":893},{},[894,899,904,909,914],{"type":27,"tag":44,"props":895,"children":896},{},[897],{"type":32,"value":898},"支持系统偏好",{"type":27,"tag":44,"props":900,"children":901},{},[902],{"type":32,"value":903},"提供手动切换选项",{"type":27,"tag":44,"props":905,"children":906},{},[907],{"type":32,"value":908},"确保足够的对比度",{"type":27,"tag":44,"props":910,"children":911},{},[912],{"type":32,"value":913},"优化图片和图表",{"type":27,"tag":44,"props":915,"children":916},{},[917],{"type":32,"value":918},"防止加载闪烁",{"type":27,"tag":28,"props":920,"children":921},{},[922,923,927],{"type":32,"value":597},{"type":27,"tag":552,"props":924,"children":925},{},[926],{"type":32,"value":602},{"type":32,"value":558},{"type":27,"tag":40,"props":929,"children":930},{},[931,936,941,946,951],{"type":27,"tag":44,"props":932,"children":933},{},[934],{"type":32,"value":935},"强制单一模式",{"type":27,"tag":44,"props":937,"children":938},{},[939],{"type":32,"value":940},"忽视性能影响",{"type":27,"tag":44,"props":942,"children":943},{},[944],{"type":32,"value":945},"使用相同的颜色",{"type":27,"tag":44,"props":947,"children":948},{},[949],{"type":32,"value":950},"忘记保存用户偏好",{"type":27,"tag":44,"props":952,"children":953},{},[954],{"type":32,"value":955},"过度使用深色背景",{"type":27,"tag":70,"props":957,"children":958},{"id":649},[959],{"type":32,"value":649},{"type":27,"tag":40,"props":961,"children":963},{"className":962},[655],[964,973,982,991,1000],{"type":27,"tag":44,"props":965,"children":967},{"className":966},[660],[968,971],{"type":27,"tag":663,"props":969,"children":970},{"disabled":665,"type":666},[],{"type":32,"value":972}," 在浅色和深色模式下测试所有页面",{"type":27,"tag":44,"props":974,"children":976},{"className":975},[660],[977,980],{"type":27,"tag":663,"props":978,"children":979},{"disabled":665,"type":666},[],{"type":32,"value":981}," 检查颜色对比度符合 WCAG 标准",{"type":27,"tag":44,"props":983,"children":985},{"className":984},[660],[986,989],{"type":27,"tag":663,"props":987,"children":988},{"disabled":665,"type":666},[],{"type":32,"value":990}," 验证图片和图表在两种模式下清晰",{"type":27,"tag":44,"props":992,"children":994},{"className":993},[660],[995,998],{"type":27,"tag":663,"props":996,"children":997},{"disabled":665,"type":666},[],{"type":32,"value":999}," 测试主题切换的平滑性",{"type":27,"tag":44,"props":1001,"children":1003},{"className":1002},[660],[1004,1007],{"type":27,"tag":663,"props":1005,"children":1006},{"disabled":665,"type":666},[],{"type":32,"value":1008}," 检查用户偏好是否被保存",{"title":7,"searchDepth":350,"depth":350,"links":1010},[1011,1012,1016,1021,1022,1023,1024,1025],{"id":729,"depth":353,"text":729},{"id":751,"depth":353,"text":751,"children":1013},[1014,1015],{"id":756,"depth":350,"text":759},{"id":771,"depth":350,"text":774},{"id":786,"depth":353,"text":786,"children":1017},[1018,1019,1020],{"id":791,"depth":350,"text":794},{"id":806,"depth":350,"text":809},{"id":823,"depth":350,"text":826},{"id":838,"depth":353,"text":838},{"id":852,"depth":353,"text":852},{"id":866,"depth":353,"text":866},{"id":543,"depth":353,"text":543},{"id":649,"depth":353,"text":649},"content:topics:design:dark-mode-design.md","topics/design/dark-mode-design.md","topics/design/dark-mode-design",{"_path":1030,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1031,"description":1032,"keywords":1033,"image":1038,"author":1039,"date":378,"readingTime":737,"topic":5,"body":1040,"_type":360,"_id":1305,"_source":362,"_file":1306,"_stem":1307,"_extension":365},"/topics/design/form-controls-design","表单控件设计规范","学习输入框、选择框、复选框等表单控件的设计和实现",[1034,1035,1036,1037,376],"表单设计","Form Controls","输入框","验证反馈","/images/topics/form-controls-design.jpg","AI Content Team",{"type":24,"children":1041,"toc":1291},[1042,1046,1051,1056,1061,1070,1075,1084,1088,1097,1102,1111,1116,1125,1130,1139,1144,1153,1157,1166,1192,1201,1229,1233],{"type":27,"tag":70,"props":1043,"children":1044},{"id":1031},[1045],{"type":32,"value":1031},{"type":27,"tag":28,"props":1047,"children":1048},{},[1049],{"type":32,"value":1050},"优秀的表单设计能够提高用户完成率和满意度。",{"type":27,"tag":70,"props":1052,"children":1054},{"id":1053},"输入框设计",[1055],{"type":32,"value":1053},{"type":27,"tag":397,"props":1057,"children":1059},{"id":1058},"基础文本输入",[1060],{"type":32,"value":1058},{"type":27,"tag":404,"props":1062,"children":1065},{"className":1063,"code":1064,"language":409,"meta":7},[407],".input {\n  width: 100%;\n  padding: 12px 16px;\n  font-size: 16px;\n  border: 2px solid #e0e0e0;\n  border-radius: 4px;\n  font-family: inherit;\n  transition: border-color 0.2s;\n}\n\n.input:hover {\n  border-color: #bdbdbd;\n}\n\n.input:focus {\n  outline: none;\n  border-color: #0066cc;\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);\n}\n\n.input:disabled {\n  background-color: #f5f5f5;\n  color: #999999;\n  cursor: not-allowed;\n}\n\n.input.error {\n  border-color: #cc0000;\n}\n\n.input.success {\n  border-color: #00cc00;\n}\n",[1066],{"type":27,"tag":412,"props":1067,"children":1068},{"__ignoreMap":7},[1069],{"type":32,"value":1064},{"type":27,"tag":397,"props":1071,"children":1073},{"id":1072},"标签和提示",[1074],{"type":32,"value":1072},{"type":27,"tag":404,"props":1076,"children":1079},{"className":1077,"code":1078,"language":521,"meta":7},[519],"\u003Cdiv class=\"form-group\">\n  \u003Clabel for=\"email\" class=\"form-label\">\n    邮箱地址 \u003Cspan class=\"required\">*\u003C/span>\n  \u003C/label>\n  \u003Cinput\n    id=\"email\"\n    type=\"email\"\n    placeholder=\"user@example.com\"\n    class=\"input\"\n    aria-describedby=\"email-hint\"\n  />\n  \u003Cp id=\"email-hint\" class=\"form-hint\">\n    我们永远不会分享你的邮箱\n  \u003C/p>\n\u003C/div>\n",[1080],{"type":27,"tag":412,"props":1081,"children":1082},{"__ignoreMap":7},[1083],{"type":32,"value":1078},{"type":27,"tag":70,"props":1085,"children":1086},{"id":1037},[1087],{"type":32,"value":1037},{"type":27,"tag":404,"props":1089,"children":1092},{"className":1090,"code":1091,"language":461,"meta":7},[459],"function FormInput({ label, error, success, helperText, value, onChange, ...props }) {\n  return (\n    \u003Cdiv className=\"form-group\">\n      \u003Clabel className=\"form-label\">{label}\u003C/label>\n      \u003Cinput\n        className={`input ${\n          error ? 'error' : success ? 'success' : ''\n        }`}\n        value={value}\n        onChange={onChange}\n        {...props}\n      />\n      {error && (\n        \u003Cp className=\"form-error\" role=\"alert\">\n          {error}\n        \u003C/p>\n      )}\n      {success && (\n        \u003Cp className=\"form-success\">\n          ✓ {success}\n        \u003C/p>\n      )}\n      {helperText && (\n        \u003Cp className=\"form-hint\">{helperText}\u003C/p>\n      )}\n    \u003C/div>\n  );\n}\n",[1093],{"type":27,"tag":412,"props":1094,"children":1095},{"__ignoreMap":7},[1096],{"type":32,"value":1091},{"type":27,"tag":70,"props":1098,"children":1100},{"id":1099},"选择框设计",[1101],{"type":32,"value":1099},{"type":27,"tag":404,"props":1103,"children":1106},{"className":1104,"code":1105,"language":409,"meta":7},[407],".select {\n  appearance: none;\n  width: 100%;\n  padding: 12px 16px;\n  border: 2px solid #e0e0e0;\n  border-radius: 4px;\n  background-image: url('data:image/svg+xml;...');\n  background-repeat: no-repeat;\n  background-position: right 12px center;\n  padding-right: 40px;\n  font-size: 16px;\n  cursor: pointer;\n}\n\n.select:hover {\n  border-color: #bdbdbd;\n}\n\n.select:focus {\n  outline: none;\n  border-color: #0066cc;\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);\n}\n",[1107],{"type":27,"tag":412,"props":1108,"children":1109},{"__ignoreMap":7},[1110],{"type":32,"value":1105},{"type":27,"tag":70,"props":1112,"children":1114},{"id":1113},"复选框和单选按钮",[1115],{"type":32,"value":1113},{"type":27,"tag":404,"props":1117,"children":1120},{"className":1118,"code":1119,"language":409,"meta":7},[407],".checkbox-group {\n  display: flex;\n  gap: 12px;\n  align-items: center;\n}\n\n.checkbox-input {\n  width: 20px;\n  height: 20px;\n  cursor: pointer;\n  accent-color: #0066cc;\n}\n\n.checkbox-label {\n  cursor: pointer;\n  user-select: none;\n}\n\n/* 自定义复选框 */\n.custom-checkbox {\n  appearance: none;\n  width: 20px;\n  height: 20px;\n  border: 2px solid #e0e0e0;\n  border-radius: 4px;\n  cursor: pointer;\n  background-color: white;\n  transition: all 0.2s;\n}\n\n.custom-checkbox:checked {\n  background-color: #0066cc;\n  border-color: #0066cc;\n  background-image: url('data:image/svg+xml;...');\n}\n\n.custom-checkbox:focus {\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);\n}\n",[1121],{"type":27,"tag":412,"props":1122,"children":1123},{"__ignoreMap":7},[1124],{"type":32,"value":1119},{"type":27,"tag":70,"props":1126,"children":1128},{"id":1127},"文本区域",[1129],{"type":32,"value":1127},{"type":27,"tag":404,"props":1131,"children":1134},{"className":1132,"code":1133,"language":409,"meta":7},[407],".textarea {\n  width: 100%;\n  min-height: 120px;\n  padding: 12px 16px;\n  border: 2px solid #e0e0e0;\n  border-radius: 4px;\n  font-family: inherit;\n  font-size: 16px;\n  resize: vertical;\n  transition: border-color 0.2s;\n}\n\n.textarea:focus {\n  outline: none;\n  border-color: #0066cc;\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);\n}\n",[1135],{"type":27,"tag":412,"props":1136,"children":1137},{"__ignoreMap":7},[1138],{"type":32,"value":1133},{"type":27,"tag":70,"props":1140,"children":1142},{"id":1141},"完整表单示例",[1143],{"type":32,"value":1141},{"type":27,"tag":404,"props":1145,"children":1148},{"className":1146,"code":1147,"language":461,"meta":7},[459],"function SignupForm() {\n  const [formData, setFormData] = useState({\n    name: '',\n    email: '',\n    password: '',\n    confirmPassword: '',\n    subscribe: false,\n    terms: false,\n  });\n  \n  const [errors, setErrors] = useState({});\n  const [touched, setTouched] = useState({});\n  const [submitted, setSubmitted] = useState(false);\n  \n  const handleChange = (e) => {\n    const { name, value, type, checked } = e.target;\n    setFormData(prev => ({\n      ...prev,\n      [name]: type === 'checkbox' ? checked : value,\n    }));\n    \n    // 实时验证\n    if (touched[name]) {\n      validateField(name, type === 'checkbox' ? checked : value);\n    }\n  };\n  \n  const handleBlur = (e) => {\n    const { name } = e.target;\n    setTouched(prev => ({ ...prev, [name]: true }));\n    validateField(name, formData[name]);\n  };\n  \n  const validateField = (name, value) => {\n    const newErrors = { ...errors };\n    \n    switch (name) {\n      case 'name':\n        if (!value) newErrors.name = '名字不能为空';\n        else delete newErrors.name;\n        break;\n      case 'email':\n        if (!value) newErrors.email = '邮箱不能为空';\n        else if (!/^[^\\\\s@]+@[^\\\\s@]+\\\\.[^\\\\s@]+$/.test(value)) {\n          newErrors.email = '请输入有效的邮箱';\n        } else {\n          delete newErrors.email;\n        }\n        break;\n      case 'password':\n        if (!value) newErrors.password = '密码不能为空';\n        else if (value.length \u003C 8) newErrors.password = '密码至少 8 位';\n        else delete newErrors.password;\n        break;\n      case 'confirmPassword':\n        if (value !== formData.password) {\n          newErrors.confirmPassword = '两次密码输入不一致';\n        } else {\n          delete newErrors.confirmPassword;\n        }\n        break;\n      case 'terms':\n        if (!value) newErrors.terms = '必须同意服务条款';\n        else delete newErrors.terms;\n        break;\n      default:\n        break;\n    }\n    \n    setErrors(newErrors);\n  };\n  \n  const validate = () => {\n    const newErrors = {};\n    \n    if (!formData.name) newErrors.name = '名字不能为空';\n    if (!formData.email) newErrors.email = '邮箱不能为空';\n    if (formData.password.length \u003C 8) newErrors.password = '密码至少 8 位';\n    if (formData.password !== formData.confirmPassword) {\n      newErrors.confirmPassword = '两次密码输入不一致';\n    }\n    if (!formData.terms) newErrors.terms = '必须同意服务条款';\n    \n    return newErrors;\n  };\n  \n  const handleSubmit = async (e) => {\n    e.preventDefault();\n    \n    // 标记所有字段已触碰\n    setTouched({\n      name: true,\n      email: true,\n      password: true,\n      confirmPassword: true,\n      terms: true,\n    });\n    \n    const newErrors = validate();\n    \n    if (Object.keys(newErrors).length === 0) {\n      setSubmitted(true);\n      // 提交表单\n      console.log('Form submitted:', formData);\n      // 重置表单\n      setFormData({\n        name: '',\n        email: '',\n        password: '',\n        confirmPassword: '',\n        subscribe: false,\n        terms: false,\n      });\n    } else {\n      setErrors(newErrors);\n    }\n  };\n  \n  return (\n    \u003Cform onSubmit={handleSubmit} noValidate>\n      {submitted && (\n        \u003Cdiv className=\"form-success-message\" role=\"alert\">\n          注册成功！\n        \u003C/div>\n      )}\n      \n      \u003CFormInput\n        label=\"姓名\"\n        name=\"name\"\n        value={formData.name}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        error={touched.name && errors.name}\n        helperText=\"请输入你的全名\"\n      />\n      \n      \u003CFormInput\n        label=\"邮箱\"\n        name=\"email\"\n        type=\"email\"\n        value={formData.email}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        error={touched.email && errors.email}\n      />\n      \n      \u003CFormInput\n        label=\"密码\"\n        name=\"password\"\n        type=\"password\"\n        value={formData.password}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        error={touched.password && errors.password}\n        helperText=\"至少 8 个字符\"\n      />\n      \n      \u003CFormInput\n        label=\"确认密码\"\n        name=\"confirmPassword\"\n        type=\"password\"\n        value={formData.confirmPassword}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        error={touched.confirmPassword && errors.confirmPassword}\n      />\n      \n      \u003Cdiv className=\"form-group\">\n        \u003Clabel className=\"checkbox-label\">\n          \u003Cinput\n            type=\"checkbox\"\n            name=\"subscribe\"\n            checked={formData.subscribe}\n            onChange={handleChange}\n            className=\"checkbox-input\"\n          />\n          订阅我们的新闻通讯\n        \u003C/label>\n      \u003C/div>\n      \n      \u003Cdiv className=\"form-group\">\n        \u003Clabel className=\"checkbox-label\">\n          \u003Cinput\n            type=\"checkbox\"\n            name=\"terms\"\n            checked={formData.terms}\n            onChange={handleChange}\n            onBlur={handleBlur}\n            className=\"checkbox-input\"\n          />\n          我同意\n          \u003Ca href=\"/terms\" target=\"_blank\" rel=\"noopener noreferrer\">\n            服务条款\n          \u003C/a>\n          和\n          \u003Ca href=\"/privacy\" target=\"_blank\" rel=\"noopener noreferrer\">\n            隐私政策\n          \u003C/a>\n        \u003C/label>\n        {touched.terms && errors.terms && (\n          \u003Cp className=\"form-error\">{errors.terms}\u003C/p>\n        )}\n      \u003C/div>\n      \n      \u003Cbutton type=\"submit\" className=\"btn btn-primary btn-block\">\n        注册\n      \u003C/button>\n    \u003C/form>\n  );\n}\n",[1149],{"type":27,"tag":412,"props":1150,"children":1151},{"__ignoreMap":7},[1152],{"type":32,"value":1147},{"type":27,"tag":70,"props":1154,"children":1155},{"id":543},[1156],{"type":32,"value":543},{"type":27,"tag":28,"props":1158,"children":1159},{},[1160,1161,1165],{"type":32,"value":550},{"type":27,"tag":552,"props":1162,"children":1163},{},[1164],{"type":32,"value":556},{"type":32,"value":558},{"type":27,"tag":40,"props":1167,"children":1168},{},[1169,1174,1179,1184,1188],{"type":27,"tag":44,"props":1170,"children":1171},{},[1172],{"type":32,"value":1173},"使用正确的输入类型",{"type":27,"tag":44,"props":1175,"children":1176},{},[1177],{"type":32,"value":1178},"提供实时验证反馈",{"type":27,"tag":44,"props":1180,"children":1181},{},[1182],{"type":32,"value":1183},"清晰的标签和提示",{"type":27,"tag":44,"props":1185,"children":1186},{},[1187],{"type":32,"value":566},{"type":27,"tag":44,"props":1189,"children":1190},{},[1191],{"type":32,"value":592},{"type":27,"tag":28,"props":1193,"children":1194},{},[1195,1196,1200],{"type":32,"value":597},{"type":27,"tag":552,"props":1197,"children":1198},{},[1199],{"type":32,"value":602},{"type":32,"value":558},{"type":27,"tag":40,"props":1202,"children":1203},{},[1204,1209,1214,1219,1224],{"type":27,"tag":44,"props":1205,"children":1206},{},[1207],{"type":32,"value":1208},"隐藏标签",{"type":27,"tag":44,"props":1210,"children":1211},{},[1212],{"type":32,"value":1213},"过度使用占位符",{"type":27,"tag":44,"props":1215,"children":1216},{},[1217],{"type":32,"value":1218},"验证后立即提交",{"type":27,"tag":44,"props":1220,"children":1221},{},[1222],{"type":32,"value":1223},"忽视无障碍性",{"type":27,"tag":44,"props":1225,"children":1226},{},[1227],{"type":32,"value":1228},"复杂的验证规则",{"type":27,"tag":70,"props":1230,"children":1231},{"id":649},[1232],{"type":32,"value":649},{"type":27,"tag":40,"props":1234,"children":1236},{"className":1235},[655],[1237,1246,1255,1264,1273,1282],{"type":27,"tag":44,"props":1238,"children":1240},{"className":1239},[660],[1241,1244],{"type":27,"tag":663,"props":1242,"children":1243},{"disabled":665,"type":666},[],{"type":32,"value":1245}," 所有控件都可用键盘导航",{"type":27,"tag":44,"props":1247,"children":1249},{"className":1248},[660],[1250,1253],{"type":27,"tag":663,"props":1251,"children":1252},{"disabled":665,"type":666},[],{"type":32,"value":1254}," 标签与输入框关联",{"type":27,"tag":44,"props":1256,"children":1258},{"className":1257},[660],[1259,1262],{"type":27,"tag":663,"props":1260,"children":1261},{"disabled":665,"type":666},[],{"type":32,"value":1263}," 验证消息清晰",{"type":27,"tag":44,"props":1265,"children":1267},{"className":1266},[660],[1268,1271],{"type":27,"tag":663,"props":1269,"children":1270},{"disabled":665,"type":666},[],{"type":32,"value":1272}," 色彩对比度足够",{"type":27,"tag":44,"props":1274,"children":1276},{"className":1275},[660],[1277,1280],{"type":27,"tag":663,"props":1278,"children":1279},{"disabled":665,"type":666},[],{"type":32,"value":1281}," 屏幕阅读器兼容",{"type":27,"tag":44,"props":1283,"children":1285},{"className":1284},[660],[1286,1289],{"type":27,"tag":663,"props":1287,"children":1288},{"disabled":665,"type":666},[],{"type":32,"value":1290}," 移动设备测试",{"title":7,"searchDepth":350,"depth":350,"links":1292},[1293,1294,1298,1299,1300,1301,1302,1303,1304],{"id":1031,"depth":353,"text":1031},{"id":1053,"depth":353,"text":1053,"children":1295},[1296,1297],{"id":1058,"depth":350,"text":1058},{"id":1072,"depth":350,"text":1072},{"id":1037,"depth":353,"text":1037},{"id":1099,"depth":353,"text":1099},{"id":1113,"depth":353,"text":1113},{"id":1127,"depth":353,"text":1127},{"id":1141,"depth":353,"text":1141},{"id":543,"depth":353,"text":543},{"id":649,"depth":353,"text":649},"content:topics:design:form-controls-design.md","topics/design/form-controls-design.md","topics/design/form-controls-design",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"topic":5,"author":11,"tags":1309,"image":18,"imageQuery":19,"pexelsPhotoId":20,"pexelsUrl":21,"featured":6,"readingTime":22,"body":1310,"_type":360,"_id":361,"_source":362,"_file":363,"_stem":364,"_extension":365},[13,14,15,16,17],{"type":24,"children":1311,"toc":1565},[1312,1316,1320,1335,1339,1343,1347,1351,1374,1378,1382,1386,1390,1409,1413,1417,1421,1425,1436,1440,1444,1448,1463,1467,1471,1475,1479,1498,1502,1506,1529,1533,1537,1541],{"type":27,"tag":28,"props":1313,"children":1314},{},[1315],{"type":32,"value":33},{"type":27,"tag":28,"props":1317,"children":1318},{},[1319],{"type":32,"value":38},{"type":27,"tag":40,"props":1321,"children":1322},{},[1323,1327,1331],{"type":27,"tag":44,"props":1324,"children":1325},{},[1326],{"type":32,"value":48},{"type":27,"tag":44,"props":1328,"children":1329},{},[1330],{"type":32,"value":53},{"type":27,"tag":44,"props":1332,"children":1333},{},[1334],{"type":32,"value":58},{"type":27,"tag":28,"props":1336,"children":1337},{},[1338],{"type":32,"value":63},{"type":27,"tag":28,"props":1340,"children":1341},{},[1342],{"type":32,"value":68},{"type":27,"tag":70,"props":1344,"children":1345},{"id":72},[1346],{"type":32,"value":75},{"type":27,"tag":28,"props":1348,"children":1349},{},[1350],{"type":32,"value":80},{"type":27,"tag":40,"props":1352,"children":1353},{},[1354,1358,1362,1366,1370],{"type":27,"tag":44,"props":1355,"children":1356},{},[1357],{"type":32,"value":88},{"type":27,"tag":44,"props":1359,"children":1360},{},[1361],{"type":32,"value":93},{"type":27,"tag":44,"props":1363,"children":1364},{},[1365],{"type":32,"value":98},{"type":27,"tag":44,"props":1367,"children":1368},{},[1369],{"type":32,"value":103},{"type":27,"tag":44,"props":1371,"children":1372},{},[1373],{"type":32,"value":108},{"type":27,"tag":28,"props":1375,"children":1376},{},[1377],{"type":32,"value":113},{"type":27,"tag":70,"props":1379,"children":1380},{"id":116},[1381],{"type":32,"value":119},{"type":27,"tag":28,"props":1383,"children":1384},{},[1385],{"type":32,"value":124},{"type":27,"tag":28,"props":1387,"children":1388},{},[1389],{"type":32,"value":129},{"type":27,"tag":40,"props":1391,"children":1392},{},[1393,1397,1401,1405],{"type":27,"tag":44,"props":1394,"children":1395},{},[1396],{"type":32,"value":137},{"type":27,"tag":44,"props":1398,"children":1399},{},[1400],{"type":32,"value":142},{"type":27,"tag":44,"props":1402,"children":1403},{},[1404],{"type":32,"value":147},{"type":27,"tag":44,"props":1406,"children":1407},{},[1408],{"type":32,"value":152},{"type":27,"tag":28,"props":1410,"children":1411},{},[1412],{"type":32,"value":157},{"type":27,"tag":70,"props":1414,"children":1415},{"id":160},[1416],{"type":32,"value":163},{"type":27,"tag":28,"props":1418,"children":1419},{},[1420],{"type":32,"value":168},{"type":27,"tag":28,"props":1422,"children":1423},{},[1424],{"type":32,"value":173},{"type":27,"tag":40,"props":1426,"children":1427},{},[1428,1432],{"type":27,"tag":44,"props":1429,"children":1430},{},[1431],{"type":32,"value":181},{"type":27,"tag":44,"props":1433,"children":1434},{},[1435],{"type":32,"value":186},{"type":27,"tag":28,"props":1437,"children":1438},{},[1439],{"type":32,"value":191},{"type":27,"tag":70,"props":1441,"children":1442},{"id":194},[1443],{"type":32,"value":197},{"type":27,"tag":28,"props":1445,"children":1446},{},[1447],{"type":32,"value":202},{"type":27,"tag":40,"props":1449,"children":1450},{},[1451,1455,1459],{"type":27,"tag":44,"props":1452,"children":1453},{},[1454],{"type":32,"value":210},{"type":27,"tag":44,"props":1456,"children":1457},{},[1458],{"type":32,"value":215},{"type":27,"tag":44,"props":1460,"children":1461},{},[1462],{"type":32,"value":220},{"type":27,"tag":28,"props":1464,"children":1465},{},[1466],{"type":32,"value":225},{"type":27,"tag":70,"props":1468,"children":1469},{"id":228},[1470],{"type":32,"value":231},{"type":27,"tag":28,"props":1472,"children":1473},{},[1474],{"type":32,"value":236},{"type":27,"tag":28,"props":1476,"children":1477},{},[1478],{"type":32,"value":241},{"type":27,"tag":40,"props":1480,"children":1481},{},[1482,1486,1490,1494],{"type":27,"tag":44,"props":1483,"children":1484},{},[1485],{"type":32,"value":249},{"type":27,"tag":44,"props":1487,"children":1488},{},[1489],{"type":32,"value":254},{"type":27,"tag":44,"props":1491,"children":1492},{},[1493],{"type":32,"value":259},{"type":27,"tag":44,"props":1495,"children":1496},{},[1497],{"type":32,"value":264},{"type":27,"tag":28,"props":1499,"children":1500},{},[1501],{"type":32,"value":269},{"type":27,"tag":70,"props":1503,"children":1504},{"id":272},[1505],{"type":32,"value":272},{"type":27,"tag":40,"props":1507,"children":1508},{},[1509,1513,1517,1521,1525],{"type":27,"tag":44,"props":1510,"children":1511},{},[1512],{"type":32,"value":282},{"type":27,"tag":44,"props":1514,"children":1515},{},[1516],{"type":32,"value":287},{"type":27,"tag":44,"props":1518,"children":1519},{},[1520],{"type":32,"value":292},{"type":27,"tag":44,"props":1522,"children":1523},{},[1524],{"type":32,"value":297},{"type":27,"tag":44,"props":1526,"children":1527},{},[1528],{"type":32,"value":302},{"type":27,"tag":70,"props":1530,"children":1531},{"id":305},[1532],{"type":32,"value":305},{"type":27,"tag":28,"props":1534,"children":1535},{},[1536],{"type":32,"value":312},{"type":27,"tag":28,"props":1538,"children":1539},{},[1540],{"type":32,"value":317},{"type":27,"tag":40,"props":1542,"children":1543},{},[1544,1551,1558],{"type":27,"tag":44,"props":1545,"children":1546},{},[1547],{"type":27,"tag":325,"props":1548,"children":1549},{"href":327},[1550],{"type":32,"value":330},{"type":27,"tag":44,"props":1552,"children":1553},{},[1554],{"type":27,"tag":325,"props":1555,"children":1556},{"href":336},[1557],{"type":32,"value":339},{"type":27,"tag":44,"props":1559,"children":1560},{},[1561],{"type":27,"tag":325,"props":1562,"children":1563},{"href":345},[1564],{"type":32,"value":348},{"title":7,"searchDepth":350,"depth":350,"links":1566},[1567,1568,1569,1570,1571,1572,1573],{"id":72,"depth":353,"text":75},{"id":116,"depth":353,"text":119},{"id":160,"depth":353,"text":163},{"id":194,"depth":353,"text":197},{"id":228,"depth":353,"text":231},{"id":272,"depth":353,"text":272},{"id":305,"depth":353,"text":305},1777086813112]