Skip to content

Commit

Permalink
Добавляет доку про роль timer (#4786)
Browse files Browse the repository at this point in the history
* Добавляет демку

* Обновляет текст

* Дописывает текст

* Добавляет начертание

* Улучшает демку

* Улучшает текст

* Вносит уточнения

* Удаляет лишнее

* Улучшает текст

* Уточняет детали

* Выделяет термин

* Улучшает текст, дополняет его

* Убирает ковычки из `<title>`

* Переписывает Как понять

* Исправляет очепятку

* Улучшает демку

* Удаляет лишний пробел

* Делает мелкие уточнения

* Удаляет комментарий

* Объединяет параграфы

* Добавляет видео с субтитрами
  • Loading branch information
TatianaFokina authored Nov 7, 2023
1 parent 7a35f29 commit 9139dc8
Show file tree
Hide file tree
Showing 4 changed files with 291 additions and 17 deletions.
222 changes: 222 additions & 0 deletions a11y/role-timer/demos/basic-timer/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Пример с простым таймером — timer — Дока</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap">
<style>
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}

html {
color-scheme: dark;
font-size: 16px;
}

body {
min-height: 100vh;
padding: 50px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #18191C;
font-family: "Roboto", sans-serif;
}

p {
margin: 7px 0;
font-size: 1rem;
line-height: 1.4;
}

h1 {
margin-bottom: 17px;
font-weight: 500;
font-size: 1.625rem;
}

.button {
display: block;
min-width: 210px;
border: 2px solid transparent;
border-radius: 6px;
padding: 9px 15px;
color: #000000;
font-size: 1.125rem;
font-weight: 300;
font-family: inherit;
transition: background-color 0.2s linear;
}

.button-aqua {
background-color: #10F3AF;
}

.button-pink {
background-color: #F498AD;
}

.button:hover {
background-color: #FFFFFF;
cursor: pointer;
transition: background-color 0.2s linear;
}

.button:focus-visible {
border: 2px solid #FFFFFF;
outline: none;
}

.button:focus {
border: 2px solid #FFFFFF;
outline: none;
}

.timer, .timer-controls {
display: flex;
}

.timer {
gap: 130px;
}

.timer-controls {
align-items: center;
flex-wrap: wrap;
margin-top: 30px;
gap: 20px;
}

.timer__item {
position: relative;
font-size: 6.25rem;
line-height: 1;
}

.timer__item--min::after,
.timer__item--sec::after {
bottom: 11px;
padding-left: 20px;
font-size: 1.375rem;
}

.timer__item--min::after {
content: "минут";
position: absolute;
}

.timer__item--sec::after {
content: "секунд";
position: absolute;
}

.timer-message {
height: 22px;
margin-top: 10px;
}

@media (max-width: 768px) {
body {
padding: 30px;
}

.timer {
gap: 60px;
}

.timer__item--min::after,
.timer__item--sec::after {
left: 0;
bottom: -20px;
padding-left: 0;
}

.timer-message {
margin-top: 50px;
}
}
</style>
</head>
<body>
<div>
<h1>Оставшееся время</h1>
<div role="timer" class="timer" id="timer" aria-atomic="true">
<span class="timer__item timer__item--min" id="min">02</span>
<span class="timer__item timer__item--sec" id="sec">00</span>
</div>
<div class="timer-message" id="message" aria-live="polite"></div>

<div class="timer-controls">
<button class="button button-aqua" id="start-button">
Старт
</button>
<button class="button button-pink" id="pause-button">
Пауза
</button>
</div>
</div>

<script>
const startButton = document.getElementById('start-button')
const pauseButton = document.getElementById('pause-button')
const timer = document.getElementById('timer')
const minute = document.getElementById('min')
const seconds = document.getElementById('sec')
const message = document.getElementById('message')

let interval
let totalSeconds = 120

function setAriaLive() {
timer.setAttribute('aria-live', 'polite')
setTimeout(() => {
timer.removeAttribute('aria-live')
}, 100)
}

startButton.addEventListener('click', () => {
startTimer()
})

pauseButton.addEventListener('click', () => {
pauseTimer()
})

function pauseTimer() {
clearInterval(interval)
}

function startTimer() {
message.textContent = ''

interval = setInterval(() => {
--totalSeconds
let currentMinutes = String(Math.floor(totalSeconds / 60)).padStart(2, '0')
let currentSeconds = String(totalSeconds % 60).padStart(2, '0')

minute.textContent = currentMinutes
seconds.textContent = currentSeconds

if (totalSeconds === 119 || totalSeconds === 60 || totalSeconds === 10) {
setAriaLive()
}

if (totalSeconds === 0) {
clearInterval(interval)
message.textContent = 'Время вышло!'
totalSeconds = 120
minute.textContent = '02'
seconds.textContent = '00'
}
}, 1000)
}
</script>
</body>
</html>
66 changes: 49 additions & 17 deletions a11y/role-timer/index.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,81 @@
---
title: "`timer`"
description: "Роль для области со счётчиком."
description: "Отсчитываем время доступно."
authors:
- doka-dog
- tatianafokina
contributors:
- skorobaeus
keywords:
- доступность
- a11y
- ARIA
- ARIA-атрибут
- доступный таймер
- доступный секундомер
- live region
- живая область
- интерактивная область
related:
- a11y/role-status
- a11y/role-alert
- a11y/aria-live
tags:
- doka
- placeholder
---

## Кратко

[Роль изменяющихся областей](/a11y/aria-roles/#roli-izmenyayushchihsya-oblastey). Делает часть страницы live region или «живой» областью. `timer` нужна для областей со счётчиками, которые отсчитывают время в обычном или обратном порядке.
[Роль изменяющихся областей](/a11y/aria-roles/#roli-izmenyayushchihsya-oblastey) из [WAI-ARIA](/a11y/aria-intro/#specifikaciya). Делает часть страницы изменяющейся или «живой» областью. `timer` пригодится для областей, где идёт отсчёт времени в обычном или обратном порядке.

## Пример

```html
<div id="clock" role="timer" aria-live="polite">
<span id="clock-hours"></span>
<span id="clock-mins"></span>
<div role="timer">
<span id="timer-hours">00</span>
<span id="timer-mins">00</span>
</div>
```

## Как пишется

Добавьте к тегу атрибут `role="timer"`. Роль можно использовать для всех тегов.
Добавьте к элементу атрибут `role="timer"`. Роль можно использовать для всех тегов и [ARIA-ролей](/a11y/aria-roles/).

У `timer` по умолчанию есть свойство [`aria-live="off"`](/a11y/aria-live/).
Внутри контейнера с ролью таймера не обязательно использовать [`<time>`](/html/time/) и указывать время в машиночитаемом формате. Это могут быть обычные цифры и текст.

[Скринридер](/a11y/screenreaders/) объявит об изменениях в области с `timer` после завершения пользователями действий со страницей и другой информации.
По умолчанию у `timer` есть свойство [`aria-live="off"`](/a11y/aria-live/). Так что [скринридеры](/a11y/screenreaders/) не расскажут об изменениях до того, как пользователь сделает на фокус на области с этой ролью.

Чтобы скринридер объявлял об изменениях через определённый интервал времени, используйте [JavaScript](/js/). Для этого переключайте значение `aria-live` c `off` на `polite` через нужный промежуток времени. Например, каждые 60 минут.
Чтобы изменить поведение роли, используйте `aria-live` со значением `polite` и [JavaScript](/js/). Переключайте значение c `polite` на `off` или удаляйте весь атрибут через нужные интервалы времени. Например, каждые 60 минут. Так объявления не будут навязчивыми. В большинстве случаев лучше не изменять поведение `timer`. Например, постоянно рассказывать о том, сколько часов, минут и секунд осталось до Чёрной пятницы, — не самая лучшая идея. Пользователям скринридеров будет мучительно это слушать 😫 Другое дело — отсчёт времени до конца теста или на выполнение банковской операции. В этом случае пользователям важно знать, сколько у них осталось времени.

## Как понять
Атрибут [`aria-atomic="true"`](/a11y/aria-busy/) поможет улучшить таймер. Благодаря ему вспомогательные технологии расскажут про всё содержимое таймера, а не только про изменившиеся часы, секунды или минуты. Например, таймер отсчитывает две минуты в обратном направлении. Когда остаётся 59 секунд, без `aria-atomic` скринридер расскажет только о минутах: «Ноль минут». Так что пользователи могут подумать, что время вышло, хотя у них осталась ещё пара секунд. Чтобы объявления не были назойливыми, устанавливайте интервалы между объявлениями. Это удобно делать [функцией `setInterval()`](/js/setinterval/). Так можно добавлять и удалять `aria-live="true"` через нужные промежутки времени.

В примере элементу, в котором отсчитывается время, заданы `role="timer"` и `aria-atomic="true"`. После того, как время вышло, появляется сообщение «Время вышло!». `aria-live` удаляется и добавляется через секунду после начала отсчёта, потом через минуту и затем за 10 секунд до завершения.

Подсказки про то, минуты это или секунды, добавлены с помощью псевдоэлемента [`::after`](/css/after/) и [`content`](/css/content/). Скринридеры всегда зачитывают текст из этого CSS-свойства.

«Живая» область — это область страницы, в которой что-то постоянно обновляется из-за внешних событий. Например, появляется уведомление или ошибка, когда пользователь сделал что-то неправильно. Так пользователи скринридеров могут узнать об изменениях автоматически, без перехода к этой части страницы.
```html
<h2>Оставшееся время</h2>
<div
role="timer"
id="timer"
aria-atomic="true"
>
<span id="min">02</span>
<span id="sec">00</span>
</div>
<div id="message" aria-live="polite"></div>
```

<iframe title="Таймер с ролью timer" src="demos/basic-timer/" height="500"></iframe>

<video controls width="640">
<source src="video/role-timer.mp4" type="video/mp4">
<track
label="Russian"
kind="subtitles"
srclang="ru"
src="video/closed-captions.vtt"
>
</video>
Элементам с `role="timer"` можно задавать подписи. Для видимой подойдёт атрибут [`aria-labelledby`](/a11y/aria-labelledby/), а для невидимой — [`aria-label`](/a11y/aria-label/). Только помните, что хоть на практике и можно добавлять подписи ко всем элементам, спецификация не рекомендует подписывать [`<div>`](/html/div/), [`<span>`](/html/span/) и другие неинтерактивные элементы.

## Как понять

Роль `timer` часто используют для таймеров.
_Изменяющаяся область_ — это область страницы, в которой содержимое обновляется из-за внешних событий или действий пользователей. Благодаря изменяющимся областям вспомогательные технологии узнают об обновлениях на странице и автоматически рассказывают о них пользователям.
20 changes: 20 additions & 0 deletions a11y/role-timer/video/closed-captions.vtt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
WEBVTT
00:00:00.001 --> 00:00:01.134
(NVDA)
Старт, кнопка.

00:00:02.253 --> 00:00:07.404
Ноль-один минут,
пятьдесят девять секунд.

00:00:12.833 --> 00:00:15.021
Ноль-один минут,
ноль-ноль секунд.

00:00:20.004 --> 00:00:22.214
Ноль-ноль минут,
десять секунд.

00:00:30.047 --> 00:00:31.370
Время вышло!
Binary file added a11y/role-timer/video/role-timer.mp4
Binary file not shown.

0 comments on commit 9139dc8

Please sign in to comment.