Поднимите стилизованные компоненты на новый уровень

Большинство из нас знают о библиотеках CSS-in-JS примерно с 2015 года, и с тех пор они прошли долгий путь! Основные библиотеки, с которыми знакомо большинство людей, это styled-components и emotion. Они имеют в основном одинаковый API и синтаксис, и в этой статье я не буду углубляться в различия между ними.

Одним из основных преимуществ, которые предоставляет CSS-in-JS (в этой статье я буду в основном ссылаться на styled-components), является возможность писать, вполне очевидно, CSS в файлах javascript. Обычно это делается либо с помощью строки шаблона, например:

import { styled } from 'styled-components'

const Container = styled.div`
  background-color: white;
`
Войти в полноэкранный режим Выйти из полноэкранного режима

…так и с помощью объекта Javascript:

import { styled } from 'styled-components'

const Container = styled.div({
  backgroundColor: 'white',
})
Enter fullscreen mode Выход из полноэкранного режима

Это особенно изменило игру для мира React, потому что теперь мы можем передавать реквизиты этим стилизованным компонентам для контекстуальных случаев использования

import { styled } from 'styled-components'

const Container = styled.div((props) => ({
  backgroundColor: props.mode === 'light' ? 'white' : 'black',
}))

const MyComponent = () => {
  const { mode } = useThemeContext()

  return <Container mode={mode}>...</Container>
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Больше никакой возни с классами и файлами CSS (Sass/Less)!

Подводные камни

Гибкость стилизованных компонентов отлично подходит для разработчиков, чтобы начать использовать их, но она также может создать проблемы для больших команд, которые могут не иметь лучших стандартов коммуникации и лучших практик. Некоторые разработчики могут использовать литералы шаблонов, в то время как другие используют объекты CSS. Это может привести к некоторой несогласованности в использовании маркеров дизайна и к появлению одноразовых значений, которые могут затруднить обновление в соответствии с заданной темой. Именно здесь styled-system может помочь придать CSS-in-JS больше структуры для создания надежной библиотеки компонентов системы дизайна.

Что такое styled-system

Styled System позволяет быстро создавать пользовательские компоненты пользовательского интерфейса с реквизитами стиля на основе ограничений, основанных на шкалах, определенных в вашей теме.

Она позволяет добавлять стилевые реквизиты непосредственно к styled-компонентам, так что это не нужно делать вручную. Кроме того, он подключается к теме безопасным для типов способом, чтобы не пришлось гадать, какой тип переменной следует использовать в соответствии с системой дизайна.

<Box
  fontSize={4} // 4th index in theme fontSizes = ['0.5rem', 0.75rem', '1rem', 1.5rem']
  fontWeight='bold'
  p={3} // 3rd index in theme spacing = ['0px', '2px', '4px', '8px', '16px']
  mb={[ 4, 5 ]}
  color='white'
  bg='primary' // contextual color value at the theme level
>
  Hello World
</Box>
Вход в полноэкранный режим Выход из полноэкранного режима

Как это может помочь?

Зачем нам добавлять что-то подобное к тому, что мы уже делаем с помощью styled-components?

Первоклассная тематизация

При работе с styled-components мы часто используем предлагаемую функцию styled. С помощью этой функции мы можем определить, какой тип HTML-элемента мы хотим использовать. Если пойти еще дальше, мы даже можем добавить стили к любому компоненту React (при условии, что он принимает и передает className базовым элементам компонента).

import { styled } from 'styled-components'
import { colors } from 'design'

const Container = styled.div`
  background-color: white;
  color: ${colors.green4};
  border-color: ${(props) => props.theme.primaryColor}
`
Вход в полноэкранный режим Выход из полноэкранного режима

Как видите, у нас есть три разных способа определить цвет. И правильный способ может быть не столь очевиден, особенно для того, кто не знаком с кодовой базой. Эта двусмысленность позволяет тематизации быть гражданином второго сорта и считать приемлемым наличие множества одноразовых значений (в некоторых случаях это может быть приемлемо). Так что же делать, если существует только один реальный способ определить этот цвет (два, если вы хотите рассмотреть «аварийный люк» css prop как вариант)?

<Box
  {/* with Typescript we can restrict these values to what is a part of the theme */}
  bg="white"
  color="green3"
  borderColor="primaryColor"
>
  ...
</Box>
Войти в полноэкранный режим Выйти из полноэкранного режима

Эти три значения берутся непосредственно из объекта темы, если бы он выглядел следующим образом:

export const theme = {
  colors: {
    white: '#fff',
    green3: '#1ea676',
    primaryColor: '#1ea676',
  }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Отзывчивость

Мы живем в мире, в котором так много устройств и размеров устройств для доступа в Интернет. И поскольку все эти различные устройства имеют свои собственные размеры экрана, наш сайт должен быть отзывчивым, чтобы обеспечить элегантный пользовательский интерфейс для каждого из этих устройств. Для этого мы используем media queries и отображаем стиль в зависимости от размеров экрана различных устройств. В настоящее время мы делаем это с помощью styled-components, что выглядит следующим образом:

import { styled } from 'styled-components'
import { size, mediaQueries } from 'design'

const Container = styled.div`
  margin-top: ${size.sm}px; /* sometimes we forget about handling the mobile size */

  ${mediaQueries.forTabletVerticalUp} {
    margin-top: ${size.md}px;
  }

  /* sometimes we forget about handling the large desktop size */
`
Войти в полноэкранный режим Выход из полноэкранного режима

В styled-system почти каждый реквизит поставляется с опцией масштабированного значения — это означает, что мы можем легко задать значение для каждой определенной точки останова. Допустим, точки останова нашей темы настроены следующим образом

export const theme = {
  breakpoints: ['400px', '600px', '900px', '1200px'], // mobile, tablet, desktop, large desktop
  size: {
    0: '0px',
    sm: '4px',
    md: '8px',
    lg: '16px',
  }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Мы можем написать наши компоненты, как показано ниже, без необходимости оборачивать styled вокруг него и вручную устанавливать медиа-запросы

<Box
  marginTop={['sm', 'md']} // 'sm' for mobile, 'md' for everything larger
>
  ...
</Box>
Вход в полноэкранный режим Выход из полноэкранного режима

Атомарный дизайн

Атомарный дизайн — это концепция дизайна, согласно которой веб-элементы должны строиться друг на друге, как атомы, молекулы, организмы и так далее.

Этой концепции трудно достичь с помощью styled-components, потому что, используя метод styled, мы склонны постоянно «расширять» компоненты только для того, чтобы добавить немного стиля. Когда мы так расширяем эти базовые компоненты, мы, по сути, пытаемся воссоздать атом с разными протонами и нейтронами, и для любого новичка это выглядит как новый атом.

В styled-system мы максимально сохраняем базовые компоненты, полагаясь на специализацию — это означает добавление различных значений prop для добавления специализации к более общему компоненту. Таким образом, по мере роста команды и ознакомления новых разработчиков с кодовой базой становится более очевидным, что лежит в основе HTML-разметки и каковы ее намерения.

Поясним на примере:

  • элемент button — это атом.
  • styled-system + styled-component Button — это молекула
  • компоненты, которые поглощают кнопку, являются организмом
  • коллекция организмов, составляющих опыт, — это шаблон
  • шаблоны составляют страницу

Недостатки styled-system

Не поддерживается активно

К сожалению, репозиторий styled-system на Github активно не поддерживается, но это не значит, что он бесполезен. Это просто означает, что дальнейших улучшений или исправлений не будет, и если инструмент не нуждается в исправлениях, то это нормально. styled-system очень легкий и не имеет никаких реальных (поставляемых) зависимостей. По сути, это набор методов, которые могут быть добавлены в styled-components или emotion для включения различных стилевых реквизитов. Именно поэтому размер пакета составляет ~150kb, что довольно мало!

Другие альтернативы более надежны

Создатели styled-system также создали theme-ui, который является более полноценным (и скоро будет более полноценным), чем styled-system. Основное различие между ними в том, что theme-ui по мнению разработчиков использует emotion под капотом и не совместим с styled-components (подробнее). Оба они используют спецификацию System UI, а также несколько других, которые вы можете найти здесь.

Заключение

Я считаю, что концепция styled-system имеет огромное значение, особенно в паре с Typescript, для разработки надежной системы дизайна и библиотеки компонентов. Она позволяет определять стили в компоненте, а не где-то еще, что может сделать написание CSS менее болезненным — особенно если Typescript может указать вам переменные, из которых вы можете выбирать, и не дает вам возможности отклониться от них, если вы не очень постараетесь. А поскольку он позволяет вам сделать ваши компоненты более строгими в отношении того, какие варианты маркеров дизайна они принимают, то они более устойчивы к изменениям, поскольку эти маркеры могут быть изменены в одном месте, и это изменение обновляет все компоненты соответственно, поскольку они должны использовать маркеры, а не одноразовые значения.

Итак, если вы работаете с большой группой и хотите избежать переписывания одних и тех же стилей и значений CSS, я бы очень рекомендовал styled-system или любую другую библиотеку, использующую спецификацию System UI. #happycoding

Оцените статью
devanswers.ru
Добавить комментарий