Перейти к содержимому
v2.5.0
English
Русский
Документация

Button

Button — основной компонент действия на базе ButtonBase с поддержкой размеров и растягивания на всю ширину для типовых действий в продукте.

Паттерны

Основное действие формы

Когда использовать:

  • Форме нужно одно ясное основное действие.

Заметки по композиции:

  • Делайте основное действие визуально сильнее соседних второстепенных.
  • Используйте type='submit' осознанно.

Компромиссы:

  • Действие выглядит однозначно.
  • Интерфейс становится визуально шумным, если слишком много кнопок соревнуются за внимание.
form-footer-actions.tsx · 44 строки
import { Button, Label, TextField, TextFieldInput } from '@vega-ui/react';
import { FormEvent, useState } from 'react';

export default function FormFooterActions() {
  const [submitted, setSubmitted] = useState('');

  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    const data = new FormData(event.currentTarget);
    setSubmitted(`${data.get('workspace')} (${data.get('slug')})`);
  };

Пара с второстепенным действием

Когда использовать:

  • Локальному сценарию нужны основное и второстепенное действия рядом.

Заметки по композиции:

  • Для отмены или возврата используйте менее акцентное оформление.
  • Тексты кнопок должны дополнять друг друга, а не путать.

Компромиссы:

  • Легко считывается.
  • Сбивает с толку, если обе кнопки одинаково акцентны.
action-hierarchy.tsx · 12 строк
import { Button } from '@vega-ui/react';

export default function ActionHierarchy() {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--spacing-4)', width: '100%' }}>
      <Button type='button' fullWidth>Publish article</Button>
      <Button type='button' fullWidth variant='secondary' appearance='ghost'>Save draft</Button>
      <Button type='button' fullWidth variant='secondary' appearance='ghost'>Preview</Button>
      <Button type='button' fullWidth variant='secondary' appearance='transparent'>Discard</Button>
    </div>
  );
}

Когда использовать:

  • Навигация должна выглядеть как кнопка, но семантически оставаться навигацией.

Заметки по композиции:

  • Используйте asChild с настоящей ссылкой.
  • Сохраняйте семантику ссылки, если взаимодействие действительно ведёт на другую страницу.

Компромиссы:

  • Сильный визуальный акцент для навигации.
  • Легко злоупотребить там, где обычная ссылка была бы понятнее.
navigation-with-button-visuals.tsx · 22 строки
import { Button, Icon } from '@vega-ui/react';
import { ArrowRightIcon, ExternalLinkIcon } from '@vega-ui/icons';
import './examples.css';

export default function NavigationWithButtonVisuals() {
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 'var(--spacing-4)' }}>
      <Button asChild>
        <a href='/onboarding/import'>
          Import contacts
          <Icon size='sm' className='directionalIcon'><ArrowRightIcon /></Icon>
        </a>

Сравнение

Быстрое правило выбора

Используйте Button для явных действий, которые инициирует пользователь.

Используйте Button, когда:

  • действие меняет состояние или отправляет данные

Используйте Link, когда:

  • взаимодействие в первую очередь ведёт на другую страницу

Главный компромисс: у кнопки семантика действия, у ссылки — семантика навигации.

Button или IconButton

Используйте Button, когда:

  • видимый текст делает действие понятнее

Используйте IconButton, когда:

  • действие компактное и уже узнаваемо как контрол из одной иконки

Главный компромисс: кнопка понятнее, кнопка-иконка компактнее.

Button или ButtonBase

Используйте Button, когда:

  • продуктовому коду нужна стандартная текстовая поверхность действия

Используйте ButtonBase, когда:

  • для кастомной композиции нужен низкоуровневый примитив действия

Выбирайте этот компонент, когда

  • Основная задача — действие, а не навигация.
  • Видимый текст помогает понять действие.
  • Интерфейсу подходит стандартная поверхность кнопки.
  • компонент должен быть выбором по умолчанию для действия, а не низкоуровневым примитивом

Не выбирайте этот компонент, когда

  • Основная задача — навигация.
  • Действие обозначено только иконкой и места мало.
  • На самом деле это текстовая ссылка в основном тексте.

Решение проблем

Кнопка неожиданно отправляет форму

Симптом

Кнопка находится внутри формы, и клик по ней отправляет форму.

Вероятная причина

У Button нет type по умолчанию, поэтому, как и нативный <button>, внутри формы она работает как кнопка отправки.

Как проверить

  • Посмотрите отрендеренный type.
  • Проверьте, должна ли кнопка отправлять форму.

Решение

  • Задайте type='button', если кнопка не должна отправлять форму.

Полиморфная кнопка ведёт себя странно

Симптом

Контрол рендерится, но дочерний элемент не поддерживает передаваемые пропсы так, как ожидалось.

Вероятная причина

asChild использован с несовместимым дочерним элементом.

Как проверить

  • Изучите отрендеренный дочерний элемент.
  • Проверьте, поддерживает ли он нужные пропсы и семантику.

Решение

  • Используйте дочерний элемент с подходящей семантикой, например ссылку для навигации.
  • Оставьте обычный рендер кнопки, если полиморфизм не нужен.

Симптом

Визуально контрол работает, но на самом деле это навигация.

Вероятная причина

Button выбран для навигационного паттерна, которому нужна семантика ссылки.

Как проверить

  • Определите, что главное: действие или навигация.
  • Сравните сценарий с Link или Button asChild.

Решение

  • Используйте Link для обычной текстовой навигации.
  • Используйте Button asChild с настоящей ссылкой, если вид кнопки всё же нужен.