[{"data":1,"prerenderedAt":1151},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Ftheming":199,"\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Ftheming-surround":1146},[4,9,41,111,116,132],{"title":5,"path":6,"stem":7,"icon":8},"准备","\u002Fdocs\u002Fpreparation","1.docs\u002F1.preparation","i-lucide-rocket",{"title":10,"icon":11,"path":12,"stem":13,"children":14,"page":40},"用户手册","i-lucide-book-open","\u002Fdocs\u002Fgetting-started","1.docs\u002F2.getting-started",[15,20,25,30,35],{"title":16,"path":17,"stem":18,"icon":19},"认识 UDhold","\u002Fdocs\u002Fgetting-started\u002Fwhat-is-udhold","1.docs\u002F2.getting-started\u002F1.what-is-udhold","i-lucide-info",{"title":21,"path":22,"stem":23,"icon":24},"核心概念","\u002Fdocs\u002Fgetting-started\u002Fcore-concepts","1.docs\u002F2.getting-started\u002F2.core-concepts","i-lucide-lightbulb",{"title":26,"path":27,"stem":28,"icon":29},"主面板布局","\u002Fdocs\u002Fgetting-started\u002Fmain-interface","1.docs\u002F2.getting-started\u002F3.main-interface","i-lucide-monitor",{"title":31,"path":32,"stem":33,"icon":34},"快速上手 5 分钟","\u002Fdocs\u002Fgetting-started\u002Fquick-tour","1.docs\u002F2.getting-started\u002F4.quick-tour","i-lucide-zap",{"title":36,"path":37,"stem":38,"icon":39},"常用快捷键","\u002Fdocs\u002Fgetting-started\u002Fshortcut-keys","1.docs\u002F2.getting-started\u002F5.shortcut-keys","i-lucide-keyboard",false,{"title":42,"path":43,"stem":44,"children":45,"icon":110},"核心功能","\u002Fdocs\u002Ffeatures","1.docs\u002F3.features\u002F1.index",[46,49,53,58,63,67,71,76,81,86,91,96,101,106],{"title":47,"path":43,"stem":44,"icon":48},"功能总览","i-lucide-layout-grid",{"title":50,"path":51,"stem":52,"icon":39},"快捷键","\u002Fdocs\u002Ffeatures\u002Fshortcuts","1.docs\u002F3.features\u002F10.shortcuts",{"title":54,"path":55,"stem":56,"icon":57},"AI 模型","\u002Fdocs\u002Ffeatures\u002Fai-models","1.docs\u002F3.features\u002F16.ai-models","i-lucide-bot",{"title":59,"path":60,"stem":61,"icon":62},"AI 助手","\u002Fdocs\u002Ffeatures\u002Fai-helper","1.docs\u002F3.features\u002F17.ai-helper","i-lucide-bot-message-square",{"title":64,"path":65,"stem":66,"icon":19},"关于","\u002Fdocs\u002Ffeatures\u002Fabout","1.docs\u002F3.features\u002F19.about",{"title":68,"path":69,"stem":70,"icon":29},"系统命令","\u002Fdocs\u002Ffeatures\u002Fsystem","1.docs\u002F3.features\u002F2.system",{"title":72,"path":73,"stem":74,"icon":75},"调试日志","\u002Fdocs\u002Ffeatures\u002Fdebug","1.docs\u002F3.features\u002F20.debug","i-lucide-terminal",{"title":77,"path":78,"stem":79,"icon":80},"通用设置","\u002Fdocs\u002Ffeatures\u002Fsettings","1.docs\u002F3.features\u002F21.settings","i-mdi-cog-outline",{"title":82,"path":83,"stem":84,"icon":85},"文件资源管理器","\u002Fdocs\u002Ffeatures\u002Ffiles","1.docs\u002F3.features\u002F3.files","i-lucide-folder-tree",{"title":87,"path":88,"stem":89,"icon":90},"文件树","\u002Fdocs\u002Ffeatures\u002Ffiles-tree","1.docs\u002F3.features\u002F4.files-tree","i-lucide-list-tree",{"title":92,"path":93,"stem":94,"icon":95},"文件预览","\u002Fdocs\u002Ffeatures\u002Fpreview","1.docs\u002F3.features\u002F5.preview","i-lucide-eye",{"title":97,"path":98,"stem":99,"icon":100},"本地启动","\u002Fdocs\u002Ffeatures\u002Flocal-launch","1.docs\u002F3.features\u002F6.local-launch","i-lucide-app-window",{"title":102,"path":103,"stem":104,"icon":105},"插件中心","\u002Fdocs\u002Ffeatures\u002Fplugins","1.docs\u002F3.features\u002F7.plugins","i-lucide-puzzle",{"title":107,"path":108,"stem":109,"icon":8},"快速启动","\u002Fdocs\u002Ffeatures\u002Fquick-start","1.docs\u002F3.features\u002F8.quick-start","i-lucide-star",{"title":112,"path":113,"stem":114,"icon":115},"主题","\u002Fdocs\u002Fthemes","1.docs\u002F4.themes","i-lucide-palette",{"title":117,"icon":118,"path":119,"stem":120,"children":121,"page":40},"相关协议","i-lucide-scroll","\u002Fdocs\u002Flegal","1.docs\u002F5.legal",[122,127],{"title":123,"path":124,"stem":125,"icon":126},"用户须知","\u002Fdocs\u002Flegal\u002Fuser-notice","1.docs\u002F5.legal\u002F1.user-notice","i-lucide-file-text",{"title":128,"path":129,"stem":130,"icon":131},"隐私协议","\u002Fdocs\u002Flegal\u002Fprivacy","1.docs\u002F5.legal\u002F2.privacy","i-lucide-shield-check",{"title":133,"icon":134,"path":135,"stem":136,"children":137,"page":40},"开发指南","i-lucide-code","\u002Fdocs\u002Fdevelopment","1.docs\u002F6.development",[138,156,190],{"title":139,"icon":8,"path":140,"stem":141,"children":142,"page":40},"快速开始","\u002Fdocs\u002Fdevelopment\u002Fquick-start","1.docs\u002F6.development\u002F1.quick-start",[143,147,151],{"title":144,"path":145,"stem":146,"icon":19},"介绍","\u002Fdocs\u002Fdevelopment\u002Fquick-start\u002Fintroduction","1.docs\u002F6.development\u002F1.quick-start\u002F1.introduction",{"title":148,"path":149,"stem":150,"icon":34},"快速上手","\u002Fdocs\u002Fdevelopment\u002Fquick-start\u002Fgetting-started","1.docs\u002F6.development\u002F1.quick-start\u002F2.getting-started",{"title":152,"path":153,"stem":154,"icon":155},"常见问题","\u002Fdocs\u002Fdevelopment\u002Fquick-start\u002Ffaq","1.docs\u002F6.development\u002F1.quick-start\u002F3.faq","i-lucide-circle-help",{"title":157,"icon":115,"path":158,"stem":159,"children":160,"page":40},"设计系统","\u002Fdocs\u002Fdevelopment\u002Fdesign-system","1.docs\u002F6.development\u002F2.design-system",[161,166,171,176,181,186],{"title":162,"path":163,"stem":164,"icon":165},"设计令牌","\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Ftokens","1.docs\u002F6.development\u002F2.design-system\u002F1.tokens","i-lucide-pipette",{"title":167,"path":168,"stem":169,"icon":170},"主题与明暗模式","\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Ftheming","1.docs\u002F6.development\u002F2.design-system\u002F2.theming","i-lucide-sun-moon",{"title":172,"path":173,"stem":174,"icon":175},"基础样式类","\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Fbase-styles","1.docs\u002F6.development\u002F2.design-system\u002F3.base-styles","i-lucide-layout-template",{"title":177,"path":178,"stem":179,"icon":180},"图标体系","\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Ficons","1.docs\u002F6.development\u002F2.design-system\u002F4.icons","i-lucide-shapes",{"title":182,"path":183,"stem":184,"icon":185},"通用组件","\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Fcomponents","1.docs\u002F6.development\u002F2.design-system\u002F5.components","i-lucide-component",{"title":187,"path":188,"stem":189,"icon":48},"场景组件","\u002Fdocs\u002Fdevelopment\u002Fdesign-system\u002Fscene-components","1.docs\u002F6.development\u002F2.design-system\u002F6.scene-components",{"title":191,"icon":57,"path":192,"stem":193,"children":194,"page":40},"AI","\u002Fdocs\u002Fdevelopment\u002Fai","1.docs\u002F6.development\u002F3.ai",[195],{"title":196,"path":197,"stem":198,"icon":126},"LLMs.txt","\u002Fdocs\u002Fdevelopment\u002Fai\u002Fllms-txt","1.docs\u002F6.development\u002F3.ai\u002F1.llms-txt",{"id":200,"title":167,"body":201,"description":1139,"extension":1140,"meta":1141,"navigation":1142,"path":168,"rawbody":1143,"seo":1144,"stem":169,"__hash__":1145},"docs\u002F1.docs\u002F6.development\u002F2.design-system\u002F2.theming.md",{"type":202,"value":203,"toc":1132},"minimark",[204,213,217,220,290,300,307,311,318,347,357,407,437,446,612,618,621,627,919,922,1005,1008,1046,1049,1052,1121,1128],[205,206,207,208,212],"p",{},"设计令牌的两套值（亮 \u002F 暗）靠 ",[209,210,211],"code",{},"html"," 上的 class 切换。这一章讲清楚切换机制，以及插件接入主题联动的标准做法。",[214,215,216],"h2",{"id":216},"切换机制",[205,218,219],{},"体系支持三条通道，优先级从高到低：",[221,222,223,239],"table",{},[224,225,226],"thead",{},[227,228,229,233,236],"tr",{},[230,231,232],"th",{},"通道",[230,234,235],{},"触发方式",[230,237,238],{},"效果",[240,241,242,259,275],"tbody",{},[227,243,244,248,253],{},[245,246,247],"td",{},"强制暗色",[245,249,250],{},[209,251,252],{},"html.dark",[245,254,255,256],{},"应用整套暗色变量，",[209,257,258],{},"color-scheme: dark",[227,260,261,264,269],{},[245,262,263],{},"强制亮色",[245,265,266],{},[209,267,268],{},"html.light",[245,270,271,272],{},"应用亮色变量，",[209,273,274],{},"color-scheme: light",[227,276,277,280,283],{},[245,278,279],{},"跟随系统",[245,281,282],{},"无 class",[245,284,285,286,289],{},"按系统 ",[209,287,288],{},"prefers-color-scheme"," 自动切换",[205,291,292,295,296,299],{},[209,293,294],{},"color-scheme"," 同时让原生控件（",[209,297,298],{},"\u003Cselect>"," 弹出面板、滚动条、表单底色）跟随主题，这是免费获得的一致性。",[205,301,302,303,306],{},"宿主设置里选「跟随系统 \u002F 浅色 \u002F 深色」时，会向所有 WebView 广播 ",[209,304,305],{},"update-theme-info"," 事件；主题色（六预设 + 自定义）与窗口透明度也走同一事件。",[214,308,310],{"id":309},"三步接入工程型插件","三步接入（工程型插件）",[205,312,313,317],{},[314,315,316],"strong",{},"第一步","，入口引入全局样式（设计令牌都在里面）：",[319,320,325],"pre",{"className":321,"code":322,"language":323,"meta":324,"style":324},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import '@udhold\u002Fudhold-ui\u002Fstyles\u002Fglobal.css'\n","ts","",[209,326,327],{"__ignoreMap":324},[328,329,332,336,340,344],"span",{"class":330,"line":331},"line",1,[328,333,335],{"class":334},"s7zQu","import",[328,337,339],{"class":338},"sMK4o"," '",[328,341,343],{"class":342},"sfazB","@udhold\u002Fudhold-ui\u002Fstyles\u002Fglobal.css",[328,345,346],{"class":338},"'\n",[205,348,349,352,353,356],{},[314,350,351],{},"第二步","，入口调用一次 ",[209,354,355],{},"setupThemeSync()","：",[319,358,360],{"className":321,"code":359,"language":323,"meta":324,"style":324},"import { setupThemeSync } from '@udhold\u002Fudhold-ui\u002Futils'\n\nsetupThemeSync() \u002F\u002F 拉取宿主当前主题 + 监听后续变更，宿主不可用时静默降级\n",[209,361,362,386,393],{"__ignoreMap":324},[328,363,364,366,369,373,376,379,381,384],{"class":330,"line":331},[328,365,335],{"class":334},[328,367,368],{"class":338}," {",[328,370,372],{"class":371},"sTEyZ"," setupThemeSync",[328,374,375],{"class":338}," }",[328,377,378],{"class":334}," from",[328,380,339],{"class":338},[328,382,383],{"class":342},"@udhold\u002Fudhold-ui\u002Futils",[328,385,346],{"class":338},[328,387,389],{"class":330,"line":388},2,[328,390,392],{"emptyLinePlaceholder":391},true,"\n",[328,394,396,400,403],{"class":330,"line":395},3,[328,397,399],{"class":398},"s2Zo4","setupThemeSync",[328,401,402],{"class":371},"() ",[328,404,406],{"class":405},"sHwdD","\u002F\u002F 拉取宿主当前主题 + 监听后续变更，宿主不可用时静默降级\n",[205,408,409,410,413,414,416,417,420,421,424,425,428,429,432,433,436],{},"它做三件事：向宿主查询当前 ",[209,411,412],{},"ThemeInfo"," 立即应用；监听 ",[209,415,305],{}," 事件实时跟随；每次变更同步三样东西——",[209,418,419],{},"html.dark\u002Flight"," class（明暗）、",[209,422,423],{},"body.theme-*"," class 或内联 ",[209,426,427],{},"--primary-color","（主题色）、",[209,430,431],{},"--window-opacity"," \u002F ",[209,434,435],{},"--panel-opacity","（透明度）。",[205,438,439,442,443,356],{},[314,440,441],{},"第三步","，组件里需要感知明暗做逻辑分支时（比如给代码编辑器换主题），用 ",[209,444,445],{},"useColorScheme",[319,447,451],{"className":448,"code":449,"language":450,"meta":324,"style":324},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cscript setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useColorScheme } from '@udhold\u002Fudhold-ui\u002Fcomposables'\n\nconst { isDark } = useColorScheme()\nconst editorTheme = computed(() => (isDark.value ? 'vs-dark' : 'vs'))\n\u003C\u002Fscript>\n","vue",[209,452,453,482,501,521,526,548,602],{"__ignoreMap":324},[328,454,455,458,462,466,469,472,475,477,479],{"class":330,"line":331},[328,456,457],{"class":338},"\u003C",[328,459,461],{"class":460},"swJcz","script",[328,463,465],{"class":464},"spNyl"," setup",[328,467,468],{"class":464}," lang",[328,470,471],{"class":338},"=",[328,473,474],{"class":338},"\"",[328,476,323],{"class":342},[328,478,474],{"class":338},[328,480,481],{"class":338},">\n",[328,483,484,486,488,491,493,495,497,499],{"class":330,"line":388},[328,485,335],{"class":334},[328,487,368],{"class":338},[328,489,490],{"class":371}," computed",[328,492,375],{"class":338},[328,494,378],{"class":334},[328,496,339],{"class":338},[328,498,450],{"class":342},[328,500,346],{"class":338},[328,502,503,505,507,510,512,514,516,519],{"class":330,"line":395},[328,504,335],{"class":334},[328,506,368],{"class":338},[328,508,509],{"class":371}," useColorScheme",[328,511,375],{"class":338},[328,513,378],{"class":334},[328,515,339],{"class":338},[328,517,518],{"class":342},"@udhold\u002Fudhold-ui\u002Fcomposables",[328,520,346],{"class":338},[328,522,524],{"class":330,"line":523},4,[328,525,392],{"emptyLinePlaceholder":391},[328,527,529,532,534,537,540,543,545],{"class":330,"line":528},5,[328,530,531],{"class":464},"const",[328,533,368],{"class":338},[328,535,536],{"class":371}," isDark ",[328,538,539],{"class":338},"}",[328,541,542],{"class":338}," =",[328,544,509],{"class":398},[328,546,547],{"class":371},"()\n",[328,549,551,553,556,558,560,563,566,569,572,575,578,581,583,586,589,592,594,597,599],{"class":330,"line":550},6,[328,552,531],{"class":464},[328,554,555],{"class":371}," editorTheme ",[328,557,471],{"class":338},[328,559,490],{"class":398},[328,561,562],{"class":371},"(",[328,564,565],{"class":338},"()",[328,567,568],{"class":464}," =>",[328,570,571],{"class":371}," (isDark",[328,573,574],{"class":338},".",[328,576,577],{"class":371},"value ",[328,579,580],{"class":338},"?",[328,582,339],{"class":338},[328,584,585],{"class":342},"vs-dark",[328,587,588],{"class":338},"'",[328,590,591],{"class":338}," :",[328,593,339],{"class":338},[328,595,596],{"class":342},"vs",[328,598,588],{"class":338},[328,600,601],{"class":371},"))\n",[328,603,605,608,610],{"class":330,"line":604},7,[328,606,607],{"class":338},"\u003C\u002F",[328,609,461],{"class":460},[328,611,481],{"class":338},[205,613,614,617],{},[209,615,616],{},"isDark"," 是响应式的：宿主切换主题的瞬间自动更新。样式层面则不需要它——令牌本身就是双份的，跟着 class 自动切换。",[214,619,620],{"id":620},"免构建插件的做法",[205,622,623,624,626],{},"没有 npm 工程的静态插件拿不到 ",[209,625,399],{},"，用宿主桥直接暴露的 API 等价实现：",[319,628,631],{"className":629,"code":630,"language":211,"meta":324,"style":324},"language-html shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cscript>\n  \u002F\u002F 初始快照：webview 创建时宿主注入\n  const boot = window.__UDHOLD_BOOT__ || {}\n  apply(boot.theme || {})\n\n  \u002F\u002F 跟随变更\n  window.udhold.onThemeChange((theme) => apply(theme))\n\n  function apply(info) {\n    const dark = info.theme === 'dark'\n      || (info.theme !== 'light' && matchMedia('(prefers-color-scheme: dark)').matches)\n    document.documentElement.classList.toggle('dark', dark)\n    document.documentElement.classList.toggle('light', !dark)\n  }\n\u003C\u002Fscript>\n",[209,632,633,641,646,670,691,695,700,734,739,757,785,834,870,904,910],{"__ignoreMap":324},[328,634,635,637,639],{"class":330,"line":331},[328,636,457],{"class":338},[328,638,461],{"class":460},[328,640,481],{"class":338},[328,642,643],{"class":330,"line":388},[328,644,645],{"class":405},"  \u002F\u002F 初始快照：webview 创建时宿主注入\n",[328,647,648,651,654,656,659,661,664,667],{"class":330,"line":395},[328,649,650],{"class":464},"  const",[328,652,653],{"class":371}," boot ",[328,655,471],{"class":338},[328,657,658],{"class":371}," window",[328,660,574],{"class":338},[328,662,663],{"class":371},"__UDHOLD_BOOT__ ",[328,665,666],{"class":338},"||",[328,668,669],{"class":338}," {}\n",[328,671,672,675,678,680,683,685,688],{"class":330,"line":523},[328,673,674],{"class":398},"  apply",[328,676,677],{"class":371},"(boot",[328,679,574],{"class":338},[328,681,682],{"class":371},"theme ",[328,684,666],{"class":338},[328,686,687],{"class":338}," {}",[328,689,690],{"class":371},")\n",[328,692,693],{"class":330,"line":528},[328,694,392],{"emptyLinePlaceholder":391},[328,696,697],{"class":330,"line":550},[328,698,699],{"class":405},"  \u002F\u002F 跟随变更\n",[328,701,702,705,707,710,712,715,717,719,723,726,728,731],{"class":330,"line":604},[328,703,704],{"class":371},"  window",[328,706,574],{"class":338},[328,708,709],{"class":371},"udhold",[328,711,574],{"class":338},[328,713,714],{"class":398},"onThemeChange",[328,716,562],{"class":371},[328,718,562],{"class":338},[328,720,722],{"class":721},"sHdIc","theme",[328,724,725],{"class":338},")",[328,727,568],{"class":464},[328,729,730],{"class":398}," apply",[328,732,733],{"class":371},"(theme))\n",[328,735,737],{"class":330,"line":736},8,[328,738,392],{"emptyLinePlaceholder":391},[328,740,742,745,747,749,752,754],{"class":330,"line":741},9,[328,743,744],{"class":464},"  function",[328,746,730],{"class":398},[328,748,562],{"class":338},[328,750,751],{"class":721},"info",[328,753,725],{"class":338},[328,755,756],{"class":338}," {\n",[328,758,760,763,766,768,771,773,775,778,780,783],{"class":330,"line":759},10,[328,761,762],{"class":464},"    const",[328,764,765],{"class":371}," dark",[328,767,542],{"class":338},[328,769,770],{"class":371}," info",[328,772,574],{"class":338},[328,774,722],{"class":371},[328,776,777],{"class":338}," ===",[328,779,339],{"class":338},[328,781,782],{"class":342},"dark",[328,784,346],{"class":338},[328,786,788,791,794,796,798,800,803,805,808,810,813,816,818,820,823,825,827,829,832],{"class":330,"line":787},11,[328,789,790],{"class":338},"      ||",[328,792,793],{"class":460}," (",[328,795,751],{"class":371},[328,797,574],{"class":338},[328,799,722],{"class":371},[328,801,802],{"class":338}," !==",[328,804,339],{"class":338},[328,806,807],{"class":342},"light",[328,809,588],{"class":338},[328,811,812],{"class":338}," &&",[328,814,815],{"class":398}," matchMedia",[328,817,562],{"class":460},[328,819,588],{"class":338},[328,821,822],{"class":342},"(prefers-color-scheme: dark)",[328,824,588],{"class":338},[328,826,725],{"class":460},[328,828,574],{"class":338},[328,830,831],{"class":371},"matches",[328,833,690],{"class":460},[328,835,837,840,842,845,847,850,852,855,857,859,861,863,866,868],{"class":330,"line":836},12,[328,838,839],{"class":371},"    document",[328,841,574],{"class":338},[328,843,844],{"class":371},"documentElement",[328,846,574],{"class":338},[328,848,849],{"class":371},"classList",[328,851,574],{"class":338},[328,853,854],{"class":398},"toggle",[328,856,562],{"class":460},[328,858,588],{"class":338},[328,860,782],{"class":342},[328,862,588],{"class":338},[328,864,865],{"class":338},",",[328,867,765],{"class":371},[328,869,690],{"class":460},[328,871,873,875,877,879,881,883,885,887,889,891,893,895,897,900,902],{"class":330,"line":872},13,[328,874,839],{"class":371},[328,876,574],{"class":338},[328,878,844],{"class":371},[328,880,574],{"class":338},[328,882,849],{"class":371},[328,884,574],{"class":338},[328,886,854],{"class":398},[328,888,562],{"class":460},[328,890,588],{"class":338},[328,892,807],{"class":342},[328,894,588],{"class":338},[328,896,865],{"class":338},[328,898,899],{"class":338}," !",[328,901,782],{"class":371},[328,903,690],{"class":460},[328,905,907],{"class":330,"line":906},14,[328,908,909],{"class":338},"  }\n",[328,911,913,915,917],{"class":330,"line":912},15,[328,914,607],{"class":338},[328,916,461],{"class":460},[328,918,481],{"class":338},[205,920,921],{},"页面样式则按双通道写：",[319,923,927],{"className":924,"code":925,"language":926,"meta":324,"style":324},"language-css shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","body { background: #f1f2f3; color: #1f2124; }\nhtml.dark body { background: #1c1d1f; color: #f2f3f4; }\n","css",[209,928,929,968],{"__ignoreMap":324},[328,930,931,935,937,941,944,947,950,953,956,958,960,963,965],{"class":330,"line":331},[328,932,934],{"class":933},"sBMFI","body",[328,936,368],{"class":338},[328,938,940],{"class":939},"sqsOY"," background",[328,942,943],{"class":338},":",[328,945,946],{"class":338}," #",[328,948,949],{"class":371},"f1f2f3",[328,951,952],{"class":338},";",[328,954,955],{"class":939}," color",[328,957,943],{"class":338},[328,959,946],{"class":338},[328,961,962],{"class":371},"1f2124",[328,964,952],{"class":338},[328,966,967],{"class":338}," }\n",[328,969,970,972,974,976,979,981,983,985,987,990,992,994,996,998,1001,1003],{"class":330,"line":388},[328,971,211],{"class":933},[328,973,574],{"class":338},[328,975,782],{"class":933},[328,977,978],{"class":933}," body",[328,980,368],{"class":338},[328,982,940],{"class":939},[328,984,943],{"class":338},[328,986,946],{"class":338},[328,988,989],{"class":371},"1c1d1f",[328,991,952],{"class":338},[328,993,955],{"class":939},[328,995,943],{"class":338},[328,997,946],{"class":338},[328,999,1000],{"class":371},"f2f3f4",[328,1002,952],{"class":338},[328,1004,967],{"class":338},[214,1006,1007],{"id":1007},"主题色的正确用法",[1009,1010,1011,1022,1033],"ol",{},[1012,1013,1014,1021],"li",{},[314,1015,1016,1017,1020],{},"永远用 ",[209,1018,1019],{},"var(--primary-color)"," 表达主色","，不要抄某个预设的色值——用户切到紫色主题时，写死的蓝色会立刻变得刺眼。",[1012,1023,1024,1025,1028,1029,1032],{},"选中、高亮、品牌氛围用派生令牌 ",[209,1026,1027],{},"--primary-light-bg","（10% 底）与 ",[209,1030,1031],{},"--primary-hover","（hover 加深）。",[1012,1034,1035,1036,432,1039,432,1042,1045],{},"红 \u002F 绿 \u002F 黄等结果语义用 ",[209,1037,1038],{},"--danger-color",[209,1040,1041],{},"--success-color",[209,1043,1044],{},"--warning-color","，与主色区分开：主色表达「这是谁」，语义色表达「发生了什么」。",[214,1047,1048],{"id":1048},"检查清单",[205,1050,1051],{},"上线前过一遍：",[1053,1054,1057,1069,1079,1099,1113],"ul",{"className":1055},[1056],"contains-task-list",[1012,1058,1061,1065,1066,1068],{"className":1059},[1060],"task-list-item",[1062,1063],"input",{"disabled":391,"type":1064},"checkbox"," 入口调用了 ",[209,1067,355],{},"，宿主切明暗时插件实时跟随",[1012,1070,1072,1074,1075,1078],{"className":1071},[1060],[1062,1073],{"disabled":391,"type":1064}," 样式里没有写死的颜色（搜一遍 ",[209,1076,1077],{},"#"," 开头的色值）",[1012,1080,1082,1084,1085,1088,1089,1093,1094,1098],{"className":1081},[1060],[1062,1083],{"disabled":391,"type":1064}," 图片图标用 ",[209,1086,1087],{},"currentColor"," 或自适应反色（见",[1090,1091,177],"a",{"href":1092},".\u002Ficons","与 ",[1090,1095,1097],{"href":1096},".\u002Fcomponents","AdaptiveIcon","）",[1012,1100,1102,1104,1105,1108,1109,1112],{"className":1101},[1060],[1062,1103],{"disabled":391,"type":1064}," 暗色下检查过对比度：次级文字 ",[209,1106,1107],{},"--ink-2"," 在 ",[209,1110,1111],{},"--surface"," 上仍可读",[1012,1114,1116,1118,1119,1098],{"className":1115},[1060],[1062,1117],{"disabled":391,"type":1064}," 原生控件（下拉、日期选择）没有突兀地保持亮色（确认没有显式设置 ",[209,1120,294],{},[205,1122,1123,1124,1127],{},"接下来看",[1090,1125,172],{"href":1126},".\u002Fbase-styles","：按钮、输入框、开关这些高频控件，引完样式文件就能直接写 class 用。",[1129,1130,1131],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sqsOY, html code.shiki .sqsOY{--shiki-light:#8796B0;--shiki-default:#B2CCD6;--shiki-dark:#B2CCD6}",{"title":324,"searchDepth":388,"depth":388,"links":1133},[1134,1135,1136,1137,1138],{"id":216,"depth":388,"text":216},{"id":309,"depth":388,"text":310},{"id":620,"depth":388,"text":620},{"id":1007,"depth":388,"text":1007},{"id":1048,"depth":388,"text":1048},"插件如何跟随宿主的明暗主题、主题色与窗口透明度，三步接入与底层机制。","md",{},{"icon":170},"---\ntitle: 主题与明暗模式\ndescription: 插件如何跟随宿主的明暗主题、主题色与窗口透明度，三步接入与底层机制。\nnavigation:\n  icon: i-lucide-sun-moon\n---\n\n设计令牌的两套值（亮 \u002F 暗）靠 `html` 上的 class 切换。这一章讲清楚切换机制，以及插件接入主题联动的标准做法。\n\n## 切换机制\n\n体系支持三条通道，优先级从高到低：\n\n| 通道 | 触发方式 | 效果 |\n|------|----------|------|\n| 强制暗色 | `html.dark` | 应用整套暗色变量，`color-scheme: dark` |\n| 强制亮色 | `html.light` | 应用亮色变量，`color-scheme: light` |\n| 跟随系统 | 无 class | 按系统 `prefers-color-scheme` 自动切换 |\n\n`color-scheme` 同时让原生控件（`\u003Cselect>` 弹出面板、滚动条、表单底色）跟随主题，这是免费获得的一致性。\n\n宿主设置里选「跟随系统 \u002F 浅色 \u002F 深色」时，会向所有 WebView 广播 `update-theme-info` 事件；主题色（六预设 + 自定义）与窗口透明度也走同一事件。\n\n## 三步接入（工程型插件）\n\n**第一步**，入口引入全局样式（设计令牌都在里面）：\n\n```ts\nimport '@udhold\u002Fudhold-ui\u002Fstyles\u002Fglobal.css'\n```\n\n**第二步**，入口调用一次 `setupThemeSync()`：\n\n```ts\nimport { setupThemeSync } from '@udhold\u002Fudhold-ui\u002Futils'\n\nsetupThemeSync() \u002F\u002F 拉取宿主当前主题 + 监听后续变更，宿主不可用时静默降级\n```\n\n它做三件事：向宿主查询当前 `ThemeInfo` 立即应用；监听 `update-theme-info` 事件实时跟随；每次变更同步三样东西——`html.dark\u002Flight` class（明暗）、`body.theme-*` class 或内联 `--primary-color`（主题色）、`--window-opacity` \u002F `--panel-opacity`（透明度）。\n\n**第三步**，组件里需要感知明暗做逻辑分支时（比如给代码编辑器换主题），用 `useColorScheme`：\n\n```vue\n\u003Cscript setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useColorScheme } from '@udhold\u002Fudhold-ui\u002Fcomposables'\n\nconst { isDark } = useColorScheme()\nconst editorTheme = computed(() => (isDark.value ? 'vs-dark' : 'vs'))\n\u003C\u002Fscript>\n```\n\n`isDark` 是响应式的：宿主切换主题的瞬间自动更新。样式层面则不需要它——令牌本身就是双份的，跟着 class 自动切换。\n\n## 免构建插件的做法\n\n没有 npm 工程的静态插件拿不到 `setupThemeSync`，用宿主桥直接暴露的 API 等价实现：\n\n```html\n\u003Cscript>\n  \u002F\u002F 初始快照：webview 创建时宿主注入\n  const boot = window.__UDHOLD_BOOT__ || {}\n  apply(boot.theme || {})\n\n  \u002F\u002F 跟随变更\n  window.udhold.onThemeChange((theme) => apply(theme))\n\n  function apply(info) {\n    const dark = info.theme === 'dark'\n      || (info.theme !== 'light' && matchMedia('(prefers-color-scheme: dark)').matches)\n    document.documentElement.classList.toggle('dark', dark)\n    document.documentElement.classList.toggle('light', !dark)\n  }\n\u003C\u002Fscript>\n```\n\n页面样式则按双通道写：\n\n```css\nbody { background: #f1f2f3; color: #1f2124; }\nhtml.dark body { background: #1c1d1f; color: #f2f3f4; }\n```\n\n## 主题色的正确用法\n\n1. **永远用 `var(--primary-color)` 表达主色**，不要抄某个预设的色值——用户切到紫色主题时，写死的蓝色会立刻变得刺眼。\n2. 选中、高亮、品牌氛围用派生令牌 `--primary-light-bg`（10% 底）与 `--primary-hover`（hover 加深）。\n3. 红 \u002F 绿 \u002F 黄等结果语义用 `--danger-color` \u002F `--success-color` \u002F `--warning-color`，与主色区分开：主色表达「这是谁」，语义色表达「发生了什么」。\n\n## 检查清单\n\n上线前过一遍：\n\n- [ ] 入口调用了 `setupThemeSync()`，宿主切明暗时插件实时跟随\n- [ ] 样式里没有写死的颜色（搜一遍 `#` 开头的色值）\n- [ ] 图片图标用 `currentColor` 或自适应反色（见[图标体系](.\u002Ficons)与 [AdaptiveIcon](.\u002Fcomponents)）\n- [ ] 暗色下检查过对比度：次级文字 `--ink-2` 在 `--surface` 上仍可读\n- [ ] 原生控件（下拉、日期选择）没有突兀地保持亮色（确认没有显式设置 `color-scheme`）\n\n接下来看[基础样式类](.\u002Fbase-styles)：按钮、输入框、开关这些高频控件，引完样式文件就能直接写 class 用。\n",{"title":167,"description":1139},"dWuEeuUDROL0Oe9YXluBs-qJ3hO-zuJm6uAmsyWVncE",[1147,1149],{"title":162,"path":163,"stem":164,"description":1148,"icon":165},"UDhold 设计系统的颜色、字体、圆角、阴影与动效变量参考，插件界面与宿主保持一致视觉的基础。",{"title":172,"path":173,"stem":174,"description":1150,"icon":175},"开箱即用的按钮、输入框、开关、卡片样式类，引一个 CSS 文件就有全套控件底子。",1793010253429]