Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Button use="link" ломает верстку в тексте с переносами #1728

Closed
d-hand opened this issue Nov 12, 2019 · 12 comments

Comments

@d-hand
Copy link
Contributor

d-hand commented Nov 12, 2019

<Button use="link" />` ломает верстку в тексте с переносами.

Есть такой компонент, который раскрывается/скрывается по клику

1

При попытке использовать <Button use="link" /> ломается верстка

2

Пытался обернуть текст в кнопке и навесить класс white-space: normal;

3

Перенос починился, но выравнивание по центру и все ломает.
<Button align={"left"} ... /> не помогает.

  • Библиотека @skbkontur/react-ui": "1.3.0"
  • Браузер chrome 71
  • ОС Windows 10;

Кажется, что <Button use="link" /> должен вести себя точно также как <Link />

@d-hand d-hand changed the title Button use="link" ломает верстку в инлайновом контексте с переносами Button use="link" ломает верстку в тексте с переносами Nov 12, 2019
@wKich
Copy link
Contributor

wKich commented Nov 12, 2019

В компоненте Button для класса caption указан стиль white-space: nowrap;, а выравнивание по центру происходит из-за стиля text-align: center; в классе root.

Кажется что ничего не мешает нам для кнопки-ссылки поменять white-space и text-align на соответствующие тому как должны отображаться ссылки.

Нужно иметь в виду что если мы изменим для кнопки с use="link" выравнивание по левому краю, что с точки зрения логики является более правильным, так как именно таким образом должны вести себя ссылки. То мы сломаем верстку в проектах, которые каким-то образом завязались на выравнивание таких кнопок по центру. Нужно не забыть отразить этот в Changelog

@dzekh
Copy link
Contributor

dzekh commented Nov 14, 2019

Да, она по идее тут инлайн элементом должна становиться, и ей тогда, так же как инлайн элементу нельзя будет задать определенную ширину, и она должна будет наследовать параметры текста в который она вставляется — если текст выровнен по левому краю — она по левому, если по центру — она по центру.

Может сделаем новый проп use="inline"?

@lossir
Copy link
Member

lossir commented Nov 14, 2019

Мне кажется ошибочным, что свойство use содержит значение, влияние которого серьёзно отличается от всех других значений.
Обсуждали устно с @wKich, он предложил, как вариант, добавить отдельный проп:

<Button link />

@dzekh
Copy link
Contributor

dzekh commented May 19, 2020

@d-hand Еще актуально? Вы как-то вышли из этой ситуации?

@dzekh
Copy link
Contributor

dzekh commented May 26, 2020

Можно закрыть?

@zhzz
Copy link
Member

zhzz commented Sep 18, 2020

Мне кажется мы так и не определились, что такое все-таки этот <Button use="link" />:

  • либо это кнопка, которая просто выглядит как ссылка, но не наследует размер шрифта и не переносит текст внутри себя;
  • либо это ссылка, которая ведет себя как настоящая ссылка, просто с элементом <button /> внутри для семантики;

Второй кейс выглядит так, как будто бы он должен реализовываться в компоненте <Link />, а не <Button />.

@d-hand
Copy link
Contributor Author

d-hand commented Sep 18, 2020

Ох... Это так давно было, что я забыл про эту багу... Чтобы обойти проблему мы стали использоваться Link вместо Button, но кажется, это неправильно, потому что нет href. Поэтому создали эту багу.

@JackUait
Copy link
Contributor

JackUait commented Oct 19, 2021

Предисловие

Считаю, что в данном случае действительно должен использоваться контрол Button, а не Link, ссылаясь на шестой пункт гайдов для ссылки, а также на доклад Вадима Макеева. Из этого доклада нас интересуют слова:

Это всегда кнопка, если вы понимаете, что вам чего-то не хватает, то это - ссылка.

В другом своём докладе Вадим Макеев ругается на пустые ссылки и рассказывает, почему пустые ссылки - это плохо.

Выжимка из сказанного в этом докладе: ссылка с атрибутом href - это интерактивный элемент (согласно вечнозелёной документации HTML), а ссылка без href - это пустая ссылка, ссылка, которая никуда ни ведёт, другими словами, это обычный текст, и, следовательно такая "ссылка" уже не является интерактивным элементом.

Пример

Если использовать контрол Link без атрибута href, то получим результат который видим на скриншоте:

Поведение контрола Link

Разберём увиденное сверху вниз:

  1. У ссылки есть подчёркивание, это хорошо, так как у ссылки при наведении (в общем случае) должно быть подчёркивание.
  2. У контрола Link нет явно указанного атрибута href, ага, значит этот элемент не ссылка, а обычный текст (в чём нас убеждает пример из скриншота ниже). Получается, что поведение из первого пункта некорректно и у ссылки не должно быть подчёркивания.

Снимок экрана 2021-10-19 в 09 51 52

  1. Но когда мы доходим до DOM'а, то видим, что у элемента ссылки всё же присутствует атрибут href, несмотря на то, что мы его явно не задавали во втором пункте. Следовательно это баг в библиотеке, из-за которого в ссылку передаётся атрибут href, даже если он не был передан в контрол Link.

Из сказанного выше можно сделать несколько выводов

  1. Контрол Link не должен быть использован в качестве кнопки.
  2. Контрол Link неявно добавляет href к ссылке, даже если атрибут href не был передан контролу Link, тем самым делая любую ссылку интерактивным элементом. Но из прочитанного выше становится очевидно, что такое поведение не является правильным, так как не любая ссылка это интерактивный элемент.
    Решение: добавлять атрибут href элементу ссылки, только в том случае, если он действительно был передан.
  3. В гайдах для ссылки нет пункта для случая, когда ссылка никуда ни ведёт, возможно стоит добавить пункт с описанием этого поведения в гайд. Что скажешь @dzekh?

Замечание

Как отметил @wKich, нужно не забывать что эти изменения являются ломающими, чтобы не забыть пометить их соответствующим образом при релизе.

@zhzz
Copy link
Member

zhzz commented Oct 19, 2021

@JackUait, спасибо за погружение в проблему и стремление помочь!

Есть еще несколько нюансов, которые следует учесть:

  1. У компонента <Link /> помимо href есть еще проп onClick. Т.е. он может быть интерактивным в отсутствии href.
  2. По моему мнению, <Button use="link" /> не должен копировать поведение обычной ссылки, только внешний вид. А такие вещи как размеры, отступы, выравнивание и перенос текста должно сохраняться от Button. Иначе какой смысл использовать именно Button? В том же пункте 6 есть пометка про кликабельную область ссылки-кнопки. Но тут можно поспорить. Нужно понять, для чего вообще создавался этот use="link" и когда он нужен.
  3. Гайды все-таки допускают использование ссылок для запуска неосновных действий. И иногда при этом требуется сохранить inline-поведение ссылки и наследование стиля текста (как в этом issue). Для этого можно предусмотреть использование тега <button /> внутри компонента <Link />, чтобы удовлетворить стилям и семантике.

Т.е. я лично склоняюсь к тому, чтобы различать <Button use="link" /> и <Link />. Можно добавить в каждый что не хватает и использовать по назначению. Но думаю, что Button должен всегда оставаться инлайн-блочным с размерами и прочим, а Link - инлайновым.

@JackUait
Copy link
Contributor

JackUait commented Oct 29, 2021

Иначе какой смысл использовать именно Button?

На уровне семантики тег <button/> предназначен для обработки события клика, а тег <a/> предназначен для перехода на ресурс указанный в href, поэтому браузеры, вспомогательные устройства и поисковые системы воспринимают их по-разному.

Ссылка не должна быть способна производить основное действие. Основное действие ссылки - это переход на ресурс указанный в href.

Вот лишь часть проблем, с которыми мы столкнёмся использовав ссылку, вместо кнопки:

  1. Если в тег <a/> не передан href это вызовет проблемы у пользователей пользующихся скрин-ридерами.
  2. Поисковые системы не любят ссылки, которые никуда не ведут и расценивают большое количество пустых ссылок (так как пустые ссылки рендерятся в обычный текст) на странице как нечестный способ SEO продвижения и наоборот занижают такую страницу в поисковой выдаче.

Различия в восприятии тегов <a/> и <button/> браузерами:

  1. При клике на тег <a/> правой кнопкой мыши вызывается интерфейс, позволяющий произвести дополнительные действия с ссылкой, такие как: открытие в новой вкладке, сохранение ссылки или отправка ссылки на устройство.
    Клик правой кнопкой мыши на тег <button/> равен клику по пустому месту страницы.
  2. При наведении на тег <a/> браузер слева снизу указывает адрес из href.
    Так как у тега <button/> нет атрибута href браузеру нечего выводить слева снизу.

У компонента помимо href есть еще проп onClick.

Не уверен, что это пример хорошего дизайна, из-за причин описанных выше.
Не вижу ничего плохого в том, чтобы ссылка обрабатывала дополнительное действие (особенно в контексте SPA/SSR), но только в том случае, если это действие дополнительное, а не основное, потому что основное действие у ссылки - это переход по адресу указанному в href, иначе это не ссылка, а кнопка.

При попытке использовать контрол Link в качестве кнопки должна быть выброшена ошибка, сообщающая о том, что для использования onClick в контрол Link также должен быть передан проп href, иначе (если нет ссылки, которую можно прокинуть) предлагать использовать контрол Button.

Сообщение об ошибке может выглядеть так:

Основное действие контрола Link - переход по ссылке указанной в href. В контроле Link проп onClick обрабатывает дополнительное действие. Если вы хотите обрабатывать основное действие в onClick - воспользуйтесь контролом Button.



Для этого можно предусмотреть использование тега <button /> внутри компонента <Link />, чтобы удовлетворить стилям и семантике.

На первый взгляд это хорошее решение, но тег <button/> не может быть вложен в тег <a/>.
Если отправить код ниже на проверку в валидатор, то мы получим ошибку: "The element button must not appear as a descendant of the a element". Если не ошибаюсь, даже React предупреждает, что такие штуки незаконны.

 <a href="www.test.com">
   <button>simple button</button>
 </a>

Можно добавить в каждый что не хватает и использовать по назначению.

Да, отличная идея, нужно продумать API обоих компонентов, часть нехватающего API для контрола Link я уже описал в #2594. Намедни подумаю над тем, что можно сделать с API контрола Button относительно контрола Link и наоборот.

@zhzz
Copy link
Member

zhzz commented Nov 26, 2021

Еще кейс про ширину и text-overflow, которые не работают для use="link".

@dzekh
Copy link
Contributor

dzekh commented Jul 7, 2022

Надеюсь что эта проблема решится в рамках 2598

@dzekh dzekh closed this as completed Jul 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

6 participants