-
Notifications
You must be signed in to change notification settings - Fork 131
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] [Link] Доработка API
контролов Button
и Link
IF-376
#2598
Comments
Крутой, доскональный анализ! Долго эта проблема ждала его) Я бы только поспорил с некоторыми предлагаемыми правками. По сути, сейчас у нас есть 3 состояния: Ссылка, Кнопка и Кнопка-Ссылка. <Link displayAs="button" /> Т.е. визуально это будет Кнопка, но функционально Ссылка. Соглашусь с синхронизацией пропа
Кажется, что такое будет проще реализовать, и поддерживать. И также разработчикам нагляднее пользоваться. |
Нашёл отличный сайт, на котором можно посмотреть можно ли вложить один тэг в другой. |
прокомментирую здесь, "неинтерактивная ссылка" это оксюморон, не нужно его использовать. не читал весь анализ, но удобное апи должно выглядеть так (назовем элемент Clickable):
<>
<Clickable as="button" onClick={console.log} />
<Clickable as="a" href="/href" target="_blank" onClick={console.log} />
<Clickable as={Link} to={{ path: "/href" }} onClick={console.log} />
</>
<>
<Clickable as="button" variant="outlined" onClick={console.log} />
<Clickable as="a" variant="filled" href="/href" target="_blank" onClick={console.log} />
<Clickable as={Link} variant="text" to={{ path: "/href" }} onClick={console.log} />
</> при этом не стоит стараться отгадать за пользователя какой элемент нужно рисовать, лучше всегда требовать пропсу неплохой пример есть у Material UI: https://mui.com/material-ui/react-button/ |
Тоже прокомментирую, анализ прочитал. Очень круто разобрано, это большая работа. Спасибо. 1. Нужно уточнитьНепонятно что имели в ввиду в гайдах под фразой
Это не так. В интерфейсах прямо сейчас встречаются инлайн-кнопки в тексте. 2. Общие правки 1.Не согласен с дизайном контракта. Проп 3. Общие правки 1.1.
Это не так. Автор гайда упускает большой пласт сценариев с инлайн-кнопками. В пункте 1 я привёл пример. 4. Общие правки 2.Не получится унифицировать пропы, они не идентичны. Лучшим решением было бы избавляться от Но давайте посчитаем сколько видов кнопок есть сейчас и будем помнить что фантазия проектировщиков неудержима. Проектировщики решают свои интерфейсные задачи и в любой момент может появиться необходимость в новом представлении для контрола. Где-то новое представление необходимо, где-то может показаться избыточным, нужно смотреть конкретный сценарий. 5. Правки Link 1.
Категорически против самого постулата и решения бросать ошибку. Не нужно бросать runtime ошибку, неправильно создавать разработчикам проблемы на ровном месте.
В пункте приведён отличный пример с кодом, который можно перенести в документацию. Если хотим ограничить использование - лучше это сделать на уровне тайпингов. 6. Правки Link 2Согласен с @nulladdict, что "неинтерактивная ссылка" это оксюморон. Не согласен с предложением в анализе, что для этого кейса нужно описывать отдельное поведение. Всё не зарегулировать. 7. Правки Link 4Не согласен с
Контролы не должны наказывать разработчика. Они должны быть инструментом, который упрощает работу, а не инструментом с которым приходится бороться. Повторюсь, что направление развития контролов через дополнительный проп Что в итоге?
|
ПредложенияРазличие между кнопкой и ссылкой сильно размыто. Дизайнеру важно как контрол выглядит и как работает. При этом разработчик, на мой взгляд, стоит понимать что нужно использовать в конкретной ситуации. Какой контрол применить чтобы пользовательский опыт был максимально доступным. Считаю что пора отделить внешний вид контрола от функциональной принадлежности. Предлагаю оставить два контрола Как это можно сделать:
По сути предлагаю передавать в контрол маленькую локальную тему.
|
API
контролов Button
и Link
API
контролов Button
и Link
IF-376
Вот ещё сценарий на подумать. Элемент, при клике на который происходит браузерное pop (если есть куда идти) или replace (если пользователь пришел по прямой ссылке) Очевидно, что под капотом должен быть тег a, потому что у места куда этот элемент ведет есть адрес. При этот основное действие (push этого адреса) никогда не происходит, потому что ломает браузерную историю. При этом пользователь может захотеть открыть «предыдущую» страницу в новой вкладке, поэтому это точно не button. Встречается в логически вложенных страницах (переход из списка статей в статью и обратно) и всяких модалках/сайдпеждах, которые умеют открываться в разных контекстах (как в стаффе/инсте/твиттере) |
Основано на обсуждении из #1728.
Дополнительную информацию касательно этой проблемы можно найти в #2594, в треде в слаке про Clickable, в треде в слаке про видение дизайнеров.
Терминология
Примечание: все термины из этого раздела выделены в тексте
как сниппеты
.Неинтерактивная ссылка
- это элемент разметки со следующими характеристиками:href
иonClick
.body
илиhtml
.Пояснение: так как
неинтерактивная ссылка
- это отклонение от нормального состояния, то мы не хотим вводить пользователей в заблуждение, выделяянеинтерактивный элемент
другим цветом, так как пользователь может подумать, что элемент выделенный другим цветом - это интерактивный элемент.Хорошим примером плохого дизайна служит сайт Apple Jesus на этом сайте для ссылок используется оранжевый цвет с подчёркиванием и для выделения важной информации используется тот же оранжевый цвет, но уже без подчёркивания.
Дополнительное действие
- это действие запускаемое при клике на интерактивную ссылку, происходящее помимо перехода на ресурс указанный вhref
. Примером такого действия может быть отправление дополнительной статистики в метрики.Постулаты
Link
иButton
должны быть использованы в зависимости от их функциональной принадлежности, а не внешнего вида. То есть контролLink
не может быть использован как кнопка, а контролButton
не может быть использован как ссылка.Button
не должен быть использован для любого типа перехода по ссылке, в том числе и программного (т.е. перехода с использованием роутера). Для этой цели должен быть использован контролLink
. Это же сказано в гайдах.Link
способен выполнятьдополнительное действие
при клике на него.Button
, когда этот контрол выглядит как ссылка, должна быть больше, чем кликабельная область контролаLink
как описано в гайдах.Link
иButton
должны иметь идентичные визуальные состояния (не считая кликабельной области), чтобы у пользователя была возможность выбрать нужный ему контрол опираясь не на визуальный стиль, а на функциональную составляющую.Link
должен выбрасывать ошибку, при попытке передачи атрибутаonClick
без атрибутаhref
.Аргументация
<button/>
в качестве ссылки вызывает проблемы с доступностью интерфейса. Пользователи скрин-ридеров не смогут понять что нажатие на кнопку-ссылку произведёт не действие на странице, а переход по ссылке.<a/>
, в отличие от тега<button/>
по-другому воспринимается браузерами: при нажатии правой кнопкой мыши по ссылке (или удерживании пальца на ссылке на мобильных устройствах) вызывается контекстное меню с действиями, которые можно проделать с ссылкой.<a/>
браузер слева снизу отображает путь на который ведёт ссылка.<a/>
в качестве кнопки может привести к проблемам с SEO. Поисковые системы могут занижать сайты в поисковой выдаче из-за использования пустых ссылок, расценив такие ссылки как способ нечестного SEO продвижения.Ошибки гайдов
Примечание: в данном разделе гайды рассматриваются со стороны разработчика, а не со стороны дизайнера, поэтому некоторые из пунктов могут быть справедливы для дизайна.
href
, поэтому ссылки согласно 3-му постулату могут выполнять толькодополнительное действие
.дополнительное действие
".Клик по ссылке всегда должен открывать другую страницу (на самом деле не открывать другую страницу, а делать переход на ресурс указанный в
href
, из-за того, что мы рассматриваем проблему в рамкахSPA
/SSR
это различные понятия), за исключением того случая, когда ссылка этонеинтерактивный
элемент.Button
не может быть использован для совершения действия перехода по ссылке, следовательно и открывать в новом окне нечего.У обоих элементов есть чёткое предназначение.
Кнопка предназначена для обработки события клика.
Ссылка предназначена для перехода на ресурс указанный в
href
.В этом нас убеждают 1-ый, 2-ой и 3-ий постулаты, а также аргументация.
Если кнопка выглядит как ссылка, это всё ещё кнопка, что возможно благодаря 5-му постулату.
Общие правки: правки, которые нужно внести в контролы
Link
иButton
displayAs
с типомdisplayAs?: 'link' | 'button'
. По умолчанию для контролаLink
этот проп будет равенlink
и для контролаButton
-button
. Этот проп будет задавать контекст для пропаuse
, что позволит реализовать 5-ый постулат.При этом, есть несколько важных моментов, которые нужно учесть:
Button
сdisplayAs="link"
это не совсем то же самое, что контролLink
сdisplayAs="link"
. Согласно 4-му постулату в таком случае у контролаButton
кликабельная область должна быть больше, чем у контролаLink
.Link
сdisplayAs="button"
должен иметь такую же кликабельную область, как контролButton
сdisplayAs="button"
. Следовательно, при заданииdisplayAs="button"
внутри контролаLink
мы должны менять стильdisplay: inline
наdisplay: inline-block
.use
.Таблица совместимости пропов:
Чтобы упростить работу со стилизацией ссылок и кнопок нужно, чтобы в голове разработчика соотносились название цвета и сам цвет, следовательно, я думаю, что стоит отказаться от названия
default
в пользу более описательныхgrayed
иprimary
.Правки, которые нужно внести в контрол
Link
Link
должен выбрасывать ошибку, при попытке передачи атрибута onClick без атрибутаhref
.".Так делать не стоит.
А вот так делать стоит.
Link
нет пропаhref
- ссылка которую этот контрол отрендерит должна бытьнеинтерактивной
.Link
не был передан пропhref
- ссылка должна быть отрендерена без атрибутаhref
.size
с типомsize?: ButtonSize
для задания размеров когдаdisplayAs="button"
.Если передан проп
size
, ноdisplayAs="link"
- должна быть выброшена ошибка.The text was updated successfully, but these errors were encountered: