[{"data":1,"prerenderedAt":2195},["ShallowReactive",2],{"article-/topics/design/modal-overlay-design-specification":3,"related-design":709,"content-query-JOKKfmzoe1":1650},{"_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":703,"_id":704,"_source":705,"_file":706,"_stem":707,"_extension":708},"/topics/design/modal-overlay-design-specification","design",false,"","模态与弹层设计规范：什么时候该阻断，什么时候该让路","Modal、Drawer、Popover、Dropdown 看起来都像“浮层”，但它们承载的任务完全不同。本文从阻断等级、信息密度、焦点管理、退出路径和失败案例出发，讲清模态与弹层组件的设计规范。","2026-04-14","HTMLPAGE 团队",[13,14,15,16,17],"Modal","Overlay","Drawer","Design System","UX","/images/topics/design/modal-overlay-design-specification.jpg","modern software modal dialog interface design on laptop",30530406,"https://www.pexels.com/photo/ai-chat-interface-display-on-laptop-30530406/",14,{"type":24,"children":25,"toc":690},"root",[26,34,39,44,64,94,101,106,124,129,232,237,243,248,253,271,276,294,299,305,310,315,333,338,343,349,354,372,377,395,400,418,424,429,434,467,472,485,490,495,500,518,523,546,551,557,562,580,585,603,608,613,651,656,661,666],{"type":27,"tag":28,"props":29,"children":30},"element","p",{},[31],{"type":32,"value":33},"text","很多产品的弹层体验差，不是因为样式不够精致，而是因为组件边界混乱。",{"type":27,"tag":28,"props":35,"children":36},{},[37],{"type":32,"value":38},"明明只是一个轻量筛选，却用了会打断用户任务的 Modal；明明是高风险删除确认，却做成了容易误触消失的 Popover。用户感受到的不是“组件选错”，而是产品不稳定、不可信。",{"type":27,"tag":28,"props":40,"children":41},{},[42],{"type":32,"value":43},"所以这篇文章不再从“弹层组件有哪些”入手，而是直接回答更关键的问题：",{"type":27,"tag":45,"props":46,"children":47},"ul",{},[48,54,59],{"type":27,"tag":49,"props":50,"children":51},"li",{},[52],{"type":32,"value":53},"什么场景该用 Modal",{"type":27,"tag":49,"props":55,"children":56},{},[57],{"type":32,"value":58},"什么场景更适合 Drawer、Popover 或 Dropdown",{"type":27,"tag":49,"props":60,"children":61},{},[62],{"type":32,"value":63},"阻断等级、焦点路径和退出方式该如何统一",{"type":27,"tag":28,"props":65,"children":66},{},[67,69,76,78,84,86,92],{"type":32,"value":68},"如果你想先补反馈组件体系，可以先看 ",{"type":27,"tag":70,"props":71,"children":73},"a",{"href":72},"/topics/design/feedback-component-guide",[74],{"type":32,"value":75},"反馈提示组件设计规范完全指南",{"type":32,"value":77},"、",{"type":27,"tag":70,"props":79,"children":81},{"href":80},"/topics/design/navigation-component-guide",[82],{"type":32,"value":83},"导航组件设计最佳实践指南",{"type":32,"value":85}," 和 ",{"type":27,"tag":70,"props":87,"children":89},{"href":88},"/topics/design/accessibility-a11y-guide",[90],{"type":32,"value":91},"无障碍设计指南",{"type":32,"value":93},"。",{"type":27,"tag":95,"props":96,"children":98},"h2",{"id":97},"先分清一件事弹层的本质不是浮起来而是打断程度",[99],{"type":32,"value":100},"先分清一件事：弹层的本质不是“浮起来”，而是“打断程度”",{"type":27,"tag":28,"props":102,"children":103},{},[104],{"type":32,"value":105},"很多团队在做 overlay 体系时，只按视觉形态分类：",{"type":27,"tag":45,"props":107,"children":108},{},[109,114,119],{"type":27,"tag":49,"props":110,"children":111},{},[112],{"type":32,"value":113},"这个有遮罩",{"type":27,"tag":49,"props":115,"children":116},{},[117],{"type":32,"value":118},"那个从侧边滑出",{"type":27,"tag":49,"props":120,"children":121},{},[122],{"type":32,"value":123},"这个悬浮在按钮旁边",{"type":27,"tag":28,"props":125,"children":126},{},[127],{"type":32,"value":128},"但更稳的分类方式，是按对用户任务的打断程度划分。",{"type":27,"tag":130,"props":131,"children":132},"table",{},[133,157],{"type":27,"tag":134,"props":135,"children":136},"thead",{},[137],{"type":27,"tag":138,"props":139,"children":140},"tr",{},[141,147,152],{"type":27,"tag":142,"props":143,"children":144},"th",{},[145],{"type":32,"value":146},"组件",{"type":27,"tag":142,"props":148,"children":149},{},[150],{"type":32,"value":151},"打断程度",{"type":27,"tag":142,"props":153,"children":154},{},[155],{"type":32,"value":156},"适合场景",{"type":27,"tag":158,"props":159,"children":160},"tbody",{},[161,179,196,214],{"type":27,"tag":138,"props":162,"children":163},{},[164,169,174],{"type":27,"tag":165,"props":166,"children":167},"td",{},[168],{"type":32,"value":13},{"type":27,"tag":165,"props":170,"children":171},{},[172],{"type":32,"value":173},"高",{"type":27,"tag":165,"props":175,"children":176},{},[177],{"type":32,"value":178},"删除确认、关键提交、需要专注处理的任务",{"type":27,"tag":138,"props":180,"children":181},{},[182,186,191],{"type":27,"tag":165,"props":183,"children":184},{},[185],{"type":32,"value":15},{"type":27,"tag":165,"props":187,"children":188},{},[189],{"type":32,"value":190},"中",{"type":27,"tag":165,"props":192,"children":193},{},[194],{"type":32,"value":195},"侧边编辑、辅助配置、保留原上下文的子流程",{"type":27,"tag":138,"props":197,"children":198},{},[199,204,209],{"type":27,"tag":165,"props":200,"children":201},{},[202],{"type":32,"value":203},"Popover",{"type":27,"tag":165,"props":205,"children":206},{},[207],{"type":32,"value":208},"低到中",{"type":27,"tag":165,"props":210,"children":211},{},[212],{"type":32,"value":213},"补充说明、局部操作、短时表单",{"type":27,"tag":138,"props":215,"children":216},{},[217,222,227],{"type":27,"tag":165,"props":218,"children":219},{},[220],{"type":32,"value":221},"Dropdown",{"type":27,"tag":165,"props":223,"children":224},{},[225],{"type":32,"value":226},"低",{"type":27,"tag":165,"props":228,"children":229},{},[230],{"type":32,"value":231},"选择项展开、动作菜单",{"type":27,"tag":28,"props":233,"children":234},{},[235],{"type":32,"value":236},"如果不先统一这层原则，后面无论是交互、视觉还是无障碍，都会变得摇摆。",{"type":27,"tag":95,"props":238,"children":240},{"id":239},"modal-只该用于必须停下来决策的场景",[241],{"type":32,"value":242},"Modal 只该用于“必须停下来决策”的场景",{"type":27,"tag":28,"props":244,"children":245},{},[246],{"type":32,"value":247},"Modal 的价值不在于显眼，而在于阻断。",{"type":27,"tag":28,"props":249,"children":250},{},[251],{"type":32,"value":252},"它更适合：",{"type":27,"tag":45,"props":254,"children":255},{},[256,261,266],{"type":27,"tag":49,"props":257,"children":258},{},[259],{"type":32,"value":260},"高风险不可逆操作",{"type":27,"tag":49,"props":262,"children":263},{},[264],{"type":32,"value":265},"需要用户完整读完并确认的信息",{"type":27,"tag":49,"props":267,"children":268},{},[269],{"type":32,"value":270},"必须在当前上下文下完成的短流程",{"type":27,"tag":28,"props":272,"children":273},{},[274],{"type":32,"value":275},"它不适合：",{"type":27,"tag":45,"props":277,"children":278},{},[279,284,289],{"type":27,"tag":49,"props":280,"children":281},{},[282],{"type":32,"value":283},"普通筛选条件",{"type":27,"tag":49,"props":285,"children":286},{},[287],{"type":32,"value":288},"轻量查看详情",{"type":27,"tag":49,"props":290,"children":291},{},[292],{"type":32,"value":293},"不重要的设置项",{"type":27,"tag":28,"props":295,"children":296},{},[297],{"type":32,"value":298},"如果一个任务不用强制阻断用户，也能顺利完成，那通常就不该上 Modal。",{"type":27,"tag":95,"props":300,"children":302},{"id":301},"drawer-适合继续当前工作但需要更多空间",[303],{"type":32,"value":304},"Drawer 适合“继续当前工作，但需要更多空间”",{"type":27,"tag":28,"props":306,"children":307},{},[308],{"type":32,"value":309},"Drawer 的核心价值，是保留主界面的上下文感。",{"type":27,"tag":28,"props":311,"children":312},{},[313],{"type":32,"value":314},"更典型的场景包括：",{"type":27,"tag":45,"props":316,"children":317},{},[318,323,328],{"type":27,"tag":49,"props":319,"children":320},{},[321],{"type":32,"value":322},"查看侧边详情",{"type":27,"tag":49,"props":324,"children":325},{},[326],{"type":32,"value":327},"编辑部分信息",{"type":27,"tag":49,"props":329,"children":330},{},[331],{"type":32,"value":332},"做中等复杂度的表单配置",{"type":27,"tag":28,"props":334,"children":335},{},[336],{"type":32,"value":337},"它不像 Modal 那么强打断，也比 Popover 更能容纳复杂内容。",{"type":27,"tag":28,"props":339,"children":340},{},[341],{"type":32,"value":342},"所以很多后台产品里的编辑面板、详情面板，其实更适合 Drawer，而不是层层叠叠的对话框。",{"type":27,"tag":95,"props":344,"children":346},{"id":345},"popover-和-dropdown-不该承担高风险任务",[347],{"type":32,"value":348},"Popover 和 Dropdown 不该承担高风险任务",{"type":27,"tag":28,"props":350,"children":351},{},[352],{"type":32,"value":353},"Popover 很容易被误用，因为它很灵活：",{"type":27,"tag":45,"props":355,"children":356},{},[357,362,367],{"type":27,"tag":49,"props":358,"children":359},{},[360],{"type":32,"value":361},"能放说明",{"type":27,"tag":49,"props":363,"children":364},{},[365],{"type":32,"value":366},"能放按钮",{"type":27,"tag":49,"props":368,"children":369},{},[370],{"type":32,"value":371},"甚至能放小表单",{"type":27,"tag":28,"props":373,"children":374},{},[375],{"type":32,"value":376},"但它的问题也很明显：",{"type":27,"tag":45,"props":378,"children":379},{},[380,385,390],{"type":27,"tag":49,"props":381,"children":382},{},[383],{"type":32,"value":384},"容易因外部点击而关闭",{"type":27,"tag":49,"props":386,"children":387},{},[388],{"type":32,"value":389},"焦点管理复杂",{"type":27,"tag":49,"props":391,"children":392},{},[393],{"type":32,"value":394},"容量一大就失控",{"type":27,"tag":28,"props":396,"children":397},{},[398],{"type":32,"value":399},"因此更稳的规则是：",{"type":27,"tag":45,"props":401,"children":402},{},[403,408,413],{"type":27,"tag":49,"props":404,"children":405},{},[406],{"type":32,"value":407},"Popover 适合局部补充和轻操作",{"type":27,"tag":49,"props":409,"children":410},{},[411],{"type":32,"value":412},"Dropdown 适合标准选择和动作列表",{"type":27,"tag":49,"props":414,"children":415},{},[416],{"type":32,"value":417},"一旦涉及高风险确认或长流程，立刻升级到更稳定的容器",{"type":27,"tag":95,"props":419,"children":421},{"id":420},"退出路径必须明确不能靠用户猜",[422],{"type":32,"value":423},"退出路径必须明确，不能靠用户猜",{"type":27,"tag":28,"props":425,"children":426},{},[427],{"type":32,"value":428},"模态与弹层真正影响体验的，往往不是打开方式，而是关闭方式。",{"type":27,"tag":28,"props":430,"children":431},{},[432],{"type":32,"value":433},"建议统一 4 类退出路径：",{"type":27,"tag":435,"props":436,"children":437},"ol",{},[438,443,448,462],{"type":27,"tag":49,"props":439,"children":440},{},[441],{"type":32,"value":442},"明确的关闭按钮",{"type":27,"tag":49,"props":444,"children":445},{},[446],{"type":32,"value":447},"明确的取消动作",{"type":27,"tag":49,"props":449,"children":450},{},[451,453,460],{"type":32,"value":452},"键盘 ",{"type":27,"tag":454,"props":455,"children":457},"code",{"className":456},[],[458],{"type":32,"value":459},"Esc",{"type":32,"value":461}," 关闭规则",{"type":27,"tag":49,"props":463,"children":464},{},[465],{"type":32,"value":466},"点击遮罩或外部区域是否允许关闭",{"type":27,"tag":28,"props":468,"children":469},{},[470],{"type":32,"value":471},"这里最关键的是一致性：",{"type":27,"tag":45,"props":473,"children":474},{},[475,480],{"type":27,"tag":49,"props":476,"children":477},{},[478],{"type":32,"value":479},"低风险弹层可以更容易退出",{"type":27,"tag":49,"props":481,"children":482},{},[483],{"type":32,"value":484},"高风险弹层必须更克制，避免误关",{"type":27,"tag":28,"props":486,"children":487},{},[488],{"type":32,"value":489},"如果不同页面的退出规则都不同，用户很快就会失去控制感。",{"type":27,"tag":95,"props":491,"children":493},{"id":492},"焦点管理和层级规范必须写进组件文档",[494],{"type":32,"value":492},{"type":27,"tag":28,"props":496,"children":497},{},[498],{"type":32,"value":499},"Overlay 组件一旦没有统一焦点规则，很容易出现：",{"type":27,"tag":45,"props":501,"children":502},{},[503,508,513],{"type":27,"tag":49,"props":504,"children":505},{},[506],{"type":32,"value":507},"打开后焦点仍留在背景页面",{"type":27,"tag":49,"props":509,"children":510},{},[511],{"type":32,"value":512},"关闭后焦点回不去触发源",{"type":27,"tag":49,"props":514,"children":515},{},[516],{"type":32,"value":517},"Tab 键跳到不可见区域",{"type":27,"tag":28,"props":519,"children":520},{},[521],{"type":32,"value":522},"一个可执行的规范至少应包含：",{"type":27,"tag":45,"props":524,"children":525},{},[526,531,536,541],{"type":27,"tag":49,"props":527,"children":528},{},[529],{"type":32,"value":530},"打开时焦点落点",{"type":27,"tag":49,"props":532,"children":533},{},[534],{"type":32,"value":535},"关闭时焦点回退逻辑",{"type":27,"tag":49,"props":537,"children":538},{},[539],{"type":32,"value":540},"Modal 是否启用 focus trap",{"type":27,"tag":49,"props":542,"children":543},{},[544],{"type":32,"value":545},"多层弹层的 z-index 和交互优先级",{"type":27,"tag":28,"props":547,"children":548},{},[549],{"type":32,"value":550},"这不是“无障碍附加项”，而是基础可用性要求。",{"type":27,"tag":95,"props":552,"children":554},{"id":553},"失败案例同一个产品里删除确认和筛选面板都用了同款-modal",[555],{"type":32,"value":556},"失败案例：同一个产品里，删除确认和筛选面板都用了同款 Modal",{"type":27,"tag":28,"props":558,"children":559},{},[560],{"type":32,"value":561},"这是非常常见的设计失衡：",{"type":27,"tag":45,"props":563,"children":564},{},[565,570,575],{"type":27,"tag":49,"props":566,"children":567},{},[568],{"type":32,"value":569},"删除确认需要强提醒",{"type":27,"tag":49,"props":571,"children":572},{},[573],{"type":32,"value":574},"筛选配置只是辅助任务",{"type":27,"tag":49,"props":576,"children":577},{},[578],{"type":32,"value":579},"但两个场景都用了同样大小、同样布局、同样按钮结构的 Modal",{"type":27,"tag":28,"props":581,"children":582},{},[583],{"type":32,"value":584},"结果就是：",{"type":27,"tag":45,"props":586,"children":587},{},[588,593,598],{"type":27,"tag":49,"props":589,"children":590},{},[591],{"type":32,"value":592},"用户逐渐对危险弹层失去警觉",{"type":27,"tag":49,"props":594,"children":595},{},[596],{"type":32,"value":597},"又对普通操作产生不必要的中断感",{"type":27,"tag":49,"props":599,"children":600},{},[601],{"type":32,"value":602},"组件看似统一，实际语义已经崩了",{"type":27,"tag":28,"props":604,"children":605},{},[606],{"type":32,"value":607},"更稳的做法，是先统一语义，再统一视觉。",{"type":27,"tag":95,"props":609,"children":611},{"id":610},"一份可直接复用的检查清单",[612],{"type":32,"value":610},{"type":27,"tag":45,"props":614,"children":615},{},[616,621,626,631,636,641,646],{"type":27,"tag":49,"props":617,"children":618},{},[619],{"type":32,"value":620},"这个场景是否真的需要阻断用户当前任务",{"type":27,"tag":49,"props":622,"children":623},{},[624],{"type":32,"value":625},"它更适合 Modal、Drawer、Popover 还是 Dropdown",{"type":27,"tag":49,"props":627,"children":628},{},[629],{"type":32,"value":630},"退出路径是否明确且符合风险等级",{"type":27,"tag":49,"props":632,"children":633},{},[634],{"type":32,"value":635},"打开、关闭时的焦点移动是否可预测",{"type":27,"tag":49,"props":637,"children":638},{},[639],{"type":32,"value":640},"遮罩点击关闭是否会造成误操作风险",{"type":27,"tag":49,"props":642,"children":643},{},[644],{"type":32,"value":645},"是否存在把轻任务过度升级成强阻断的情况",{"type":27,"tag":49,"props":647,"children":648},{},[649],{"type":32,"value":650},"多层弹层的层级和优先级是否已定义",{"type":27,"tag":95,"props":652,"children":654},{"id":653},"总结",[655],{"type":32,"value":653},{"type":27,"tag":28,"props":657,"children":658},{},[659],{"type":32,"value":660},"模态与弹层设计的关键，不在于让界面“浮起来”，而在于把打断等级、任务密度和退出路径设计正确。只要先把语义边界统一，再做视觉和实现规范，overlay 体系就会稳定很多。",{"type":27,"tag":28,"props":662,"children":663},{},[664],{"type":32,"value":665},"进一步阅读：",{"type":27,"tag":45,"props":667,"children":668},{},[669,676,683],{"type":27,"tag":49,"props":670,"children":671},{},[672],{"type":27,"tag":70,"props":673,"children":674},{"href":72},[675],{"type":32,"value":75},{"type":27,"tag":49,"props":677,"children":678},{},[679],{"type":27,"tag":70,"props":680,"children":681},{"href":80},[682],{"type":32,"value":83},{"type":27,"tag":49,"props":684,"children":685},{},[686],{"type":27,"tag":70,"props":687,"children":688},{"href":88},[689],{"type":32,"value":91},{"title":7,"searchDepth":691,"depth":691,"links":692},3,[693,695,696,697,698,699,700,701,702],{"id":97,"depth":694,"text":100},2,{"id":239,"depth":694,"text":242},{"id":301,"depth":694,"text":304},{"id":345,"depth":694,"text":348},{"id":420,"depth":694,"text":423},{"id":492,"depth":694,"text":492},{"id":553,"depth":694,"text":556},{"id":610,"depth":694,"text":610},{"id":653,"depth":694,"text":653},"markdown","content:topics:design:modal-overlay-design-specification.md","content","topics/design/modal-overlay-design-specification.md","topics/design/modal-overlay-design-specification","md",[710,1069,1371],{"_path":711,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":712,"description":713,"keywords":714,"image":720,"author":11,"date":721,"readingTime":722,"topic":5,"body":723,"_type":703,"_id":1066,"_source":705,"_file":1067,"_stem":1068,"_extension":708},"/topics/design/button-component-design","按钮组件设计详解","学习按钮样式、交互状态、无障碍性和最佳实践",[715,716,717,718,719],"按钮设计","Button Component","交互状态","UI 组件","用户体验","/images/topics/button-design.jpg","2025-12-08",18,{"type":24,"children":724,"toc":1048},[725,729,734,739,746,758,764,773,779,788,792,798,809,815,824,830,839,844,853,858,869,874,883,888,901,935,946,989,994],{"type":27,"tag":95,"props":726,"children":727},{"id":712},[728],{"type":32,"value":712},{"type":27,"tag":28,"props":730,"children":731},{},[732],{"type":32,"value":733},"按钮是 UI 中最重要的交互元素。优秀的按钮设计能够指导用户行为。",{"type":27,"tag":95,"props":735,"children":737},{"id":736},"按钮类型",[738],{"type":32,"value":736},{"type":27,"tag":740,"props":741,"children":743},"h3",{"id":742},"primary-button主按钮",[744],{"type":32,"value":745},"Primary Button（主按钮）",{"type":27,"tag":747,"props":748,"children":753},"pre",{"className":749,"code":751,"language":752,"meta":7},[750],"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",[754],{"type":27,"tag":454,"props":755,"children":756},{"__ignoreMap":7},[757],{"type":32,"value":751},{"type":27,"tag":740,"props":759,"children":761},{"id":760},"secondary-button次按钮",[762],{"type":32,"value":763},"Secondary Button（次按钮）",{"type":27,"tag":747,"props":765,"children":768},{"className":766,"code":767,"language":752,"meta":7},[750],".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",[769],{"type":27,"tag":454,"props":770,"children":771},{"__ignoreMap":7},[772],{"type":32,"value":767},{"type":27,"tag":740,"props":774,"children":776},{"id":775},"danger-button危险按钮",[777],{"type":32,"value":778},"Danger Button（危险按钮）",{"type":27,"tag":747,"props":780,"children":783},{"className":781,"code":782,"language":752,"meta":7},[750],".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",[784],{"type":27,"tag":454,"props":785,"children":786},{"__ignoreMap":7},[787],{"type":32,"value":782},{"type":27,"tag":95,"props":789,"children":790},{"id":717},[791],{"type":32,"value":717},{"type":27,"tag":740,"props":793,"children":795},{"id":794},"loading-状态",[796],{"type":32,"value":797},"Loading 状态",{"type":27,"tag":747,"props":799,"children":804},{"className":800,"code":802,"language":803,"meta":7},[801],"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",[805],{"type":27,"tag":454,"props":806,"children":807},{"__ignoreMap":7},[808],{"type":32,"value":802},{"type":27,"tag":740,"props":810,"children":812},{"id":811},"disabled-状态",[813],{"type":32,"value":814},"Disabled 状态",{"type":27,"tag":747,"props":816,"children":819},{"className":817,"code":818,"language":752,"meta":7},[750],".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",[820],{"type":27,"tag":454,"props":821,"children":822},{"__ignoreMap":7},[823],{"type":32,"value":818},{"type":27,"tag":740,"props":825,"children":827},{"id":826},"focus-状态",[828],{"type":32,"value":829},"Focus 状态",{"type":27,"tag":747,"props":831,"children":834},{"className":832,"code":833,"language":752,"meta":7},[750],".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",[835],{"type":27,"tag":454,"props":836,"children":837},{"__ignoreMap":7},[838],{"type":32,"value":833},{"type":27,"tag":95,"props":840,"children":842},{"id":841},"按钮大小",[843],{"type":32,"value":841},{"type":27,"tag":747,"props":845,"children":848},{"className":846,"code":847,"language":752,"meta":7},[750],"/* 小按钮 */\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",[849],{"type":27,"tag":454,"props":850,"children":851},{"__ignoreMap":7},[852],{"type":32,"value":847},{"type":27,"tag":95,"props":854,"children":856},{"id":855},"无障碍性",[857],{"type":32,"value":855},{"type":27,"tag":747,"props":859,"children":864},{"className":860,"code":862,"language":863,"meta":7},[861],"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",[865],{"type":27,"tag":454,"props":866,"children":867},{"__ignoreMap":7},[868],{"type":32,"value":862},{"type":27,"tag":95,"props":870,"children":872},{"id":871},"完整组件示例",[873],{"type":32,"value":871},{"type":27,"tag":747,"props":875,"children":878},{"className":876,"code":877,"language":803,"meta":7},[801],"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",[879],{"type":27,"tag":454,"props":880,"children":881},{"__ignoreMap":7},[882],{"type":32,"value":877},{"type":27,"tag":95,"props":884,"children":886},{"id":885},"最佳实践",[887],{"type":32,"value":885},{"type":27,"tag":28,"props":889,"children":890},{},[891,893,899],{"type":32,"value":892},"✅ ",{"type":27,"tag":894,"props":895,"children":896},"strong",{},[897],{"type":32,"value":898},"应该做的事",{"type":32,"value":900},":",{"type":27,"tag":45,"props":902,"children":903},{},[904,909,914,925,930],{"type":27,"tag":49,"props":905,"children":906},{},[907],{"type":32,"value":908},"最小触摸目标 44x44px",{"type":27,"tag":49,"props":910,"children":911},{},[912],{"type":32,"value":913},"清晰的视觉反馈",{"type":27,"tag":49,"props":915,"children":916},{},[917,919],{"type":32,"value":918},"使用语义 HTML ",{"type":27,"tag":454,"props":920,"children":922},{"className":921},[],[923],{"type":32,"value":924},"\u003Cbutton>",{"type":27,"tag":49,"props":926,"children":927},{},[928],{"type":32,"value":929},"提供加载状态反馈",{"type":27,"tag":49,"props":931,"children":932},{},[933],{"type":32,"value":934},"支持键盘导航",{"type":27,"tag":28,"props":936,"children":937},{},[938,940,945],{"type":32,"value":939},"❌ ",{"type":27,"tag":894,"props":941,"children":942},{},[943],{"type":32,"value":944},"不应该做的事",{"type":32,"value":900},{"type":27,"tag":45,"props":947,"children":948},{},[949,962,967,972,977],{"type":27,"tag":49,"props":950,"children":951},{},[952,954,960],{"type":32,"value":953},"使用 ",{"type":27,"tag":454,"props":955,"children":957},{"className":956},[],[958],{"type":32,"value":959},"\u003Cdiv>",{"type":32,"value":961}," 模拟按钮",{"type":27,"tag":49,"props":963,"children":964},{},[965],{"type":32,"value":966},"隐藏焦点指示器",{"type":27,"tag":49,"props":968,"children":969},{},[970],{"type":32,"value":971},"过多的按钮样式",{"type":27,"tag":49,"props":973,"children":974},{},[975],{"type":32,"value":976},"忽视禁用状态",{"type":27,"tag":49,"props":978,"children":979},{},[980,981,987],{"type":32,"value":953},{"type":27,"tag":454,"props":982,"children":984},{"className":983},[],[985],{"type":32,"value":986},"\u003Ca>",{"type":32,"value":988}," 代替按钮",{"type":27,"tag":95,"props":990,"children":992},{"id":991},"测试清单",[993],{"type":32,"value":991},{"type":27,"tag":45,"props":995,"children":998},{"className":996},[997],"contains-task-list",[999,1012,1021,1030,1039],{"type":27,"tag":49,"props":1000,"children":1003},{"className":1001},[1002],"task-list-item",[1004,1010],{"type":27,"tag":1005,"props":1006,"children":1009},"input",{"disabled":1007,"type":1008},true,"checkbox",[],{"type":32,"value":1011}," 在各种浏览器中测试",{"type":27,"tag":49,"props":1013,"children":1015},{"className":1014},[1002],[1016,1019],{"type":27,"tag":1005,"props":1017,"children":1018},{"disabled":1007,"type":1008},[],{"type":32,"value":1020}," 验证键盘导航",{"type":27,"tag":49,"props":1022,"children":1024},{"className":1023},[1002],[1025,1028],{"type":27,"tag":1005,"props":1026,"children":1027},{"disabled":1007,"type":1008},[],{"type":32,"value":1029}," 检查色彩对比度",{"type":27,"tag":49,"props":1031,"children":1033},{"className":1032},[1002],[1034,1037],{"type":27,"tag":1005,"props":1035,"children":1036},{"disabled":1007,"type":1008},[],{"type":32,"value":1038}," 测试触摸设备",{"type":27,"tag":49,"props":1040,"children":1042},{"className":1041},[1002],[1043,1046],{"type":27,"tag":1005,"props":1044,"children":1045},{"disabled":1007,"type":1008},[],{"type":32,"value":1047}," 屏幕阅读器兼容性",{"title":7,"searchDepth":691,"depth":691,"links":1049},[1050,1051,1056,1061,1062,1063,1064,1065],{"id":712,"depth":694,"text":712},{"id":736,"depth":694,"text":736,"children":1052},[1053,1054,1055],{"id":742,"depth":691,"text":745},{"id":760,"depth":691,"text":763},{"id":775,"depth":691,"text":778},{"id":717,"depth":694,"text":717,"children":1057},[1058,1059,1060],{"id":794,"depth":691,"text":797},{"id":811,"depth":691,"text":814},{"id":826,"depth":691,"text":829},{"id":841,"depth":694,"text":841},{"id":855,"depth":694,"text":855},{"id":871,"depth":694,"text":871},{"id":885,"depth":694,"text":885},{"id":991,"depth":694,"text":991},"content:topics:design:button-component-design.md","topics/design/button-component-design.md","topics/design/button-component-design",{"_path":1070,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1071,"description":1072,"keywords":1073,"image":1078,"author":11,"date":721,"readingTime":1079,"topic":5,"body":1080,"_type":703,"_id":1368,"_source":705,"_file":1369,"_stem":1370,"_extension":708},"/topics/design/dark-mode-design","暗黑模式设计完整方案","学习暗黑模式实现、色彩方案、对比度管理和最佳实践",[1074,1075,1076,1077,719],"暗黑模式","Dark Mode","色彩系统","CSS 变量","/images/topics/dark-mode-design.jpg",20,{"type":24,"children":1081,"toc":1351},[1082,1086,1091,1096,1102,1111,1117,1126,1131,1137,1146,1152,1163,1169,1178,1183,1192,1197,1206,1211,1220,1224,1233,1261,1270,1298,1302],{"type":27,"tag":95,"props":1083,"children":1084},{"id":1071},[1085],{"type":32,"value":1071},{"type":27,"tag":28,"props":1087,"children":1088},{},[1089],{"type":32,"value":1090},"暗黑模式已成为现代应用的标准功能。它能够减少眼睛疲劳、节省电池、改善用户体验。",{"type":27,"tag":95,"props":1092,"children":1094},{"id":1093},"核心色彩系统",[1095],{"type":32,"value":1093},{"type":27,"tag":740,"props":1097,"children":1099},{"id":1098},"light-mode-配色",[1100],{"type":32,"value":1101},"Light Mode 配色",{"type":27,"tag":747,"props":1103,"children":1106},{"className":1104,"code":1105,"language":752,"meta":7},[750],":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",[1107],{"type":27,"tag":454,"props":1108,"children":1109},{"__ignoreMap":7},[1110],{"type":32,"value":1105},{"type":27,"tag":740,"props":1112,"children":1114},{"id":1113},"dark-mode-配色",[1115],{"type":32,"value":1116},"Dark Mode 配色",{"type":27,"tag":747,"props":1118,"children":1121},{"className":1119,"code":1120,"language":752,"meta":7},[750],"@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",[1122],{"type":27,"tag":454,"props":1123,"children":1124},{"__ignoreMap":7},[1125],{"type":32,"value":1120},{"type":27,"tag":95,"props":1127,"children":1129},{"id":1128},"实现方案",[1130],{"type":32,"value":1128},{"type":27,"tag":740,"props":1132,"children":1134},{"id":1133},"方案-1prefers-color-scheme",[1135],{"type":32,"value":1136},"方案 1：prefers-color-scheme",{"type":27,"tag":747,"props":1138,"children":1141},{"className":1139,"code":1140,"language":752,"meta":7},[750],"/* 自动跟随系统设置 */\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",[1142],{"type":27,"tag":454,"props":1143,"children":1144},{"__ignoreMap":7},[1145],{"type":32,"value":1140},{"type":27,"tag":740,"props":1147,"children":1149},{"id":1148},"方案-2javascript-切换",[1150],{"type":32,"value":1151},"方案 2：JavaScript 切换",{"type":27,"tag":747,"props":1153,"children":1158},{"className":1154,"code":1156,"language":1157,"meta":7},[1155],"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",[1159],{"type":27,"tag":454,"props":1160,"children":1161},{"__ignoreMap":7},[1162],{"type":32,"value":1156},{"type":27,"tag":740,"props":1164,"children":1166},{"id":1165},"方案-3css-variables-javascript",[1167],{"type":32,"value":1168},"方案 3：CSS Variables + JavaScript",{"type":27,"tag":747,"props":1170,"children":1173},{"className":1171,"code":1172,"language":1157,"meta":7},[1155],"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",[1174],{"type":27,"tag":454,"props":1175,"children":1176},{"__ignoreMap":7},[1177],{"type":32,"value":1172},{"type":27,"tag":95,"props":1179,"children":1181},{"id":1180},"对比度管理",[1182],{"type":32,"value":1180},{"type":27,"tag":747,"props":1184,"children":1187},{"className":1185,"code":1186,"language":752,"meta":7},[750],"/* 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",[1188],{"type":27,"tag":454,"props":1189,"children":1190},{"__ignoreMap":7},[1191],{"type":32,"value":1186},{"type":27,"tag":95,"props":1193,"children":1195},{"id":1194},"图片和图表处理",[1196],{"type":32,"value":1194},{"type":27,"tag":747,"props":1198,"children":1201},{"className":1199,"code":1200,"language":863,"meta":7},[861],"\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",[1202],{"type":27,"tag":454,"props":1203,"children":1204},{"__ignoreMap":7},[1205],{"type":32,"value":1200},{"type":27,"tag":95,"props":1207,"children":1209},{"id":1208},"完整示例",[1210],{"type":32,"value":1208},{"type":27,"tag":747,"props":1212,"children":1215},{"className":1213,"code":1214,"language":803,"meta":7},[801],"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",[1216],{"type":27,"tag":454,"props":1217,"children":1218},{"__ignoreMap":7},[1219],{"type":32,"value":1214},{"type":27,"tag":95,"props":1221,"children":1222},{"id":885},[1223],{"type":32,"value":885},{"type":27,"tag":28,"props":1225,"children":1226},{},[1227,1228,1232],{"type":32,"value":892},{"type":27,"tag":894,"props":1229,"children":1230},{},[1231],{"type":32,"value":898},{"type":32,"value":900},{"type":27,"tag":45,"props":1234,"children":1235},{},[1236,1241,1246,1251,1256],{"type":27,"tag":49,"props":1237,"children":1238},{},[1239],{"type":32,"value":1240},"支持系统偏好",{"type":27,"tag":49,"props":1242,"children":1243},{},[1244],{"type":32,"value":1245},"提供手动切换选项",{"type":27,"tag":49,"props":1247,"children":1248},{},[1249],{"type":32,"value":1250},"确保足够的对比度",{"type":27,"tag":49,"props":1252,"children":1253},{},[1254],{"type":32,"value":1255},"优化图片和图表",{"type":27,"tag":49,"props":1257,"children":1258},{},[1259],{"type":32,"value":1260},"防止加载闪烁",{"type":27,"tag":28,"props":1262,"children":1263},{},[1264,1265,1269],{"type":32,"value":939},{"type":27,"tag":894,"props":1266,"children":1267},{},[1268],{"type":32,"value":944},{"type":32,"value":900},{"type":27,"tag":45,"props":1271,"children":1272},{},[1273,1278,1283,1288,1293],{"type":27,"tag":49,"props":1274,"children":1275},{},[1276],{"type":32,"value":1277},"强制单一模式",{"type":27,"tag":49,"props":1279,"children":1280},{},[1281],{"type":32,"value":1282},"忽视性能影响",{"type":27,"tag":49,"props":1284,"children":1285},{},[1286],{"type":32,"value":1287},"使用相同的颜色",{"type":27,"tag":49,"props":1289,"children":1290},{},[1291],{"type":32,"value":1292},"忘记保存用户偏好",{"type":27,"tag":49,"props":1294,"children":1295},{},[1296],{"type":32,"value":1297},"过度使用深色背景",{"type":27,"tag":95,"props":1299,"children":1300},{"id":991},[1301],{"type":32,"value":991},{"type":27,"tag":45,"props":1303,"children":1305},{"className":1304},[997],[1306,1315,1324,1333,1342],{"type":27,"tag":49,"props":1307,"children":1309},{"className":1308},[1002],[1310,1313],{"type":27,"tag":1005,"props":1311,"children":1312},{"disabled":1007,"type":1008},[],{"type":32,"value":1314}," 在浅色和深色模式下测试所有页面",{"type":27,"tag":49,"props":1316,"children":1318},{"className":1317},[1002],[1319,1322],{"type":27,"tag":1005,"props":1320,"children":1321},{"disabled":1007,"type":1008},[],{"type":32,"value":1323}," 检查颜色对比度符合 WCAG 标准",{"type":27,"tag":49,"props":1325,"children":1327},{"className":1326},[1002],[1328,1331],{"type":27,"tag":1005,"props":1329,"children":1330},{"disabled":1007,"type":1008},[],{"type":32,"value":1332}," 验证图片和图表在两种模式下清晰",{"type":27,"tag":49,"props":1334,"children":1336},{"className":1335},[1002],[1337,1340],{"type":27,"tag":1005,"props":1338,"children":1339},{"disabled":1007,"type":1008},[],{"type":32,"value":1341}," 测试主题切换的平滑性",{"type":27,"tag":49,"props":1343,"children":1345},{"className":1344},[1002],[1346,1349],{"type":27,"tag":1005,"props":1347,"children":1348},{"disabled":1007,"type":1008},[],{"type":32,"value":1350}," 检查用户偏好是否被保存",{"title":7,"searchDepth":691,"depth":691,"links":1352},[1353,1354,1358,1363,1364,1365,1366,1367],{"id":1071,"depth":694,"text":1071},{"id":1093,"depth":694,"text":1093,"children":1355},[1356,1357],{"id":1098,"depth":691,"text":1101},{"id":1113,"depth":691,"text":1116},{"id":1128,"depth":694,"text":1128,"children":1359},[1360,1361,1362],{"id":1133,"depth":691,"text":1136},{"id":1148,"depth":691,"text":1151},{"id":1165,"depth":691,"text":1168},{"id":1180,"depth":694,"text":1180},{"id":1194,"depth":694,"text":1194},{"id":1208,"depth":694,"text":1208},{"id":885,"depth":694,"text":885},{"id":991,"depth":694,"text":991},"content:topics:design:dark-mode-design.md","topics/design/dark-mode-design.md","topics/design/dark-mode-design",{"_path":1372,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1373,"description":1374,"keywords":1375,"image":1380,"author":1381,"date":721,"readingTime":1079,"topic":5,"body":1382,"_type":703,"_id":1647,"_source":705,"_file":1648,"_stem":1649,"_extension":708},"/topics/design/form-controls-design","表单控件设计规范","学习输入框、选择框、复选框等表单控件的设计和实现",[1376,1377,1378,1379,719],"表单设计","Form Controls","输入框","验证反馈","/images/topics/form-controls-design.jpg","AI Content Team",{"type":24,"children":1383,"toc":1633},[1384,1388,1393,1398,1403,1412,1417,1426,1430,1439,1444,1453,1458,1467,1472,1481,1486,1495,1499,1508,1534,1543,1571,1575],{"type":27,"tag":95,"props":1385,"children":1386},{"id":1373},[1387],{"type":32,"value":1373},{"type":27,"tag":28,"props":1389,"children":1390},{},[1391],{"type":32,"value":1392},"优秀的表单设计能够提高用户完成率和满意度。",{"type":27,"tag":95,"props":1394,"children":1396},{"id":1395},"输入框设计",[1397],{"type":32,"value":1395},{"type":27,"tag":740,"props":1399,"children":1401},{"id":1400},"基础文本输入",[1402],{"type":32,"value":1400},{"type":27,"tag":747,"props":1404,"children":1407},{"className":1405,"code":1406,"language":752,"meta":7},[750],".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",[1408],{"type":27,"tag":454,"props":1409,"children":1410},{"__ignoreMap":7},[1411],{"type":32,"value":1406},{"type":27,"tag":740,"props":1413,"children":1415},{"id":1414},"标签和提示",[1416],{"type":32,"value":1414},{"type":27,"tag":747,"props":1418,"children":1421},{"className":1419,"code":1420,"language":863,"meta":7},[861],"\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",[1422],{"type":27,"tag":454,"props":1423,"children":1424},{"__ignoreMap":7},[1425],{"type":32,"value":1420},{"type":27,"tag":95,"props":1427,"children":1428},{"id":1379},[1429],{"type":32,"value":1379},{"type":27,"tag":747,"props":1431,"children":1434},{"className":1432,"code":1433,"language":803,"meta":7},[801],"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",[1435],{"type":27,"tag":454,"props":1436,"children":1437},{"__ignoreMap":7},[1438],{"type":32,"value":1433},{"type":27,"tag":95,"props":1440,"children":1442},{"id":1441},"选择框设计",[1443],{"type":32,"value":1441},{"type":27,"tag":747,"props":1445,"children":1448},{"className":1446,"code":1447,"language":752,"meta":7},[750],".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",[1449],{"type":27,"tag":454,"props":1450,"children":1451},{"__ignoreMap":7},[1452],{"type":32,"value":1447},{"type":27,"tag":95,"props":1454,"children":1456},{"id":1455},"复选框和单选按钮",[1457],{"type":32,"value":1455},{"type":27,"tag":747,"props":1459,"children":1462},{"className":1460,"code":1461,"language":752,"meta":7},[750],".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",[1463],{"type":27,"tag":454,"props":1464,"children":1465},{"__ignoreMap":7},[1466],{"type":32,"value":1461},{"type":27,"tag":95,"props":1468,"children":1470},{"id":1469},"文本区域",[1471],{"type":32,"value":1469},{"type":27,"tag":747,"props":1473,"children":1476},{"className":1474,"code":1475,"language":752,"meta":7},[750],".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",[1477],{"type":27,"tag":454,"props":1478,"children":1479},{"__ignoreMap":7},[1480],{"type":32,"value":1475},{"type":27,"tag":95,"props":1482,"children":1484},{"id":1483},"完整表单示例",[1485],{"type":32,"value":1483},{"type":27,"tag":747,"props":1487,"children":1490},{"className":1488,"code":1489,"language":803,"meta":7},[801],"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",[1491],{"type":27,"tag":454,"props":1492,"children":1493},{"__ignoreMap":7},[1494],{"type":32,"value":1489},{"type":27,"tag":95,"props":1496,"children":1497},{"id":885},[1498],{"type":32,"value":885},{"type":27,"tag":28,"props":1500,"children":1501},{},[1502,1503,1507],{"type":32,"value":892},{"type":27,"tag":894,"props":1504,"children":1505},{},[1506],{"type":32,"value":898},{"type":32,"value":900},{"type":27,"tag":45,"props":1509,"children":1510},{},[1511,1516,1521,1526,1530],{"type":27,"tag":49,"props":1512,"children":1513},{},[1514],{"type":32,"value":1515},"使用正确的输入类型",{"type":27,"tag":49,"props":1517,"children":1518},{},[1519],{"type":32,"value":1520},"提供实时验证反馈",{"type":27,"tag":49,"props":1522,"children":1523},{},[1524],{"type":32,"value":1525},"清晰的标签和提示",{"type":27,"tag":49,"props":1527,"children":1528},{},[1529],{"type":32,"value":908},{"type":27,"tag":49,"props":1531,"children":1532},{},[1533],{"type":32,"value":934},{"type":27,"tag":28,"props":1535,"children":1536},{},[1537,1538,1542],{"type":32,"value":939},{"type":27,"tag":894,"props":1539,"children":1540},{},[1541],{"type":32,"value":944},{"type":32,"value":900},{"type":27,"tag":45,"props":1544,"children":1545},{},[1546,1551,1556,1561,1566],{"type":27,"tag":49,"props":1547,"children":1548},{},[1549],{"type":32,"value":1550},"隐藏标签",{"type":27,"tag":49,"props":1552,"children":1553},{},[1554],{"type":32,"value":1555},"过度使用占位符",{"type":27,"tag":49,"props":1557,"children":1558},{},[1559],{"type":32,"value":1560},"验证后立即提交",{"type":27,"tag":49,"props":1562,"children":1563},{},[1564],{"type":32,"value":1565},"忽视无障碍性",{"type":27,"tag":49,"props":1567,"children":1568},{},[1569],{"type":32,"value":1570},"复杂的验证规则",{"type":27,"tag":95,"props":1572,"children":1573},{"id":991},[1574],{"type":32,"value":991},{"type":27,"tag":45,"props":1576,"children":1578},{"className":1577},[997],[1579,1588,1597,1606,1615,1624],{"type":27,"tag":49,"props":1580,"children":1582},{"className":1581},[1002],[1583,1586],{"type":27,"tag":1005,"props":1584,"children":1585},{"disabled":1007,"type":1008},[],{"type":32,"value":1587}," 所有控件都可用键盘导航",{"type":27,"tag":49,"props":1589,"children":1591},{"className":1590},[1002],[1592,1595],{"type":27,"tag":1005,"props":1593,"children":1594},{"disabled":1007,"type":1008},[],{"type":32,"value":1596}," 标签与输入框关联",{"type":27,"tag":49,"props":1598,"children":1600},{"className":1599},[1002],[1601,1604],{"type":27,"tag":1005,"props":1602,"children":1603},{"disabled":1007,"type":1008},[],{"type":32,"value":1605}," 验证消息清晰",{"type":27,"tag":49,"props":1607,"children":1609},{"className":1608},[1002],[1610,1613],{"type":27,"tag":1005,"props":1611,"children":1612},{"disabled":1007,"type":1008},[],{"type":32,"value":1614}," 色彩对比度足够",{"type":27,"tag":49,"props":1616,"children":1618},{"className":1617},[1002],[1619,1622],{"type":27,"tag":1005,"props":1620,"children":1621},{"disabled":1007,"type":1008},[],{"type":32,"value":1623}," 屏幕阅读器兼容",{"type":27,"tag":49,"props":1625,"children":1627},{"className":1626},[1002],[1628,1631],{"type":27,"tag":1005,"props":1629,"children":1630},{"disabled":1007,"type":1008},[],{"type":32,"value":1632}," 移动设备测试",{"title":7,"searchDepth":691,"depth":691,"links":1634},[1635,1636,1640,1641,1642,1643,1644,1645,1646],{"id":1373,"depth":694,"text":1373},{"id":1395,"depth":694,"text":1395,"children":1637},[1638,1639],{"id":1400,"depth":691,"text":1400},{"id":1414,"depth":691,"text":1414},{"id":1379,"depth":694,"text":1379},{"id":1441,"depth":694,"text":1441},{"id":1455,"depth":694,"text":1455},{"id":1469,"depth":694,"text":1469},{"id":1483,"depth":694,"text":1483},{"id":885,"depth":694,"text":885},{"id":991,"depth":694,"text":991},"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":1651,"image":18,"imageQuery":19,"pexelsPhotoId":20,"pexelsUrl":21,"featured":6,"readingTime":22,"body":1652,"_type":703,"_id":704,"_source":705,"_file":706,"_stem":707,"_extension":708},[13,14,15,16,17],{"type":24,"children":1653,"toc":2184},[1654,1658,1662,1666,1681,1700,1704,1708,1723,1727,1811,1815,1819,1823,1827,1842,1846,1861,1865,1869,1873,1877,1892,1896,1900,1904,1908,1923,1927,1942,1946,1961,1965,1969,1973,1998,2002,2013,2017,2021,2025,2040,2044,2063,2067,2071,2075,2090,2094,2109,2113,2117,2148,2152,2156,2160],{"type":27,"tag":28,"props":1655,"children":1656},{},[1657],{"type":32,"value":33},{"type":27,"tag":28,"props":1659,"children":1660},{},[1661],{"type":32,"value":38},{"type":27,"tag":28,"props":1663,"children":1664},{},[1665],{"type":32,"value":43},{"type":27,"tag":45,"props":1667,"children":1668},{},[1669,1673,1677],{"type":27,"tag":49,"props":1670,"children":1671},{},[1672],{"type":32,"value":53},{"type":27,"tag":49,"props":1674,"children":1675},{},[1676],{"type":32,"value":58},{"type":27,"tag":49,"props":1678,"children":1679},{},[1680],{"type":32,"value":63},{"type":27,"tag":28,"props":1682,"children":1683},{},[1684,1685,1689,1690,1694,1695,1699],{"type":32,"value":68},{"type":27,"tag":70,"props":1686,"children":1687},{"href":72},[1688],{"type":32,"value":75},{"type":32,"value":77},{"type":27,"tag":70,"props":1691,"children":1692},{"href":80},[1693],{"type":32,"value":83},{"type":32,"value":85},{"type":27,"tag":70,"props":1696,"children":1697},{"href":88},[1698],{"type":32,"value":91},{"type":32,"value":93},{"type":27,"tag":95,"props":1701,"children":1702},{"id":97},[1703],{"type":32,"value":100},{"type":27,"tag":28,"props":1705,"children":1706},{},[1707],{"type":32,"value":105},{"type":27,"tag":45,"props":1709,"children":1710},{},[1711,1715,1719],{"type":27,"tag":49,"props":1712,"children":1713},{},[1714],{"type":32,"value":113},{"type":27,"tag":49,"props":1716,"children":1717},{},[1718],{"type":32,"value":118},{"type":27,"tag":49,"props":1720,"children":1721},{},[1722],{"type":32,"value":123},{"type":27,"tag":28,"props":1724,"children":1725},{},[1726],{"type":32,"value":128},{"type":27,"tag":130,"props":1728,"children":1729},{},[1730,1748],{"type":27,"tag":134,"props":1731,"children":1732},{},[1733],{"type":27,"tag":138,"props":1734,"children":1735},{},[1736,1740,1744],{"type":27,"tag":142,"props":1737,"children":1738},{},[1739],{"type":32,"value":146},{"type":27,"tag":142,"props":1741,"children":1742},{},[1743],{"type":32,"value":151},{"type":27,"tag":142,"props":1745,"children":1746},{},[1747],{"type":32,"value":156},{"type":27,"tag":158,"props":1749,"children":1750},{},[1751,1766,1781,1796],{"type":27,"tag":138,"props":1752,"children":1753},{},[1754,1758,1762],{"type":27,"tag":165,"props":1755,"children":1756},{},[1757],{"type":32,"value":13},{"type":27,"tag":165,"props":1759,"children":1760},{},[1761],{"type":32,"value":173},{"type":27,"tag":165,"props":1763,"children":1764},{},[1765],{"type":32,"value":178},{"type":27,"tag":138,"props":1767,"children":1768},{},[1769,1773,1777],{"type":27,"tag":165,"props":1770,"children":1771},{},[1772],{"type":32,"value":15},{"type":27,"tag":165,"props":1774,"children":1775},{},[1776],{"type":32,"value":190},{"type":27,"tag":165,"props":1778,"children":1779},{},[1780],{"type":32,"value":195},{"type":27,"tag":138,"props":1782,"children":1783},{},[1784,1788,1792],{"type":27,"tag":165,"props":1785,"children":1786},{},[1787],{"type":32,"value":203},{"type":27,"tag":165,"props":1789,"children":1790},{},[1791],{"type":32,"value":208},{"type":27,"tag":165,"props":1793,"children":1794},{},[1795],{"type":32,"value":213},{"type":27,"tag":138,"props":1797,"children":1798},{},[1799,1803,1807],{"type":27,"tag":165,"props":1800,"children":1801},{},[1802],{"type":32,"value":221},{"type":27,"tag":165,"props":1804,"children":1805},{},[1806],{"type":32,"value":226},{"type":27,"tag":165,"props":1808,"children":1809},{},[1810],{"type":32,"value":231},{"type":27,"tag":28,"props":1812,"children":1813},{},[1814],{"type":32,"value":236},{"type":27,"tag":95,"props":1816,"children":1817},{"id":239},[1818],{"type":32,"value":242},{"type":27,"tag":28,"props":1820,"children":1821},{},[1822],{"type":32,"value":247},{"type":27,"tag":28,"props":1824,"children":1825},{},[1826],{"type":32,"value":252},{"type":27,"tag":45,"props":1828,"children":1829},{},[1830,1834,1838],{"type":27,"tag":49,"props":1831,"children":1832},{},[1833],{"type":32,"value":260},{"type":27,"tag":49,"props":1835,"children":1836},{},[1837],{"type":32,"value":265},{"type":27,"tag":49,"props":1839,"children":1840},{},[1841],{"type":32,"value":270},{"type":27,"tag":28,"props":1843,"children":1844},{},[1845],{"type":32,"value":275},{"type":27,"tag":45,"props":1847,"children":1848},{},[1849,1853,1857],{"type":27,"tag":49,"props":1850,"children":1851},{},[1852],{"type":32,"value":283},{"type":27,"tag":49,"props":1854,"children":1855},{},[1856],{"type":32,"value":288},{"type":27,"tag":49,"props":1858,"children":1859},{},[1860],{"type":32,"value":293},{"type":27,"tag":28,"props":1862,"children":1863},{},[1864],{"type":32,"value":298},{"type":27,"tag":95,"props":1866,"children":1867},{"id":301},[1868],{"type":32,"value":304},{"type":27,"tag":28,"props":1870,"children":1871},{},[1872],{"type":32,"value":309},{"type":27,"tag":28,"props":1874,"children":1875},{},[1876],{"type":32,"value":314},{"type":27,"tag":45,"props":1878,"children":1879},{},[1880,1884,1888],{"type":27,"tag":49,"props":1881,"children":1882},{},[1883],{"type":32,"value":322},{"type":27,"tag":49,"props":1885,"children":1886},{},[1887],{"type":32,"value":327},{"type":27,"tag":49,"props":1889,"children":1890},{},[1891],{"type":32,"value":332},{"type":27,"tag":28,"props":1893,"children":1894},{},[1895],{"type":32,"value":337},{"type":27,"tag":28,"props":1897,"children":1898},{},[1899],{"type":32,"value":342},{"type":27,"tag":95,"props":1901,"children":1902},{"id":345},[1903],{"type":32,"value":348},{"type":27,"tag":28,"props":1905,"children":1906},{},[1907],{"type":32,"value":353},{"type":27,"tag":45,"props":1909,"children":1910},{},[1911,1915,1919],{"type":27,"tag":49,"props":1912,"children":1913},{},[1914],{"type":32,"value":361},{"type":27,"tag":49,"props":1916,"children":1917},{},[1918],{"type":32,"value":366},{"type":27,"tag":49,"props":1920,"children":1921},{},[1922],{"type":32,"value":371},{"type":27,"tag":28,"props":1924,"children":1925},{},[1926],{"type":32,"value":376},{"type":27,"tag":45,"props":1928,"children":1929},{},[1930,1934,1938],{"type":27,"tag":49,"props":1931,"children":1932},{},[1933],{"type":32,"value":384},{"type":27,"tag":49,"props":1935,"children":1936},{},[1937],{"type":32,"value":389},{"type":27,"tag":49,"props":1939,"children":1940},{},[1941],{"type":32,"value":394},{"type":27,"tag":28,"props":1943,"children":1944},{},[1945],{"type":32,"value":399},{"type":27,"tag":45,"props":1947,"children":1948},{},[1949,1953,1957],{"type":27,"tag":49,"props":1950,"children":1951},{},[1952],{"type":32,"value":407},{"type":27,"tag":49,"props":1954,"children":1955},{},[1956],{"type":32,"value":412},{"type":27,"tag":49,"props":1958,"children":1959},{},[1960],{"type":32,"value":417},{"type":27,"tag":95,"props":1962,"children":1963},{"id":420},[1964],{"type":32,"value":423},{"type":27,"tag":28,"props":1966,"children":1967},{},[1968],{"type":32,"value":428},{"type":27,"tag":28,"props":1970,"children":1971},{},[1972],{"type":32,"value":433},{"type":27,"tag":435,"props":1974,"children":1975},{},[1976,1980,1984,1994],{"type":27,"tag":49,"props":1977,"children":1978},{},[1979],{"type":32,"value":442},{"type":27,"tag":49,"props":1981,"children":1982},{},[1983],{"type":32,"value":447},{"type":27,"tag":49,"props":1985,"children":1986},{},[1987,1988,1993],{"type":32,"value":452},{"type":27,"tag":454,"props":1989,"children":1991},{"className":1990},[],[1992],{"type":32,"value":459},{"type":32,"value":461},{"type":27,"tag":49,"props":1995,"children":1996},{},[1997],{"type":32,"value":466},{"type":27,"tag":28,"props":1999,"children":2000},{},[2001],{"type":32,"value":471},{"type":27,"tag":45,"props":2003,"children":2004},{},[2005,2009],{"type":27,"tag":49,"props":2006,"children":2007},{},[2008],{"type":32,"value":479},{"type":27,"tag":49,"props":2010,"children":2011},{},[2012],{"type":32,"value":484},{"type":27,"tag":28,"props":2014,"children":2015},{},[2016],{"type":32,"value":489},{"type":27,"tag":95,"props":2018,"children":2019},{"id":492},[2020],{"type":32,"value":492},{"type":27,"tag":28,"props":2022,"children":2023},{},[2024],{"type":32,"value":499},{"type":27,"tag":45,"props":2026,"children":2027},{},[2028,2032,2036],{"type":27,"tag":49,"props":2029,"children":2030},{},[2031],{"type":32,"value":507},{"type":27,"tag":49,"props":2033,"children":2034},{},[2035],{"type":32,"value":512},{"type":27,"tag":49,"props":2037,"children":2038},{},[2039],{"type":32,"value":517},{"type":27,"tag":28,"props":2041,"children":2042},{},[2043],{"type":32,"value":522},{"type":27,"tag":45,"props":2045,"children":2046},{},[2047,2051,2055,2059],{"type":27,"tag":49,"props":2048,"children":2049},{},[2050],{"type":32,"value":530},{"type":27,"tag":49,"props":2052,"children":2053},{},[2054],{"type":32,"value":535},{"type":27,"tag":49,"props":2056,"children":2057},{},[2058],{"type":32,"value":540},{"type":27,"tag":49,"props":2060,"children":2061},{},[2062],{"type":32,"value":545},{"type":27,"tag":28,"props":2064,"children":2065},{},[2066],{"type":32,"value":550},{"type":27,"tag":95,"props":2068,"children":2069},{"id":553},[2070],{"type":32,"value":556},{"type":27,"tag":28,"props":2072,"children":2073},{},[2074],{"type":32,"value":561},{"type":27,"tag":45,"props":2076,"children":2077},{},[2078,2082,2086],{"type":27,"tag":49,"props":2079,"children":2080},{},[2081],{"type":32,"value":569},{"type":27,"tag":49,"props":2083,"children":2084},{},[2085],{"type":32,"value":574},{"type":27,"tag":49,"props":2087,"children":2088},{},[2089],{"type":32,"value":579},{"type":27,"tag":28,"props":2091,"children":2092},{},[2093],{"type":32,"value":584},{"type":27,"tag":45,"props":2095,"children":2096},{},[2097,2101,2105],{"type":27,"tag":49,"props":2098,"children":2099},{},[2100],{"type":32,"value":592},{"type":27,"tag":49,"props":2102,"children":2103},{},[2104],{"type":32,"value":597},{"type":27,"tag":49,"props":2106,"children":2107},{},[2108],{"type":32,"value":602},{"type":27,"tag":28,"props":2110,"children":2111},{},[2112],{"type":32,"value":607},{"type":27,"tag":95,"props":2114,"children":2115},{"id":610},[2116],{"type":32,"value":610},{"type":27,"tag":45,"props":2118,"children":2119},{},[2120,2124,2128,2132,2136,2140,2144],{"type":27,"tag":49,"props":2121,"children":2122},{},[2123],{"type":32,"value":620},{"type":27,"tag":49,"props":2125,"children":2126},{},[2127],{"type":32,"value":625},{"type":27,"tag":49,"props":2129,"children":2130},{},[2131],{"type":32,"value":630},{"type":27,"tag":49,"props":2133,"children":2134},{},[2135],{"type":32,"value":635},{"type":27,"tag":49,"props":2137,"children":2138},{},[2139],{"type":32,"value":640},{"type":27,"tag":49,"props":2141,"children":2142},{},[2143],{"type":32,"value":645},{"type":27,"tag":49,"props":2145,"children":2146},{},[2147],{"type":32,"value":650},{"type":27,"tag":95,"props":2149,"children":2150},{"id":653},[2151],{"type":32,"value":653},{"type":27,"tag":28,"props":2153,"children":2154},{},[2155],{"type":32,"value":660},{"type":27,"tag":28,"props":2157,"children":2158},{},[2159],{"type":32,"value":665},{"type":27,"tag":45,"props":2161,"children":2162},{},[2163,2170,2177],{"type":27,"tag":49,"props":2164,"children":2165},{},[2166],{"type":27,"tag":70,"props":2167,"children":2168},{"href":72},[2169],{"type":32,"value":75},{"type":27,"tag":49,"props":2171,"children":2172},{},[2173],{"type":27,"tag":70,"props":2174,"children":2175},{"href":80},[2176],{"type":32,"value":83},{"type":27,"tag":49,"props":2178,"children":2179},{},[2180],{"type":27,"tag":70,"props":2181,"children":2182},{"href":88},[2183],{"type":32,"value":91},{"title":7,"searchDepth":691,"depth":691,"links":2185},[2186,2187,2188,2189,2190,2191,2192,2193,2194],{"id":97,"depth":694,"text":100},{"id":239,"depth":694,"text":242},{"id":301,"depth":694,"text":304},{"id":345,"depth":694,"text":348},{"id":420,"depth":694,"text":423},{"id":492,"depth":694,"text":492},{"id":553,"depth":694,"text":556},{"id":610,"depth":694,"text":610},{"id":653,"depth":694,"text":653},1776174410188]