Emotion

Emotion — это библиотека для стилизации компонентов в экосистеме JavaScript и React, предоставляющая мощные возможности CSS-in-JS. Она позволяет создавать динамические стили с использованием JavaScript, сохраняя гибкость CSS и удобство компонентного подхода. В сочетании с MDX, Emotion становится инструментом для создания интерактивных и стилизованных документаций, блогов и презентаций компонентов.


Подключение Emotion в MDX

Для начала необходимо установить основные пакеты:

npm install @emotion/react @emotion/styled
  • @emotion/react — основной пакет, предоставляющий хук css и контекст для ThemeProvider.
  • @emotion/styled — позволяет создавать стилизованные компоненты аналогично styled-components.

В MDX-файле можно импортировать необходимые модули:

import { css } from '@emotion/react';
import styled from '@emotion/styled';

Использование css для стилизации элементов

Функция css позволяет создавать динамические стили, которые могут зависеть от пропсов компонента или состояния:

const headingStyle = css`
  font-size: 2rem;
  color: #2c3e50;
  margin-bottom: 1rem;

  &:hover {
    color: #e74c3c;
  }
`;

<h1 css={headingStyle}>MDX с Emotion</h1>

Ключевые моменты:

  • Поддержка вложенных селекторов и псевдоклассов (:hover, :focus и др.).
  • Возможность использования JS-переменных и функций внутри шаблонной строки.
  • Стили генерируются в уникальные классы, предотвращая конфликты CSS.

Создание styled-компонентов

Styled-компоненты предоставляют более декларативный способ создания компонентов с CSS:

const Button = styled.button`
  background-color: #3498db;
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s ease;

  &:hover {
    background-color: #2980b9;
  }
`;

<Button>Кнопка</Button>

Преимущества подхода:

  • Легко читаемый синтаксис, близкий к обычному CSS.
  • Возможность передачи пропсов для динамической стилизации:
const Button = styled.button`
  background-color: ${props => (props.primary ? '#3498db' : '#95a5a6')};
  color: white;
`;
<Button primary>Главная</Button>
<Button>Второстепенная</Button>

Интеграция темы через ThemeProvider

Emotion позволяет управлять глобальными стилями через темы:

import { ThemeProvider } from '@emotion/react';

const theme = {
  colors: {
    primary: '#3498db',
    secondary: '#2ecc71',
  },
  spacing: factor => `${factor * 8}px`,
};

<ThemeProvider theme={theme}>
  <Button primary>Главная</Button>
</ThemeProvider>

Доступ к теме внутри styled-компонентов:

const Button = styled.button`
  background-color: ${props => props.theme.colors.primary};
  padding: ${props => props.theme.spacing(2)};
`;

Использование темы делает стили более консистентными и управляемыми, особенно в крупных проектах MDX.


Анимации и динамические стили

Emotion поддерживает создание анимаций с помощью ключевых кадров:

import { keyframes } from '@emotion/react';

const fadeIn = keyframes`
  from { opacity: 0; }
  to { opacity: 1; }
`;

const AnimatedDiv = styled.div`
  animation: ${fadeIn} 1s ease-in-out;
`;

<AnimatedDiv>Появляющийся блок</AnimatedDiv>

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

  • Локальные анимации для отдельных компонентов.
  • Использование динамических свойств через пропсы.
  • Совместимость с pseudo-классами и медиа-запросами.

Медиа-запросы и адаптивная стилизация

Встроенные медиа-запросы позволяют создавать responsive-компоненты:

const Container = styled.div`
  padding: 16px;

  @media (min-width: 768px) {
    padding: 32px;
  }
`;

Преимущества:

  • Отсутствие необходимости создавать отдельные CSS-файлы.
  • Простая интеграция в MDX, где контент может быть интерактивным и адаптивным.

Смешивание css и styled

Для сложных случаев можно комбинировать css и styled:

const dynamicStyle = props => css`
  color: ${props.color};
  font-weight: ${props.bold ? 'bold' : 'normal'};
`;

const Text = styled.p`
  font-size: 16px;
  ${dynamicStyle}
`;

<Text color="red" bold>Важный текст</Text>

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


Глобальные стили и сброс CSS

Emotion предоставляет возможность задавать глобальные стили через Global компонент:

import { Global, css } from '@emotion/react';

<Global
  styles={css`
    body {
      margin: 0;
      font-family: 'Arial', sans-serif;
      background-color: #f5f5f5;
    }
    h1, h2, h3 {
      color: #34495e;
    }
  `}
/>

Это особенно полезно в MDX-документации, где необходимо единообразное оформление всего контента.


Советы по оптимизации

  • Использовать styled для компонентов с постоянными стилями.
  • css применять для динамических или условных стилей.
  • Разделять темы и глобальные стили для масштабируемости.
  • Минимизировать дублирование CSS через утилиты и функции.
  • Использовать Babel-плагин Emotion для ускорения сборки и улучшения дебага.

Итоговая структура MDX с Emotion

Пример полной интеграции:

import { css, Global, keyframes, ThemeProvider } from '@emotion/react';
import styled from '@emotion/styled';

const theme = {
  colors: { primary: '#3498db', secondary: '#2ecc71' },
};

const fadeIn = keyframes`
  from { opacity: 0; }
  to { opacity: 1; }
`;

const Button = styled.button`
  background-color: ${props => props.theme.colors.primary};
  color: white;
  padding: 8px 16px;
  border-radius: 4px;
  animation: ${fadeIn} 0.5s ease-in;
`;

<ThemeProvider theme={theme}>
  <Global
    styles={css`
      body { font-family: sans-serif; margin: 0; padding: 0; }
    `}
  />
  <Button>MDX с Emotion</Button>
</ThemeProvider>

Это обеспечивает мощный и гибкий подход к стилизации MDX-документов, сочетая преимущества CSS-in-JS и React-компонентов.