Обратная связь
Точка и каретка
Две мельчайшие метки кита. Точка называет состояние объекта, каретка показывает,
что текст ещё поступает. Обе — метки без подписи, и потому обе берут
--tone-mark, а не --tone-ink.
Разметка
<span class="inst-badge"><span class="inst-dot"></span>в очереди</span>
<span class="inst-badge" data-tone="running"><span class="inst-dot"></span>идёт</span>
<span class="inst-badge" data-tone="ok"><span class="inst-dot"></span>готово</span>
<span class="inst-badge" data-tone="warn"><span class="inst-dot"></span>с замечаниями</span>
<span class="inst-badge" data-tone="error"><span class="inst-dot"></span>упало</span>
Использование
<!-- точка внутри носителя тона -->
<span class="inst-badge" data-tone="ok"><span class="inst-dot"></span>готово</span>
<!-- каретка в конце потокового текста -->
<span>Стриминг ответа<span class="inst-caret"></span></span>
| Что | Обязательно | Почему |
|---|---|---|
| Слово рядом с точкой | да | Точка без подписи — это цвет как единственный носитель, то есть дефект |
data-tone на точке или на её предке |
да | Точка не знает своего тона: она читает --tone-mark у ближайшего предка, который его поставил |
| Каретка вплотную к последнему знаку | да | Отбивка на просвет, 0.1em. Отодвинутая на пробел каретка показывает не туда |
Когда использовать
Точка:
| Используйте | Возьмите другое |
|---|---|
| Второй признак статуса рядом со словом | Статус без слова — бейдж целиком: одна точка не называет состояние |
| Метка фазы в строке очереди или шага | Число рядом с пунктом навигации — inst-nav-count |
| Индикатор «идёт» на месте, где нет места спиннеру | Ожидание без известной фазы — спиннер: у него есть роль status |
Каретка:
| Используйте | Возьмите другое |
|---|---|
| Текст, который печатается прямо сейчас, знак за знаком | Ожидание перед первым знаком — скелетон: каретка на пустом месте показывает курсор в никуда |
| Конец потокового вывода агента | Занятость всего вида — спиннер с подписью |
| Признак «ответ ещё не закончен» | Фаза объекта — точка со словом в бейдже |
Устройство
Точка
Круг в --size-dot (6px). Носитель второго признака состояния: цвет не
имеет права быть единственным носителем, поэтому статус ходит с точкой и
словом.
Каретка
Прямоугольник в высоту строки, мигающий ступенями. Это курсор терминала: он показывает точку, куда придёт следующий символ.
Разметка
<span>Стриминг ответа<span class="inst-caret"></span></span>
Три решения, каждое из которых легко сделать наоборот:
- Стоит вплотную к последнему знаку, отбивка на просвет (
0.1em). Каретка, отодвинутая на пробел, показывает не туда. - Мигает ступенями (
steps(2, start)). Плавное затухание читается как артефакт отрисовки. - Размер в
em:0.45emна1.05em. Каретка привязана к кеглю строки, в которой стоит, и не требует настройки под каждый размер текста.
Варианты
data-tone — один словарь на весь кит, и он закрыт.
| Тон | Значит | Точка |
|---|---|---|
| без атрибута | Ещё не начиналось | --text-faint |
data-tone="neutral" |
Явно нейтральное. Оно же исполняет роль info | Нейтральная |
data-tone="running" |
Идёт сейчас | Пульсирует: opacity 1 → 0.35 за 1.6с |
data-tone="ok" |
Успешно завершено | Тон успеха |
data-tone="warn" |
Завершено с замечаниями | Тон замечания |
data-tone="error" |
Упало | Тон отказа |
Поведение
Наследование тона
Точка не знает своего тона — она читает --tone-mark у ближайшего предка,
который его поставил. Поэтому data-tone ставится один раз на группу.
Разметка
<span class="inst-badge" data-tone="ok"><span class="inst-dot"></span>готово</span>
<span class="inst-dot" data-tone="error"></span>
Где стоит data-tone |
Когда так |
|---|---|
| На бейдже, строке очереди, шаге | Обычный случай. Точка наследует |
| На самой точке | Точка стоит отдельно, без обёртки, несущей тон |
Пульсация заводится не только от data-tone="running", но и от фазы
компонента: .inst-task[data-state="running"] и
.inst-step[data-state="running"] дают точке ту же анимацию. Список анимируемых
точек в src/motion.css обязан совпадать с этим — иначе часть из них
перестанет замедляться при prefers-reduced-motion.
Анимации
| Что | Как |
|---|---|
Пульсация точки running |
opacity 1 → 0.35 → 1 за 1.6с, --ease-in-out, бесконечно |
| Мигание каретки | opacity 0 на половине цикла, steps(2, start), 1с, бесконечно |
Правила
Так Точка всегда со словом
Два носителя признака. Читатель, не различающий тон, читает подпись.
Не так Точка в одиночку
Цветной кружок без подписи — это цвет как единственный носитель состояния, то есть дефект по закону кита.
Так Тон один раз на группу
data-tone на носителе; точка читает --tone-mark у предка. Дублировать
атрибут не нужно.
Не так Каретка на пустом месте
До первого знака она показывает курсор в никуда. Ожидание содержимого — это скелетон.
Доступность
| Цвет не единственный носитель | Точка всегда стоит рядом со словом. Точка без подписи — это цвет как единственный носитель, то есть дефект |
| Уменьшенное движение точки | Пульсация замедляется до 3с, а не гаснет: кит, вся работа которого — показывать занятость машины, обязан показывать её всегда |
| Уменьшенное движение каретки | Мигание выключается, каретка остаётся видимой (opacity: 1). Исключение из исключения: мигание не несёт информации о скорости, только о факте, а факт передаёт сама каретка |
| Режим принудительных цветов | Точка переживает сброс (forced-color-adjust: none) и переходит на Highlight, потому что несёт значение |
| Печать | Точка печатается, каретка — нет: мигающий курсор на бумаге не значит ничего |
| Размер | 6px — метка, а не цель нажатия. Нажимается строка целиком, не точка |
Настройка
--tone-mark, а не --tone-ink: у тона два передних плана, и брать надо
тот, что по работе.
| Переменная | Для чего | Порог |
|---|---|---|
--tone-ink |
Текст | 4.5:1 |
--tone-mark |
Метка без подписи | 3:1, и ещё против дорожки |
У статусов они совпадают, у акцента расходятся.
API
| Имя | Значение | Что делает |
|---|---|---|
| класс | ||
inst-dot | — | Точка состояния. Читает --tone-mark |
inst-caret | — | Каретка потокового текста |
| атрибут | ||
data-tone | — | neutral running ok warn error. Закрыт. Ставится на точке или на любом её предке |
| токен | ||
--size-dot | 6px | |
--radius-full | 999px | |
--tone-mark | var(--text-secondary) | |
--text-faint | light-dark(var(--n-7), var(--n-7)) | |
--accent-mark | light-dark(var(--a-4), var(--a-3)) | |
--ease-in-out | cubic-bezier(0.65, 0, 0.35, 1) | |
Почему кит устроен именно так — конституция · Открытый код под MIT, github.com/keshon/instrument