
airi 项目实战用 VueUse usePreferredContrast 响应式追踪 prefers-contrast构建自适应对比度的 UI【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airiusePreferredContrast是 VueUse 提供的响应式封装用于在 Vue 3 组件中实时订阅 CSSprefers-contrast媒体查询返回more | less | custom | no-preference四态对比度偏好。在 airi 这类同时拥有 Web、Electron 桌面端与 Capacitor 移动端见 apps/stage-web、apps/stage-tamagotchi、apps/stage-pocket的多端 UI 项目中它可以帮助开发者自动感知用户系统级的无障碍设置动态调整文字、边框、图标的对比度从而让界面在弱视、强光等环境下依然清晰可读。读完本文你将掌握该 composable 的完整 API、组件式用法、返回值语义以及它在 VueUse 媒体查询体系中的实现原理与配套组合。一、功能定位把系统级对比度偏好变成响应式状态prefers-contrast是 CSS Media Queries Level 5 引入的用户偏好媒体特性浏览器会根据操作系统的辅助功能设置如 Windows 的增加对比度、macOS 的增强对比度报告用户对高/低对比度的倾向。usePreferredContrast的核心职责就是把这个静态查询变为 Vue 的响应式状态用户修改系统对比度设置时返回值自动更新无需手动监听change事件返回值是ComputedRef可直接在模板、computed 或 watcher 中使用无副作用、SSR 友好适合在 airi 的 Nuxt/Vite 渲染链路 中安全引入。在 .agents/skills/vueuse-functions/SKILL.md 的函数清单中它被归类在Browser类别下与usePreferredColorScheme、usePreferredDark、usePreferredReducedMotion、usePreferredReducedTransparency同属系统偏好响应家族且标注为AUTO调用级别——即在 Vue/Nuxt 开发中遇到需要感知系统无障碍偏好的场景应优先考虑使用它而不是手写媒体查询监听。二、Composable 用法一行代码接入对比度状态按照参考文档 usePreferredContrast.md 的标准用法在任意script setup中import { usePreferredContrast } from vueuse/core const preferredContrast usePreferredContrast()preferredContrast是一个ComputedRefContrastType其取值语义如下返回值含义对应的系统/浏览器状态more用户要求增强对比度系统开启增加对比度/高对比度less用户要求降低对比度系统偏好低对比度显示custom用户自定义了对比度曲线系统启用了自定义对比度调整no-preference用户未做任何对比度设置默认状态大多数用户据此可以驱动动态样式例如高对比度用户获得更粗的边框与更强的文本颜色script setup langts import { computed } from vue import { usePreferredContrast } from vueuse/core const contrast usePreferredContrast() const textClass computed(() { if (contrast.value more) return font-bold text-black dark:text-white if (contrast.value less) return text-gray-600 dark:text-gray-400 return text-gray-900 dark:text-gray-100 }) /script template p :classtextClass当前对比度偏好{{ contrast }}/p /template当用户在系统中切换对比度设置时contrast.value会自动更新并触发视图重渲染无需任何手动订阅与清理逻辑。三、组件式用法模板内直接消费对于不希望引入额外 setup 逻辑的纯展示场景VueUse 还提供了同名渲染插槽组件UsePreferredContrasttemplate UsePreferredContrast v-slot{ contrast } Preferred Contrast: {{ contrast }} /UsePreferredContrast /template组件通过v-slot将对比度值暴露给插槽内容适合在模板中做局部条件渲染例如根据contrast more决定是否显示高对比度徽标或切换强调色。需要全局注册该组件时可参考 airi 各前端应用对 VueUse 的引入方式——例如 apps/stage-web/package.json 与 apps/stage-pocket/package.json 均以vueuse/core: catalog:的方式声明依赖通过 pnpm workspace 的 catalog 统一版本管理。四、类型声明与参数解析参考文档给出了完整的类型签名export type ContrastType more | less | custom | no-preference export declare function usePreferredContrast( options?: ConfigurableWindow, ): ComputedRefContrastType值得注意的要点唯一可选参数是ConfigurableWindow即可以传入{ window?: Window }覆盖默认的全局window对象。这在 airi 的 Electron 渲染进程或 packages/electron-vueuse 这类多窗口场景中非常实用——当组件需要在特定窗口而非默认主窗口中读取偏好时可以显式传入该窗口的引用在 SSR 阶段没有window时VueUse 会自动降级处理避免引用报错。返回值是不可变计算属性ComputedRefContrastType只能读取不能手动赋值状态完全由浏览器媒体查询驱动符合单一数据源原则。无副作用标注类型声明带有__NO_SIDE_EFFECTS__标记便于打包器做 tree-shaking仅在真正使用该函数时才会引入相关代码。五、底层原理它与 useMediaQuery 的关系从 VueUse 的实现结构看usePreferredContrast是对通用媒体查询 composableuseMediaQuery的特化封装其核心实现等价于const contrast useMediaQuery((prefers-contrast: more)) ? more : /* 依次探测 less / custom / no-preference */而useMediaQuery的完整签名见 useMediaQuery.md为export declare function useMediaQuery( query: MaybeRefOrGetterstring, options?: ConfigurableWindow { ssrWidth?: number }, ): ComputedRefboolean这意味着在 airi 的项目中你完全可以用useMediaQuery自行组合更细粒度的查询例如只关心是否高对比度这一个布尔状态import { useMediaQuery } from vueuse/core // 与 usePreferredContrast() 返回 more 时等价 const isHighContrast useMediaQuery((prefers-contrast: more))airi 的 packages/stage-ui 中已有useMediaQuery的实际使用先例例如 Live2DReportModal.vue 与 tachieReportModal.vue 中通过useMediaQuery((min-width: 768px))判断桌面端布局。同一套底层机制同样支撑着usePreferredContrast因此两者在响应式行为、SSR 处理策略上是完全一致的。SSR 与多端注意点useMediaQuery在 SSR如 Nuxt环境下需要显式声明ssrWidth以避免水合不一致例如const isLarge useMediaQuery((min-width: 1024px), { ssrWidth: 768 // 服务端按 768px 视口渲染 })对usePreferredContrast而言SSR 阶段浏览器环境尚未就绪推荐的做法是将其作为客户端渐进增强手段服务端渲染时使用默认的no-preference视觉样式待客户端挂载、系统偏好读取成功后再渐进式切换对比度样式避免水合闪烁。在 airi 的 Electronapps/stage-tamagotchi与 Capacitorapps/stage-pocket环境中window始终可用可直接在组件顶层调用。六、实战组合与其他偏好类 composable 协同usePreferredContrast通常不是单独使用的——无障碍适配需要同时响应多个系统偏好。VueUse 为 airi 这类多端 UI 项目提供了完整矩阵均位于 .agents/skills/vueuse-functions/references 目录composable订阅的媒体特性典型用途usePreferredContrastprefers-contrast增强/减弱文字与边框对比度usePreferredColorSchemeprefers-color-scheme亮色/暗色主题切换usePreferredDarkprefers-color-scheme: dark布尔化暗色偏好usePreferredReducedMotionprefers-reduced-motion关闭/减弱动画与过渡usePreferredReducedTransparencyprefers-reduced-transparency减少毛玻璃等透明效果一个面向无障碍的完整适配示例import { usePreferredContrast } from vueuse/core import { usePreferredReducedMotion } from vueuse/core const contrast usePreferredContrast() const reducedMotion usePreferredReducedMotion() // 高对比度 减少动画用户的最终可访问性配置 const accessibilityClass computed(() { const classes: string[] [] if (contrast.value more) classes.push(contrast-more) if (reducedMotion.value) classes.push(motion-safe-off) return classes.join( ) })在 airi 的对话舞台界面中可以据此为更多对比度用户自动加深聊天气泡与文字的区分度同时为减少动画用户关闭 Live2D 模型的呼吸摆动等非必要动效从而在不增加配置项的情况下同时覆盖两类无障碍诉求。七、小结usePreferredContrast以极低的接入成本把系统级的对比度偏好引入 Vue 响应式体系Composable 形式适合逻辑层使用插槽组件形式适合模板层使用返回值四态语义清晰可直接驱动样式计算。结合其底层useMediaQuery的通用能力airi 的 packages/stage-ui 已有实际调用先例以及同族的偏好类 composable它构成了 airi 多端 UI 无障碍适配中对比度维度的标准答案。在开发新界面时遇到需要感知用户无障碍设置的场景应优先选择它而不是手写matchMedia监听。如需继续深入可查阅仓库中的相关参考文档usePreferredContrast.md、useMediaQuery.md、usePreferredReducedMotion.md以及 SKILL.md 中完整的函数选择指南。【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考