Andrew
2024-08-09 27a41abb62cc9005ed4234bdb02f38b6cfeedec3
feat(toc,explorer): add accessibility for toggle (#1327)

* Restore focus highlight on explorer toggle button.

Remove `unset: all` declaration causing `outline`
property to be unset. This allows the default
browser focus highlight to be shown.

* Fix semantics of expandable sections (explorer, toc).

This adds the appropriate aria attributes for the [disclosure pattern](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-image-description/#javascriptandcsssourcecode) and uses `visibility: hidden` to remove the hidden elements from the focus order without disrupting the animations. Further work is needed on the tree view nodes.

* Run prettier for SCSS files.
6 files modified
43 ■■■■■ changed files
quartz/components/Explorer.tsx 2 ●●●●● patch | view | raw | blame | history
quartz/components/TableOfContents.tsx 8 ●●●● patch | view | raw | blame | history
quartz/components/scripts/explorer.inline.ts 4 ●●●● patch | view | raw | blame | history
quartz/components/scripts/toc.inline.ts 4 ●●●● patch | view | raw | blame | history
quartz/components/styles/explorer.scss 13 ●●●● patch | view | raw | blame | history
quartz/components/styles/toc.scss 12 ●●●●● patch | view | raw | blame | history
quartz/components/Explorer.tsx
@@ -91,6 +91,8 @@
          data-collapsed={opts.folderDefaultState}
          data-savestate={opts.useSavedState}
          data-tree={jsonTree}
          aria-controls="explorer-content"
          aria-expanded={opts.folderDefaultState === "open"}
        >
          <h2>{opts.title ?? i18n(cfg.locale).components.explorer.title}</h2>
          <svg
quartz/components/TableOfContents.tsx
@@ -26,7 +26,13 @@
  return (
    <div class={classNames(displayClass, "toc")}>
      <button type="button" id="toc" class={fileData.collapseToc ? "collapsed" : ""}>
      <button
        type="button"
        id="toc"
        class={fileData.collapseToc ? "collapsed" : ""}
        aria-controls="toc-content"
        aria-expanded={!fileData.collapseToc}
      >
        <h3>{i18n(cfg.locale).components.tableOfContents.title}</h3>
        <svg
          xmlns="http://www.w3.org/2000/svg"
quartz/components/scripts/explorer.inline.ts
@@ -17,6 +17,10 @@
function toggleExplorer(this: HTMLElement) {
  this.classList.toggle("collapsed")
  this.setAttribute(
    "aria-expanded",
    this.getAttribute("aria-expanded") === "true" ? "false" : "true",
  )
  const content = this.nextElementSibling as MaybeHTMLElement
  if (!content) return
quartz/components/scripts/toc.inline.ts
@@ -16,6 +16,10 @@
function toggleToc(this: HTMLElement) {
  this.classList.toggle("collapsed")
  this.setAttribute(
    "aria-expanded",
    this.getAttribute("aria-expanded") === "true" ? "false" : "true",
  )
  const content = this.nextElementSibling as HTMLElement | undefined
  if (!content) return
  content.classList.toggle("collapsed")
quartz/components/styles/explorer.scss
@@ -1,7 +1,6 @@
@use "../../styles/variables.scss" as *;
button#explorer {
  all: unset;
  background-color: transparent;
  border: none;
  text-align: left;
@@ -46,8 +45,18 @@
  list-style: none;
  overflow: hidden;
  max-height: none;
  transition: max-height 0.35s ease;
  transition:
    max-height 0.35s ease,
    visibility 0s linear 0s;
  margin-top: 0.5rem;
  visibility: visible;
  &.collapsed {
    transition:
      max-height 0.35s ease,
      visibility 0s linear 0.35s;
    visibility: hidden;
  }
  &.collapsed > .overflow::after {
    opacity: 0;
quartz/components/styles/toc.scss
@@ -29,8 +29,18 @@
  list-style: none;
  overflow: hidden;
  max-height: none;
  transition: max-height 0.5s ease;
  transition:
    max-height 0.5s ease,
    visibility 0s linear 0s;
  position: relative;
  visibility: visible;
  &.collapsed {
    transition:
      max-height 0.5s ease,
      visibility 0s linear 0.5s;
    visibility: hidden;
  }
  &.collapsed > .overflow::after {
    opacity: 0;