Перейти к содержимому
Плотность
Тема

Отображение данных

Код и копируемое значение

JS Копирование в буфер — делает кит

Блок кода и однострочное значение, которое хочется скопировать: путь, хеш, идентификатор.

Компонент
go -C tools run ./cmd/contrast
Разметка
<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

Варианты

Копируемое значение

Однострочное значение с кнопкой — хеш, идентификатор, путь.

Пример
a4f7c2e
Разметка
<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-copiedtrue · falseОтвет кнопки. Ставит и снимает кит
токен
--surface-sunkenlight-dark(var(--n-2), var(--n-14))
--border-subtlelight-dark(oklch(0 0 0 / 0.07), oklch(1 0 0 / 0.06))
--hairline1px
--radius-md7px
--space-48px
--pad-panelvar(--space-5)
--text-xs0.75rem
--font-monoui-monospace, "Cascadia Code", "JetBrains Mono", "SF Mono", Consolas, "Liberation Mono", monospace

Почему кит устроен именно так — конституция · Открытый код под MIT, github.com/keshon/instrument