Skip to content

Commit 2c60f45

Browse files
committed
docs(sphinx-ux-tabs): Document :class-container:, --large variant, deep-links, prehydrate
why: Four author-facing capabilities landed without reference docs; make them discoverable. what: - Add :class-container: row to {tab-item} option table - Add Size variants section to reference.md and how-to.md - Add Persistence and deep-links section to reference.md and how-to.md - Add Prehydrate subsection under JavaScript in reference.md - Examples.md gains side-by-side default-vs-large tab-set and deep-link demo
1 parent 6db6c31 commit 2c60f45

3 files changed

Lines changed: 227 additions & 0 deletions

File tree

docs/packages/sphinx-ux-tabs/examples.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,93 @@ source ~/.config/fish/config.fish
133133

134134
Click a tab in either tab-set; the other follows.
135135

136+
## Size variants
137+
138+
Default size — compact labels at `0.95em`:
139+
140+
::::{tab-set}
141+
142+
:::{tab-item} pip
143+
```console
144+
$ pip install gp-sphinx
145+
```
146+
:::
147+
148+
:::{tab-item} uv
149+
```console
150+
$ uv add gp-sphinx
151+
```
152+
:::
153+
154+
:::{tab-item} pipx
155+
```console
156+
$ pipx install gp-sphinx
157+
```
158+
:::
159+
160+
::::
161+
162+
`:class: gp-sphinx-tabs--large` — body-size labels with roomier
163+
padding:
164+
165+
::::{tab-set}
166+
:class: gp-sphinx-tabs--large
167+
168+
:::{tab-item} pip
169+
```console
170+
$ pip install gp-sphinx
171+
```
172+
:::
173+
174+
:::{tab-item} uv
175+
```console
176+
$ uv add gp-sphinx
177+
```
178+
:::
179+
180+
:::{tab-item} pipx
181+
```console
182+
$ pipx install gp-sphinx
183+
```
184+
:::
185+
186+
::::
187+
188+
## Deep-link to a tab
189+
190+
::::{tab-set}
191+
:sync-group: example
192+
193+
:::{tab-item} Python
194+
:sync: python
195+
```python
196+
print("hello world")
197+
```
198+
:::
199+
200+
:::{tab-item} Rust
201+
:sync: rust
202+
```rust
203+
println!("hello world");
204+
```
205+
:::
206+
207+
:::{tab-item} Go
208+
:sync: go
209+
```go
210+
fmt.Println("hello world")
211+
```
212+
:::
213+
214+
::::
215+
216+
Open this page with <a href="?example=python"><code>?example=python</code></a>
217+
to pre-select the Python tab via the sphinx-design URL form. The
218+
legacy sphinx-inline-tabs form is supported too:
219+
<a href="?tabs=Python"><code>?tabs=Python</code></a>. Either form
220+
writes through to `localStorage`, so the choice persists on subsequent
221+
visits.
222+
136223
## `:new-set:` breaks a consecutive run
137224

138225
```{eval-rst}

docs/packages/sphinx-ux-tabs/how-to.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,59 @@ Later: see {ref}`the Python tab <py-tab>` for details.
9292
The label is the anchor — clicking the `{ref}` jumps to the tab's
9393
label, the radio remains in whichever state the user last selected.
9494

95+
## Deep-link to a specific tab
96+
97+
`sphinx-ux-tabs` reads two URL query-parameter forms on first paint and
98+
writes the resolved selection through to `localStorage`, so a link
99+
that sets a tab also persists the choice for the user's next visit.
100+
101+
The label form deep-links by visible text — appropriate when the link
102+
target shouldn't care about authoring details:
103+
104+
```
105+
https://example.org/install/?tabs=Python
106+
```
107+
108+
The group form deep-links by the `:sync-group:` / `:sync:` pair —
109+
appropriate when more than one tab on the page shares a label, or when
110+
the link should target a specific sync-group:
111+
112+
```
113+
https://example.org/install/?shell=zsh
114+
```
115+
116+
Both forms persist to `localStorage` under the key
117+
`gp-sphinx-tabs.sync.<group>`, so the next page load on the same
118+
sync-group restores the user's last choice automatically. URL params
119+
apply on first paint only — subsequent SPA-nav events read from
120+
`localStorage`.
121+
122+
## Use the larger size variant
123+
124+
The default tab size is compact (`0.95em` labels) to match the
125+
workspace's tight prose rhythm. Use `:class: gp-sphinx-tabs--large` on
126+
the `{tab-set}` for callout sections, feature-comparison tables, or
127+
landing-page hero tabs — anywhere touch-target size or label
128+
prominence matters more than vertical economy.
129+
130+
````markdown
131+
:::{tab-set}
132+
:class: gp-sphinx-tabs--large
133+
134+
:::{tab-item} pip
135+
...
136+
:::
137+
138+
:::{tab-item} uv
139+
...
140+
:::
141+
142+
:::
143+
````
144+
145+
The `:class:` option preserves the BEM `--` modifier verbatim — no
146+
extra escaping required.
147+
95148
## Use tabs after SPA navigation
96149

97150
Tabs work without JS — the `:checked + label + .panel` selectors

docs/packages/sphinx-ux-tabs/reference.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,73 @@ The first tab with `:selected:` wins. If none is selected, index 0 is
130130
checked. Multiple `:selected:` tabs emit a Sphinx warning under the
131131
subtype `gp-sphinx-tabs.tab`.
132132

133+
## Size variants
134+
135+
The default size renders labels at `0.95em` with tight padding to match
136+
the workspace's compact prose rhythm. Authors can opt into a larger
137+
size with `:class: gp-sphinx-tabs--large` on `{tab-set}` — labels paint
138+
at normal body size with roomier padding, suitable for callout
139+
sections, feature-comparison tables, or landing-page hero tabs.
140+
141+
````markdown
142+
:::{tab-set}
143+
:class: gp-sphinx-tabs--large
144+
145+
:::{tab-item} pip
146+
`pip install gp-sphinx`
147+
:::
148+
149+
:::{tab-item} uv
150+
`uv add gp-sphinx`
151+
:::
152+
153+
:::
154+
````
155+
156+
The `:class:` option preserves BEM `--` modifiers verbatim.
157+
`sphinx-ux-tabs` uses a custom class-option parser specifically so the
158+
`gp-sphinx-tabs--large` token survives — docutils' built-in
159+
`class_option` would collapse the `--` to a single `-`.
160+
161+
## Persistence and deep-links
162+
163+
`sphinx-ux-tabs` persists each user's tab choice and accepts URL query
164+
parameters to deep-link a specific tab.
165+
166+
### localStorage
167+
168+
Every `:sync-group:` gets its own `localStorage` key under the
169+
namespace `gp-sphinx-tabs.sync.<group>`. On click, the JS writes the
170+
chosen `:sync:` ID under that key. On script-load and on every
171+
`gp-sphinx:navigated` event (workspace SPA navigation), the JS reads
172+
every distinct `data-sync-group` on the page and restores the saved
173+
selection.
174+
175+
### URL query parameters
176+
177+
URL query parameters take precedence over `localStorage` on first
178+
paint and write through to `localStorage` so the choice persists for
179+
subsequent visits. Two formats are accepted:
180+
181+
```{list-table}
182+
:header-rows: 1
183+
:widths: 30 70
184+
185+
* - Form
186+
- Behaviour
187+
* - `?tabs=Label`
188+
- sphinx-inline-tabs idiom — matches by tab label text,
189+
case-insensitive. Pre-selects every label whose visible text equals
190+
`Label`.
191+
* - `?<group>=<id>`
192+
- sphinx-design idiom — matches by `:sync-group:` / `:sync:`.
193+
Multiple `?key=val` pairs accumulate, one per distinct group.
194+
```
195+
196+
URL parameters apply on first paint only. Subsequent SPA-nav events
197+
read from `localStorage` only — re-applying URL params on every
198+
navigation would let stale query strings override a fresh click.
199+
133200
## CSS classes
134201

135202
```{list-table}
@@ -140,6 +207,8 @@ subtype `gp-sphinx-tabs.tab`.
140207
- Applied to
141208
* - `gp-sphinx-tabs`
142209
- Outer tab-set container.
210+
* - `gp-sphinx-tabs--large`
211+
- Modifier on `gp-sphinx-tabs` opting into the larger size variant.
143212
* - `gp-sphinx-tabs__input`
144213
- Hidden radio input (`<input type="radio">`).
145214
* - `gp-sphinx-tabs__label`
@@ -191,6 +260,24 @@ The shipped sync JS is page-scoped, idempotent, and SPA-aware:
191260
Tabs work without the JS — pure CSS handles single-page switching.
192261
The JS is only needed for cross-tab-set sync.
193262

263+
### Prehydrate
264+
265+
Pages that host sync'd tabs receive a small inline `<head>` payload —
266+
a `<script data-cfasync="false">` and a `<style>` block under
267+
`@layer gp-sphinx-tabs-prehydrate`. The script reads URL query
268+
parameters and `localStorage`, then sets
269+
`<html data-gp-sphinx-tabs-sync-<group>="<id>">` before any stylesheet
270+
loads. The CSS layer's attribute selectors then paint the saved
271+
label colour and panel visibility on the first frame, so the user
272+
never sees the server-rendered default tab flash to the saved
273+
selection.
274+
275+
`data-cfasync="false"` opts the inline script out of Cloudflare Rocket
276+
Loader so it runs synchronously as written. Pages without sync'd tabs
277+
carry zero prehydrate payload — the prehydrate injection short-circuits
278+
when the post-transform records no `(sync_group, sync_id)` pairs for
279+
the page.
280+
194281
## Python API
195282

196283
```{eval-rst}

0 commit comments

Comments
 (0)