Stylemapper — лучший способ стилизации приложений React

Существует множество способов стилизации приложений React. От библиотек CSS-in-JS, таких как Emotion, Styled Components или Stitches, до написания CSS (или SCSS / SASS) и последующего использования инструментов сборки для объединения всего вместе. Все они могут отлично подойти, но я никогда не был на 100% удовлетворен этими подходами. Одни приводят к повторяющемуся коду, другие усложняют использование встроенных возможностей CSS. Иногда стили трудно использовать повторно, а иногда их трудно настраивать.

Но я нашел новый способ, которым хочу поделиться с сообществом веб-разработчиков:

Сочетание CSS-фреймворка на основе утилит, такого как Tailwind CSS, с небольшой библиотекой, которую я написал под названием Slicknode Stylemapper.

Почему Stylemapper?

Я долгое время был скептиком Tailwind CSS. Я много читал о нем и видел восторженные отзывы уважаемых мною разработчиков. Но поскольку мне давно не приходилось выбирать CSS-решение для крупного проекта, я лишь наблюдал за фреймворком, фактически не используя его.

Недавно я начал работать над большой базой кода, используя Tailwind CSS. Над проектом работают несколько команд, и это очень помогает в масштабировании системы дизайна и сохранении последовательной верстки. Поначалу подход, основанный на использовании CSS-фреймворка, может показаться странным, но как только я преодолел первоначальные сомнения по поводу добавления стилей прямо в JSX-код, оказалось, что это очень продуктивно.

Тем не менее, было несколько вещей, которые мне не понравились в использовании Tailwind CSS в проекте React:

Tailwind CSS в React выглядит некрасиво.

Возможно, это только мое мнение, но я считаю использование Tailwind CSS в React довольно уродливым. CSS-классы разбросаны по всему коду компонентов React, что затрудняет их чтение. Многие определения стилей настолько длинные, что не помещаются в одну строку на моем большом экране. Мне приходится либо прокручивать код по горизонтали, либо включать автоматический перенос строк в IDE. Вот пример с сайта TailwindCSS (это даже без учета отзывчивости и темного режима):

export function ProjectListButton() {
  return (
    <a href="/new" class="hover:border-blue-500 hover:border-solid hover:bg-white hover:text-blue-500 group w-full flex flex-col items-center justify-center rounded-md border-2 border-dashed border-slate-300 text-sm leading-6 text-slate-900 font-medium py-3">
      New project
    </a>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

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

Ручная повторяющаяся работа

Утомительно создавать все эти компоненты-обертки React только для того, чтобы добавить несколько стилей. Если вы хотите писать код расширяемым образом, вам придется вручную объединять базовые стили компонентов с именами классов реквизитов React. А если вы используете Typescript, вам придется вручную создавать определения типов реквизитов для каждого компонента. С поддержкой рефлексов, обработчиков событий, расширяемости и простого варианта «selected» вот как будет выглядеть один из примеров:

import * as React from 'react';

export interface NavProps extends React.ComponentPropsWithoutRef<'div'> {
  selected?: boolean;
}

export const Nav = React.forwardRef<HTMLDivElement, NavProps>((props, ref) => {
  const { className, children, selected, ...rest } = props;
  return (
    <div
      {...rest}
      ref={ref}
      className={`py-4 px-6 text-sm ${
        selected ? 'font-bold' : 'font-medium'
      } ${className}`}
    >
      {' '}
      <ul className="flex space-x-3"> {children} </ul>{' '}
    </div>
  );
});
Вход в полноэкранный режим Выход из полноэкранного режима

Представьте себе компонент <Button/> с множеством вариантов, таких как intent (danger, primary, neutral), outline, disabled, size, и это быстро выходит из-под контроля.

Вводим Slicknode Stylemapper

Я написал небольшую библиотеку утилит, которая решает все вышеперечисленные проблемы и значительно упрощает код компонента. Вдохновленный Stitches, я хотел привнести аналогичный API в CSS-фреймворки, основанные на утилитах. Вы можете установить ее через npm и начать создавать свои собственные компоненты:

Создание стилизованных компонентов

import {styled} from '@slicknode/stylemapper';

// Create styled components with CSS classes
const Menu = styled('ul', 'space-x-2 flex');
const MenuItem = styled('li', 'w-9 h-9 flex items-center justify-center');

// Then use the components in your app
const App = () => {
  return (
    <Menu>
      <MenuItem>Home</MenuItem>
      <MenuItem>Product</MenuItem>
      <MenuItem>Signup Now</MenuItem>
    </Menu>
  );
};
Вход в полноэкранный режим Выход из полноэкранного режима

Компоненты с вариантами

Вы можете легко создавать компоненты с несколькими вариантами, которые меняют свой стиль на основе реквизитов. Stylemapper автоматически определяет типы реквизитов и создает строго типизированный компонент.

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

const Button = styled('button', {
  variants: {
    intent: {
      neutral: 'bg-slate-300 border border-slate-500',
      danger: 'bg-red-300 border border-red-500',
      success: 'bg-green-300 border border-green-500',
    },
    size: {
      small: 'p-2',
      medium: 'p-4',
      large: 'p-8',
    },
    // Add any number of variants...
  },
  // Optionally set default variant values
  defaultVariants: {
    intent: 'neutral',
    size: 'medium',
  },
});

const App = () => {
  return (
    <Button intent={'danger'} size={'large'}>
      Delete Account
    </Button>
  );
};
Вход в полноэкранный режим Выход из полноэкранного режима

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

Stylemapper работает с любым компонентом, который имеет свойство className. Это делает его идеальным решением для библиотек безголового пользовательского интерфейса, таких как Headless UI, Radix UI и Reach UI. Просто передайте компонент в качестве первого аргумента:

import {FancyComponent} from './fancy-component`;

const StyledFancyComponent = styled(FancyComponent, 'py-2 px3', {
  variants: {
    intent: {
      danger: 'bg-red-300 border border-red-500',
      success: 'bg-green-300 border border-green-500',
    },
  },
});
Войти в полноэкранный режим Выход из полноэкранного режима

Начните работу

Slicknode Stylemapper теперь доступен на npm под лицензией MIT. Чтобы ознакомиться с полным API и начать работу, загляните в репозиторий Github. Я буду рад услышать ваши отзывы! Вы можете следить за мной в Twitter или присоединиться к сообществу Slicknode в Slack.

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