diff --git a/README.md b/README.md index 4fe7156..f89bdca 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,15 @@ - 页面与布局:`src/pages/`、`src/layouts/` - 通用组件:`src/components/`(如 `Img.astro` 支持外部图床) - 内容扩展抽象:`src/lib/content/`(为未来 Typst 等格式预留) - - 标签规范:根目录 `tags.config.yaml`(建议统一文章标签使用) +- 标签规范:根目录 `tags.config.yaml`(建议统一文章标签使用) + - 全局样式:`src/styles/theme.css`, `src/styles/prose.css`(支持浅/深色与容器宽度等变量) ## 配置与类型 - `PUBLIC_MEDIA_BASE_URL`:外部图床前缀(避免图片入库) - `PUBLIC_SITE_URL`:站点地址(可选,用于 canonical 等) - 修改内容集合(src/content/config.ts)后,需在本机运行 `pnpm astro sync`(Node >= 18.20.8,建议 >= 20),以生成 `.astro/types.d.ts`,否则类型可能退化为 any。 + - 主题:`PUBLIC_THEME`(可选:`light`/`dark`/`system`,默认 `system`) ## 约定 diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index cc9c3fa..87ac014 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -4,25 +4,50 @@ interface Props { } const { title } = Astro.props; const site = import.meta.env.PUBLIC_SITE_URL ?? ''; +const theme = import.meta.env.PUBLIC_THEME ?? 'system'; // 'light' | 'dark' | 'system' --- - + {title ? `${title} | 学习博客` : '学习博客'} + + -
+ -
+
+ + - diff --git a/src/styles/prose.css b/src/styles/prose.css new file mode 100644 index 0000000..8118bdb --- /dev/null +++ b/src/styles/prose.css @@ -0,0 +1,71 @@ +.container { + max-width: var(--container-max); + margin: 0 auto; + padding: var(--space-6) var(--space-4); +} + +body { + background: var(--color-bg); + color: var(--color-text); + font-family: var(--font-sans); + line-height: var(--line-height); + font-size: var(--text-base); +} + +a { color: var(--color-primary); } + +header.site-header { + display: flex; + gap: var(--space-4); + align-items: center; + padding: var(--space-3) var(--space-4); + border-bottom: 1px solid var(--color-border); +} + +select.theme-select { + appearance: none; + background: var(--color-bg); + color: var(--color-text); + border: 1px solid var(--color-border); + border-radius: 6px; + padding: 6px 28px 6px 10px; + position: relative; +} +select.theme-select:focus { outline: 2px solid color-mix(in oklab, var(--color-primary) 30%, transparent) } +.select-wrap { position: relative; } +.select-wrap::after { + content: '▾'; + position: absolute; + right: 10px; + top: 50%; + transform: translateY(-50%); + color: var(--color-muted); + pointer-events: none; +} + +.prose { + line-height: var(--line-height); +} +.prose h1, .prose h2, .prose h3 { + margin: var(--space-6) 0 var(--space-3); +} +.prose p { margin: var(--space-3) 0; } +.prose ul, .prose ol { padding-left: var(--space-6); } +.prose code { + font-family: var(--font-mono); + background: color-mix(in oklab, var(--color-border) 60%, transparent); + padding: 0 0.25em; + border-radius: 4px; +} +.prose pre { + padding: var(--space-3); + border: 1px solid var(--color-border); + border-radius: var(--radius); + overflow: auto; +} +.prose blockquote { + margin: var(--space-4) 0; + padding-left: var(--space-4); + border-left: 3px solid var(--color-border); + color: var(--color-muted); +} diff --git a/src/styles/theme.css b/src/styles/theme.css new file mode 100644 index 0000000..9e47658 --- /dev/null +++ b/src/styles/theme.css @@ -0,0 +1,52 @@ +:root { + /* Colors */ + --color-bg: #ffffff; + --color-text: #1f2937; + --color-muted: #6b7280; + --color-primary: #2563eb; + --color-border: #e5e7eb; + + /* Layout */ + --container-max: 860px; + --radius: 8px; + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-6: 24px; + --space-8: 32px; + + /* Typography */ + --font-sans: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, Arial, "Apple Color Emoji", "Segoe UI Emoji"; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + --text-base: 16px; + --line-height: 1.65; +} + +/* Follow system when no override is set */ +@media (prefers-color-scheme: dark) { + :root { + --color-bg: #0b1020; + --color-text: #e5e7eb; + --color-muted: #9ca3af; + --color-primary: #60a5fa; + --color-border: #1f2937; + } +} + +/* Explicit overrides take precedence */ +[data-theme="dark"] { + --color-bg: #0b1020; + --color-text: #e5e7eb; + --color-muted: #9ca3af; + --color-primary: #60a5fa; + --color-border: #1f2937; +} + +[data-theme="light"] { + --color-bg: #ffffff; + --color-text: #1f2937; + --color-muted: #6b7280; + --color-primary: #2563eb; + --color-border: #e5e7eb; +}