Skip to content

Commit

Permalink
Match Sphinx toggle button and Sphinx Design hover and focus styles (#…
Browse files Browse the repository at this point in the history
…2061)

This PR makes the hover and focus styles more consistent for the various
collapsible admonitions we support (Sphinx Design and Sphinx Toggle
Button).

It also makes the focus rings better match the [design
system](https://www.figma.com/design/SnLFWtSKEBLYrtLHbs4TSE/PyData-Sphinx-Theme-Design-System-(Community)?node-id=1233-8360&node-type=frame&t=4kx1rhhCuQNUGldF-0).

Screenshot of the admonition focus rings from the design system:


![](https://github.com/user-attachments/assets/6725942d-85e9-41da-bce9-eabe3f39a57e)

Screenshots from my local git branch, for comparison:

![image](https://github.com/user-attachments/assets/797e298c-d755-455e-b470-9690ea41b353)


![image](https://github.com/user-attachments/assets/7ac58e27-edcf-4baf-8783-da886eab0802)
  • Loading branch information
gabalafou authored Dec 6, 2024
1 parent 933ce14 commit 85aba79
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,6 @@ $link-hover-decoration-thickness: string.unquote(
&:focus-visible {
box-shadow: none; // override Bootstrap
outline: 3px solid var(--pst-color-accent);
outline-offset: 3px;
outline-offset: $focus-ring-width;
}
}
12 changes: 12 additions & 0 deletions src/pydata_sphinx_theme/assets/styles/abstracts/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,15 @@
min-width: 24px;
min-height: 24px;
}

// Meant to darken the element on hover in light mode, or
// lighten on hover in dark mode.
@mixin hover-darken-lighten {
&:hover {
filter: brightness(0.9);

html[data-theme="dark"] & {
filter: brightness(1.1);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -322,12 +322,20 @@ details.sd-dropdown {
top: 0.7rem;
}

@include hover-darken-lighten;

// Focus ring
&:focus:focus-visible {
outline: $focus-ring-outline;
outline-offset: -$focus-ring-width;
outline-offset: $focus-ring-offset;
border-radius: $focus-ring-width;
}
}

&[open] summary.sd-card-header:focus:focus-visible {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
}

/*******************************************************************************
Expand Down Expand Up @@ -358,14 +366,16 @@ html {
.sd-btn-#{$name},
.sd-btn-outline-#{$name} {
&:focus-visible {
outline: var(--sd-color-#{$name}) solid $focus-ring-width;
outline-offset: $focus-ring-offset;
border-radius: $focus-ring-width;

// Override Sphinx Design's use of -highlight colors. The -highlight
// colors are 15% darker, so this would create the effect of darkening
// the button when focused but we just want the button to have a focus
// ring of the same (non-highlight) color.
background-color: var(--sd-color-#{$name}) !important;
border-color: var(--sd-color-#{$name}) !important;
outline: var(--sd-color-#{$name}) solid $focus-ring-width;
outline-offset: $focus-ring-width;
}
}
}
Expand Down
101 changes: 77 additions & 24 deletions src/pydata_sphinx_theme/assets/styles/extensions/_togglebutton.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
/**
* Sphinx togglebutton
*
* The rules in this style sheet are meant to tweak the
* [sphinx-togglebutton](https://sphinx-togglebutton.readthedocs.io/en/latest/index.html)
* extension so that it matches the look and feel of this theme.
*/

.bd-content {
Expand All @@ -17,8 +21,31 @@
}
}

// Admonition toggles
.admonition {
// Apply this mixin to the element that will be hovered. These styles are
// intended to match what sphinx-design does for its dropdown admonitions.
@mixin icon-hover-effects {
&:hover .tb-icon {
opacity: 1;
scale: 1.1;
}

.tb-icon {
opacity: 0.6;
}
}

// Collapsible admonition, implemented as <div> + <button>
.dropdown.admonition.toggle {
// The title is visible when the admonition is collapsed and expanded
.admonition-title {
@include icon-hover-effects;
@include hover-darken-lighten;

&:hover {
box-shadow: none;
}
}

button.toggle-button {
color: inherit;

Expand All @@ -34,49 +61,75 @@
// Focus ring
// ----------
// Sphinx-togglebutton makes the entire admonition header clickable, but
// only the button within the header is focusable. We want the entire
// clickable area to be surrounded with a focus ring, so that's why we use
// the :focus-within selector, rather than a :focus-visible selector on the
// button.
&:focus-within {
// only the button within the header is focusable. But we want the entire
// header and not just the button inside the header to be surrounded by a
// a focus ring.
&:has(:focus-visible) {
/* Override Sphinx Toggle Button. Make the overflow visible, otherwise the
focus ring is hidden. */
overflow: visible;

// The complicated focus ring styles here are a consequence of the markup
// and border styles for this particular admonition class. (For the other
// type of admonition on this site, the focus ring style is achieved with
// simple `outline` and `outline-offset` rules on the admonition's
// header.) The problem is that Sphinx-togglebutton puts the admonition's
// left border on the outermost container (rather than separately setting
// the left border on the container's children). This makes it complicated
// to get the focus ring to simultaneously cover the left border in the
// header and align perfectly on the right with the body.
.admonition-title:focus-within::before {
/*
Why not just do the following?
```
.admonition-title {
outline: $focus-ring-outline;
}
```
Why use ::before? If we put the focus ring on the ::before pseudo-element,
we can reposition the focus ring by repositioning the pseudo-element.
Why reposition? The left edge of the admonition title box does not align
with the left edge of the overall admonition box. There is a left border
that belongs to the overall box. The border is outside of the admonition
title, which means it is also outside of a focus ring around the title. We
can make the focus ring bigger, with `outline-offset`, but this will
result in a ring that looks off-centered. So we have to pull the ring left
and stretch it right. That's what the pseudo-element allows us to do.
Note: we do not have to do this for collapsible admonitions made with
Sphinx Design (as opposed to sphinx-togglebutton).
*/
.admonition-title::before {
content: "";
transform: translateX(
-$admonition-left-border-width
); // align left edges of admonition and ring

width: calc(100% + $admonition-left-border-width); // align right edges
// pull the focus ring left and expand it right to be perfectly centered
// between the left border and the right edge of the admonition title
left: -$admonition-left-border-width;
width: calc(100% + $admonition-left-border-width);
height: 100%;
border: $focus-ring-outline;
outline: $focus-ring-outline;
outline-offset: $focus-ring-offset;
border-radius: $focus-ring-width;
}

// When expanded, sharpen the bottom left and right corners of the focus ring
&:not(.toggle-hidden) .admonition-title:focus-within::before {
&:not(.toggle-hidden) .admonition-title::before {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
}
}

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

@include chevron-down;
@include icon-hover-effects;
@include hover-darken-lighten;

&:hover {
box-shadow: none;
}

&:focus-visible {
outline-offset: $focus-ring-offset;
}
}

// When expanded, sharpen the bottom left and right corners of the focus ring
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ $focus-ring-color: var(--pst-color-accent);
$focus-ring-blur: 0;
$focus-ring-box-shadow: 0 0 $focus-ring-blur $focus-ring-width $focus-ring-color;

// For many elements, we do not use `outline-offset`. For some we set the offset
// equal to the focus ring width (either outwards or inwards). But for some
// other elements (e.g., collapsible admonitions) we set it to this value.
$focus-ring-offset: 0.125rem; // 2px at 100% zoom (0.125 * 16px base font = 2px)

// outline creates the same style of focus ring, it just uses CSS outline instead of box shadow
$focus-ring-outline: $focus-ring-color solid $focus-ring-width;
$btn-focus-box-shadow: $focus-ring-box-shadow;

0 comments on commit 85aba79

Please sign in to comment.