Адаптивный дизайн

SkateJS — это современная библиотека для создания веб-компонентов на чистом JavaScript. Она обеспечивает декларативный подход к компонентам и поддерживает реактивные свойства, что упрощает управление состоянием и интеграцию с адаптивными интерфейсами.

Адаптивный дизайн в контексте SkateJS строится на трёх основных принципах: реактивные свойства, слоты и шаблоны, работа с медиа-запросами и динамическая стилизация.


Реактивные свойства и их влияние на адаптивность

SkateJS позволяет определять свойства компонента с помощью объекта props. Каждое свойство может быть наблюдаемым, что обеспечивает автоматическое обновление DOM при изменении значения.

import { define, props, h } from 'skatejs';

class ResponsiveCard extends HTMLElement {
  static props = {
    width: props.number,
    isCompact: props.boolean
  };

  render() {
    return h('div', {
      class: this.isCompact ? 'compact' : 'full'
    }, `Ширина компонента: ${this.width}px`);
  }
}

define(ResponsiveCard);

В этом примере свойство isCompact может автоматически изменяться в зависимости от ширины экрана, что обеспечивает динамическую подстройку интерфейса под устройство пользователя.


Использование слотов для гибкой структуры

SkateJS поддерживает стандартные веб-слоты. Это позволяет компоненту быть универсальным и легко адаптируемым под разные сценарии использования.

render() {
  return h('div', { class: 'card' }, [
    h('header', null, h('slot', { name: 'header' })),
    h('section', null, h('slot', { name: 'content' })),
    h('footer', null, h('slot', { name: 'footer' }))
  ]);
}

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


Динамическая стилизация и медиа-запросы

Адаптивный дизайн невозможно реализовать без возможности изменения стилей компонента в зависимости от размера экрана. SkateJS позволяет подключать CSS через static styles или работать с CSSStyleSheet программно.

import { css } from 'skatejs';

class ResponsiveButton extends HTMLElement {
  static styles = css`
    button {
      padding: 12px 24px;
      font-size: 16px;
    }

    @media (max-width: 600px) {
      button {
        padding: 8px 16px;
        font-size: 14px;
      }
    }
  `;

  render() {
    return h('button', null, 'Нажми меня');
  }
}

define(ResponsiveButton);

Здесь показан пример адаптации стилей кнопки под узкие экраны. Комбинация реактивных свойств и медиа-запросов позволяет изменять не только внешний вид, но и поведение компонентов:

updated() {
  this.isCompact = window.innerWidth < 600;
}

Подключение динамических классов и условных стилей

Иногда достаточно не изменять весь CSS, а менять отдельные классы компонента в зависимости от состояния. SkateJS упрощает это через свойство class при рендере:

render() {
  const cardClass = this.isCompact ? 'card compact' : 'card full';
  return h('div', { class: cardClass }, 'Содержимое карточки');
}

Такой подход позволяет минимизировать дублирование стилей и поддерживать единый набор правил для разных размеров экранов.


Управление адаптивностью через события

Изменение размеров окна может быть обработано внутри компонента с помощью стандартного события resize. В SkateJS это реализуется через подключение слушателей при connectedCallback и удаление при disconnectedCallback:

connectedCallback() {
  super.connectedCallback();
  this._resizeHandler = () => {
    this.isCompact = window.innerWidth < 600;
  };
  window.addEventListener('resize', this._resizeHandler);
}

disconnectedCallback() {
  window.removeEventListener('resize', this._resizeHandler);
  super.disconnectedCallback();
}

Такой метод обеспечивает автоматическое переключение интерфейса без дополнительных библиотек и сложной логики.


Анимации и переходы в адаптивных компонентах

SkateJS легко интегрируется с CSS-анимациями и Web Animations API. Для адаптивного дизайна это важно, чтобы изменение состояния выглядело плавным, а не резким.

updated() {
  const card = this.shadowRoot.querySelector('.card');
  card.animate([
    { transform: 'scale(1)', opacity: 1 },
    { transform: this.isCompact ? 'scale(0.9)' : 'scale(1)', opacity: 1 }
  ], { duration: 200, fill: 'forwards' });
}

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


Реактивные массивы и адаптивные списки

Для динамических списков или таблиц можно использовать реактивные массивы, что позволяет автоматически перестраивать компоненты при изменении данных:

static props = {
  items: props.array
};

render() {
  return h('ul', null,
    this.items.map(item => h('li', null, item))
  );
}

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


Итоговые принципы

  1. Реактивные свойства позволяют автоматически менять состояние и стиль компонентов.
  2. Слоты делают структуру компонента гибкой.
  3. Медиа-запросы и динамическая стилизация управляют визуальной адаптацией.
  4. События окна и реактивные массивы поддерживают интерфейс, который изменяется вместе с пользователем и данными.
  5. Анимации делают переходы между состояниями плавными и естественными.

Эти методы вместе обеспечивают полноценную адаптивность компонентов, сохраняя декларативный и модульный подход, который является основой SkateJS.