跳到正文
svedocs

主题

自定义 Tailwind CSS v4 默认主题、颜色变量、明暗模式、导航和首页布局。

默认主题内置在 svedocs 包里。它使用 Tailwind CSS v4 和框架 CSS 变量,不需要安装额外主题包。

样式

在 SvelteKit 根布局里导入主题样式:

Sveltesrc/routes/+layout.svelte
<script> import 'svedocs/theme/styles.css';</script><slot />

这份样式定义了 --sd-* 变量,并通过 data-theme 切换明暗模式。

表单控件

主题也导出了一组基础表单组件,适合自定义布局、嵌入式工具和交互式文档页使用。它们保留 Svelte 的原生使用习惯,例如 bind:value、DOM 事件转发和标准表单属性。

Svelte
<script lang="ts"> import { Button, Checkbox, FormField, Input, Select, Textarea } from 'svedocs/theme'; let email = ''; let role = 'reader'; let note = ''; let updates = true;</script><FormField label="邮箱" for="email" description="仅用于工作区通知。"> <Input id="email" type="email" bind:value={email} placeholder="you@example.com" /></FormField><FormField label="角色" for="role"> <Select id="role" bind:value={role}> <option value="reader">读者</option> <option value="editor">编辑者</option> </Select></FormField><FormField label="备注" for="note"> <Textarea id="note" bind:value={note} rows="4" /></FormField><Checkbox bind:checked={updates} label="接收版本更新" /><Button variant="primary" type="submit">保存偏好</Button>

可用控件包括 FormFieldInputTextareaSelectCheckboxButtonInputTextareaSelectCheckboxButton 支持 density="sm" | "md" | "lg"Button 支持 variant="default" | "primary" | "ghost" | "danger"

调色板

只想快速换品牌主题色时,只配置 theme.palette.accent 即可:

TypeScriptsvedocs.config.ts
import { defineConfig } from 'svedocs/config';export default defineConfig({ theme: { palette: { accent: 'sky' } }});
TypeScriptsvedocs.config.ts
import { defineConfig } from 'svedocs/config';export default defineConfig({ theme: { defaultMode: 'system', palette: { accent: 'emerald', neutral: 'zinc' }, fonts: { sans: '"IBM Plex Sans", "Avenir Next", sans-serif', mono: '"JetBrains Mono", "SFMono-Regular", monospace', display: '"IBM Plex Sans", "Avenir Next", sans-serif' }, radius: '2px', codeTheme: { light: 'light-plus', dark: 'dark-plus' }, code: { copyButton: true }, brand: { label: 'svedocs', href: '/', mark: 'pixel' }, nav: [ { label: '文档', href: '/docs/zh' }, { label: '配置', href: '/docs/zh/configuration' }, { label: '参考', href: '/docs/zh/reference/api' } ], social: [ { label: 'GitHub', href: 'https://github.com/svedocs/svedocs', external: true } ], footer: { text: 'MIT licensed.', links: [{ label: 'Cloudflare', href: '/docs/zh/integrations/cloudflare' }] }, home: { kicker: '边缘优先的 Svelte 文档站', primaryAction: { label: '阅读文档', href: '/docs/zh' }, secondaryAction: { label: '去配置', href: '/docs/zh/configuration' }, visual: { type: 'pixel' } } }});

palette.accent 可以使用 emeraldtealskyindigoroseamber 等内置颜色名,也可以直接填写 #0ea5e9hsl(221 83% 53%)oklch(62% 0.18 250) 等任意 CSS 颜色值。

home.visual 可以继续使用内置的像素效果,也可以指向项目中的图片:{ type: 'image', src: '/hero.png', alt: 'Preview' }

主题插槽

DocsApp 提供命名插槽,可以只替换页面中的某个区域,不必重新实现路由、元数据、页头、页脚、搜索、Ask AI 和文档导航。

Sveltesrc/routes/+page.svelte
<script lang="ts"> import { DocsApp } from 'svedocs/theme'; import components from 'virtual:svedocs/components'; import layouts from 'virtual:svedocs/layouts'; import loadSearch from 'virtual:svedocs/search-loader'; export let data;</script><DocsApp page={data.page} pages={data.pages} tree={data.tree} search={data.search} config={data.config} {components} {layouts} {loadSearch}> <div slot="background" class="brand-background"></div></DocsApp>

background 插槽会替换首页、普通单页和文档文章中的内置格子背景。它会作为 aria-hidden 的装饰层渲染,并禁用指针事件。

首页还提供更细粒度的插槽:

Sveltesrc/routes/+page.svelte
<script lang="ts"> import { resolveLocalizedHref } from 'svedocs/theme/headless';</script><DocsApp page={data.page} pages={data.pages} tree={data.tree} search={data.search} config={data.config} {components} {layouts} {loadSearch}> <div slot="home-hero-visual" class="product-orbit" aria-hidden="true"></div> <section slot="home-features" let:cards let:context class="feature-strip"> <h2>{context.t('home.features')}</h2> {#each cards as card} <a href={card.href}>{card.title}</a> {/each} </section></DocsApp>

home-hero-visual 替换首页主视觉中的像素效果或配置图片,用 home-features 替换默认的功能介绍区。home-features 会收到生成后的 cards 数组,方便自定义内容复用同一组文档链接;它也会收到 context,可以调用 context.t(...)、读取 context.localeCode 或使用 context.messages

如果要替换首页的全部内容,但保留 svedocs 的页头和页脚,可以使用 landing

Sveltesrc/routes/+page.svelte
<DocsApp page={data.page} pages={data.pages} tree={data.tree} search={data.search} config={data.config} {components} {layouts} {loadSearch}> <section slot="landing" let:page let:context class="custom-landing"> <h1>{page.title}</h1> <p>{page.description}</p> <a href={resolveLocalizedHref('/docs', context)}> {context.t('home.primaryAction')} </a> </section></DocsApp>

landing 插槽外层仍由主题提供 main#content,因此跳转到正文的无障碍链接和页面语义不会丢失。

在自定义首页和替换组件中,使用 context.t('message.key') 读取界面文案,不要把文字写死。可以在 i18n.messages 中添加内建或项目自定义的键,自定义组件会收到当前语言的文案。过滤数据时使用 context.localeCode,设置 HTML 属性或按语言格式化数据时使用 context.languageTag。完整配置见多语言

文档文章也提供 doc-header,适合只替换标题和面包屑区域:

Svelte
<DocsApp page={data.page} pages={data.pages} tree={data.tree} search={data.search} config={data.config} {components} {layouts} {loadSearch}> <header slot="doc-header" let:page let:breadcrumbs class="article-hero"> <nav> {#each breadcrumbs as item} <a href={item.path}>{item.label}</a> {/each} </nav> <h1>{page.title}</h1> </header></DocsApp>

主题开发

根据改动范围选择合适的定制方式:

层级适合场景
主题变量保留默认组件,只调整品牌色、字体、圆角、导航、首页或代码块设置。
组件替换你想保留 svedocs 路由壳层,但替换一个或多个视觉组件。
无样式组合完全接管 HTML 结构和 CSS,同时复用搜索、Ask AI、目录高亮、明暗模式、移动导航和复制行为。

默认 CSS 是可选的:

导入方式结果
svedocs/theme/styles.css完整内置视觉主题。
svedocs/theme/base.css最小样式重置、无障碍基础样式,以及正文和代码结构。
不导入主题 CSS应用或主题包完全接管所有样式。

普通配置继续放在 svedocs.config.ts。Svelte 组件路径则放在 Vite 插件中,因为它们需要在构建时导入,不应被序列化进内容配置。

在 Vite 插件里注册替换组件:

TypeScriptvite.config.ts
svedocs({ theme: { components: { Navbar: '$lib/theme/Navbar.svelte', Article: '$lib/theme/Article.svelte', Search: '$lib/theme/Search.svelte', AskAi: '$lib/theme/AskAi.svelte' } }});

生成的路由会导入 virtual:svedocs/theme-components 并传给 DocsApp,所以不用逐个页面手动接线:

Sveltesrc/routes/+page.svelte
<script lang="ts"> import { DocsApp } from 'svedocs/theme'; import components from 'virtual:svedocs/components'; import layouts from 'virtual:svedocs/layouts'; import themeComponents from 'virtual:svedocs/theme-components'; import loadSearch from 'virtual:svedocs/search-loader'; export let data;</script><DocsApp page={data.page} pages={data.pages} tree={data.tree} search={data.search} config={data.config} {components} {layouts} {themeComponents} {loadSearch}/>

替换组件可以从 svedocs/theme/types 获取属性类型。可替换组件包括 RootLayoutDocsDocsShellPagePageShellHomeErrorHeaderNavbarBrandTopNavMobileNavSocialNavSidebarArticleTocSearchAskAiFooterFooterLinksThemeTogglePageToolsRenderError。各组件的完整属性见组件

Sveltesrc/lib/theme/Navbar.svelte
<script lang="ts"> import type { SvedocsNavbarProps } from 'svedocs/theme/types'; export let context: SvedocsNavbarProps['context'];</script><header class="brand-nav"> <a href={context.config.theme.brand.href}>{context.config.theme.brand.label}</a></header>

如果只想复用交互逻辑、不使用默认界面,可以从 svedocs/theme/headless 引入控制器。其中包含主题上下文、搜索、Ask AI、目录高亮、明暗模式、移动导航、页面工具和代码复制等逻辑。

Sveltesrc/lib/theme/Search.svelte
<script lang="ts"> import { createSearchController } from 'svedocs/theme/headless'; import type { SvedocsSearchProps } from 'svedocs/theme/types'; export let records: SvedocsSearchProps['records'] = []; const search = createSearchController({ records });</script><button type="button" on:click={search.show}>搜索</button>

编写替换组件时:

  • 保留 headernavmainarticleasidefooter 等标准语义区域。
  • .svx / .mdx 页面渲染 content,没有内容组件时回退到 page.html
  • 仍然组合部分默认组件时,把 themeComponents 继续传给嵌套组件。
  • 如果替换 RootDocsPageHomeError,继续把 pagestreesearchconfigloadSearch 传入主题上下文或嵌套的默认组件,这样侧栏高亮、移动导航、搜索和 Ask AI 才能保持联动。
  • 只调整布局几何结构时,优先替换 LayoutDocsShellPageShell,再考虑替换更大的 RootDocsPageError
  • 大型站点优先使用 loadSearch,避免把所有搜索记录都放进首屏路由数据。
  • 自定义命令按钮可以用 svedocs:open-searchsvedocs:open-ai 事件打开默认搜索和 Ask AI 面板。

Markdown 输出会保留稳定的 sd-* 结构类名,默认主题和自定义主题都可以针对同一套正文、标题和代码结构编写样式。如果主题自己渲染复制按钮,可以设置 theme.code.copyButton: false

生成模板已经包含 src/routes/+error.svelte。注册 theme.components.Error 可以替换完整路由的错误页;注册 theme.components.RenderError 可以替换文章内容、布局区域、导航和工具中的局部错误提示。生成的错误路由会捕获自定义 Error 组件自身的异常,并改用内置 ErrorPage

主题包可以是普通的 Svelte 库。从包中导出组件,声明兼容的 svedocs peer dependency 版本,再让使用者在 svedocs({ theme: { components } }) 中注册对应的组件路径即可。

交互能力

默认主题包括:

  • 带键盘焦点管理的搜索弹窗。
  • 支持 JSON 和事件流响应的 Ask AI 面板。
  • 文档、搜索、Ask AI 入口工具栏。
  • 可折叠的递归侧栏,以及按语言过滤的导航树。
  • 移动端菜单状态和过渡。
  • 根据当前位置高亮目录标题。
  • 带复制按钮的代码块工具条。
  • 兼容 prefers-reduced-motion 的过渡。

单页

content/pages 下的内容默认用内置单页模板渲染。首页使用 layout: home,普通单页使用 layout: page,也可以使用注册过的自定义布局名。

Markdown
---title: 更新日志description: 使用单页模板展示产品更新。---# 更新日志

自定义布局

在 Vite 插件里注册命名布局:

TypeScriptvite.config.ts
svedocs({ layouts: { feature: '$lib/FeatureLayout.svelte' }});

然后在 frontmatter 里选择它:

Markdown
---title: Feature Pagelayout: feature---

布局组件会收到与默认页面相同的数据,因此自定义单页仍然可以使用页面列表、搜索记录、SEO 元数据和站点外壳。