Skip to content

Consistent focus ring (first pass) #1549

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 2 additions & 13 deletions src/pydata_sphinx_theme/assets/styles/abstracts/_links.scss
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ $link-hover-decoration-thickness: unquote("max(3px, .1875rem, .12em)") !default;
color: var(--pst-color-link-hover);
}
}
@include focus-indicator;
}

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

// Sidebar and TOC links
Expand Down Expand Up @@ -137,10 +135,8 @@ $link-hover-decoration-thickness: unquote("max(3px, .1875rem, .12em)") !default;
font-weight: 600;
color: var(--pst-color-primary);
@if $link-hover-decoration-thickness {
box-shadow: inset
$link-hover-decoration-thickness
0px
0px
border-left: $link-hover-decoration-thickness
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bootstrap uses box-shadow for focus rings, so I changed the code here to use border-left instead of using a box shadow to draw a vertical line or notch on the left side of the link in the TOC that corresponds to the current page that the user is on.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this caused a small glitch, because the border has an actual width compared to the box-shadow?

Comparing the readthedocs preview of this PR vs the latest docs:

https://pydata-sphinx-theme.readthedocs.io/en/latest/user_guide/layout.html#templates-and-components:

image

And on the PR (https://pydata-sphinx-theme--1549.org.readthedocs.build/en/1549/user_guide/layout.html#templates-and-components):

image

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooh, good catch @jorisvandenbossche

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks for catching that! Follow up PR: #1561

solid
var(--pst-color-primary);
}
}
Expand Down Expand Up @@ -175,10 +171,3 @@ $link-hover-decoration-thickness: unquote("max(3px, .1875rem, .12em)") !default;
}
}
}

// Focus indicator
@mixin focus-indicator {
&:focus-visible {
outline: 2px solid var(--pst-color-accent);
}
}
10 changes: 10 additions & 0 deletions src/pydata_sphinx_theme/assets/styles/base/_base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,13 @@ pre {
background-color: var(--pst-color-secondary);
border: none;
}

// Focus ring
//
// Note: The Bootstrap stylesheet provides the focus ring (customized via Sass
// variables in _bootstrap.scss) in some cases. This rules covers all other
// cases.
:focus-visible {
outline: $focus-ring-outline;
box-shadow: none; // override Bootstrap
}
19 changes: 12 additions & 7 deletions src/pydata_sphinx_theme/assets/styles/components/_search.scss
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@
&:focus,
&:focus-visible {
border: none;
box-shadow: none;
outline: 3px solid var(--pst-color-accent);
Comment on lines -61 to -62
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new :focus-visible rule in the base stylesheet now provides this focus ring.

background-color: var(--pst-color-background);
color: var(--pst-color-text-muted);
}
Expand All @@ -75,11 +73,16 @@
align-items: center;
align-content: center;
color: var(--pst-color-text-muted);
// Needed to match other icons hover
padding: 0 0 0.25rem 0;
border-radius: 0;
border: none; // Override Bootstrap button border
font-size: 1rem; // Override Bootstrap button font size
Comment on lines +77 to +78
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For both the search button and the theme switcher button, I decided to go ahead and make them consistent with the other icons at the end of the nav bar.


// Override Bootstrap button padding-x. Whitespace in nav bar is controlled
// via column gap rule on the container.
padding-left: 0;
padding-right: 0;

@include icon-navbar-hover;
@include focus-indicator;

i {
font-size: 1.3rem;
Expand Down Expand Up @@ -136,19 +139,21 @@
* Lives at components/search-button-field.html
*/
.search-button-field {
$search-button-border-radius: 1.5em;
display: inline-flex;
align-items: center;
border: var(--pst-color-border) solid 1px;
border-radius: 1.5em;
border-radius: $search-button-border-radius;
color: var(--pst-color-text-muted);
padding: 0.5em;
background-color: var(--pst-color-surface);

&:hover {
border: 2px solid var(--pst-color-link-hover);
}

&:focus-visible {
border: 2px solid var(--pst-color-accent);
border-radius: $search-button-border-radius;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed to override a rule I added in _header.scss that slightly rounds the focus rings for the links in the header, but the search button we want the focus ring to "hug" its border, so the border-radius must match.

}

// The keyboard shotcut text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@
*/

.theme-switch-button {
// overide bootstrap settings
margin: 0 -0.5rem;
padding: 0; // We pad the `span` not the container
color: var(--pst-color-text-muted);
border-radius: 0;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now gets a rounded focus ring so I decided to remove this border-radius rule.

@include focus-indicator;
border: none; // Override Bootstrap button border
font-size: 1rem; // Override Bootstrap's button font size

// Override Bootstrap button padding-x. Whitespace in nav bar is controlled
// via column gap rule on the container.
padding-left: 0;
padding-right: 0;

&:hover {
@include icon-navbar-hover;
}

span {
display: none;
padding: 0.5em;

@include icon-navbar-hover;
&:active {
text-decoration: none;
color: var(--pst-color-link-hover);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ button.btn.version-switcher__button {
}

@include link-style-hover;
@include focus-indicator;
&:active {
color: var(--pst-color-text-base);
border-color: var(--pst-color-border);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@ nav.page-toc {
}
}
}

:focus-visible {
border-radius: 0.125rem;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In several places where we want the focus ring to be rounded at the corners, I use this rule. I only apply the border-radius rule on :focus-visible because if I apply it even when the element doesn't have focus, it will change the way borders appear, which will likely mess up other styles (for example, the vertical notch when the link corresponds to the current page that the user is on).

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
* Admonitions CSS originally inspired by https://squidfunk.github.io/mkdocs-material/getting-started/
*/
$admonition-border-radius: 0.25rem;
$admonition-left-border-width: 0.2rem;
div.admonition,
.admonition {
margin: 1.5625em auto;
padding: 0 0.6rem 0.8rem 0.6rem;
overflow: hidden;
page-break-inside: avoid;
border-left: 0.2rem solid;
border-left: $admonition-left-border-width solid;
border-color: var(--pst-color-info);
border-radius: $admonition-border-radius;
background-color: var(--pst-color-on-background);
Expand Down Expand Up @@ -226,7 +227,7 @@ div.admonition,
margin-top: 0;

// Undo the .sidebar directive border
border-width: 0 0 0 0.2rem;
border-width: 0 0 0 $admonition-left-border-width;

// TODO: these semantic-color-names border-color rules might no longer be
// needed when we drop support for Sphinx 4 / docutils 0.17
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,13 @@ div.highlight button.copybtn {
color: var(--pst-color-text);
background-color: var(--pst-color-surface);
}

&:focus {
// For keyboard users, make the copy button visible when focussed.
opacity: 1;
}

&:focus-visible {
outline: $focus-ring-outline;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ html[data-theme="light"] {
.sd-card-header {
background-color: var(--pst-color-panel-background);
border-bottom: 1px solid var(--pst-color-border);

&:focus-visible {
outline: $focus-ring-outline;
outline-offset: -$focus-ring-width;
}
}
.sd-card-footer {
background-color: var(--pst-color-panel-background);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,43 @@
button.toggle-button {
color: inherit;
}

// 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 {
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 {
content: "";
transform: translateX(
-$admonition-left-border-width
); // align left edges of admonition and ring
width: calc(100% + $admonition-left-border-width); // align right edges
height: 100%;
border: $focus-ring-outline;
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 {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
}
}

// Details buttons
Expand All @@ -16,5 +53,11 @@
summary {
border-left: 3px solid var(--pst-color-primary);
}

// When expanded, sharpen the bottom left and right corners of the focus ring
&[open] :focus-visible {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
}
}
6 changes: 4 additions & 2 deletions src/pydata_sphinx_theme/assets/styles/sections/_header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
padding-right: 1rem;
}

:focus-visible {
border-radius: 0.125rem;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want all of the focusable links and buttons in the header nav to have rounded corners, so I decided to use this blanket rule, but this means I have to override the border-radius for the search button.

I thought about writing this rule as:

:focus-visible:not(.search-button-field) {
  border-radius: 0.125rem;
}

But I noticed that this file has no other reference to anything search related. It's completely ignorant of the fact that it contains a search button, so I decided that it would be better to add an override rule in the search stylesheet rather than couple this stylesheet to the search button. Just to keep things separate.

}

// These items will define the height of the header
.navbar-item {
height: var(--pst-header-height);
Expand Down Expand Up @@ -99,7 +103,6 @@
color: var(--pst-color-text-muted);
border: none;
@include link-style-hover;
@include focus-indicator;
}

.dropdown-menu {
Expand Down Expand Up @@ -190,7 +193,6 @@
}
}
@include icon-navbar-hover;
@include focus-indicator;
}

// Hide the navbar header items on mobile because they're in the sidebar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
font-size: var(--pst-sidebar-font-size);
}

// Focus styles
:focus-visible {
border-radius: 0.125rem;
}

// override bootstrap when navlink are displayed in the sidebar
.nav-link {
font-size: var(--pst-sidebar-font-size-mobile);
Expand Down Expand Up @@ -80,6 +85,26 @@
border: none;
background-color: inherit;
font-size: inherit;

.dropdown-item {
&:hover,
&:focus {
// In the mobile sidebar, the dropdown menu is inlined with the
// other links, which do not have background-color changes on hover
// and focus
background-color: unset;
}
}
}
}

.bd-navbar-elements {
.nav-link {
&:focus-visible {
box-shadow: none; // Override Bootstrap
outline: $focus-ring-outline;
outline-offset: $focus-ring-width;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default focus ring for the links at the top of the mobile sidebar (under "Site Navigation") was hugging the edges too closely, so this rule just adds a gap, or offset.

}
}
}

Expand All @@ -93,7 +118,7 @@
.sidebar-header-items__end {
display: flex;
align-items: center;
gap: 0.5rem;
gap: 1rem;
}

@include media-breakpoint-up($breakpoint-sidebar-primary) {
Expand Down Expand Up @@ -171,8 +196,6 @@

/* Between-page links and captions */
nav.bd-links {
margin-right: -1rem;

Comment on lines -174 to -175
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't figure out why this rule was here but it was clipping the focus ring, so I removed it. I asked @12rambau if he could remember why he added it and if I could remove it, and he replied, "I guess the only way to find out is to remove it 😄"

@include media-breakpoint-up($breakpoint-sidebar-primary) {
display: block;
}
Expand Down
20 changes: 13 additions & 7 deletions src/pydata_sphinx_theme/assets/styles/sections/_skip-link.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***
* Rules for the UX/UI of skip navigation link btn.
*It's only visible to people
* Rules for the UX/UI of skip navigation link btn.
* It's only visible to people
* navigating with keyboard for accessibility purposes
* ref: https://www.youtube.com/watch?v=VUR0I5mqq7I
***/
Expand All @@ -12,18 +12,24 @@
right: 0;
text-align: center;
background-color: var(--pst-color-warning);
// Ensure we are using a WCAG conformant colour
color: var(--pst-color-warning-text) !important;
padding: 0.5rem;
z-index: $zindex-modal;
border-bottom: 1px solid var(--pst-color-border);

// This shows / hides the button
transform: translateY(-100%);
transition: transform 150ms ease-in-out;
&:focus {
&:focus-within {
transform: translateY(0%);
// ensure this is visible
outline: 3px solid $foundation-black;
}

a {
// Ensure we are using a WCAG conformant colour
color: var(--pst-color-warning-text) !important;

&:focus-visible {
// use color with sufficient contrast
outline-color: $foundation-black;
}
}
}
Loading