Files
svg-sprites/preview/ai/applied/components.md
S.Gromov e77e7dfcf1 refactor: заменить shiki на самописный highlighter и обновить архитектуру
- Удалён shiki (9.5→0 МБ), создан regex-токенизатор для html/css/xml
- CLI переведён с аргументов на конфиг-файл svg-sprites.config.ts
- Превью переработано: React-приложение вместо инлайн HTML
- Добавлен футер с названием пакета и ссылкой на репозиторий
- Исправлена загрузка dev-data.js для Vite 8
- Футер прижат к низу, содержимое центрировано
2026-04-22 16:54:35 +03:00

5.1 KiB
Raw Blame History

title, scope, keywords, when
title scope keywords when
Компоненты applied
компонент
props
jsx
ui
clsx
cl
React
FC
Создание или редактирование React-компонентов: структура, пропсы, стили

Компоненты

Правила написания React-компонентов: файловая структура модуля, типизация пропсов, документирование и реализация. Раздел охватывает компоненты всех слоёв — от shared/ui до screens.

Архитектурные слои и их назначение описаны в разделе Архитектура.

Правила организации

  1. Один компонент — один файл.
  2. Компонент не содержит бизнес-логики — логика и сайд-эффекты выносятся в хуки или сторы.
  3. Дочерние компоненты размещаются в сегменте ui/ и подчиняются тем же правилам структуры.
  4. Публичный API модуля — только index.ts. Прямые импорты внутренних файлов запрещены.

Базовая структура компонента

Минимальный набор файлов: компонент, стили, типы и публичный экспорт.

container/
├── styles/
│   └── container.module.css
├── types/
│   └── container.type.ts
├── container.ui.tsx
└── index.ts

Именования

  • Имя корневого css класса всегда .root
  • Тип пропсов именуется {ComponentName}Props.
  • Тип пользовательских параметров именуется {ComponentName}Params.

Типизация

Структура типов компонента показана в примере. Ниже — обоснования ключевых решений.

  • type вместо interface — гибче для пропсов: поддерживает union, intersection, mapped types. Declaration merging пропсам не нужно.
  • Без FC — неявно добавляет children, усложняет дженерики, не даёт преимуществ перед аннотацией параметра.
  • Типы в types/, а не в .tsx — предотвращает циклические зависимости (компонент импортирует хук, хук импортирует тип из компонента) и разделяет ответственность: .tsx для рендера, .type.ts для данных.
  • Без возвращаемого типа — TypeScript выводит из JSX. Осознанное исключение из базового правила.

Реализация

  • Пропсы деструктурируются в теле компонента, не в параметрах.
  • Порядок: пользовательские → системные (children, className) → ...htmlAttr.
  • className объединяется с корневым классом через cl(): cl(styles.root, className).
  • ...htmlAttr прокидывается на корневой элемент.

Пример

container/types/container.type.ts

import type { HTMLAttributes } from 'react'

/**
 * Параметры компонента Container.
 */
export type ContainerParams = {}

/** HTML-атрибуты корневого элемента. */
type RootAttrs = HTMLAttributes<HTMLDivElement>

export type ContainerProps = RootAttrs & ContainerParams

container/styles/container.module.css

.root {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 0 var(--spacing-4);
}

container/container.ui.tsx

import cl from 'clsx'
import type { ContainerProps } from './types/container.type'
import styles from './styles/container.module.css'

/**
 * Контейнер с адаптивной максимальной шириной.
 *
 * Используется для:
 *  - обёртки контента страниц с ограничением ширины
 *  - центрирования блоков в лейауте
 */
export const Container = (props: ContainerProps) => {
  const { children, className, ...htmlAttr } = props

  return (
    <div {...htmlAttr} className={cl(styles.root, className)}>
      {children}
    </div>
  )
}

container/index.ts

export { Container } from './container.ui'

Дочерние компоненты

Если модулю нужны внутренние подкомпоненты — генерировать их из шаблона component в папку ui/ внутри родительского модуля. Дочерние компоненты не экспортируются через index.ts родителя.