詳解:明暗模式自適應(yīng) CSS 變量完全參考)
MCP Apps 主題系統(tǒng)詳解明暗模式自適應(yīng) CSS 變量完全參考【免費(fèi)下載鏈接】ext-appsOfficial repo for spec SDK of MCP Apps protocol - standard for UIs embedded AI chatbots, served by MCP servers項(xiàng)目地址: https://gitcode.com/GitHub_Trending/ex/ext-apps如果你正在開(kāi)發(fā)運(yùn)行在 AI 聊天機(jī)器人里的MCP Apps界面主題系統(tǒng)是你繞不開(kāi)的一課用戶切換到深色模式時(shí)你的應(yīng)用必須立刻跟著變暗且無(wú)需重新加載頁(yè)面。MCP Apps 協(xié)議通過(guò)一套明暗模式自適應(yīng) CSS 變量如--color-background-primary、light-dark()函數(shù)和data-theme屬性讓宿主應(yīng)用Host把自己的配色、字體、字號(hào)下發(fā)給嵌入的 App實(shí)現(xiàn)無(wú)縫的明暗模式切換。為什么 MCP Apps 需要一套主題系統(tǒng)MCP App 通常以沙箱 iframe的形式嵌入到宿主應(yīng)用如 Claude 等 AI 客戶端的對(duì)話流中。你的 App 不是獨(dú)立網(wǎng)站而是住在別人家里——所以配色不能自己說(shuō)了算宿主的品牌色、明暗偏好必須由 App 跟隨明暗模式要實(shí)時(shí)切換用戶在聊天窗口一鍵切深色你的 UI 毫秒級(jí)響應(yīng)字體字號(hào)要對(duì)齊宿主有自己的字體體系A(chǔ)pp 復(fù)用后視覺(jué)才統(tǒng)一。MCP Apps 協(xié)議的解法是宿主把主題令牌Theme Tokens打包成一個(gè) CSS 變量對(duì)象通過(guò) Host Context 傳給 AppApp 把這些變量寫(xiě)到根元素上CSS 里用var()引用即可。主題數(shù)據(jù)流從宿主到你的 App整個(gè)機(jī)制的核心類型定義在 src/spec.types.ts 中export type McpUiTheme light | dark;主題相關(guān)的三類數(shù)據(jù)都攜帶在McpUiHostContext宿主上下文里見(jiàn) src/spec.types.ts字段類型作用themelight \| dark宿主當(dāng)前的明暗偏好styles.variablesMcpUiStyles一組 CSS 變量顏色、字體、圓角、陰影styles.css.fontsstringfont-face/import字體 CSS數(shù)據(jù)流可以概括為一條鏈路宿主偏好變化時(shí)比如用戶切換深色模式SDK 會(huì)觸發(fā)hostcontextchanged事件你的 App 重新應(yīng)用一遍即可——無(wú)刷新、毫秒級(jí)??焖偕鲜? 個(gè)函數(shù)搞定明暗模式自適應(yīng)SDK 在 src/styles.ts 中提供了 3 個(gè)開(kāi)箱即用的函數(shù)覆蓋了 90% 的主題需求一鍵設(shè)置當(dāng)前明暗主題applyDocumentTheme(dark)會(huì)同時(shí)做兩件事src/styles.ts給html設(shè)置data-themedark屬性 → 你的 CSS 可以用[data-themedark]選擇器設(shè)置color-scheme屬性 →light-dark()函數(shù)和原生控件滾動(dòng)條、下拉框自動(dòng)適配。getDocumentTheme()則負(fù)責(zé)讀取當(dāng)前主題且兼容 Tailwind 的classdark約定src/styles.ts。一鍵注入宿主 CSS 變量applyHostStyleVariables(ctx.styles.variables)把宿主下發(fā)的每個(gè)變量逐個(gè)寫(xiě)到根元素上src/styles.ts。之后你的樣式表就能這樣寫(xiě)body { background-color: var(--color-background-primary); color: var(--color-text-primary); } .card { border: 1px solid var(--color-border-primary); border-radius: var(--border-radius-md); box-shadow: var(--shadow-sm); }一鍵加載宿主字體applyHostFonts(css)把宿主提供的字體 CSS 注入為style標(biāo)簽且保證只注入一次src/styles.ts。完整的連接后應(yīng)用 變化時(shí)重新應(yīng)用寫(xiě)法可直接參考官方模式文檔 docs/patterns.mdfunction applyHostContext(ctx: McpUiHostContext) { if (ctx.theme) applyDocumentTheme(ctx.theme); if (ctx.styles?.variables) applyHostStyleVariables(ctx.styles.styles?.variables ?? ctx.styles.variables); if (ctx.styles?.css?.fonts) applyHostFonts(ctx.styles.css.fonts); } app.onhostcontextchanged applyHostContext; app.connect().then(() { const ctx app.getHostContext(); if (ctx) applyHostContext(ctx); });CSS 變量完整清單顏色、字體、圓角、陰影協(xié)議為宿主可下發(fā)的變量定義了完整清單McpUiStyleVariableKeysrc/spec.types.ts所有變量均為可選——宿主可以只下發(fā)子集。分類速查如下顏色類共 5 組語(yǔ)義色分組變量前綴典型成員用途背景色--color-background-*primary / secondary / tertiary / inverse / ghost / info / danger / success / warning / disabled頁(yè)面、卡片、狀態(tài)提示背景文本色--color-text-*同上正文、輔助文字、狀態(tài)文字邊框色--color-border-*同上分割線、卡片描邊聚焦環(huán)--color-ring-*primary / inverse / info / danger…輸入框 focus 光圈狀態(tài)語(yǔ)義info / danger / success / warning各分組內(nèi)均含提示、報(bào)錯(cuò)、成功、警告字體與排版類變量示例值說(shuō)明--font-sans/--font-monosystem-ui, sans-serif正文字體 / 等寬字體族--font-weight-normal ~ bold400 / 500 / 600 / 700四級(jí)字重--font-text-{xs,sm,md,lg}-size0.75rem ~ 1.125rem正文四檔字號(hào)--font-heading-{xs ~ 3xl}-size0.75rem ~ 2.25rem標(biāo)題七檔字號(hào)--font-*-line-height1.1 ~ 1.5對(duì)應(yīng)字號(hào)的行高尺寸與效果類變量說(shuō)明--border-radius-{xs,sm,md,lg,xl,full}2px → 9999px 六級(jí)圓角--border-width-regular常規(guī)邊框?qū)挾?px--shadow-{hairline,sm,md,lg}從發(fā)絲線陰影到大投影官方示例中的完整取值可參考 examples/basic-host/src/host-styles.ts。明暗模式自適應(yīng)的三種寫(xiě)法由淺入深寫(xiě)法一data-theme屬性選擇器最直白的方式自己為每個(gè)顏色寫(xiě)兩套[data-themelight] { --bg-color: #ffffff; } [data-themedark] { --bg-color: #1a1a1a; } body { background: var(--bg-color); }適合變量少、需要精確控制每個(gè)色值的場(chǎng)景。寫(xiě)法二light-dark()函數(shù)推薦現(xiàn)代瀏覽器的 CSS 函數(shù)一份變量同時(shí)聲明亮色和暗色值瀏覽器根據(jù)color-scheme自動(dòng)選邊。SDK 的applyDocumentTheme正是為此服務(wù)——它同時(shí)設(shè)置了color-scheme讓light-dark()立即生效。官方宿主示例就是這樣定義全部配色的examples/basic-host/src/host-styles.ts--color-background-primary: light-dark(#ffffff, #1a1a1a); /* 亮色值, 暗色值 */ --color-text-primary: light-dark(#1f2937, #f3f4f6); --color-ring-danger: light-dark(#dc2626, #ef4444);這是 MCP Apps 推薦的聲明式方案宿主只需一份變量表就能同時(shí)覆蓋明暗兩套 UI。寫(xiě)法三JS 監(jiān)聽(tīng)主題變化做條件渲染當(dāng)某些邏輯而不只是 CSS依賴主題時(shí)用 React HookuseDocumentTheme()即可響應(yīng)式拿到light | dark它內(nèi)部用MutationObserver監(jiān)聽(tīng)根元素的data-theme屬性變化主題一變組件自動(dòng)重渲染src/react/useDocumentTheme.ts。function ThemedButton() { const theme useDocumentTheme(); return button style{{ background: theme dark ? #333 : #fff }}點(diǎn)擊我/button; }React 項(xiàng)目一個(gè) Hook 全自動(dòng)應(yīng)用主題如果你用 React 寫(xiě) MCP Appsrc/react/useHostStyles.ts 提供了三檔 HookHook職責(zé)useHostStyleVariables應(yīng)用styles.variablestheme含color-scheme保證light-dark()生效useHostFonts應(yīng)用styles.css.fonts字體 CSSuseHostStyles上面兩者的合體通常只需這一個(gè)function MyApp() { const { app } useApp({ appInfo: { name: MyApp, version: 1.0.0 }, capabilities: {}, }); // 一個(gè) Hook變量 主題 字體全部自動(dòng)應(yīng)用 useHostStyles(app, app?.getHostContext()); return ( div style{{ background: var(--color-background-primary) }} 跟隨宿主主題明暗秒切換 /div ); }兩個(gè)細(xì)節(jié)幫你避坑傳第二個(gè)參數(shù)app?.getHostContext()連接完成時(shí)的初始主題/變量會(huì)在掛載瞬間就應(yīng)用避免白屏閃爍一幀亮色再變暗Hook 同時(shí)監(jiān)聽(tīng)hostcontextchanged事件宿主后續(xù)切主題時(shí)自動(dòng)重新應(yīng)用卸載時(shí)自動(dòng)解綁。配套示例src/react/useHostStyles.examples.tsx、src/react/useDocumentTheme.examples.tsx。宿主視角如何為 App 提供主題如果你是寫(xiě)宿主應(yīng)用Host而非 App主題管理同樣有現(xiàn)成參考——官方 basic-host 示例的 examples/basic-host/src/theme.ts 實(shí)現(xiàn)了一個(gè)迷你主題管理器初始化用window.matchMedia((prefers-color-scheme: dark))讀取系統(tǒng)明暗偏好作為初始值應(yīng)用document.documentElement.setAttribute(data-theme, theme)colorScheme theme響應(yīng)系統(tǒng)切換監(jiān)聽(tīng)prefers-color-scheme的change事件自動(dòng)跟隨操作系統(tǒng)通知 App主題變化后經(jīng) Host Context 下發(fā)觸發(fā) App 側(cè)的hostcontextchanged。再搭配一份light-dark()變量表examples/basic-host/src/host-styles.ts宿主與 App 就完成了雙向適配。最佳實(shí)踐清單?優(yōu)先使用宿主下發(fā)的變量var(--color-*)而不是硬編碼色值宿主沒(méi)下發(fā)的變量再寫(xiě)默認(rèn)值兜底var(--font-sans, system-ui, sans-serif)?聲明式雙主題用light-dark()它比手寫(xiě)兩套[data-theme]選擇器更省一半代碼?記得設(shè)置color-schemeSDK 已幫你做否則原生滾動(dòng)條、表單控件在暗色下會(huì)是刺眼的白色?React 項(xiàng)目直接用useHostStyles(app, app?.getHostContext())別手動(dòng)管理addEventListener/removeEventListener??所有變量都是可選的Recordkey, string | undefined寫(xiě) CSS 時(shí)給var()提供 fallback?? 主題只可能是light | dark二值協(xié)議未定義第三態(tài)不要依賴跟隨系統(tǒng)這種中間值。總結(jié)MCP Apps 的主題系統(tǒng) McpUiTheme二值主題 語(yǔ)義化 CSS 變量表 light-dark()自適應(yīng)宿主通過(guò)McpUiHostContext下發(fā)theme與styles.variablesApp 用 src/styles.ts 三個(gè)函數(shù)React 用useHostStyles把它們落到根元素你的 CSS 全部引用var(--color-xxx)明暗切換自動(dòng)完成、零刷新。想繼續(xù)深入建議按順序閱讀協(xié)議規(guī)范 specification/2026-01-26/apps.mdx、模式手冊(cè) docs/patterns.md、可運(yùn)行示例 examples/basic-server-react/ 與 examples/basic-host/。【免費(fèi)下載鏈接】ext-appsOfficial repo for spec SDK of MCP Apps protocol - standard for UIs embedded AI chatbots, served by MCP servers項(xiàng)目地址: https://gitcode.com/GitHub_Trending/ex/ext-apps創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考