quarto-dev / quarto-cli

Open-source scientific and technical publishing system built on Pandoc.
https://quarto.org
Other
3.96k stars 326 forks source link

Implement some sort of accessible/text-alternative for callout icons or blocks (a11y issue) #726

Open batpigandme opened 2 years ago

batpigandme commented 2 years ago

I'd argue that the icons used in callout blocks are semantic icons, or (alternatively) that the blocks themselves are intended as "semantic" classes.

As such, I think there should be visually hidden, but accessible text for either the icons or the callout divs. Because the icons are used as background images, I think that of the accessibility techniques for semantic icons (link is from Font Awesome, but the same ideas apply), we'd probably want to use Bootstrap's .visually-hidden class anyhow—which is why I think it might make sense to add this to the divs, rather than just the icons (since it will then work with appearance="minimal" or icon=false).

I suppose the downside to this is that you'd only want it to apply to HTML, which might be cumbersome given the callouts are used in other formats. One alternative would be to supply an aria-label, though I think screen-reader support for them on things like <div>s and <span>s can be a bit inconsistent.

jjallaire commented 2 years ago

Could you provide an example of what the revised callout HTML would look like? I think it would be pretty easy to add this I just want to make sure we get the structure right. Note that you should also take a look at the revealjs HTML for callouts (and whether there is some reveal equivalent of .visually-hidden)

batpigandme commented 2 years ago

Outside of Bootstrap, .visually-hidden, .sr-only, etc. are pretty common classes for accessibility. For example, here's a pattern from one of the Deque University accessibility-training courses I've been taking that uses its own .visually-hidden to make <ins> and <del> (which have no semantic meaning to screen readers) accessible:

<head>
    <title>Sample web page>
        <style>
            .visually-hidden {
                position: absolute;
                clip: rect(0 0 0 0);
                border: 0;
                height: 1px;
                margin: -1px;
                overflow: hidden;
                padding: 0 width: 1px;
            }
        </style>
</head>

<body>
    <p>If you can't say something nice, don't say
        <del>
            <span class="visually-hidden">begin deleted text</span>
            nothing
            <span class="visually-hidden">end deleted text</span>
        </del>
        <ins>
            <span class="visually-hidden">begin inserted text</span>
            anything
            <span class="visually-hidden">end inserted text</span>
        </ins>
        at all.
    </p>
</body>

For callouts, I manually added a .visually-hidden <span> inside the notes on a quarto website page here. The html comes out:

<div class="callout-note callout callout-style-simple">
    <div class="callout-body d-flex">
        <div class="callout-icon-container">
            <i class="callout-icon"></i>
        </div>
        <div class="callout-body-container">
            <p><span class="visually-hidden">Note: </span> From here on out, if I use the term “Grid” it will be in
                reference to CSS Grid, despite the fact that other grid systems exist (such as Bootstrap’s native grid).
            </p>
        </div>
    </div>
</div>

It would be somewhat more complicated to add the text to the icon, due to the fact that its in the CSS as a background-image.

There are other CSS implementations of what are, in effect,.visually-hidden, e.g. the Improved sr-only by @ffoodd (Code Pen of same.

Deque (makers of axe, which powers most of the popular accessibility tools) has a Code Library of Accessibility Examples, and their CSS patterns uses the implementation below for .visually-hidden, which should work for reveal as well:

@charset "UTF-8";

.visuallyhidden {
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

See also their .Offscreen class from their pattern library on GitHub.

batpigandme commented 2 years ago

For callouts with captions, I couldn't add the .visually-hidden span inside of the callout (it messes up the caption rendering), so I added a begin and end point outside of the callout:

<p><span class="visually-hidden">Note: </span></p>
<div class="callout-note callout callout-style-simple callout-captioned">
  <div class="callout-header d-flex align-content-center">
    <div class="callout-icon-container">
      <i class="callout-icon"></i>
    </div>
    <div class="callout-caption-container flex-fill">
      Pro Tip
    </div>
  </div>
  <div class="callout-body-container callout-body">
    <p>Contents of my tip.</p>
  </div>
</div>
<p><span class="visually-hidden">End note.</span></p>

Live in webpage here.

jjallaire commented 2 years ago

Thank you! We will do something based on what you have provided here!