Отображение данных
Код и копируемое значение
Блок кода и однострочное значение, которое хочется скопировать: путь, хеш, идентификатор.
Разметка
<div class="inst-code">go -C tools run ./cmd/contrast</div>
Использование
<div class="inst-code">go -C tools run ./cmd/contrast</div>
| Что | Обязательно | Почему |
|---|---|---|
tabindex="0" и role="region" с именем |
да, если внутри нет фокусируемого | Блок прокручивается по горизонтали, и до прокрутки надо добраться с клавиатуры |
aria-label со значением у кнопки копирования |
да | Ряд кнопок «Скопировать» на слух неразличим: «Скопировать a4f7c2e» |
aria-live="polite" на области сообщения |
да | Смена иконки для скринридера — событие без содержания |
Переноса строк в блоке кода нет намеренно: перенос в команде меняет её смысл.
Отсюда горизонтальная прокрутка, а scrollbar-gutter зарезервирован, чтобы
появление полосы не сдвигало код на пиксель при каждом обновлении.
Когда использовать
| Используйте | Возьмите другое |
|---|---|
| Команда, фрагмент конфига, разметка | Поток строк от машины — лог: у него колонки уровня и времени |
| Значение, которое понадобится вставить в другом месте | Изменения в файле — диф |
| Однострочный идентификатор рядом с текстом | Редактируемое значение — поле ввода с readonly |
Варианты
Копируемое значение
Однострочное значение с кнопкой — хеш, идентификатор, путь.
Разметка
<span class="inst-copyable">a4f7c2e
<button class="inst-copy" type="button" aria-label="Скопировать a4f7c2e">
<svg class="inst-icon inst-icon--sm" aria-hidden="true"><use href="#i-copy"/></svg>
</button>
</span>
Кнопка стоит в потоке, с просветом, и видна всегда. Абсолют в углу с проявлением по наведению — приём блока кода: там угол свободен и текста много. У однострочного значения угла нет, и значок ложился на последние символы, а на касании его не было вовсе, потому что наведения на касании не бывает.
Область нажатия у кнопки растёт до нормы невидимым ::before — тем же приёмом,
что у флажка: растёт область, а не значок, и строка остаётся прежней высоты.
inst-code |
inst-copyable |
|
|---|---|---|
| Сколько строк | Сколько угодно | Одна |
| Прокрутка | По горизонтали | Нет |
| Кнопка | Нет | Есть |
| Пример | Команда, конфиг | Хеш, путь, идентификатор |
JS
Подключите модуль один раз на страницу — инициализировать компоненты по отдельности не нужно, кит работает делегированием и видит узлы, пришедшие позже.
<script type="module" src="src/kit.js"></script>
Что делает кит
Примеры на этой странице живые: наведите на блок кода и нажмите кнопку копирования — значок сменится на галку.
Копирование целиком: текст в буфер, цветной ответ на кнопке и объявление результата вслух. Ответ обязателен — буфер обмена ничего не показывает, и без него человек жмёт кнопку второй раз.
Источник — текст ближайшего .inst-code или .inst-copyable без самой
кнопки. Читается textContent, а не innerText: второй у свёрнутого блока
возвращает пустую строку, и копирование ушло бы в ничто беззвучно.
Опции
| Атрибут | Что делает |
|---|---|
data-copy |
Копировать это значение, а не текст блока. Нужно, когда видно сокращение, а копировать надо полное |
data-copied-label |
Своя фраза для скринридера вместо «Скопировано» |
data-failed-label |
То же для неудачи. По умолчанию «Не удалось скопировать» |
<span class="inst-copyable">a4f7c2e
<button class="inst-copy" type="button" data-copy="a4f7c2e91b0d5537"
aria-label="Скопировать полный хеш"></button>
</span>
События
inst:copy всплывает с { text } и отменяем: preventDefault() означает
«копирую сам», и кит не трогает буфер.
document.addEventListener('inst:copy', (e) => {
analytics.track('copy', { length: e.detail.text.length });
});
Чего кит не делает
Подсветку синтаксиса. Она требует разбора языка, и это работа приложения.
Правила
Так Имя кнопки со значением
«Скопировать a4f7c2e». Десять кнопок «Скопировать» подряд на слух не различаются.
Не так Подтверждение только иконкой
Смена глифа для скринридера — событие без содержания. Нужен aria-live.
Так Горизонтальная прокрутка вместо переноса
Перенос в команде меняет её смысл. Прокрутка обязана быть достижима с клавиатуры.
Не так Блок кода для потока от машины
Строки от процесса — лог: у него колонки уровня и времени и своё поведение.
Доступность
| Прокрутка | Блок прокручивается по горизонтали, поэтому обязан быть достижим с клавиатуры: tabindex="0" и role="region" с именем, если внутри нет фокусируемого |
scrollbar-gutter |
Зарезервирован, чтобы появление полосы не сдвигало код на пиксель при каждом обновлении |
| Имя кнопки копирования | aria-label со значением: «Скопировать a4f7c2e». Ряд кнопок «Скопировать» на слух неразличим |
| Результат копирования | Кит меняет вид кнопки, но подтверждение обязано быть и словом: aria-live="polite" на области сообщения. Смена иконки для скринридера — событие без содержания |
| Перенос строк | В блоке кода его нет намеренно: перенос в команде меняет её смысл. Отсюда горизонтальная прокрутка |
| Кегль | --text-xs — 12px. Ниже --text-2xs кит не опускается |
API
| Имя | Значение | Что делает |
|---|---|---|
| класс | ||
inst-code | — | Блок кода. Прокручивается по горизонтали |
inst-copyable | — | Однострочное значение с кнопкой |
inst-copy | — | Кнопка копирования. Работу выполняет [kit.js](../../foundations/behavior.md) |
| атрибут | ||
data-copy | — | Копировать это значение, а не текст блока |
data-copied-label | — | Своя фраза для скринридера вместо «Скопировано» |
data-failed-label | — | То же для неудачи. По умолчанию «Не удалось скопировать» |
data-copied | true · false | Ответ кнопки. Ставит и снимает кит |
| токен | ||
--surface-sunken | light-dark(var(--n-2), var(--n-14)) | |
--border-subtle | light-dark(oklch(0 0 0 / 0.07), oklch(1 0 0 / 0.06)) | |
--hairline | 1px | |
--radius-md | 7px | |
--space-4 | 8px | |
--pad-panel | var(--space-5) | |
--text-xs | 0.75rem | |
--font-mono | ui-monospace, "Cascadia Code", "JetBrains Mono", "SF Mono", Consolas, "Liberation Mono", monospace | |
Почему кит устроен именно так — конституция · Открытый код под MIT, github.com/keshon/instrument