META
Руководства
Стилизация Lego-компонент

Стилизация Lego-компонент

Часто возникают ситуации, когда надо или стилизовать определенные элементы страницы или распределить их определённым образом. И хотя все компоненты придерживаются сетки (Bootstrap Grid), этого бывает недостаточно.

Кастомная стилизация позволяет как изменить внешний вид компонента, так и использовать альтернативные сетки (например, flex).

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

Опишем структуру Lego-компонента в части, касающейся дизайна:

{
  name: 'me-div', //Название компонента, например me-div, me-static и т.п.
  span: 6, //Ширина объекта в нотации Bootstrap Grid, применяется на уровне meLegoItem
  offset: 2, //Отступ до объекта в нотации Bootstrap Grid, применяется на уровне meLegoItem
  styles: { //Стили отдельных уровней структуры компонента. Все стили в формате ReactJS
    meLegoItem: {}, //Стили для уровня meLegoItem
    meLegoItemContainer: {}, //Стили для уровня meLegoItemContainer
    div: {}, //в данном случае для me-div предусмотрен стиль "div", но для другого компонента его может не быть
    meLego: {}, //Стили для уровня meLego
    meLegoContainer: {}, //Стили для уровня meLegoContainer
  }
  elems: [], //Список дочерних lego-компонент, если текущий компонент является контейнером (например, me-div)
}

Это свойства, которые поддерживаются всеми компонентами. Однако, кроме них, Lego содержит и другие свойства, место применения которых зависит от отдельных компонентов и требует уточнения:

  • align
  • className
  • marginBottom

Теперь немного подробнее о styles. Каждый компонент состоит из ряда слоев. Они смехатично представлены ниже:

  1. Снаружи компонент обернут в div, который мы назовём meLegoItem. Это самый верхний уровень компонента и он стилизуется атрибутом styles.meLegoItem. Именно к нему применяется сетка Bootstrap Grid и именно у него благодаря сетке появляются внутренние отступы. Из-за этих отступов графическую составляющую компонента (например, фон, границу) нужно определять на других уровнях, иначе соседние компоненты будут прилипать друг к другу.
  2. На уровне ниже - meLegoItemContainer. Стилизуется, соответственно, через styles.meLegItemContainer. Является контейнером, содержащим сам наш целевой компонент.
  3. element, т.е. наш целевой компонент. Например, me-div или me-static. Поскольку реализация элемента от одного к другому может очень сильно отличаться, стили для элементов определяются индивидуально, например:
    1. Для me-div определен стиль styles.div
    2. Для элемента me-panel определены стили styles.header для заголовка и styles.body для содержимого
  4. Если элемент является контейнером (например, тот же me-div), у него будет подуровень meLego с соответствующим стилем styles.meLego. На схеме он обведён пунктиром, т.к. для многих элементов этого уровня и всех уровней ниже не будет.
  5. И, наконец, meLegoContainer со стилем styles.meLegoContainer, который, как проиллюстрировано, может содержать уже другие компоненты meLegoItem.

Приведём пример использования всего набора этих стилей:

Широкий блок
Узкий блок, но в нём больше текста, поэтому он выше
{
  name: 'me-div',
  styles: {
    div: { //Стилизуем родительский блок
      backgroundColor: '#F0F0F0',
      border: "1px solid gray"
    },
    meLegoContainer: { //Определяем разметку flex для дочерних блоков
      display: 'flex',
      alignItems: 'stretch'
    }
  },
  elems: [
    {
      name: 'me-div',
      styles: {
        meLegoItem: {
          flex: 2 //В разметке flex блок займет 2/3 ширины. Flex при этом перекрывает установку span
        },
        meLegoItemContainer: {
          height: '100%' //meLegoItem растянут по высоте, благодаря alignItems: 'stretch', но meLegoItemContainer нужно помочь
        },
        div: {
          height: '100%', //me-div тем более уже ничего не знает о flex, ему тоже нужно помочь растянуться по высоте
          backgroundColor: "#F0F0F0",
          border: "1px solid gray"
        }
      },
      elems: []
    },
    {
      name: 'me-div',
      styles: {
        meLegoItem: {
          flex: 1 //В разметке flex блок займет 1/3 ширины. Flex при этом перекрывает установку span
        },
        meLegoItemContainer: {
          height: '100%'
        },
        div: {
          height: '100%',
          backgroundColor: "#F0F0F0",
          border: "1px solid gray"
        }
      },
      elems: []
    }
  ]
}