Skip to content

Instantly share code, notes, and snippets.

@bpmckee
Last active December 12, 2021 19:33
Show Gist options
  • Select an option

  • Save bpmckee/5f68bf1d0cd2ddff5f575d857ecb5d0c to your computer and use it in GitHub Desktop.

Select an option

Save bpmckee/5f68bf1d0cd2ddff5f575d857ecb5d0c to your computer and use it in GitHub Desktop.
A11y basics - 9. Screen Reader live region
<h1>Golf Scorecard</h1>
<p class="score">
You are at par
</p>
<div class="button-container">
<button data-offset="-1"
aria-labelledby="abc">
</button>
<span class="tooltip"
id="abc"
aria-hidden="true">
Lower score
</span>
</div>
<div class="button-container">
<div class="button"
data-offset="1"
tabindex="0"
role="button"
aria-labelledby="def">
</div>
<span class="tooltip"
id="def"
aria-hidden="true">
Increase score
</span>
</div>
<footer>
Triggering the button shouldn't have scrolled the page!
</footer>
import 'dart:html';
final buttons = querySelectorAll('.button,button');
final customButton = querySelector('.button')!;
final scoreEl = querySelector('.score')!;
var score = 0;
void main() {
buttons.onClick.listen(updateScore);
buttons.onMouseUp.listen(blur);
customButton.onKeyUp.listen(handleOnKeyUp);
customButton.onKeyDown.listen(handleOnKeyDown);
}
void handleOnKeyUp(KeyboardEvent event) {
var key = event.which ?? event.keyCode;
if (key == KeyCode.ENTER || key == KeyCode.SPACE) {
updateScore(event);
}
}
void handleOnKeyDown(KeyboardEvent event) {
var key = event.which ?? event.keyCode;
if (key == KeyCode.SPACE) {
event.preventDefault();
}
}
void updateScore(Event event) {
score += offset(event.target as HtmlElement);
scoreEl.text = scoreText();
}
int offset(HtmlElement element) =>
int.parse(element.attributes['data-offset']!);
String scoreText() {
if (score > 0) return 'You are $score above par';
if (score == 0) return 'You are at par';
return 'You are ${score.abs()} below par';
}
void blur(MouseEvent event) {
(event.target as HtmlElement).blur();
}
body {
background: #202124;
color: #FFF;
font-family: "Google Sans",Roboto,Arial,sans-serif;
font-size: 14px;
text-align: center;
}
button,
.button {
background: #8AB4F8;
color: #202124;
font-size: 14px;
font-weight: 500;
height: 36px;
min-width: 36px;
padding: 0 23px;
margin: 16px 4px;
display: inline-flex;
align-items: center;
justify-content: center;
border: 0;
border-radius: 4px;
font-family: inherit;
box-sizing: border-box;
}
button:hover,
.button:hover {
background: #D2E3FC;
cursor: pointer;
user-select: none;
}
button:focus,
.button:focus {
background: #D2E3FC;
outline: 0;
box-shadow: 0 0 0 5px rgba(255,255,255, 0.3);
}
p {
font-size: 18px;
}
.score {
color: #AECBFA;
color: #FDE293;
}
.button-container {
display: inline-block;
position: relative;
}
.tooltip {
position: absolute;
pointer-events: none;
background: #FFF;
color: black;
padding: 4px 8px;
border-radius: 4px;
top: -5px;
left: 50%;
transform: translate(-50%, -50%);
white-space: nowrap;
opacity: 0;
}
.tooltip:after {
content: '';
position: absolute;
top: 100%;
left: 50%;
margin-left: -8px;
width: 0;
height: 0;
border: 8px solid transparent;
border-top-color: #FFF;
}
button:hover + .tooltip,
.button:hover + .tooltip,
button:focus + .tooltip,
.button:focus + .tooltip {
animation: 1s ease 0s normal forwards 1 fadein;
opacity: 1;
}
button:focus + .tooltip,
.button:focus + .tooltip {
animation-duration: .3s;
}
@keyframes fadein{
0% { opacity:0; }
80% { opacity:0; }
100% { opacity:1; }
}
footer {
background: #F28B82;
color: #202124;
font-size: 24px;
display: block;
padding: 16px 32px;
margin: 550px auto 32px;
border-radius: 8px;
max-width: 80%;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment