Структура объекта button

В библиотеке Shepherd.js объект button используется для описания кнопок, отображаемых внутри шага (step) тура. Эти кнопки управляют навигацией, взаимодействием пользователя и поведением тура в целом. Каждый шаг может содержать массив кнопок, каждая из которых задаётся как отдельный объект с набором свойств.

Минимальный пример:

buttons: [
  {
    text: 'Далее',
    action: tour.next
  }
]

Каждый объект внутри массива buttons представляет одну кнопку и может включать несколько параметров, влияющих на внешний вид и поведение.


Свойство text

Определяет текст, отображаемый на кнопке.

{
  text: 'Назад'
}
  • Принимает строку
  • Поддерживает HTML-разметку (например, <strong>, <span>)
  • Используется как основной визуальный идентификатор кнопки

Пример с HTML:

{
  text: '<strong>Далее</strong>'
}

Свойство action

Определяет функцию, которая будет вызвана при нажатии на кнопку.

{
  text: 'Далее',
  action: tour.next
}

Возможные варианты:

  • Встроенные методы тура:

    • tour.next — переход к следующему шагу
    • tour.back — возврат к предыдущему шагу
    • tour.cancel — завершение тура
    • tour.complete — завершение с отметкой об успехе
  • Пользовательская функция:

{
  text: 'Проверить',
  action: () => {
    console.log('Кнопка нажата');
  }
}

Контекст выполнения:

  • Внутри функции this ссылается на текущий шаг (step)
  • Доступен объект тура через this.tour

Пример:

{
  text: 'Следующий',
  action() {
    console.log(this); // текущий шаг
    this.tour.next();
  }
}

Свойство classes

Позволяет добавить CSS-классы к кнопке.

{
  text: 'Удалить',
  classes: 'btn btn-danger'
}

Особенности:

  • Принимает строку с перечислением классов через пробел
  • Используется для кастомизации внешнего вида
  • Может комбинироваться с CSS-фреймворками (Bootstrap, Tailwind и др.)

Свойство secondary

Определяет, является ли кнопка вторичной (менее акцентированной).

{
  text: 'Отмена',
  action: tour.cancel,
  secondary: true
}

Поведение:

  • Вторичные кнопки визуально отличаются (обычно менее заметны)
  • Используются для альтернативных действий (например, отмена)

Свойство disabled

Отключает кнопку, делая её неактивной.

{
  text: 'Далее',
  action: tour.next,
  disabled: true
}

Особенности:

  • Принимает true или false
  • В отключённом состоянии кнопка не реагирует на клики
  • Может использоваться для управления логикой (например, ожидание ввода пользователя)

Свойство label

Определяет текст для атрибута aria-label, используемого для доступности.

{
  text: '→',
  label: 'Следующий шаг',
  action: tour.next
}

Назначение:

  • Улучшает доступность интерфейса
  • Используется скринридерами
  • Особенно важно при использовании иконок вместо текста

Комбинирование свойств

Объект кнопки может включать сразу несколько параметров:

{
  text: 'Продолжить',
  action: tour.next,
  classes: 'btn-primary',
  secondary: false,
  disabled: false,
  label: 'Перейти к следующему шагу'
}

Несколько кнопок в одном шаге

Массив buttons позволяет задавать несколько кнопок:

buttons: [
  {
    text: 'Назад',
    action: tour.back,
    secondary: true
  },
  {
    text: 'Далее',
    action: tour.next
  }
]

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


Динамическое поведение кнопок

Кнопки могут изменять поведение в зависимости от состояния приложения:

{
  text: 'Проверить',
  action() {
    const isValid = validateForm();

    if (isValid) {
      this.tour.next();
    } else {
      alert('Ошибка');
    }
  }
}

Возможности:

  • Проверка данных перед переходом
  • Асинхронные операции
  • Условная навигация

Использование асинхронных действий

Поддерживается работа с async/await:

{
  text: 'Загрузить',
  action: async function () {
    await fetchData();
    this.tour.next();
  }
}

Важно учитывать:

  • Shepherd не блокирует UI автоматически
  • При необходимости требуется вручную управлять состоянием (например, через disabled)

Интеграция с состоянием интерфейса

Кнопки могут взаимодействовать с DOM и внешними состояниями:

{
  text: 'Открыть меню',
  action() {
    document.querySelector('#menu').classList.add('open');
    this.tour.next();
  }
}

Частые паттерны использования

Навигационные кнопки:

[
  { text: 'Назад', action: tour.back, secondary: true },
  { text: 'Далее', action: tour.next }
]

Завершение тура:

{
  text: 'Завершить',
  action: tour.complete
}

Отмена:

{
  text: 'Пропустить',
  action: tour.cancel,
  secondary: true
}

Ошибки и подводные камни

1. Потеря контекста this:

action: function() {
  this.tour.next(); // корректно
}
action: () => {
  this.tour.next(); // ошибка — стрелочная функция не имеет собственного this
}

2. Отсутствие action:

Кнопка без обработчика не выполняет никаких действий:

{
  text: 'Ничего не делает'
}

3. Неправильное использование disabled:

disabled: 'true' // ошибка — должно быть boolean

Расширенные сценарии

Условное отображение кнопок:

Хотя Shepherd напрямую не поддерживает скрытие кнопок, можно динамически формировать массив:

const buttons = [];

if (userIsAdmin) {
  buttons.push({
    text: 'Удалить',
    action: deleteItem
  });
}

buttons.push({
  text: 'Далее',
  action: tour.next
});

Взаимодействие с шагами

Каждая кнопка связана с текущим шагом и может:

  • Управлять переходами
  • Влиять на состояние тура
  • Запускать пользовательскую логику

Контекст шага (this) позволяет обращаться к:

  • this.tour
  • this.options
  • DOM-элементу шага

Визуальная иерархия кнопок

Рекомендуемая структура:

  • Основная кнопка (primary action) — без secondary
  • Вторичная кнопка — с secondary: true

Пример:

[
  {
    text: 'Отмена',
    action: tour.cancel,
    secondary: true
  },
  {
    text: 'Продолжить',
    action: tour.next
  }
]

Такой подход улучшает UX и делает интерфейс предсказуемым.


Итоговая структура объекта

{
  text: String,
  action: Function,
  classes: String,
  secondary: Boolean,
  disabled: Boolean,
  label: String
}

Каждое свойство является опциональным, за исключением text и action, которые практически всегда используются вместе для полноценной кнопки управления.