尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Nuclear 主题系统全解:从内置预设到 JSON 高级主题与主题商店

Nuclear 主题系统全解:从内置预设到 JSON 高级主题与主题商店 Nuclear 主题系统全解从内置预设到 JSON 高级主题与主题商店【免费下载链接】nuclearStreaming music player that finds free music for you项目地址: https://gitcode.com/GitHub_Trending/nu/nuclearNuclear 的主题系统基于 CSS 自定义属性CSS custom properties构建分为三种形态开箱即用的基础主题Basic themes、可自由定制的 JSON 高级主题Advanced themes以及可从官方注册表一键安装的社区主题商店Theme store。本文基于仓库中的官方文档与packages/themes主题引擎源码完整梳理三类主题的创建、应用与底层实现原理读完后可独立编写、调试并分发一套 Nuclear 自定义主题。三种主题形态总览Nuclear 的主题运行时设计原则是所有主题切换都通过替换 CSS 变量完成不在 TypeScript 中维护第二份主题数值来源。packages/themes/README.md 明确了这一点Tailwind v4 通过 packages/tailwind-config/global.css 消费 CSS 自定义属性暗色模式统一由[data-themedark]选择器控制。三种主题形态的定位如下主题类型载体定制能力入口Basic themes内置 CSS 文件只能选择预设不能自建Preferences → Themes 按钮区Advanced themes用户目录下的 JSON 文件颜色、字体、圆角、边框、阴影全定制Preferences → Themes 的 Advanced themes 下拉框Store themes官方主题注册表下发的 JSON 文件同高级主题额外携带元数据Preferences → Themes 的 Store 标签页三类主题互斥同一时间只有一个主题处于激活状态。选择商店主题会取消任何基础/高级主题选择商店主题或高级主题后选择 Default 可恢复默认样式。基础主题一键切换的内置预设基础主题是随 Nuclear 内置的预设。打开 Nuclear → Preferences → Themes会看到每个预设对应的按钮如 Aurora、Ember点击即切换播放器外观选择 Default 可清除所有自定义并恢复原始风格。基础主题调整的是应用的核心颜色、背景与文字对比度用户无法自行创建基础主题。从源码看内置主题在 packages/themes/src/basic/index.ts 中以命名空间前缀nuclear:标识共 5 个 IDnuclear:default、nuclear:aurora、nuclear:ember、nuclear:lagoon、nuclear:arctic-moss显示名为 Moss。命名空间的目的是避免与其他主题 ID 冲突。基础主题的实现非常轻每个主题就是一个 CSS 文件通过data-theme-id属性选择器覆盖少数几个变量。以 packages/themes/src/basic/aurora.css 为例:root[data-theme-idnuclear:aurora] { --background: oklch(0.98 0.01 340); --primary: oklch(0.74 0.15 305); --foreground-secondary: oklch(0.42 0.1 305); } :root[data-theme-idnuclear:aurora][data-themedark] { --background: oklch(0.22 0.03 305); --background-secondary: oklch(0.27 0.035 305); /* ... 暗色模式的其余覆盖 */ }切换动作本身只改一个 DOM 属性。packages/themes/src/index.ts 中的setThemeId直接把 ID 写到document.documentElement的data-theme-id属性上setBasicTheme(id)是它的便捷封装export function setThemeId(id: string): void { const root document.documentElement; root.setAttribute(data-theme-id, id); }listBasicThemes()则返回内置主题的元数据id、名称和 4 色调色板供界面渲染主题按钮使用。高级主题用 JSON 获得完全的控制权高级主题Advanced themes通过 JSON 文件提供完全的自由度颜色、强调色、字体、圆角、边框宽度、阴影均可定制且同时对亮色与暗色模式生效。编辑激活中的主题文件时改动会实时反映到应用界面live update。主题文件存放位置JSON 文件需放入各平台的应用数据目录下详见 packages/docs/themes/themes-advanced.mdLinux:~/.local/share/com.nuclearplayer/themesmacOS:~/Library/Application Support/com.nuclearplayer/themesWindows:%APPDATA%/com.nuclearplayer/themes放入后到 Preferences → Themes 的Advanced themes下拉框中即可看到并选中选择后立即生效。创建步骤新建任意名称的.json文件内容基于文末完整模板修改保存到上述 themes 目录在 Nuclear 的 Advanced themes 下拉框中选中它。JSON 基本结构{ version: 1, name: My Theme, vars: { /* light mode overrides */ }, dark: { /* dark mode overrides */ } }vars与dark均为可选只需包含要改的属性。注意亮色模式值放vars、暗色模式值放dark。可定制属性清单颜色Colorsbackground、background-secondary、background-inputforeground、foreground-secondary、foreground-inputprimaryborder、border-input、ringaccent-green、accent-yellow、accent-purple、accent-blue、accent-orange、accent-cyan、accent-red字体Typographyfont-family、font-family-heading、font-family-monofont-weight-normal、font-weight-bold、font-weight-extra-bold注意自定义字体必须已安装在用户系统上主题本身不携带字体文件。边框Bordersborder-width默认亮色2px暗色1px圆角Corner radiiradius-sm、radius-md、radius-lg阴影Shadowsshadow-color、shadow-x、shadow-y、shadow-blur编写规则version必须恒为1schema 中是字面量校验变量名不需要--前缀颜色可用十六进制#ff0000、OKLCHoklch(70% 0.15 30)或任意合法 CSS 颜色值恢复默认从下拉框选择 Default。完整模板含 Nuclear 默认值{ version: 1, name: My Custom Theme, vars: { background: oklch(0.9491 0.023 341.75), background-secondary: oklch(100% 0 0), background-input: oklch(100% 0 0), foreground: oklch(0% 0 0), foreground-secondary: oklch(0.42 0.1 342), foreground-input: oklch(0% 0 0), primary: oklch(76.91% 0.173 341.75), border: oklch(0% 0 0), ring: oklch(100% 0 0), accent-green: oklch(79.05% 0.209 147.58), accent-yellow: oklch(95.53% 0.134 112.76), accent-purple: oklch(74.2% 0.149 301.88), accent-blue: oklch(55.98% 0.08 270.09), accent-orange: oklch(83.39% 0.124 66.56), accent-cyan: oklch(88.26% 0.093 212.85), accent-red: oklch(68.22% 0.206 24.43), border-width: 2px, shadow-color: oklch(0% 0 0), shadow-x: 2px, shadow-y: 2px, shadow-blur: 0px, font-family: DM Sans, system-ui, -apple-system, sans-serif, font-family-heading: Bricolage Grotesque, var(--default-font-family), font-family-mono: Space Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace, font-weight-normal: 400, font-weight-bold: 700, font-weight-extra-bold: 800, radius-sm: 4px, radius-md: 8px, radius-lg: 12px }, dark: { background: oklch(0.22 0.03 342), background-secondary: oklch(0.27 0.035 342), background-input: oklch(0.15 0.02 342), foreground: oklch(0.90 0.008 342), foreground-secondary: oklch(0.78 0.1 342), foreground-input: oklch(0.93 0 0), primary: oklch(0.65 0.13 342), border: oklch(0.48 0.04 342), border-width: 1px, shadow-x: 0px, shadow-y: 0px } }高级主题源码实现从 JSON 到注入的 CSS高级主题的运行时链路在nuclearplayer/themes包中实现可以分三段理解schema 校验、CSS 生成、DOM 注入。1. Zod schema 校验packages/themes/src/advanced/schema.ts 定义了AdvancedThemeSchemaversion必须是字面量1name非空字符串vars与dark是「字符串键 → 字符串值」的记录且有一条 refine 规则强制键不能以--开头错误信息Keys must be CSS var names without leading --。schema 还预留了author、description、tags、palette四个可选字段——这正是商店主题的扩展点。export const ThemeVars z .record(z.string(), z.string()) .refine((obj) Object.keys(obj).every((k) !!k !k.startsWith(--)), { message: Keys must be CSS var names without leading --, }); export const AdvancedThemeSchema z.object({ version: ThemeVersion, name: z.string().min(1), author: z.string().min(1).optional(), description: z.string().optional(), tags: z.array(z.string()).optional(), palette: z.tuple([z.string(), z.string(), z.string(), z.string()]).optional(), vars: ThemeVars.optional(), dark: ThemeVars.optional(), });2. CSS 生成packages/themes/src/advanced/generator.ts 把校验后的主题对象转成 CSS 声明串。vars挂在:root下dark挂在[data-themedark]下——这与 packages/tailwind-config/global.css 中声明的暗色变体custom-variant dark (:where([data-themedark], [data-themedark] *))完全对应因此暗色覆盖只在暗色模式生效export function generateAdvancedThemeCSS(theme: AdvancedTheme): string { const light toDecls(theme.vars); // --background: oklch(...); ... const dark toDecls(theme.dark); const parts: string[] []; if (light) parts.push(:root{${light}}); if (dark) parts.push([data-themedark]{${dark}}); return parts.join(\n); }生成的 CSS 会覆盖global.css中:root定义的默认变量。global.css里的theme块进一步把这些变量桥接进 Tailwind 工具类如--color-primary: var(--primary)、--radius-md: var(--radius-md)所以改一个变量即可联动所有使用对应 Tailwind 类的组件。3. 注入与清除packages/themes/src/index.ts 的applyAdvancedTheme用固定 ID 的style idadvanced-theme标签承载生成的 CSS不存在则创建并追加到head已存在则直接替换textContent。这意味着反复应用同一主题不会产生重复样式标签也为文件监听实现 live reload 提供了天然通道。clearAdvancedTheme()则移除该标签完成回退。包级快照测试见 packages/themes/README.md 与 packages/themes/src/advanced/tests/ 下的generator.test.ts、schema.test.ts断言生成的 CSS 是稳定的保证这套字符串拼接逻辑在版本间不会漂移。主题商店社区主题的一键安装与分发Nuclear 内置主题商店Theme store在 Preferences → Themes 的Store标签页中浏览并安装社区主题详见 packages/docs/themes/theme-store.md。每个条目展示调色板预览对角色块、名称、描述、作者和标签搜索框可按名称、描述、作者、标签过滤。安装与应用点击 Install 后Nuclear 从官方主题注册表下载主题文件并保存到本地按钮显示下载进度完成后变为 Installed已安装的主题出现在 My Themes 标签页的Store themes下拉框中应用商店主题有两条路径在 My Themes 的 Store themes 下拉框中选择或直接在 Store 标签页点击 Apply当前激活的商店主题在 Store 标签页中带勾选标记应用商店主题会同时取消激活任何基础/高级主题。卸载点击已安装主题上的垃圾桶图标即可卸载。若该主题当时处于激活状态Nuclear 会重置回默认主题。存放位置商店主题存放在应用数据目录的themes/store/子目录中与用户自建主题所在的themes/目录分离Linux:~/.local/share/com.nuclearplayer/themes/store/macOS:~/Library/Application Support/com.nuclearplayer/themes/store/Windows:%APPDATA%/com.nuclearplayer/themes/store/为商店制作主题从源码看商店主题就是携带额外元数据的普通高级主题 JSON。MarketplaceThemeSchemapackages/themes/src/advanced/schema.ts在高级主题 schema 基础上强制要求author、description、palette4 色元组用于列表中的对角色块预览必填并额外要求注册表条目携带id与pathexport const MarketplaceThemeSchema AdvancedThemeSchema.pick({ name: true, author: true, description: true, tags: true, palette: true, }) .required({ author: true, description: true, palette: true }) .extend({ id: z.string().min(1), path: z.string().min(1), }); export const MarketplaceThemeRegistrySchema z.object({ version: z.number(), themes: z.array(MarketplaceThemeSchema), });因此把高级主题 JSON 加上author、description、tags、palette四个字段即具备提交商店的格式基础具体提交流程与注册表结构以官方主题注册表仓库的说明为准文档中指向NuclearPlayer/theme-registry。小结Nuclear 的主题体系可以概括为一条主线主题即 CSS 变量覆盖。基础主题用data-theme-id选择器覆盖少数核心变量是内置的一等公民高级主题用 JSON 描述任意变量覆盖经 Zod 校验后生成:root与[data-themedark]两段 CSS 注入页面配合文件监听实现即时预览商店主题在高级主题之上增加强制元数据通过注册表分发并隔离存放在themes/store/。掌握vars/dark的键名约定去掉--前缀、version恒为 1、颜色支持任意 CSS 值与完整模板即可从零写出可运行、可提交社区主题商店的 Nuclear 主题。【免费下载链接】nuclearStreaming music player that finds free music for you项目地址: https://gitcode.com/GitHub_Trending/nu/nuclear创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表