feat(www): add light mode to docs (#58426)

This commit is contained in:
Filip
2026-10-23 13:19:47 +02:00
committed by GitHub
Unverified
parent 2a3e7c0f34
commit 4232b8bcd6
3 changed files with 112 additions and 19 deletions
@@ -13,7 +13,8 @@ const searchEnabled = import.meta.env.PROD
<header class="site-header">
<div class="header-inner">
<a class="brand" href={import.meta.env.BASE_URL} aria-label="OpenCode home">
<img src={`${import.meta.env.BASE_URL}assets/logo-dark.svg`} alt="OpenCode" />
<img class="logo-dark" src={`${import.meta.env.BASE_URL}assets/logo-dark.svg`} alt="OpenCode" />
<img class="logo-light" src={`${import.meta.env.BASE_URL}assets/logo-light.svg`} alt="OpenCode" />
</a>
<nav aria-label="Documentation sections">
{
@@ -33,6 +34,15 @@ const searchEnabled = import.meta.env.PROD
</button>
)
}
<button class="theme-toggle" type="button" data-theme-toggle aria-label="Toggle color theme">
<svg class="theme-icon-light" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true">
<circle cx="12" cy="12" r="4" />
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41" />
</svg>
<svg class="theme-icon-dark" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79Z" />
</svg>
</button>
<a class="github-link" href="https://github.com/anomalyco/opencode" aria-label="OpenCode on GitHub">GitHub</a>
</div>
</header>
@@ -29,6 +29,23 @@ const canonical = new URL(docsHref(Astro.props.currentSlug), "https://opencode.a
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content={description} />
<meta name="theme-color" content="#000000" />
<script is:inline>
const applyTheme = () => {
const theme =
localStorage.getItem("docs-theme") ?? (matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark")
document.documentElement.dataset.theme = theme
document.querySelector('meta[name="theme-color"]')?.setAttribute("content", theme === "light" ? "#ffffff" : "#000000")
}
applyTheme()
document.addEventListener("astro:after-swap", applyTheme)
matchMedia("(prefers-color-scheme: light)").addEventListener("change", applyTheme)
document.addEventListener("click", (event) => {
if (!(event.target instanceof Element) || !event.target.closest("[data-theme-toggle]")) return
localStorage.setItem("docs-theme", document.documentElement.dataset.theme === "light" ? "dark" : "light")
applyTheme()
})
</script>
<ClientRouter fallback="swap" />
<link rel="canonical" href={canonical} />
<link rel="icon" type="image/svg+xml" href={`${import.meta.env.BASE_URL}favicon.svg`} />
+84 -18
View File
@@ -39,12 +39,41 @@
--surface: #101010;
--surface-hover: #181818;
--link: #4d8eff;
--blue: #73a7ff;
--green: #70c997;
--yellow: #e0af68;
--red: #e67c7c;
--tip-border: #28503a;
--tip-background: #0b1b11;
--warning-border: #62471f;
--warning-background: #1c1408;
--backdrop: rgb(0 0 0 / 0.72);
--header-height: 3.875rem;
--frame-width: 96rem;
--content-width: 60rem;
--gutter: 1.5rem;
}
:root[data-theme="light"] {
color-scheme: light;
--background: #ffffff;
--foreground: #1a1a1a;
--muted: #6b6b6b;
--border: #e2e2e2;
--surface: #f6f6f6;
--surface-hover: #ededed;
--link: #1d63d8;
--blue: #1d63d8;
--green: #1a7f4b;
--yellow: #9a6700;
--red: #c62f2f;
--tip-border: #b5dcc3;
--tip-background: #eff9f2;
--warning-border: #ebd2a4;
--warning-background: #fdf6e8;
--backdrop: rgb(0 0 0 / 0.32);
}
* {
box-sizing: border-box;
scrollbar-color: var(--border) transparent;
@@ -189,6 +218,43 @@ a:hover {
font-size: 0.75rem;
}
:root[data-theme="light"] .brand .logo-dark,
.brand .logo-light {
display: none;
}
:root[data-theme="light"] .brand .logo-light {
display: block;
}
.theme-toggle {
display: inline-flex;
width: 2.25rem;
height: 2.25rem;
padding: 0;
flex-shrink: 0;
cursor: pointer;
border: 1px solid var(--border);
background: transparent;
align-items: center;
justify-content: center;
color: var(--muted);
}
.theme-toggle:hover {
border-color: var(--muted);
color: var(--foreground);
}
:root[data-theme="light"] .theme-toggle .theme-icon-light,
.theme-toggle .theme-icon-dark {
display: none;
}
:root[data-theme="light"] .theme-toggle .theme-icon-dark {
display: block;
}
.github-link {
color: var(--muted);
font-weight: 700;
@@ -360,20 +426,20 @@ main {
}
.api-navigation-method-get {
color: #73a7ff;
color: var(--blue);
}
.api-navigation-method-post {
color: #70c997;
color: var(--green);
}
.api-navigation-method-put,
.api-navigation-method-patch {
color: #e0af68;
color: var(--yellow);
}
.api-navigation-method-delete {
color: #e67c7c;
color: var(--red);
}
.api-content {
@@ -522,20 +588,20 @@ main {
}
.api-method-get {
color: #73a7ff;
color: var(--blue);
}
.api-method-post {
color: #70c997;
color: var(--green);
}
.api-method-put,
.api-method-patch {
color: #e0af68;
color: var(--yellow);
}
.api-method-delete {
color: #e67c7c;
color: var(--red);
}
.api-operation-body,
@@ -607,14 +673,14 @@ main {
.api-deprecated {
display: inline-block;
margin-left: 0.5rem;
color: #e0af68;
color: var(--yellow);
font-size: 0.6875rem;
font-weight: 400;
text-transform: uppercase;
}
.api-deprecated {
color: #e67c7c;
color: var(--red);
}
.api-muted {
@@ -655,12 +721,12 @@ main {
}
.api-status {
color: #e0af68;
color: var(--yellow);
font-weight: 700;
}
.api-status-success {
color: #70c997;
color: var(--green);
}
.api-schema-link {
@@ -874,7 +940,7 @@ main {
overflow-x: auto;
}
.prose pre span {
:root:not([data-theme="light"]) .prose pre span {
color: var(--shiki-dark) !important;
}
@@ -991,13 +1057,13 @@ main {
}
.callout-tip {
border-color: #28503a;
background: #0b1b11;
border-color: var(--tip-border);
background: var(--tip-background);
}
.callout-warning {
border-color: #62471f;
background: #1c1408;
border-color: var(--warning-border);
background: var(--warning-background);
}
.docs-card-group {
@@ -1126,7 +1192,7 @@ main {
}
.search-dialog::backdrop {
background: rgb(0 0 0 / 0.72);
background: var(--backdrop);
}
.search-bar {