Skip to content

Commit 9a80c2b

Browse files
authored
Merge branch 'feature-focus' into header-nav-link-styles
2 parents 25323b7 + 85badcb commit 9a80c2b

File tree

17 files changed

+177
-107
lines changed

17 files changed

+177
-107
lines changed

docs/examples/gallery.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Thanks for your support!
3535
link: https://fairlearn.org/main/about/
3636
- title: Feature-engine
3737
link: https://feature-engine.readthedocs.io/
38-
- title: idtracker.ai
38+
- title: idtracker.ai
3939
link: https://idtracker.ai/
4040
- title: MegEngine
4141
link: https://www.megengine.org.cn/doc/stable/en/index.html

docs/index.md

+3-5
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,11 @@ A clean, Bootstrap-based Sphinx theme by and for [the PyData community](https://
2121
- header: "{fas}`circle-half-stroke;pst-color-primary` Light / Dark theme"
2222
content: "Users can toggle between light and dark themes interactively."
2323
- header: "{fas}`palette;pst-color-primary` Customizable UI and themes"
24-
content: "Customize colors and branding with CSS variables, and build custom UIs with [Sphinx Design](user_guide/web-components)."
24+
content: "Customize colors and branding with CSS variables, and build custom UIs with [Sphinx Design components](user_guide/web-components)."
2525
- header: "{fab}`python;pst-color-primary` Supports PyData and Jupyter"
26-
content: "CSS and UI support for Jupyter extensions and PyData execution outputs."
27-
link: "examples/pydata.html"
26+
content: "CSS and UI support for [Jupyter extensions](examples/execution) and [PyData execution outputs](examples/pydata.ipynb)."
2827
- header: "{fas}`lightbulb;pst-color-primary` Example Gallery"
29-
content: "See our gallery of projects that use this theme."
30-
link: "examples/gallery.html"
28+
content: "See [our gallery](examples/gallery.md) of projects that use this theme."
3129
```
3230

3331
```{seealso}

src/pydata_sphinx_theme/assets/styles/abstracts/_links.scss

+2-73
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ $link-hover-decoration-thickness: unquote("max(3px, .1875rem, .12em)") !default;
8686
color: var(--pst-color-link-hover);
8787
}
8888
}
89-
@include focus-indicator;
9089
}
9190

9291
// Text link styles
@@ -102,7 +101,6 @@ $link-hover-decoration-thickness: unquote("max(3px, .1875rem, .12em)") !default;
102101
@include link-decoration;
103102
@include link-decoration-hover;
104103
}
105-
@include focus-indicator;
106104
}
107105

108106
// Sidebar and TOC links
@@ -137,10 +135,8 @@ $link-hover-decoration-thickness: unquote("max(3px, .1875rem, .12em)") !default;
137135
font-weight: 600;
138136
color: var(--pst-color-primary);
139137
@if $link-hover-decoration-thickness {
140-
box-shadow: inset
141-
$link-hover-decoration-thickness
142-
0px
143-
0px
138+
border-left: $link-hover-decoration-thickness
139+
solid
144140
var(--pst-color-primary);
145141
}
146142
}
@@ -175,70 +171,3 @@ $link-hover-decoration-thickness: unquote("max(3px, .1875rem, .12em)") !default;
175171
}
176172
}
177173
}
178-
179-
// Focus indicator
180-
@mixin focus-indicator {
181-
&:focus-visible {
182-
outline: 2px solid var(--pst-color-accent);
183-
}
184-
}
185-
186-
/*
187-
Mixin for links in the header (and the More dropdown toggle).
188-
189-
The mixin assumes it will be applied to some element X with a markup structure
190-
like: X > .nav-link, or X > .dropdown-toggle.
191-
192-
It also assumes X.current is how the app annotates which item in the header nav
193-
corresponds to the section in the docs that the user is currently reading.
194-
*/
195-
@mixin header-link {
196-
> .nav-link,
197-
> .dropdown-toggle {
198-
border-radius: 2px;
199-
color: var(--pst-color-text-muted);
200-
font-weight: 700;
201-
202-
&:hover {
203-
background-color: var(--pst-color-header-link-hover-bg);
204-
color: var(--pst-color-header-link-hover);
205-
text-decoration: none; // override the link-style-hover mixin
206-
}
207-
208-
&:focus {
209-
box-shadow: none; // override Bootstrap
210-
outline: 3px solid var(--pst-color-accent);
211-
outline-offset: 3px;
212-
213-
&:not(:hover) {
214-
background-color: var(--pst-color-accent-bg);
215-
}
216-
}
217-
}
218-
219-
&.current {
220-
> .nav-link,
221-
> .dropdown-toggle {
222-
color: var(--pst-color-primary);
223-
&:hover {
224-
color: var(--pst-color-header-link-hover);
225-
}
226-
227-
// These styles underline the current navbar item
228-
position: relative;
229-
&::after {
230-
content: "";
231-
display: block;
232-
position: absolute;
233-
top: 0;
234-
right: 0;
235-
bottom: 0;
236-
left: 0;
237-
border-bottom: 3px solid var(--pst-color-primary);
238-
}
239-
&:hover::after {
240-
display: none;
241-
}
242-
}
243-
}
244-
}

src/pydata_sphinx_theme/assets/styles/base/_base.scss

+10
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,13 @@ pre {
179179
background-color: var(--pst-color-secondary);
180180
border: none;
181181
}
182+
183+
// Focus ring
184+
//
185+
// Note: The Bootstrap stylesheet provides the focus ring (customized via Sass
186+
// variables in _bootstrap.scss) in some cases. This rules covers all other
187+
// cases.
188+
:focus-visible {
189+
outline: $focus-ring-outline;
190+
box-shadow: none; // override Bootstrap
191+
}

src/pydata_sphinx_theme/assets/styles/components/_search.scss

+12-7
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@
5858
&:focus,
5959
&:focus-visible {
6060
border: none;
61-
box-shadow: none;
62-
outline: 3px solid var(--pst-color-accent);
6361
background-color: var(--pst-color-background);
6462
color: var(--pst-color-text-muted);
6563
}
@@ -75,11 +73,16 @@
7573
align-items: center;
7674
align-content: center;
7775
color: var(--pst-color-text-muted);
78-
// Needed to match other icons hover
79-
padding: 0 0 0.25rem 0;
8076
border-radius: 0;
77+
border: none; // Override Bootstrap button border
78+
font-size: 1rem; // Override Bootstrap button font size
79+
80+
// Override Bootstrap button padding-x. Whitespace in nav bar is controlled
81+
// via column gap rule on the container.
82+
padding-left: 0;
83+
padding-right: 0;
84+
8185
@include icon-navbar-hover;
82-
@include focus-indicator;
8386

8487
i {
8588
font-size: 1.3rem;
@@ -136,19 +139,21 @@
136139
* Lives at components/search-button-field.html
137140
*/
138141
.search-button-field {
142+
$search-button-border-radius: 1.5em;
139143
display: inline-flex;
140144
align-items: center;
141145
border: var(--pst-color-border) solid 1px;
142-
border-radius: 1.5em;
146+
border-radius: $search-button-border-radius;
143147
color: var(--pst-color-text-muted);
144148
padding: 0.5em;
145149
background-color: var(--pst-color-surface);
146150

147151
&:hover {
148152
border: 2px solid var(--pst-color-link-hover);
149153
}
154+
150155
&:focus-visible {
151-
border: 2px solid var(--pst-color-accent);
156+
border-radius: $search-button-border-radius;
152157
}
153158

154159
// The keyboard shotcut text

src/pydata_sphinx_theme/assets/styles/components/_switcher-theme.scss

+11-6
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,23 @@
33
*/
44

55
.theme-switch-button {
6-
// overide bootstrap settings
7-
margin: 0 -0.5rem;
8-
padding: 0; // We pad the `span` not the container
96
color: var(--pst-color-text-muted);
107
border-radius: 0;
11-
@include focus-indicator;
8+
border: none; // Override Bootstrap button border
9+
font-size: 1rem; // Override Bootstrap's button font size
10+
11+
// Override Bootstrap button padding-x. Whitespace in nav bar is controlled
12+
// via column gap rule on the container.
13+
padding-left: 0;
14+
padding-right: 0;
15+
16+
&:hover {
17+
@include icon-navbar-hover;
18+
}
1219

1320
span {
1421
display: none;
15-
padding: 0.5em;
1622

17-
@include icon-navbar-hover;
1823
&:active {
1924
text-decoration: none;
2025
color: var(--pst-color-link-hover);

src/pydata_sphinx_theme/assets/styles/components/_switcher-version.scss

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ button.btn.version-switcher__button {
88
}
99

1010
@include link-style-hover;
11-
@include focus-indicator;
1211
&:active {
1312
color: var(--pst-color-text-base);
1413
border-color: var(--pst-color-border);

src/pydata_sphinx_theme/assets/styles/components/_toc-inpage.scss

+4
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,8 @@ nav.page-toc {
4848
}
4949
}
5050
}
51+
52+
:focus-visible {
53+
border-radius: 0.125rem;
54+
}
5155
}

src/pydata_sphinx_theme/assets/styles/content/_admonitions.scss

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
* Admonitions CSS originally inspired by https://squidfunk.github.io/mkdocs-material/getting-started/
44
*/
55
$admonition-border-radius: 0.25rem;
6+
$admonition-left-border-width: 0.2rem;
67
div.admonition,
78
.admonition {
89
margin: 1.5625em auto;
910
padding: 0 0.6rem 0.8rem 0.6rem;
1011
overflow: hidden;
1112
page-break-inside: avoid;
12-
border-left: 0.2rem solid;
13+
border-left: $admonition-left-border-width solid;
1314
border-color: var(--pst-color-info);
1415
border-radius: $admonition-border-radius;
1516
background-color: var(--pst-color-on-background);
@@ -226,7 +227,7 @@ div.admonition,
226227
margin-top: 0;
227228

228229
// Undo the .sidebar directive border
229-
border-width: 0 0 0 0.2rem;
230+
border-width: 0 0 0 $admonition-left-border-width;
230231

231232
// TODO: these semantic-color-names border-color rules might no longer be
232233
// needed when we drop support for Sphinx 4 / docutils 0.17

src/pydata_sphinx_theme/assets/styles/extensions/_copybutton.scss

+9
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,13 @@ div.highlight button.copybtn {
3131
color: var(--pst-color-text);
3232
background-color: var(--pst-color-surface);
3333
}
34+
35+
&:focus {
36+
// For keyboard users, make the copy button visible when focussed.
37+
opacity: 1;
38+
}
39+
40+
&:focus-visible {
41+
outline: $focus-ring-outline;
42+
}
3443
}

src/pydata_sphinx_theme/assets/styles/extensions/_sphinx_design.scss

+22
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,22 @@ html[data-theme="light"] {
149149
.sd-card-body {
150150
background-color: var(--pst-color-panel-background);
151151
}
152+
153+
// Focus ring for link-cards
154+
.sd-stretched-link:focus-visible {
155+
// Don't put the focus ring on the <a> element (it has zero height in Sphinx Design cards)
156+
outline: none;
157+
158+
// Put the focus ring on the <a> element's ::after pseudo-element
159+
&:after {
160+
outline: $focus-ring-outline;
161+
border-radius: 0.25rem; // copied from Sphinx Design CSS for .sd-card
162+
}
163+
}
164+
165+
&.sd-card-hover:hover {
166+
border-color: var(--pst-color-link-hover);
167+
}
152168
}
153169
/*******************************************************************************
154170
* tabs
@@ -256,5 +272,11 @@ details.sd-dropdown {
256272
.sd-summary-down {
257273
top: 0.7rem;
258274
}
275+
276+
// Focus ring
277+
&:focus-visible {
278+
outline: $focus-ring-outline;
279+
outline-offset: -$focus-ring-width;
280+
}
259281
}
260282
}

src/pydata_sphinx_theme/assets/styles/extensions/_togglebutton.scss

+43
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,43 @@
88
button.toggle-button {
99
color: inherit;
1010
}
11+
12+
// Focus ring
13+
//
14+
// Sphinx-togglebutton makes the entire admonition header clickable, but
15+
// only the button within the header is focusable. We want the entire
16+
// clickable area to be surrounded with a focus ring, so that's why we use
17+
// the :focus-within selector, rather than a :focus-visible selector on the
18+
// button.
19+
&:focus-within {
20+
overflow: visible;
21+
22+
// The complicated focus ring styles here are a consequence of the markup
23+
// and border styles for this particular admonition class. (For the other
24+
// type of admonition on this site, the focus ring style is achieved with
25+
// simple `outline` and `outline-offset` rules on the admonition's
26+
// header.) The problem is that Sphinx-togglebutton puts the admonition's
27+
// left border on the outermost container (rather than separately setting
28+
// the left border on the container's children). This makes it complicated
29+
// to get the focus ring to simultaneously cover the left border in the
30+
// header and align perfectly on the right with the body.
31+
.admonition-title:focus-within:before {
32+
content: "";
33+
transform: translateX(
34+
-$admonition-left-border-width
35+
); // align left edges of admonition and ring
36+
width: calc(100% + $admonition-left-border-width); // align right edges
37+
height: 100%;
38+
border: $focus-ring-outline;
39+
border-radius: $focus-ring-width;
40+
}
41+
42+
// When expanded, sharpen the bottom left and right corners of the focus ring
43+
&:not(.toggle-hidden) .admonition-title:focus-within:before {
44+
border-bottom-left-radius: 0;
45+
border-bottom-right-radius: 0;
46+
}
47+
}
1148
}
1249

1350
// Details buttons
@@ -16,5 +53,11 @@
1653
summary {
1754
border-left: 3px solid var(--pst-color-primary);
1855
}
56+
57+
// When expanded, sharpen the bottom left and right corners of the focus ring
58+
&[open] :focus-visible {
59+
border-bottom-left-radius: 0;
60+
border-bottom-right-radius: 0;
61+
}
1962
}
2063
}

src/pydata_sphinx_theme/assets/styles/sections/_header.scss

+4-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
padding-right: 1rem;
2929
}
3030

31+
:focus-visible {
32+
border-radius: 0.125rem;
33+
}
34+
3135
// These items will define the height of the header
3236
.navbar-item {
3337
height: var(--pst-header-height);
@@ -193,7 +197,6 @@
193197
}
194198
}
195199
@include icon-navbar-hover;
196-
@include focus-indicator;
197200
}
198201

199202
// Hide the navbar header items on mobile because they're in the sidebar

0 commit comments

Comments
 (0)