Skip to content

Commit 2556119

Browse files
caozx1110claude
andcommitted
docs(sphinx): move language switcher to sidebar, default to English
UI changes: - Root index.md now auto-redirects to /en/index.html (no language picker landing page) - Language dropdown moved from page body to left sidebar, below the site title and above the search box - Sidebar navigation only shows English docs; zh_CN pages are still built but accessed exclusively via the language switcher - Add _templates/sidebar/lang_switcher.html for Furo sidebar injection - Configure html_sidebars in conf.py to include the new component Dark theme fix: - Landing hero background was showing light gradient in dark mode because the old selector (body.dark) doesn't match Furo's actual dark-mode mechanism (body[data-theme="dark"] + prefers-color-scheme media query for auto mode) - Now uses CSS custom properties that update in both explicit-dark and auto-dark scenarios - Hero h1 gradient text also gets a lighter palette in dark mode for proper contrast against the dark background Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 4ab84be commit 2556119

5 files changed

Lines changed: 99 additions & 66 deletions

File tree

‎docs/sphinx/AGENTS.md‎

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,35 @@ Sphinx 文档写作规则。
1717

1818
```text
1919
source/
20-
├── index.md # root landing; language selection is site-level
21-
├── en/ # English semantic tree
22-
├── zh_CN/ # Chinese tree; legacy numbered paths are kept short-term
20+
├── index.md # root redirect → en/index.html (no language picker)
21+
├── en/ # English tree (site root, shown in sidebar nav)
22+
├── zh_CN/ # Chinese tree (hidden from sidebar, via switcher only)
2323
├── adr/ # shared ADR, one set
2424
├── api_reference/ # shared autodoc output from src/ docstrings
2525
├── glossary.md
2626
├── changelog.md
2727
├── _static/
2828
└── _templates/
29+
├── sidebar/
30+
│ └── lang_switcher.html # language dropdown in sidebar
31+
└── autosummary/
2932
```
3033

31-
`source/en/` and `source/zh_CN/` are parallel language roots, but they are **not
32-
currently a strict 1:1 path mirror**. The Chinese user guide still keeps
34+
`source/en/` is the **default site root**. Visitors land on `/en/index.html`
35+
directly (root `index.md` is a redirect). The sidebar navigation tree only
36+
shows English pages. `source/zh_CN/` pages are built but accessible only
37+
through the sidebar language switcher — they never appear in the navigation
38+
tree.
39+
40+
`source/en/` and `source/zh_CN/` are parallel language roots, but they are
41+
**not currently a strict 1:1 path mirror**. The Chinese user guide still keeps
3342
compatibility paths such as `01-getting-started.md`, `A-getting-started/`, and
3443
`C-algorithms/`. Do not rename those paths just to mirror English during an
35-
unrelated documentation change.
44+
unrelated documentation change. The language switcher uses an explicit path map
45+
in `conf.py` (`_LANGUAGE_PATH_FORWARD`) to handle the mismatch.
3646

37-
The root landing uses the site language switcher pattern. Do not add per-page
38-
language button blocks or hand-written cross-language navigation. Use the root
39-
language entry and the language switcher for language changes.
47+
Do not add per-page language button blocks or hand-written cross-language
48+
navigation. The sidebar language switcher handles language changes globally.
4049

4150
## Core Principles
4251

‎docs/sphinx/source/_static/css/custom.css‎

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,23 @@
33
:root {
44
--ul-hero-bg: linear-gradient(135deg, #eff6ff 0%, #ede9fe 50%, #fef3c7 100%);
55
--ul-hero-border: rgba(99, 102, 241, 0.18);
6+
--ul-hero-text-shadow: none;
67
--ul-card-hover: 0 8px 24px rgba(37, 99, 235, 0.10);
78
}
89

9-
body.dark .landing-hero, body[data-theme="dark"] .landing-hero {
10-
background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 60%, #312e81 100%);
11-
border-color: rgba(96, 165, 250, 0.25);
10+
/* Dark theme overrides — Furo uses body[data-theme="dark"] for explicit
11+
dark mode and the prefers-color-scheme media query for auto (when
12+
data-theme="auto"). We mirror both. */
13+
body[data-theme="dark"] {
14+
--ul-hero-bg: linear-gradient(135deg, #0f172a 0%, #1e1b4b 60%, #312e81 100%);
15+
--ul-hero-border: rgba(96, 165, 250, 0.25);
16+
}
17+
18+
@media (prefers-color-scheme: dark) {
19+
body:not([data-theme="light"]) {
20+
--ul-hero-bg: linear-gradient(135deg, #0f172a 0%, #1e1b4b 60%, #312e81 100%);
21+
--ul-hero-border: rgba(96, 165, 250, 0.25);
22+
}
1223
}
1324

1425
/* ---------- Language switcher ---------- */
@@ -75,12 +86,21 @@ body.dark .landing-hero, body[data-theme="dark"] .landing-hero {
7586
font-weight: 800;
7687
letter-spacing: -0.02em;
7788
margin: 0.3rem 0 0.5rem 0;
78-
background: linear-gradient(90deg, #1e40af, #6d28d9, #be185d);
89+
background: var(--ul-hero-h1-gradient, linear-gradient(90deg, #1e40af, #6d28d9, #be185d));
7990
-webkit-background-clip: text;
8091
background-clip: text;
8192
color: transparent;
8293
}
8394

95+
body[data-theme="dark"] {
96+
--ul-hero-h1-gradient: linear-gradient(90deg, #93c5fd, #c4b5fd, #fbcfe8);
97+
}
98+
@media (prefers-color-scheme: dark) {
99+
body:not([data-theme="light"]) {
100+
--ul-hero-h1-gradient: linear-gradient(90deg, #93c5fd, #c4b5fd, #fbcfe8);
101+
}
102+
}
103+
84104
.landing-hero h3 {
85105
font-weight: 500;
86106
margin-top: 0;
@@ -191,15 +211,26 @@ kbd {
191211
margin-top: 1rem;
192212
}
193213

194-
@media (max-width: 640px) {
195-
.language-switcher,
196-
.landing-language-picker {
197-
align-items: stretch;
198-
flex-direction: column;
199-
}
200-
201-
.language-switcher__select,
202-
.landing-language-picker__select {
203-
width: 100%;
204-
}
214+
/* ---------- Sidebar language switcher ---------- */
215+
.sidebar-lang-switcher {
216+
padding: 0.4rem 0.8rem;
217+
margin: 0 0 0.2rem 0;
205218
}
219+
.sidebar-lang-switcher__select {
220+
width: 100%;
221+
padding: 0.35rem 0.6rem;
222+
font-size: 0.85rem;
223+
border: 1px solid var(--color-foreground-border);
224+
border-radius: 6px;
225+
background: var(--color-background-secondary);
226+
color: var(--color-foreground-primary);
227+
cursor: pointer;
228+
appearance: auto;
229+
}
230+
.sidebar-lang-switcher__select:hover {
231+
border-color: var(--color-brand-primary);
232+
}
233+
234+
/* Hide old body-injected language switcher */
235+
.language-switcher { display: none !important; }
236+
.landing-language-picker { display: none !important; }
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{# Furo sidebar component: language switcher placed below brand, above search #}
2+
{%- set current = current_language|default("en") -%}
3+
{%- set en_target = language_switcher_targets.get("en", "en/index") if language_switcher_targets is defined else "en/index" -%}
4+
{%- set zh_target = language_switcher_targets.get("zh_CN", "zh_CN/index") if language_switcher_targets is defined else "zh_CN/index" -%}
5+
<div class="sidebar-lang-switcher">
6+
<select class="sidebar-lang-switcher__select" aria-label="Language">
7+
<option value="{{ pathto(en_target)|e }}"{% if current == "en" %} selected{% endif %}>English</option>
8+
<option value="{{ pathto(zh_target)|e }}"{% if current == "zh_CN" %} selected{% endif %}>简体中文</option>
9+
</select>
10+
</div>
11+
<script>
12+
(function(){
13+
var sel = document.querySelector(".sidebar-lang-switcher__select");
14+
if (!sel) return;
15+
sel.addEventListener("change", function(){
16+
var url = this.value;
17+
if (url) window.location.href = new URL(url, window.location.href).href;
18+
});
19+
})();
20+
</script>

‎docs/sphinx/source/conf.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,17 @@
198198
html_baseurl = "https://unilabsim.github.io/UniLab-doc/"
199199
sitemap_url_scheme = "{link}"
200200

201+
html_sidebars = {
202+
"**": [
203+
"sidebar/brand.html",
204+
"sidebar/lang_switcher.html",
205+
"sidebar/search.html",
206+
"sidebar/scroll-start.html",
207+
"sidebar/navigation.html",
208+
"sidebar/scroll-end.html",
209+
],
210+
}
211+
201212
html_theme_options = {
202213
"sidebar_hide_name": False,
203214
"navigation_with_keys": True,

‎docs/sphinx/source/index.md‎

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,21 @@
11
---
22
sd_hide_title: true
3+
orphan: true
34
---
45

56
# UniLab Documentation
67

7-
::::{div} landing-hero
8-
9-
:::{div} landing-hero-text
10-
11-
# UniLab Documentation
12-
13-
### Robot learning infrastructure documentation.
14-
15-
Pick a language to continue:
16-
178
```{raw} html
18-
<div class="landing-language-picker">
19-
<label class="landing-language-picker__label" for="landing-language-select">Documentation language</label>
20-
<select class="landing-language-picker__select" id="landing-language-select" aria-label="Documentation language">
21-
<option value="" selected disabled>Choose a language</option>
22-
<option value="en/index.html">English</option>
23-
<option value="zh_CN/index.html">简体中文</option>
24-
</select>
25-
</div>
26-
<script>
27-
(function () {
28-
var select = document.getElementById("landing-language-select");
29-
if (!select) {
30-
return;
31-
}
32-
select.addEventListener("change", function () {
33-
if (this.value) {
34-
window.location.href = this.value;
35-
}
36-
});
37-
}());
38-
</script>
9+
<meta http-equiv="refresh" content="0; url=en/index.html" />
10+
<script>window.location.href = "en/index.html";</script>
11+
<p>Redirecting to <a href="en/index.html">English documentation</a>…</p>
3912
```
4013

41-
:::
42-
43-
::::
44-
4514
```{toctree}
4615
:hidden:
47-
:caption: Languages
4816
4917
en/index
5018
zh_CN/index
51-
```
52-
53-
```{toctree}
54-
:hidden:
55-
:caption: Shared
56-
5719
adr/README
5820
api_reference/index
5921
glossary

0 commit comments

Comments
 (0)