Лучшие практики TailwindCSS + React: Чистый путь

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

В шаблоне используются CSS-модули, Talwind @apply и tailwind-merge. Допустим, я хочу создать Кнопку, структура папок будет такой:

|
|-button
|--Button.tsx
|--Button.module.css
|--index.ts
|
Вход в полноэкранный режим Выход из полноэкранного режима

И вот такой код:

Button /button/Button.tsx

import s from './Button.module.css'
import React from 'react'
import cn from 'classnames'
import Spinner from 'components/spinner'

type ButtonProps = {
  children: React.ReactNode
  fullWidth?: boolean
  loading?: boolean
  variant?: 'filled' | 'outlined'
  color?: 'primary' | 'secondary'
  size?: 'base' | 'lg'
} & Omit<React.ComponentProps<'button'>, 'className'>

const Button = ({
  children,
  variant = 'filled',
  color = 'primary',
  size = 'base',
  fullWidth,
  loading,
  disabled,
  ...props
}: ButtonProps) => {
  const classes = cn(s.root, s[variant], s[color], s[size], {
    [s.fullWidth]: fullWidth,
  })

  return (
    <button className={classes} disabled={disabled || loading} {...props}>
      {children}
      {loading && (
        <span className="ml-1.5">
          <Spinner className={s.spinner} />
        </span>
      )}
    </button>
  )
}

export default Button
Войти в полноэкранный режим Выйти из полноэкранного режима

Стили /button/Button.module.css

.root {
  @apply inline-flex items-center justify-center rounded-full font-semibold duration-150 disabled:pointer-events-none disabled:opacity-75;
}

.fullWidth {
  @apply w-full;
}

/*
 * SIZES
 */
.base {
  @apply px-8 py-3;
}

.lg {
  @apply px-12 py-5;
}

/*
 * VARIANTS & COLORS
 */
.filled.primary {
  @apply bg-[#FAA806] text-[#FFFFFF] hover:bg-[#EE9F04];
}

.filled.secondary {
  @apply bg-[#373E4B] text-[#97A3B7] hover:bg-[#343A47];
}

.outlined.primary {
  @apply border-[#FAA806] text-[#FAA806];
}

.outlined.secondary {
  @apply border-[#373E4B] text-[#373E4B];
}

/*
 * LOADING INDICATOR
 */
.primary .spinner {
  @apply fill-[#bc7e03] text-white;
}

.secondary .spinner {
  @apply fill-[#292e38] text-white;
}
Вход в полноэкранный режим Выход из полноэкранного режима
<NextLink href="/signin" passHref>
  <Button fullWidth {...{ disabled, loading }}>
    Register
  </Button>
</NextLink>
Вход в полноэкранный режим Выход из полноэкранного режима

Исходный код (Stackblitz)

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