retail-ui icon indicating copy to clipboard operation
retail-ui copied to clipboard

feat(Clickable): add new component

Open JackUait opened this issue 1 year ago • 2 comments

Проблема

Пользователям нужен компонент, который может выглядеть как кнопка или как ссылка, при этом под капотом у которого может быть любой тег: button, a и даже div, для тех случаев когда нужен внешний вид, но не нужна семантика. Например, когда сверху компонента есть <button> и внутрь нужно вложить нашу кнопку — в таком случае пригодится просто представление компонента без семантики и обработки событий, которую организуют <button> и <a>.

Решение

Создал компонент <Clickable>, который представляет из себя единый интерфейс доступа к внешнему виду и семантике кнопки и ссылки. Компонент основан на обсуждении из #2598 и задаче IF-959, а также ещё некоторых незадокументированных обсуждениях.

Идея: Я добавил два новых пропа: as и view. Они призваны отделить внешнее представление компонента от его семантики. Проп as позволяет задавать корневой тег, а проп view задаёт внешний вид контрола.

Изменения: Помимо нового компонента и пропов я внёс несколько изменений в API, которые призваны сделать его более удобным для пользователей, а также закрыл несколько параллельных задач

  1. Появился новый про rightIcon (IF-1450);
  2. Компонент не поддерживает DEFAULT_THEME и IE11. Я отказался от их поддержки, в пользу простоты кода, с учётом того, что в скором будущем мы планируем отказаться от их поддержки;
  3. Проп arrow теперь принимает 'left' | 'right', вместо boolean | 'left';
  4. У контрола расширился use в связи с тем, что он теперь хранит use'ы, которые ему достались от Button и Link;
  5. В <Clickable> нет скриншота со сбросом (reset) стилей, так как стили стали сбрасываться через all: unset, который не сбрасывает те стили, которые проверяются в скриншоте. Настолько сильно сбрасывать стили мне показалось избыточным, поэтому я не стал реализовывать эту логику в новом компоненте;
  6. Я убрал селектор по :enabled из стилей <ClickableButton>, так как только кнопка поддерживает этот псевдокласс. Он заменён на селектор по aria-disabled, там где это необходимо;
  7. Упростил логику и переписал <ComponentTable> в силу того, что он не умел работать с функциональными компонентами. Я удалил часть логики из <ComponentTable>, но она не использовалась ни в одном из тестируемых компонентов. После этого пришлось обновить несколько скриншотов, но на самих скриншотах ничего не изменилось, кроме того, что в некоторых местах пропали кавычки от <ComponentTable>, изменился порядок пропов, если в компонент передаётся children, а также стали выводиться все пропы, которые передаются в children.

Исправления/улучшения:

  1. На корень больше не прокидывается атрибут disabled (IF-1661). Вместо него прокидывается атрибут aria-disabled. Это позволяет фокусироваться на кнопке и сообщать пользователям скрин-ридеров, что она отключена. На замену HTML-состоянию disabled в стилях для состояния контрола disabled пришёл стиль pointer-events: none;
  2. Добавлена поддержка всех атрибутов кнопки и ссылки, включая aria-аттрибуты;
  3. Добавлен атрибут aria-live="assertive", который позволяет озвучивать текст в кнопке, если он поменялся по ходу работы приложения;
  4. Удалил старые скриншоты для <Link> и заменил их на более продвинутые скриншоты, которые используются в <ClickableLink>;
  5. Проп theme больше не падает на корневой тег (IF-1660);
  6. Компонент можно программно зафокусить (IF-638) — исправлено использованием :focus-visible;
  7. Подчёркивание у <Clickable as="a" view="button" отображается корректно (IF-521), но возможно этого бага в новой теме и не было, вероятно стоит просто закрыть IF-521 задачу;
  8. Добавлено состояние error для ссылки (IF-1651).

Итог: Перенёс всю логику из <Button> и <Link> в <Clickable>, объединил и дополнил тесты для компонентов (как скриншотные, так и интеграционные), написал документацию к новому компоненту.

Ссылки

IF-969, #2598, IF-1450, IF-1661, IF-1660, IF-638, IF-521, IF-1651

Чек-лист перед запросом ревью

  1. Добавлены тесты на все изменения ✅ unit-тесты для логики ✅ скриншоты для верстки и кросс-браузерности ⬜ нерелевантно

  2. Добавлена (обновлена) документация ✅ styleguidist для пропов и примеров использования компонентов ✅ jsdoc для утилит и хелперов ✅ комментарии для неочевидных мест в коде ⬜ прочие инструкции (README.md, contributing.md и др.) ⬜ нерелевантно

  3. Изменения корректно типизированы ✅ без использования any (см. PR 2856) ⬜ нерелевантно

  4. Прочее ✅ все тесты и линтеры на CI проходят ✅ в коде нет лишних изменений ✅ заголовок PR кратко и доступно отражает суть изменений (он попадет в changelog)

JackUait avatar Sep 14 '23 08:09 JackUait

  1. Концептуально хочется чтобы по умолчанию "Clickable" был просто button без каких либо стилей, чтобы в продуктах можно было выпилить "велосипеды Clickable"

mshatikhin avatar Mar 07 '24 08:03 mshatikhin

Концептуально хочется чтобы по умолчанию "Clickable" был просто button без каких либо стилей, чтобы в продуктах можно было выпилить "велосипеды Clickable"

Добавил view="custom", который позволяет сбросить стили. По умолчанию оставил view="button", думаю что лучше изменять это значение на основе фидбека от пользователей. Пока что кажется, что плавный переезд со старых компонентов круче, чем view="custom" по умолчанию

JackUait avatar Mar 10 '24 18:03 JackUait