Skip to content

Commit dc89430

Browse files
committed
Match Sphinx toggle button and Sphinx Design hover and focus styles
1 parent 25e01e2 commit dc89430

File tree

3 files changed

+86
-26
lines changed

3 files changed

+86
-26
lines changed

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

+12
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,15 @@
6868
min-width: 24px;
6969
min-height: 24px;
7070
}
71+
72+
// Meant to darken the element on hover in light mode, or
73+
// lighten on hover in dark mode.
74+
@mixin hover-darken-lighten {
75+
&:hover {
76+
filter: brightness(0.9);
77+
78+
html[data-theme="dark"] & {
79+
filter: brightness(1.1);
80+
}
81+
}
82+
}

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,12 @@ details.sd-dropdown {
322322
top: 0.7rem;
323323
}
324324

325+
@include hover-darken-lighten;
326+
325327
// Focus ring
326-
&:focus-visible {
328+
&:focus:focus-visible {
327329
outline: $focus-ring-outline;
328-
outline-offset: -$focus-ring-width;
330+
outline-offset: $focus-ring-width;
329331
}
330332
}
331333
}

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

+70-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
/**
22
* Sphinx togglebutton
3+
*
4+
* The rules in this style sheet are meant to tweak the
5+
* [sphinx-togglebutton](https://sphinx-togglebutton.readthedocs.io/en/latest/index.html)
6+
* extension so that it matches the look and feel of this theme.
37
*/
48

59
.bd-content {
@@ -17,8 +21,27 @@
1721
}
1822
}
1923

20-
// Admonition toggles
21-
.admonition {
24+
// Apply this mixin to the element that will be hovered. These styles are
25+
// intended to match what sphinx-design does for its dropdown admonitions.
26+
@mixin icon-hover-effects {
27+
&:hover .tb-icon {
28+
opacity: 1;
29+
scale: 1.1;
30+
}
31+
32+
.tb-icon {
33+
opacity: 0.6;
34+
}
35+
}
36+
37+
// Collapsible admonition, implemented as <div> + <button>
38+
.dropdown.admonition.toggle {
39+
// The title is visible when the admonition is collapsed and expanded
40+
.admonition-title {
41+
@include icon-hover-effects;
42+
@include hover-darken-lighten;
43+
}
44+
2245
button.toggle-button {
2346
color: inherit;
2447

@@ -34,49 +57,72 @@
3457
// Focus ring
3558
// ----------
3659
// Sphinx-togglebutton makes the entire admonition header clickable, but
37-
// only the button within the header is focusable. We want the entire
38-
// clickable area to be surrounded with a focus ring, so that's why we use
39-
// the :focus-within selector, rather than a :focus-visible selector on the
40-
// button.
41-
&:focus-within {
60+
// only the button within the header is focusable. But we want the entire
61+
// header and not just the button inside the header to be surrounded by a
62+
// a focus ring.
63+
&:has(:focus-visible) {
64+
/* Override Sphinx Toggle Button. Make the overflow visible, otherwise the
65+
focus ring is hidden. */
4266
overflow: visible;
4367

44-
// The complicated focus ring styles here are a consequence of the markup
45-
// and border styles for this particular admonition class. (For the other
46-
// type of admonition on this site, the focus ring style is achieved with
47-
// simple `outline` and `outline-offset` rules on the admonition's
48-
// header.) The problem is that Sphinx-togglebutton puts the admonition's
49-
// left border on the outermost container (rather than separately setting
50-
// the left border on the container's children). This makes it complicated
51-
// to get the focus ring to simultaneously cover the left border in the
52-
// header and align perfectly on the right with the body.
53-
.admonition-title:focus-within::before {
68+
/*
69+
Why not just do the following?
70+
71+
```
72+
.admonition-title {
73+
outline: $focus-ring-outline;
74+
}
75+
```
76+
77+
Why use ::before? If we put the focus ring on the ::before pseudo-element,
78+
we can reposition the focus ring by repositioning the pseudo-element.
79+
80+
Why reposition? The left edge of the admonition title box does not align
81+
with the left edge of the overall admonition box. There is a left border
82+
that belongs to the overall box. The border is outside of the admonition
83+
title, which means it is also outside of a focus ring around the title. We
84+
can make the focus ring bigger, with `outline-offset`, but this will
85+
result in a ring that looks off-centered. So we have to pull the ring left
86+
and stretch it right. That's what the pseudo-element allows us to do.
87+
88+
We do not have to do this with the other collapsible admonitions because
89+
those implementations put the left border and the title together so that a
90+
focus ring surrounds them both.
91+
*/
92+
.admonition-title::before {
5493
content: "";
55-
transform: translateX(
56-
-$admonition-left-border-width
57-
); // align left edges of admonition and ring
5894

59-
width: calc(100% + $admonition-left-border-width); // align right edges
95+
// pull the focus ring left and expand it right to be perfectly centered
96+
// between the left border and the right edge of the admonition title
97+
left: -$admonition-left-border-width;
98+
width: calc(100% + $admonition-left-border-width);
6099
height: 100%;
61-
border: $focus-ring-outline;
100+
outline: $focus-ring-outline;
101+
outline-offset: $focus-ring-width;
62102
border-radius: $focus-ring-width;
63103
}
64104

65105
// When expanded, sharpen the bottom left and right corners of the focus ring
66-
&:not(.toggle-hidden) .admonition-title:focus-within::before {
106+
&:not(.toggle-hidden) .admonition-title::before {
67107
border-bottom-left-radius: 0;
68108
border-bottom-right-radius: 0;
69109
}
70110
}
71111
}
72112

73-
// Details buttons
113+
// Collapsible component, implemented as <details> + <summary>
74114
details.toggle-details {
75115
// Over-ride border color to re-use our primary color
76116
summary {
77117
border-left: 3px solid var(--pst-color-primary);
78118

79119
@include chevron-down;
120+
@include icon-hover-effects;
121+
@include hover-darken-lighten;
122+
123+
&:focus-visible {
124+
outline-offset: $focus-ring-width;
125+
}
80126
}
81127

82128
// When expanded, sharpen the bottom left and right corners of the focus ring

0 commit comments

Comments
 (0)