[{"data":1,"prerenderedAt":1831},["ShallowReactive",2],{"article-/topics/design/page-design-spec-documentation-guide":3,"related-design":513,"content-query-tNF9XDBVK8":1455},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"topic":5,"author":11,"tags":12,"image":17,"imageQuery":18,"pexelsPhotoId":19,"pexelsUrl":20,"featured":6,"readingTime":21,"body":22,"_type":507,"_id":508,"_source":509,"_file":510,"_stem":511,"_extension":512},"/topics/design/page-design-spec-documentation-guide","design",false,"","页面设计说明怎么写：让设计、开发和运营都能按同一份文档执行","很多页面项目不是卡在设计稿，而是卡在没人能从设计稿里读出完整意图。本文把页面设计说明拆成目标、结构、组件状态、内容资源和上线注意事项五部分，讲清怎样写出一份真正能被执行的页面设计说明。","2026-05-19","HTMLPAGE 团队",[13,14,15,16],"页面设计","网页设计","设计文档","交付说明","/images/articles/page-design-spec-documentation-guide-featured.jpg","page design documentation notes wireframe laptop",4964749,"https://www.pexels.com/photo/shallow-focus-shot-of-papers-and-laptop-4964749/",15,{"type":23,"children":24,"toc":494},"root",[25,33,38,43,80,87,210,215,221,226,231,256,261,267,272,277,300,305,311,316,321,344,349,355,360,365,371,376,399,404,410,415,420,426,431,454,459,465,470,489],{"type":26,"tag":27,"props":28,"children":29},"element","p",{},[30],{"type":31,"value":32},"text","很多页面项目表面上已经有设计稿，真正推进时还是会不断出问号。开发问这个按钮点击后去哪，运营问这段文案是否能替换，市场问案例卡片是不是固定三张，设计又补一句“这里其实是想让用户先看方案再决定咨询”。也就是说，视觉稿虽然有了，但页面真正的执行意图并没有被完整交付出去。",{"type":26,"tag":27,"props":34,"children":35},{},[36],{"type":31,"value":37},"这类问题最容易被误会成沟通不够。更准确地说，它是文档缺位。页面设计说明的价值，并不是再把设计稿重复描述一次，而是把那些图里看不清、但执行时一定会遇到的判断写出来：页面目标是什么，模块先后为什么这样排，组件在什么状态下会变，哪些内容能改，哪些资源和上线注意事项必须跟着走。",{"type":26,"tag":27,"props":39,"children":40},{},[41],{"type":31,"value":42},"所以这篇文章不打算把页面设计说明写成厚重模板，而是回答一个更实际的问题：一份页面设计说明到底最少该包含什么，才能让设计、开发和运营按同一份文档执行，而不是在上线前后继续靠群消息补逻辑。",{"type":26,"tag":27,"props":44,"children":45},{},[46,48,55,57,63,64,70,72,78],{"type":31,"value":47},"如果你想把上下游文档链补全，可以搭配 ",{"type":26,"tag":49,"props":50,"children":52},"a",{"href":51},"/topics/design/web-design-proposal-goals-structure-visual-direction",[53],{"type":31,"value":54},"网页设计方案怎么写",{"type":31,"value":56},"、",{"type":26,"tag":49,"props":58,"children":60},{"href":59},"/topics/design/page-design-requirements-communication-guide",[61],{"type":31,"value":62},"页面设计需求怎么沟通",{"type":31,"value":56},{"type":26,"tag":49,"props":65,"children":67},{"href":66},"/topics/design/web-design-workflow-wireframe-visual-handoff-guide",[68],{"type":31,"value":69},"网页设计流程怎么推进",{"type":31,"value":71}," 和 ",{"type":26,"tag":49,"props":73,"children":75},{"href":74},"/topics/practical-tips/website-design-acceptance-visual-responsive-seo-guide",[76],{"type":31,"value":77},"网站设计验收怎么做",{"type":31,"value":79}," 一起看。",{"type":26,"tag":81,"props":82,"children":84},"h2",{"id":83},"先给结论页面设计说明至少要把五件事写清不然执行一定会靠猜",[85],{"type":31,"value":86},"先给结论：页面设计说明至少要把五件事写清，不然执行一定会靠猜",{"type":26,"tag":88,"props":89,"children":90},"table",{},[91,115],{"type":26,"tag":92,"props":93,"children":94},"thead",{},[95],{"type":26,"tag":96,"props":97,"children":98},"tr",{},[99,105,110],{"type":26,"tag":100,"props":101,"children":102},"th",{},[103],{"type":31,"value":104},"说明部分",{"type":26,"tag":100,"props":106,"children":107},{},[108],{"type":31,"value":109},"该写什么",{"type":26,"tag":100,"props":111,"children":112},{},[113],{"type":31,"value":114},"缺了会怎样",{"type":26,"tag":116,"props":117,"children":118},"tbody",{},[119,138,156,174,192],{"type":26,"tag":96,"props":120,"children":121},{},[122,128,133],{"type":26,"tag":123,"props":124,"children":125},"td",{},[126],{"type":31,"value":127},"页面目标",{"type":26,"tag":123,"props":129,"children":130},{},[131],{"type":31,"value":132},"页面服务谁、推动什么动作",{"type":26,"tag":123,"props":134,"children":135},{},[136],{"type":31,"value":137},"后续所有人都按自己的理解在补页",{"type":26,"tag":96,"props":139,"children":140},{},[141,146,151],{"type":26,"tag":123,"props":142,"children":143},{},[144],{"type":31,"value":145},"结构意图",{"type":26,"tag":123,"props":147,"children":148},{},[149],{"type":31,"value":150},"模块顺序、主路径和次路径",{"type":26,"tag":123,"props":152,"children":153},{},[154],{"type":31,"value":155},"运营和开发只能看图猜逻辑",{"type":26,"tag":96,"props":157,"children":158},{},[159,164,169],{"type":26,"tag":123,"props":160,"children":161},{},[162],{"type":31,"value":163},"组件状态",{"type":26,"tag":123,"props":165,"children":166},{},[167],{"type":31,"value":168},"按钮、表单、卡片、折叠等状态变化",{"type":26,"tag":123,"props":170,"children":171},{},[172],{"type":31,"value":173},"上线后交互和设计意图越走越远",{"type":26,"tag":96,"props":175,"children":176},{},[177,182,187],{"type":26,"tag":123,"props":178,"children":179},{},[180],{"type":31,"value":181},"内容与资源",{"type":26,"tag":123,"props":183,"children":184},{},[185],{"type":31,"value":186},"哪些文案、图片、案例可替换，来源是什么",{"type":26,"tag":123,"props":188,"children":189},{},[190],{"type":31,"value":191},"替换内容时频繁破坏版式",{"type":26,"tag":96,"props":193,"children":194},{},[195,200,205],{"type":26,"tag":123,"props":196,"children":197},{},[198],{"type":31,"value":199},"上线注意事项",{"type":26,"tag":123,"props":201,"children":202},{},[203],{"type":31,"value":204},"SEO、分享信息、埋点、异常提示等",{"type":26,"tag":123,"props":206,"children":207},{},[208],{"type":31,"value":209},"页面视觉对了，真实发布却没闭环",{"type":26,"tag":27,"props":211,"children":212},{},[213],{"type":31,"value":214},"一份有用的页面设计说明，不是把设计稿重新说一遍，而是把“图外信息”补齐。很多返工都来自这些图外信息没有被写出来。",{"type":26,"tag":81,"props":216,"children":218},{"id":217},"第一部分先写页面目标不要默认所有人都能从画面里看懂",[219],{"type":31,"value":220},"第一部分先写页面目标，不要默认所有人都能从画面里看懂",{"type":26,"tag":27,"props":222,"children":223},{},[224],{"type":31,"value":225},"页面设计说明最容易被省略的一段，就是目标说明。团队会觉得目标前面已经讲过，或者“看页面就知道是做什么的”。现实里这通常并不成立。因为同一版页面，在不同角色眼里会被理解成不同任务：设计觉得这是一版品牌页，销售觉得它更像咨询页，运营又想让它兼顾内容分发。",{"type":26,"tag":27,"props":227,"children":228},{},[229],{"type":31,"value":230},"所以页面设计说明最好直接写清：",{"type":26,"tag":232,"props":233,"children":234},"ul",{},[235,241,246,251],{"type":26,"tag":236,"props":237,"children":238},"li",{},[239],{"type":31,"value":240},"这页主要给谁看",{"type":26,"tag":236,"props":242,"children":243},{},[244],{"type":31,"value":245},"用户进入后最先该理解什么",{"type":26,"tag":236,"props":247,"children":248},{},[249],{"type":31,"value":250},"页面最希望推动的动作是什么",{"type":26,"tag":236,"props":252,"children":253},{},[254],{"type":31,"value":255},"哪些动作只是辅助，不是主路径",{"type":26,"tag":27,"props":257,"children":258},{},[259],{"type":31,"value":260},"只要这一段不写，后续所有执行动作都更容易漂移。因为每个人都在帮项目推进，但推进的是自己理解里的那个页面。",{"type":26,"tag":81,"props":262,"children":264},{"id":263},"第二部分写结构意图不要只留一张线框或高保真图",[265],{"type":31,"value":266},"第二部分写结构意图，不要只留一张线框或高保真图",{"type":26,"tag":27,"props":268,"children":269},{},[270],{"type":31,"value":271},"很多页面交付时会附上线框或视觉稿，团队就默认结构已经足够清楚。问题是，结构不只是“模块长什么样”，更是“为什么这样排”。一张图可以让你看见顺序，却不一定能告诉你：证据为什么出现在这里，FAQ 为什么放在 CTA 前，某个模块为什么可以删，另一个却不能动。",{"type":26,"tag":27,"props":273,"children":274},{},[275],{"type":31,"value":276},"页面设计说明里更该补的，就是这层结构意图：",{"type":26,"tag":232,"props":278,"children":279},{},[280,285,290,295],{"type":26,"tag":236,"props":281,"children":282},{},[283],{"type":31,"value":284},"模块的主次关系",{"type":26,"tag":236,"props":286,"children":287},{},[288],{"type":31,"value":289},"用户从上到下的判断链",{"type":26,"tag":236,"props":291,"children":292},{},[293],{"type":31,"value":294},"哪些模块属于核心逻辑，哪些只是辅助增强",{"type":26,"tag":236,"props":296,"children":297},{},[298],{"type":31,"value":299},"如果后续删减，优先删哪一类内容",{"type":26,"tag":27,"props":301,"children":302},{},[303],{"type":31,"value":304},"这部分越清楚，后续运营替换内容或开发实现时越不容易把页面主线弄散。",{"type":26,"tag":81,"props":306,"children":308},{"id":307},"第三部分必须写组件状态因为页面不是一张静态海报",[309],{"type":31,"value":310},"第三部分必须写组件状态，因为页面不是一张静态海报",{"type":26,"tag":27,"props":312,"children":313},{},[314],{"type":31,"value":315},"很多页面项目明明有设计稿，上线后还是和原意差很远，原因常常在于组件状态没人写。按钮 hover 怎么表现，表单报错怎么提示，FAQ 展开后高度如何变化，下载态、提交成功态、空状态、加载态要不要出现，这些如果只存在于设计师脑中，最终就只能由开发或运营在实现时临场决定。",{"type":26,"tag":27,"props":317,"children":318},{},[319],{"type":31,"value":320},"页面设计说明不需要把每个像素都写满，但至少要把关键组件的状态变化列出来，尤其是：",{"type":26,"tag":232,"props":322,"children":323},{},[324,329,334,339],{"type":26,"tag":236,"props":325,"children":326},{},[327],{"type":31,"value":328},"CTA 按钮的主次状态",{"type":26,"tag":236,"props":330,"children":331},{},[332],{"type":31,"value":333},"表单默认态、校验态、成功态和失败态",{"type":26,"tag":236,"props":335,"children":336},{},[337],{"type":31,"value":338},"折叠区、弹层、标签切换或轮播等交互组件",{"type":26,"tag":236,"props":340,"children":341},{},[342],{"type":31,"value":343},"图片或卡片在不同内容长度下的最小约束",{"type":26,"tag":27,"props":345,"children":346},{},[347],{"type":31,"value":348},"只要这些状态不写，页面最终呈现就很可能只保留了“静态好看”的那一半。",{"type":26,"tag":81,"props":350,"children":352},{"id":351},"内容与资源说明决定后续替换会不会持续破坏页面",[353],{"type":31,"value":354},"内容与资源说明，决定后续替换会不会持续破坏页面",{"type":26,"tag":27,"props":356,"children":357},{},[358],{"type":31,"value":359},"很多页面在设计交付阶段看起来没问题，一进入真实运营就开始走样。不是因为页面不能改，而是因为没人说明哪些内容可以自由替换，哪些内容需要保持长度、比例、顺序或语气边界。例如案例卡片到底最多几行、首屏副标题能不能换成更长版本、图片是否必须保持同一比例、CTA 文案是否能改成更强销售语气，这些都属于内容和资源边界。",{"type":26,"tag":27,"props":361,"children":362},{},[363],{"type":31,"value":364},"页面设计说明如果把这层写清，后续运营就更容易在规则内替换；如果完全不写，设计交付很快就会变成“上线后一改就散”。",{"type":26,"tag":81,"props":366,"children":368},{"id":367},"上线注意事项别再留给群消息直接写进说明里",[369],{"type":31,"value":370},"上线注意事项别再留给群消息，直接写进说明里",{"type":26,"tag":27,"props":372,"children":373},{},[374],{"type":31,"value":375},"页面设计说明还有一个最常被忽视的部分，就是上线注意事项。很多团队会觉得这属于运营或技术，不必放在设计说明里。但只要这些动作会改变页面最终体验，它就应该被写进说明。例如：",{"type":26,"tag":232,"props":377,"children":378},{},[379,384,389,394],{"type":26,"tag":236,"props":380,"children":381},{},[382],{"type":31,"value":383},"页面标题、描述和分享图要求",{"type":26,"tag":236,"props":385,"children":386},{},[387],{"type":31,"value":388},"表单提交后的跳转或反馈方式",{"type":26,"tag":236,"props":390,"children":391},{},[392],{"type":31,"value":393},"埋点位置或关键动作追踪",{"type":26,"tag":236,"props":395,"children":396},{},[397],{"type":31,"value":398},"特定区块在不同渠道分享时的注意点",{"type":26,"tag":27,"props":400,"children":401},{},[402],{"type":31,"value":403},"这些信息如果散落在聊天记录里，项目越往后越难回收。说明文档真正值钱的地方，就是它能让关键信息不再只依赖“谁还记得”。",{"type":26,"tag":81,"props":405,"children":407},{"id":406},"失败案例设计稿很完整上线后还是变成了另一种页面",[408],{"type":31,"value":409},"失败案例：设计稿很完整，上线后还是变成了另一种页面",{"type":26,"tag":27,"props":411,"children":412},{},[413],{"type":31,"value":414},"一个典型情况是，某团队交付了一版看起来很完整的活动页设计稿：首屏、卖点、案例、FAQ、表单一应俱全。开发按图实现，运营上线前又把文案和图片换成了真实版本。最后页面并没有明显 bug，但转化表现却不如预期。回头看才发现，首屏副标题被拉长后把 CTA 挤到了折叠下，案例卡片标题长度不受控导致布局参差，表单成功态也被做成了很弱的一行字。",{"type":26,"tag":27,"props":416,"children":417},{},[418],{"type":31,"value":419},"这些都不是单点失误，而是因为页面设计说明里只交了图，没有把内容边界、组件状态和上线注意事项一起交出去。于是每个环节都做了“看起来合理”的改动，整页却慢慢偏离了原本意图。",{"type":26,"tag":81,"props":421,"children":423},{"id":422},"什么时候说明文档可以轻什么时候不能省",[424],{"type":31,"value":425},"什么时候说明文档可以轻，什么时候不能省",{"type":26,"tag":27,"props":427,"children":428},{},[429],{"type":31,"value":430},"并不是每个页面都要一份很长的设计说明。如果只是一次性简单页面、内容短、参与角色少，说明可以很轻。但只要出现下面这些条件，说明文档最好不要省：",{"type":26,"tag":232,"props":432,"children":433},{},[434,439,444,449],{"type":26,"tag":236,"props":435,"children":436},{},[437],{"type":31,"value":438},"页面会被多个角色长期维护",{"type":26,"tag":236,"props":440,"children":441},{},[442],{"type":31,"value":443},"文案和素材会频繁替换",{"type":26,"tag":236,"props":445,"children":446},{},[447],{"type":31,"value":448},"页面里有表单、下载、折叠、切换等状态变化",{"type":26,"tag":236,"props":450,"children":451},{},[452],{"type":31,"value":453},"页面上线后还要持续做优化和复用",{"type":26,"tag":27,"props":455,"children":456},{},[457],{"type":31,"value":458},"说明文档是否需要完整，不取决于页面美不美，而取决于执行链有多长、会不会持续变化。",{"type":26,"tag":81,"props":460,"children":462},{"id":461},"先做什么先把图外信息从聊天记录里拉回文档",[463],{"type":31,"value":464},"先做什么：先把图外信息从聊天记录里拉回文档",{"type":26,"tag":27,"props":466,"children":467},{},[468],{"type":31,"value":469},"如果你现在就要交付一版页面，更稳的起手动作通常是这三步：",{"type":26,"tag":471,"props":472,"children":473},"ol",{},[474,479,484],{"type":26,"tag":236,"props":475,"children":476},{},[477],{"type":31,"value":478},"先补一页“页面目标 + 结构意图”说明，不要只交画面。",{"type":26,"tag":236,"props":480,"children":481},{},[482],{"type":31,"value":483},"把关键组件状态和内容替换边界单独列出来。",{"type":26,"tag":236,"props":485,"children":486},{},[487],{"type":31,"value":488},"把 SEO、表单、埋点和分享信息这些上线要求，直接写进同一份文档。",{"type":26,"tag":27,"props":490,"children":491},{},[492],{"type":31,"value":493},"页面设计说明真正的价值，不是把文档做得像规范手册，而是让执行链上的每个人都不必靠猜来完成工作。只要目标、结构、状态、内容和上线注意事项被写清，一份页面才算真正被交付出去，而不是只被画出来。",{"title":7,"searchDepth":495,"depth":495,"links":496},3,[497,499,500,501,502,503,504,505,506],{"id":83,"depth":498,"text":86},2,{"id":217,"depth":498,"text":220},{"id":263,"depth":498,"text":266},{"id":307,"depth":498,"text":310},{"id":351,"depth":498,"text":354},{"id":367,"depth":498,"text":370},{"id":406,"depth":498,"text":409},{"id":422,"depth":498,"text":425},{"id":461,"depth":498,"text":464},"markdown","content:topics:design:page-design-spec-documentation-guide.md","content","topics/design/page-design-spec-documentation-guide.md","topics/design/page-design-spec-documentation-guide","md",[514,874,1176],{"_path":515,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":516,"description":517,"keywords":518,"image":524,"author":11,"date":525,"readingTime":526,"topic":5,"body":527,"_type":507,"_id":871,"_source":509,"_file":872,"_stem":873,"_extension":512},"/topics/design/button-component-design","按钮组件设计详解","学习按钮样式、交互状态、无障碍性和最佳实践",[519,520,521,522,523],"按钮设计","Button Component","交互状态","UI 组件","用户体验","/images/topics/button-design.jpg","2025-12-08",18,{"type":23,"children":528,"toc":853},[529,533,538,543,550,563,569,578,584,593,597,603,614,620,629,635,644,649,658,663,674,679,688,693,706,740,751,794,799],{"type":26,"tag":81,"props":530,"children":531},{"id":516},[532],{"type":31,"value":516},{"type":26,"tag":27,"props":534,"children":535},{},[536],{"type":31,"value":537},"按钮是 UI 中最重要的交互元素。优秀的按钮设计能够指导用户行为。",{"type":26,"tag":81,"props":539,"children":541},{"id":540},"按钮类型",[542],{"type":31,"value":540},{"type":26,"tag":544,"props":545,"children":547},"h3",{"id":546},"primary-button主按钮",[548],{"type":31,"value":549},"Primary Button（主按钮）",{"type":26,"tag":551,"props":552,"children":557},"pre",{"className":553,"code":555,"language":556,"meta":7},[554],"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",[558],{"type":26,"tag":559,"props":560,"children":561},"code",{"__ignoreMap":7},[562],{"type":31,"value":555},{"type":26,"tag":544,"props":564,"children":566},{"id":565},"secondary-button次按钮",[567],{"type":31,"value":568},"Secondary Button（次按钮）",{"type":26,"tag":551,"props":570,"children":573},{"className":571,"code":572,"language":556,"meta":7},[554],".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",[574],{"type":26,"tag":559,"props":575,"children":576},{"__ignoreMap":7},[577],{"type":31,"value":572},{"type":26,"tag":544,"props":579,"children":581},{"id":580},"danger-button危险按钮",[582],{"type":31,"value":583},"Danger Button（危险按钮）",{"type":26,"tag":551,"props":585,"children":588},{"className":586,"code":587,"language":556,"meta":7},[554],".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",[589],{"type":26,"tag":559,"props":590,"children":591},{"__ignoreMap":7},[592],{"type":31,"value":587},{"type":26,"tag":81,"props":594,"children":595},{"id":521},[596],{"type":31,"value":521},{"type":26,"tag":544,"props":598,"children":600},{"id":599},"loading-状态",[601],{"type":31,"value":602},"Loading 状态",{"type":26,"tag":551,"props":604,"children":609},{"className":605,"code":607,"language":608,"meta":7},[606],"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",[610],{"type":26,"tag":559,"props":611,"children":612},{"__ignoreMap":7},[613],{"type":31,"value":607},{"type":26,"tag":544,"props":615,"children":617},{"id":616},"disabled-状态",[618],{"type":31,"value":619},"Disabled 状态",{"type":26,"tag":551,"props":621,"children":624},{"className":622,"code":623,"language":556,"meta":7},[554],".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",[625],{"type":26,"tag":559,"props":626,"children":627},{"__ignoreMap":7},[628],{"type":31,"value":623},{"type":26,"tag":544,"props":630,"children":632},{"id":631},"focus-状态",[633],{"type":31,"value":634},"Focus 状态",{"type":26,"tag":551,"props":636,"children":639},{"className":637,"code":638,"language":556,"meta":7},[554],".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",[640],{"type":26,"tag":559,"props":641,"children":642},{"__ignoreMap":7},[643],{"type":31,"value":638},{"type":26,"tag":81,"props":645,"children":647},{"id":646},"按钮大小",[648],{"type":31,"value":646},{"type":26,"tag":551,"props":650,"children":653},{"className":651,"code":652,"language":556,"meta":7},[554],"/* 小按钮 */\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",[654],{"type":26,"tag":559,"props":655,"children":656},{"__ignoreMap":7},[657],{"type":31,"value":652},{"type":26,"tag":81,"props":659,"children":661},{"id":660},"无障碍性",[662],{"type":31,"value":660},{"type":26,"tag":551,"props":664,"children":669},{"className":665,"code":667,"language":668,"meta":7},[666],"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",[670],{"type":26,"tag":559,"props":671,"children":672},{"__ignoreMap":7},[673],{"type":31,"value":667},{"type":26,"tag":81,"props":675,"children":677},{"id":676},"完整组件示例",[678],{"type":31,"value":676},{"type":26,"tag":551,"props":680,"children":683},{"className":681,"code":682,"language":608,"meta":7},[606],"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",[684],{"type":26,"tag":559,"props":685,"children":686},{"__ignoreMap":7},[687],{"type":31,"value":682},{"type":26,"tag":81,"props":689,"children":691},{"id":690},"最佳实践",[692],{"type":31,"value":690},{"type":26,"tag":27,"props":694,"children":695},{},[696,698,704],{"type":31,"value":697},"✅ ",{"type":26,"tag":699,"props":700,"children":701},"strong",{},[702],{"type":31,"value":703},"应该做的事",{"type":31,"value":705},":",{"type":26,"tag":232,"props":707,"children":708},{},[709,714,719,730,735],{"type":26,"tag":236,"props":710,"children":711},{},[712],{"type":31,"value":713},"最小触摸目标 44x44px",{"type":26,"tag":236,"props":715,"children":716},{},[717],{"type":31,"value":718},"清晰的视觉反馈",{"type":26,"tag":236,"props":720,"children":721},{},[722,724],{"type":31,"value":723},"使用语义 HTML ",{"type":26,"tag":559,"props":725,"children":727},{"className":726},[],[728],{"type":31,"value":729},"\u003Cbutton>",{"type":26,"tag":236,"props":731,"children":732},{},[733],{"type":31,"value":734},"提供加载状态反馈",{"type":26,"tag":236,"props":736,"children":737},{},[738],{"type":31,"value":739},"支持键盘导航",{"type":26,"tag":27,"props":741,"children":742},{},[743,745,750],{"type":31,"value":744},"❌ ",{"type":26,"tag":699,"props":746,"children":747},{},[748],{"type":31,"value":749},"不应该做的事",{"type":31,"value":705},{"type":26,"tag":232,"props":752,"children":753},{},[754,767,772,777,782],{"type":26,"tag":236,"props":755,"children":756},{},[757,759,765],{"type":31,"value":758},"使用 ",{"type":26,"tag":559,"props":760,"children":762},{"className":761},[],[763],{"type":31,"value":764},"\u003Cdiv>",{"type":31,"value":766}," 模拟按钮",{"type":26,"tag":236,"props":768,"children":769},{},[770],{"type":31,"value":771},"隐藏焦点指示器",{"type":26,"tag":236,"props":773,"children":774},{},[775],{"type":31,"value":776},"过多的按钮样式",{"type":26,"tag":236,"props":778,"children":779},{},[780],{"type":31,"value":781},"忽视禁用状态",{"type":26,"tag":236,"props":783,"children":784},{},[785,786,792],{"type":31,"value":758},{"type":26,"tag":559,"props":787,"children":789},{"className":788},[],[790],{"type":31,"value":791},"\u003Ca>",{"type":31,"value":793}," 代替按钮",{"type":26,"tag":81,"props":795,"children":797},{"id":796},"测试清单",[798],{"type":31,"value":796},{"type":26,"tag":232,"props":800,"children":803},{"className":801},[802],"contains-task-list",[804,817,826,835,844],{"type":26,"tag":236,"props":805,"children":808},{"className":806},[807],"task-list-item",[809,815],{"type":26,"tag":810,"props":811,"children":814},"input",{"disabled":812,"type":813},true,"checkbox",[],{"type":31,"value":816}," 在各种浏览器中测试",{"type":26,"tag":236,"props":818,"children":820},{"className":819},[807],[821,824],{"type":26,"tag":810,"props":822,"children":823},{"disabled":812,"type":813},[],{"type":31,"value":825}," 验证键盘导航",{"type":26,"tag":236,"props":827,"children":829},{"className":828},[807],[830,833],{"type":26,"tag":810,"props":831,"children":832},{"disabled":812,"type":813},[],{"type":31,"value":834}," 检查色彩对比度",{"type":26,"tag":236,"props":836,"children":838},{"className":837},[807],[839,842],{"type":26,"tag":810,"props":840,"children":841},{"disabled":812,"type":813},[],{"type":31,"value":843}," 测试触摸设备",{"type":26,"tag":236,"props":845,"children":847},{"className":846},[807],[848,851],{"type":26,"tag":810,"props":849,"children":850},{"disabled":812,"type":813},[],{"type":31,"value":852}," 屏幕阅读器兼容性",{"title":7,"searchDepth":495,"depth":495,"links":854},[855,856,861,866,867,868,869,870],{"id":516,"depth":498,"text":516},{"id":540,"depth":498,"text":540,"children":857},[858,859,860],{"id":546,"depth":495,"text":549},{"id":565,"depth":495,"text":568},{"id":580,"depth":495,"text":583},{"id":521,"depth":498,"text":521,"children":862},[863,864,865],{"id":599,"depth":495,"text":602},{"id":616,"depth":495,"text":619},{"id":631,"depth":495,"text":634},{"id":646,"depth":498,"text":646},{"id":660,"depth":498,"text":660},{"id":676,"depth":498,"text":676},{"id":690,"depth":498,"text":690},{"id":796,"depth":498,"text":796},"content:topics:design:button-component-design.md","topics/design/button-component-design.md","topics/design/button-component-design",{"_path":875,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":876,"description":877,"keywords":878,"image":883,"author":11,"date":525,"readingTime":884,"topic":5,"body":885,"_type":507,"_id":1173,"_source":509,"_file":1174,"_stem":1175,"_extension":512},"/topics/design/dark-mode-design","暗黑模式设计完整方案","学习暗黑模式实现、色彩方案、对比度管理和最佳实践",[879,880,881,882,523],"暗黑模式","Dark Mode","色彩系统","CSS 变量","/images/topics/dark-mode-design.jpg",20,{"type":23,"children":886,"toc":1156},[887,891,896,901,907,916,922,931,936,942,951,957,968,974,983,988,997,1002,1011,1016,1025,1029,1038,1066,1075,1103,1107],{"type":26,"tag":81,"props":888,"children":889},{"id":876},[890],{"type":31,"value":876},{"type":26,"tag":27,"props":892,"children":893},{},[894],{"type":31,"value":895},"暗黑模式已成为现代应用的标准功能。它能够减少眼睛疲劳、节省电池、改善用户体验。",{"type":26,"tag":81,"props":897,"children":899},{"id":898},"核心色彩系统",[900],{"type":31,"value":898},{"type":26,"tag":544,"props":902,"children":904},{"id":903},"light-mode-配色",[905],{"type":31,"value":906},"Light Mode 配色",{"type":26,"tag":551,"props":908,"children":911},{"className":909,"code":910,"language":556,"meta":7},[554],":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",[912],{"type":26,"tag":559,"props":913,"children":914},{"__ignoreMap":7},[915],{"type":31,"value":910},{"type":26,"tag":544,"props":917,"children":919},{"id":918},"dark-mode-配色",[920],{"type":31,"value":921},"Dark Mode 配色",{"type":26,"tag":551,"props":923,"children":926},{"className":924,"code":925,"language":556,"meta":7},[554],"@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",[927],{"type":26,"tag":559,"props":928,"children":929},{"__ignoreMap":7},[930],{"type":31,"value":925},{"type":26,"tag":81,"props":932,"children":934},{"id":933},"实现方案",[935],{"type":31,"value":933},{"type":26,"tag":544,"props":937,"children":939},{"id":938},"方案-1prefers-color-scheme",[940],{"type":31,"value":941},"方案 1：prefers-color-scheme",{"type":26,"tag":551,"props":943,"children":946},{"className":944,"code":945,"language":556,"meta":7},[554],"/* 自动跟随系统设置 */\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",[947],{"type":26,"tag":559,"props":948,"children":949},{"__ignoreMap":7},[950],{"type":31,"value":945},{"type":26,"tag":544,"props":952,"children":954},{"id":953},"方案-2javascript-切换",[955],{"type":31,"value":956},"方案 2：JavaScript 切换",{"type":26,"tag":551,"props":958,"children":963},{"className":959,"code":961,"language":962,"meta":7},[960],"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",[964],{"type":26,"tag":559,"props":965,"children":966},{"__ignoreMap":7},[967],{"type":31,"value":961},{"type":26,"tag":544,"props":969,"children":971},{"id":970},"方案-3css-variables-javascript",[972],{"type":31,"value":973},"方案 3：CSS Variables + JavaScript",{"type":26,"tag":551,"props":975,"children":978},{"className":976,"code":977,"language":962,"meta":7},[960],"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",[979],{"type":26,"tag":559,"props":980,"children":981},{"__ignoreMap":7},[982],{"type":31,"value":977},{"type":26,"tag":81,"props":984,"children":986},{"id":985},"对比度管理",[987],{"type":31,"value":985},{"type":26,"tag":551,"props":989,"children":992},{"className":990,"code":991,"language":556,"meta":7},[554],"/* 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",[993],{"type":26,"tag":559,"props":994,"children":995},{"__ignoreMap":7},[996],{"type":31,"value":991},{"type":26,"tag":81,"props":998,"children":1000},{"id":999},"图片和图表处理",[1001],{"type":31,"value":999},{"type":26,"tag":551,"props":1003,"children":1006},{"className":1004,"code":1005,"language":668,"meta":7},[666],"\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",[1007],{"type":26,"tag":559,"props":1008,"children":1009},{"__ignoreMap":7},[1010],{"type":31,"value":1005},{"type":26,"tag":81,"props":1012,"children":1014},{"id":1013},"完整示例",[1015],{"type":31,"value":1013},{"type":26,"tag":551,"props":1017,"children":1020},{"className":1018,"code":1019,"language":608,"meta":7},[606],"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",[1021],{"type":26,"tag":559,"props":1022,"children":1023},{"__ignoreMap":7},[1024],{"type":31,"value":1019},{"type":26,"tag":81,"props":1026,"children":1027},{"id":690},[1028],{"type":31,"value":690},{"type":26,"tag":27,"props":1030,"children":1031},{},[1032,1033,1037],{"type":31,"value":697},{"type":26,"tag":699,"props":1034,"children":1035},{},[1036],{"type":31,"value":703},{"type":31,"value":705},{"type":26,"tag":232,"props":1039,"children":1040},{},[1041,1046,1051,1056,1061],{"type":26,"tag":236,"props":1042,"children":1043},{},[1044],{"type":31,"value":1045},"支持系统偏好",{"type":26,"tag":236,"props":1047,"children":1048},{},[1049],{"type":31,"value":1050},"提供手动切换选项",{"type":26,"tag":236,"props":1052,"children":1053},{},[1054],{"type":31,"value":1055},"确保足够的对比度",{"type":26,"tag":236,"props":1057,"children":1058},{},[1059],{"type":31,"value":1060},"优化图片和图表",{"type":26,"tag":236,"props":1062,"children":1063},{},[1064],{"type":31,"value":1065},"防止加载闪烁",{"type":26,"tag":27,"props":1067,"children":1068},{},[1069,1070,1074],{"type":31,"value":744},{"type":26,"tag":699,"props":1071,"children":1072},{},[1073],{"type":31,"value":749},{"type":31,"value":705},{"type":26,"tag":232,"props":1076,"children":1077},{},[1078,1083,1088,1093,1098],{"type":26,"tag":236,"props":1079,"children":1080},{},[1081],{"type":31,"value":1082},"强制单一模式",{"type":26,"tag":236,"props":1084,"children":1085},{},[1086],{"type":31,"value":1087},"忽视性能影响",{"type":26,"tag":236,"props":1089,"children":1090},{},[1091],{"type":31,"value":1092},"使用相同的颜色",{"type":26,"tag":236,"props":1094,"children":1095},{},[1096],{"type":31,"value":1097},"忘记保存用户偏好",{"type":26,"tag":236,"props":1099,"children":1100},{},[1101],{"type":31,"value":1102},"过度使用深色背景",{"type":26,"tag":81,"props":1104,"children":1105},{"id":796},[1106],{"type":31,"value":796},{"type":26,"tag":232,"props":1108,"children":1110},{"className":1109},[802],[1111,1120,1129,1138,1147],{"type":26,"tag":236,"props":1112,"children":1114},{"className":1113},[807],[1115,1118],{"type":26,"tag":810,"props":1116,"children":1117},{"disabled":812,"type":813},[],{"type":31,"value":1119}," 在浅色和深色模式下测试所有页面",{"type":26,"tag":236,"props":1121,"children":1123},{"className":1122},[807],[1124,1127],{"type":26,"tag":810,"props":1125,"children":1126},{"disabled":812,"type":813},[],{"type":31,"value":1128}," 检查颜色对比度符合 WCAG 标准",{"type":26,"tag":236,"props":1130,"children":1132},{"className":1131},[807],[1133,1136],{"type":26,"tag":810,"props":1134,"children":1135},{"disabled":812,"type":813},[],{"type":31,"value":1137}," 验证图片和图表在两种模式下清晰",{"type":26,"tag":236,"props":1139,"children":1141},{"className":1140},[807],[1142,1145],{"type":26,"tag":810,"props":1143,"children":1144},{"disabled":812,"type":813},[],{"type":31,"value":1146}," 测试主题切换的平滑性",{"type":26,"tag":236,"props":1148,"children":1150},{"className":1149},[807],[1151,1154],{"type":26,"tag":810,"props":1152,"children":1153},{"disabled":812,"type":813},[],{"type":31,"value":1155}," 检查用户偏好是否被保存",{"title":7,"searchDepth":495,"depth":495,"links":1157},[1158,1159,1163,1168,1169,1170,1171,1172],{"id":876,"depth":498,"text":876},{"id":898,"depth":498,"text":898,"children":1160},[1161,1162],{"id":903,"depth":495,"text":906},{"id":918,"depth":495,"text":921},{"id":933,"depth":498,"text":933,"children":1164},[1165,1166,1167],{"id":938,"depth":495,"text":941},{"id":953,"depth":495,"text":956},{"id":970,"depth":495,"text":973},{"id":985,"depth":498,"text":985},{"id":999,"depth":498,"text":999},{"id":1013,"depth":498,"text":1013},{"id":690,"depth":498,"text":690},{"id":796,"depth":498,"text":796},"content:topics:design:dark-mode-design.md","topics/design/dark-mode-design.md","topics/design/dark-mode-design",{"_path":1177,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1178,"description":1179,"keywords":1180,"image":1185,"author":1186,"date":525,"readingTime":884,"topic":5,"body":1187,"_type":507,"_id":1452,"_source":509,"_file":1453,"_stem":1454,"_extension":512},"/topics/design/form-controls-design","表单控件设计规范","学习输入框、选择框、复选框等表单控件的设计和实现",[1181,1182,1183,1184,523],"表单设计","Form Controls","输入框","验证反馈","/images/topics/form-controls-design.jpg","AI Content Team",{"type":23,"children":1188,"toc":1438},[1189,1193,1198,1203,1208,1217,1222,1231,1235,1244,1249,1258,1263,1272,1277,1286,1291,1300,1304,1313,1339,1348,1376,1380],{"type":26,"tag":81,"props":1190,"children":1191},{"id":1178},[1192],{"type":31,"value":1178},{"type":26,"tag":27,"props":1194,"children":1195},{},[1196],{"type":31,"value":1197},"优秀的表单设计能够提高用户完成率和满意度。",{"type":26,"tag":81,"props":1199,"children":1201},{"id":1200},"输入框设计",[1202],{"type":31,"value":1200},{"type":26,"tag":544,"props":1204,"children":1206},{"id":1205},"基础文本输入",[1207],{"type":31,"value":1205},{"type":26,"tag":551,"props":1209,"children":1212},{"className":1210,"code":1211,"language":556,"meta":7},[554],".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",[1213],{"type":26,"tag":559,"props":1214,"children":1215},{"__ignoreMap":7},[1216],{"type":31,"value":1211},{"type":26,"tag":544,"props":1218,"children":1220},{"id":1219},"标签和提示",[1221],{"type":31,"value":1219},{"type":26,"tag":551,"props":1223,"children":1226},{"className":1224,"code":1225,"language":668,"meta":7},[666],"\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",[1227],{"type":26,"tag":559,"props":1228,"children":1229},{"__ignoreMap":7},[1230],{"type":31,"value":1225},{"type":26,"tag":81,"props":1232,"children":1233},{"id":1184},[1234],{"type":31,"value":1184},{"type":26,"tag":551,"props":1236,"children":1239},{"className":1237,"code":1238,"language":608,"meta":7},[606],"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",[1240],{"type":26,"tag":559,"props":1241,"children":1242},{"__ignoreMap":7},[1243],{"type":31,"value":1238},{"type":26,"tag":81,"props":1245,"children":1247},{"id":1246},"选择框设计",[1248],{"type":31,"value":1246},{"type":26,"tag":551,"props":1250,"children":1253},{"className":1251,"code":1252,"language":556,"meta":7},[554],".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",[1254],{"type":26,"tag":559,"props":1255,"children":1256},{"__ignoreMap":7},[1257],{"type":31,"value":1252},{"type":26,"tag":81,"props":1259,"children":1261},{"id":1260},"复选框和单选按钮",[1262],{"type":31,"value":1260},{"type":26,"tag":551,"props":1264,"children":1267},{"className":1265,"code":1266,"language":556,"meta":7},[554],".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",[1268],{"type":26,"tag":559,"props":1269,"children":1270},{"__ignoreMap":7},[1271],{"type":31,"value":1266},{"type":26,"tag":81,"props":1273,"children":1275},{"id":1274},"文本区域",[1276],{"type":31,"value":1274},{"type":26,"tag":551,"props":1278,"children":1281},{"className":1279,"code":1280,"language":556,"meta":7},[554],".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",[1282],{"type":26,"tag":559,"props":1283,"children":1284},{"__ignoreMap":7},[1285],{"type":31,"value":1280},{"type":26,"tag":81,"props":1287,"children":1289},{"id":1288},"完整表单示例",[1290],{"type":31,"value":1288},{"type":26,"tag":551,"props":1292,"children":1295},{"className":1293,"code":1294,"language":608,"meta":7},[606],"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",[1296],{"type":26,"tag":559,"props":1297,"children":1298},{"__ignoreMap":7},[1299],{"type":31,"value":1294},{"type":26,"tag":81,"props":1301,"children":1302},{"id":690},[1303],{"type":31,"value":690},{"type":26,"tag":27,"props":1305,"children":1306},{},[1307,1308,1312],{"type":31,"value":697},{"type":26,"tag":699,"props":1309,"children":1310},{},[1311],{"type":31,"value":703},{"type":31,"value":705},{"type":26,"tag":232,"props":1314,"children":1315},{},[1316,1321,1326,1331,1335],{"type":26,"tag":236,"props":1317,"children":1318},{},[1319],{"type":31,"value":1320},"使用正确的输入类型",{"type":26,"tag":236,"props":1322,"children":1323},{},[1324],{"type":31,"value":1325},"提供实时验证反馈",{"type":26,"tag":236,"props":1327,"children":1328},{},[1329],{"type":31,"value":1330},"清晰的标签和提示",{"type":26,"tag":236,"props":1332,"children":1333},{},[1334],{"type":31,"value":713},{"type":26,"tag":236,"props":1336,"children":1337},{},[1338],{"type":31,"value":739},{"type":26,"tag":27,"props":1340,"children":1341},{},[1342,1343,1347],{"type":31,"value":744},{"type":26,"tag":699,"props":1344,"children":1345},{},[1346],{"type":31,"value":749},{"type":31,"value":705},{"type":26,"tag":232,"props":1349,"children":1350},{},[1351,1356,1361,1366,1371],{"type":26,"tag":236,"props":1352,"children":1353},{},[1354],{"type":31,"value":1355},"隐藏标签",{"type":26,"tag":236,"props":1357,"children":1358},{},[1359],{"type":31,"value":1360},"过度使用占位符",{"type":26,"tag":236,"props":1362,"children":1363},{},[1364],{"type":31,"value":1365},"验证后立即提交",{"type":26,"tag":236,"props":1367,"children":1368},{},[1369],{"type":31,"value":1370},"忽视无障碍性",{"type":26,"tag":236,"props":1372,"children":1373},{},[1374],{"type":31,"value":1375},"复杂的验证规则",{"type":26,"tag":81,"props":1377,"children":1378},{"id":796},[1379],{"type":31,"value":796},{"type":26,"tag":232,"props":1381,"children":1383},{"className":1382},[802],[1384,1393,1402,1411,1420,1429],{"type":26,"tag":236,"props":1385,"children":1387},{"className":1386},[807],[1388,1391],{"type":26,"tag":810,"props":1389,"children":1390},{"disabled":812,"type":813},[],{"type":31,"value":1392}," 所有控件都可用键盘导航",{"type":26,"tag":236,"props":1394,"children":1396},{"className":1395},[807],[1397,1400],{"type":26,"tag":810,"props":1398,"children":1399},{"disabled":812,"type":813},[],{"type":31,"value":1401}," 标签与输入框关联",{"type":26,"tag":236,"props":1403,"children":1405},{"className":1404},[807],[1406,1409],{"type":26,"tag":810,"props":1407,"children":1408},{"disabled":812,"type":813},[],{"type":31,"value":1410}," 验证消息清晰",{"type":26,"tag":236,"props":1412,"children":1414},{"className":1413},[807],[1415,1418],{"type":26,"tag":810,"props":1416,"children":1417},{"disabled":812,"type":813},[],{"type":31,"value":1419}," 色彩对比度足够",{"type":26,"tag":236,"props":1421,"children":1423},{"className":1422},[807],[1424,1427],{"type":26,"tag":810,"props":1425,"children":1426},{"disabled":812,"type":813},[],{"type":31,"value":1428}," 屏幕阅读器兼容",{"type":26,"tag":236,"props":1430,"children":1432},{"className":1431},[807],[1433,1436],{"type":26,"tag":810,"props":1434,"children":1435},{"disabled":812,"type":813},[],{"type":31,"value":1437}," 移动设备测试",{"title":7,"searchDepth":495,"depth":495,"links":1439},[1440,1441,1445,1446,1447,1448,1449,1450,1451],{"id":1178,"depth":498,"text":1178},{"id":1200,"depth":498,"text":1200,"children":1442},[1443,1444],{"id":1205,"depth":495,"text":1205},{"id":1219,"depth":495,"text":1219},{"id":1184,"depth":498,"text":1184},{"id":1246,"depth":498,"text":1246},{"id":1260,"depth":498,"text":1260},{"id":1274,"depth":498,"text":1274},{"id":1288,"depth":498,"text":1288},{"id":690,"depth":498,"text":690},{"id":796,"depth":498,"text":796},"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":1456,"image":17,"imageQuery":18,"pexelsPhotoId":19,"pexelsUrl":20,"featured":6,"readingTime":21,"body":1457,"_type":507,"_id":508,"_source":509,"_file":510,"_stem":511,"_extension":512},[13,14,15,16],{"type":23,"children":1458,"toc":1820},[1459,1463,1467,1471,1495,1499,1598,1602,1606,1610,1614,1633,1637,1641,1645,1649,1668,1672,1676,1680,1684,1703,1707,1711,1715,1719,1723,1727,1746,1750,1754,1758,1762,1766,1770,1789,1793,1797,1801,1816],{"type":26,"tag":27,"props":1460,"children":1461},{},[1462],{"type":31,"value":32},{"type":26,"tag":27,"props":1464,"children":1465},{},[1466],{"type":31,"value":37},{"type":26,"tag":27,"props":1468,"children":1469},{},[1470],{"type":31,"value":42},{"type":26,"tag":27,"props":1472,"children":1473},{},[1474,1475,1479,1480,1484,1485,1489,1490,1494],{"type":31,"value":47},{"type":26,"tag":49,"props":1476,"children":1477},{"href":51},[1478],{"type":31,"value":54},{"type":31,"value":56},{"type":26,"tag":49,"props":1481,"children":1482},{"href":59},[1483],{"type":31,"value":62},{"type":31,"value":56},{"type":26,"tag":49,"props":1486,"children":1487},{"href":66},[1488],{"type":31,"value":69},{"type":31,"value":71},{"type":26,"tag":49,"props":1491,"children":1492},{"href":74},[1493],{"type":31,"value":77},{"type":31,"value":79},{"type":26,"tag":81,"props":1496,"children":1497},{"id":83},[1498],{"type":31,"value":86},{"type":26,"tag":88,"props":1500,"children":1501},{},[1502,1520],{"type":26,"tag":92,"props":1503,"children":1504},{},[1505],{"type":26,"tag":96,"props":1506,"children":1507},{},[1508,1512,1516],{"type":26,"tag":100,"props":1509,"children":1510},{},[1511],{"type":31,"value":104},{"type":26,"tag":100,"props":1513,"children":1514},{},[1515],{"type":31,"value":109},{"type":26,"tag":100,"props":1517,"children":1518},{},[1519],{"type":31,"value":114},{"type":26,"tag":116,"props":1521,"children":1522},{},[1523,1538,1553,1568,1583],{"type":26,"tag":96,"props":1524,"children":1525},{},[1526,1530,1534],{"type":26,"tag":123,"props":1527,"children":1528},{},[1529],{"type":31,"value":127},{"type":26,"tag":123,"props":1531,"children":1532},{},[1533],{"type":31,"value":132},{"type":26,"tag":123,"props":1535,"children":1536},{},[1537],{"type":31,"value":137},{"type":26,"tag":96,"props":1539,"children":1540},{},[1541,1545,1549],{"type":26,"tag":123,"props":1542,"children":1543},{},[1544],{"type":31,"value":145},{"type":26,"tag":123,"props":1546,"children":1547},{},[1548],{"type":31,"value":150},{"type":26,"tag":123,"props":1550,"children":1551},{},[1552],{"type":31,"value":155},{"type":26,"tag":96,"props":1554,"children":1555},{},[1556,1560,1564],{"type":26,"tag":123,"props":1557,"children":1558},{},[1559],{"type":31,"value":163},{"type":26,"tag":123,"props":1561,"children":1562},{},[1563],{"type":31,"value":168},{"type":26,"tag":123,"props":1565,"children":1566},{},[1567],{"type":31,"value":173},{"type":26,"tag":96,"props":1569,"children":1570},{},[1571,1575,1579],{"type":26,"tag":123,"props":1572,"children":1573},{},[1574],{"type":31,"value":181},{"type":26,"tag":123,"props":1576,"children":1577},{},[1578],{"type":31,"value":186},{"type":26,"tag":123,"props":1580,"children":1581},{},[1582],{"type":31,"value":191},{"type":26,"tag":96,"props":1584,"children":1585},{},[1586,1590,1594],{"type":26,"tag":123,"props":1587,"children":1588},{},[1589],{"type":31,"value":199},{"type":26,"tag":123,"props":1591,"children":1592},{},[1593],{"type":31,"value":204},{"type":26,"tag":123,"props":1595,"children":1596},{},[1597],{"type":31,"value":209},{"type":26,"tag":27,"props":1599,"children":1600},{},[1601],{"type":31,"value":214},{"type":26,"tag":81,"props":1603,"children":1604},{"id":217},[1605],{"type":31,"value":220},{"type":26,"tag":27,"props":1607,"children":1608},{},[1609],{"type":31,"value":225},{"type":26,"tag":27,"props":1611,"children":1612},{},[1613],{"type":31,"value":230},{"type":26,"tag":232,"props":1615,"children":1616},{},[1617,1621,1625,1629],{"type":26,"tag":236,"props":1618,"children":1619},{},[1620],{"type":31,"value":240},{"type":26,"tag":236,"props":1622,"children":1623},{},[1624],{"type":31,"value":245},{"type":26,"tag":236,"props":1626,"children":1627},{},[1628],{"type":31,"value":250},{"type":26,"tag":236,"props":1630,"children":1631},{},[1632],{"type":31,"value":255},{"type":26,"tag":27,"props":1634,"children":1635},{},[1636],{"type":31,"value":260},{"type":26,"tag":81,"props":1638,"children":1639},{"id":263},[1640],{"type":31,"value":266},{"type":26,"tag":27,"props":1642,"children":1643},{},[1644],{"type":31,"value":271},{"type":26,"tag":27,"props":1646,"children":1647},{},[1648],{"type":31,"value":276},{"type":26,"tag":232,"props":1650,"children":1651},{},[1652,1656,1660,1664],{"type":26,"tag":236,"props":1653,"children":1654},{},[1655],{"type":31,"value":284},{"type":26,"tag":236,"props":1657,"children":1658},{},[1659],{"type":31,"value":289},{"type":26,"tag":236,"props":1661,"children":1662},{},[1663],{"type":31,"value":294},{"type":26,"tag":236,"props":1665,"children":1666},{},[1667],{"type":31,"value":299},{"type":26,"tag":27,"props":1669,"children":1670},{},[1671],{"type":31,"value":304},{"type":26,"tag":81,"props":1673,"children":1674},{"id":307},[1675],{"type":31,"value":310},{"type":26,"tag":27,"props":1677,"children":1678},{},[1679],{"type":31,"value":315},{"type":26,"tag":27,"props":1681,"children":1682},{},[1683],{"type":31,"value":320},{"type":26,"tag":232,"props":1685,"children":1686},{},[1687,1691,1695,1699],{"type":26,"tag":236,"props":1688,"children":1689},{},[1690],{"type":31,"value":328},{"type":26,"tag":236,"props":1692,"children":1693},{},[1694],{"type":31,"value":333},{"type":26,"tag":236,"props":1696,"children":1697},{},[1698],{"type":31,"value":338},{"type":26,"tag":236,"props":1700,"children":1701},{},[1702],{"type":31,"value":343},{"type":26,"tag":27,"props":1704,"children":1705},{},[1706],{"type":31,"value":348},{"type":26,"tag":81,"props":1708,"children":1709},{"id":351},[1710],{"type":31,"value":354},{"type":26,"tag":27,"props":1712,"children":1713},{},[1714],{"type":31,"value":359},{"type":26,"tag":27,"props":1716,"children":1717},{},[1718],{"type":31,"value":364},{"type":26,"tag":81,"props":1720,"children":1721},{"id":367},[1722],{"type":31,"value":370},{"type":26,"tag":27,"props":1724,"children":1725},{},[1726],{"type":31,"value":375},{"type":26,"tag":232,"props":1728,"children":1729},{},[1730,1734,1738,1742],{"type":26,"tag":236,"props":1731,"children":1732},{},[1733],{"type":31,"value":383},{"type":26,"tag":236,"props":1735,"children":1736},{},[1737],{"type":31,"value":388},{"type":26,"tag":236,"props":1739,"children":1740},{},[1741],{"type":31,"value":393},{"type":26,"tag":236,"props":1743,"children":1744},{},[1745],{"type":31,"value":398},{"type":26,"tag":27,"props":1747,"children":1748},{},[1749],{"type":31,"value":403},{"type":26,"tag":81,"props":1751,"children":1752},{"id":406},[1753],{"type":31,"value":409},{"type":26,"tag":27,"props":1755,"children":1756},{},[1757],{"type":31,"value":414},{"type":26,"tag":27,"props":1759,"children":1760},{},[1761],{"type":31,"value":419},{"type":26,"tag":81,"props":1763,"children":1764},{"id":422},[1765],{"type":31,"value":425},{"type":26,"tag":27,"props":1767,"children":1768},{},[1769],{"type":31,"value":430},{"type":26,"tag":232,"props":1771,"children":1772},{},[1773,1777,1781,1785],{"type":26,"tag":236,"props":1774,"children":1775},{},[1776],{"type":31,"value":438},{"type":26,"tag":236,"props":1778,"children":1779},{},[1780],{"type":31,"value":443},{"type":26,"tag":236,"props":1782,"children":1783},{},[1784],{"type":31,"value":448},{"type":26,"tag":236,"props":1786,"children":1787},{},[1788],{"type":31,"value":453},{"type":26,"tag":27,"props":1790,"children":1791},{},[1792],{"type":31,"value":458},{"type":26,"tag":81,"props":1794,"children":1795},{"id":461},[1796],{"type":31,"value":464},{"type":26,"tag":27,"props":1798,"children":1799},{},[1800],{"type":31,"value":469},{"type":26,"tag":471,"props":1802,"children":1803},{},[1804,1808,1812],{"type":26,"tag":236,"props":1805,"children":1806},{},[1807],{"type":31,"value":478},{"type":26,"tag":236,"props":1809,"children":1810},{},[1811],{"type":31,"value":483},{"type":26,"tag":236,"props":1813,"children":1814},{},[1815],{"type":31,"value":488},{"type":26,"tag":27,"props":1817,"children":1818},{},[1819],{"type":31,"value":493},{"title":7,"searchDepth":495,"depth":495,"links":1821},[1822,1823,1824,1825,1826,1827,1828,1829,1830],{"id":83,"depth":498,"text":86},{"id":217,"depth":498,"text":220},{"id":263,"depth":498,"text":266},{"id":307,"depth":498,"text":310},{"id":351,"depth":498,"text":354},{"id":367,"depth":498,"text":370},{"id":406,"depth":498,"text":409},{"id":422,"depth":498,"text":425},{"id":461,"depth":498,"text":464},1779260404244]