7.9 KiB
title, description
| title | description |
|---|---|
| Компонент | Как должен выглядеть сгенерированный React-компонент внутри SLM-модуля. |
Компонент
Как должен выглядеть сгенерированный React-компонент внутри SLM-модуля.
Назначение
Архитектурное определение компонента описано в разделе Модули → Компонент, а структура сегмента ui/ — в разделе Сегменты → ui/.
Эта страница не повторяет архитектурные ограничения. Она показывает, каким должен быть результат генерации компонента: структура папки, .tsx, типы, стили и локальный экспорт.
::: danger Компоненты не создаются вручную Компоненты в проекте создаются только через кодогенератор: через VS Code или CLI.
Ручное создание компонента запрещено. Это грубое нарушение правил работы в проекте для разработчика и AI-ассистента.
Если в проекте нет шаблона .templates/component, сначала создайте шаблон по разделу Создание шаблонов, и только потом генерируйте компонент на его основе.
:::
Создание
- Проверьте, что в проекте есть шаблон
.templates/component. - Если шаблона нет — создайте его по разделу Создание шаблонов.
- Сгенерируйте компонент через VS Code или CLI.
Структура и код ниже показывают ожидаемый результат генерации. Их нельзя использовать как инструкцию для ручного создания файлов.
Структура
Компонент размещается в ui/{component-name}/ родительского модуля.
Для каждого компонента обязательны .tsx, типы, стили и локальный index.ts.
user-card/
└── ui/
└── user-status/
├── styles/
│ └── user-status.module.css
├── types/
│ └── user-status-props.type.ts
├── user-status.tsx
└── index.ts
Реализация
Пример ниже показывает файлы базового компонента.
Типы
Файл типов делится на три части:
UserStatusParams— собственные параметры компонента. Здесь лежат только данные, которые нужны именно этому компоненту.RootAttrs— параметры корневой обёртки:div,span,a,buttonили другого HTML-элемента. Если компонент сам управляетchildren, они исключаются черезOmit.UserStatusProps— итоговые пропсы компонента. Тип объединяет собственные параметры и параметры корневой обёртки.
Собственные параметры и их поля документируются по правилам раздела Документирование → Типы, интерфейсы, enum.
user-card/ui/user-status/types/user-status-props.type.ts
import type { ComponentPropsWithoutRef } from 'react'
/**
* Параметры UserStatus.
*/
export type UserStatusParams = {
/** Текст статуса пользователя. */
label: string
/** Доступен ли пользователь сейчас. */
isOnline: boolean
}
/** Атрибуты корневого элемента без children. */
type RootAttrs = Omit<ComponentPropsWithoutRef<'span'>, 'children'>
export type UserStatusProps = RootAttrs & UserStatusParams
TSX
В .tsx лежит только сам компонент:
- Компонент объявляется через
constи именованный экспорт. React.FCне используется.- Параметры компонента типизируются через
Props. - Возвращаемый тип не указывается: TypeScript корректно выводит JSX-результат, а явный
ReactElementсужает допустимые варианты возврата. - JSDoc-комментарий обязателен и пишется по правилам раздела Документирование → Компоненты.
- Пропсы деструктурируются в теле компонента, а не в сигнатуре.
- Из пропсов обязательно выделяются
classNameи...rootAttrs. - Функция конкатенации CSS-классов импортируется и именуется
cl. - Корневой CSS-класс всегда называется
.root.
Комментарий описывает назначение и сценарии применения компонента, а не DOM-разметку или внутреннюю реализацию.
className — внешний CSS-класс, который родитель может передать компоненту. rootAttrs — остальные атрибуты корневой обёртки: id, aria-*, data-*, обработчики событий и другие HTML-атрибуты. Они прокидываются на корневой DOM-элемент компонента.
.root нужен, чтобы в DevTools быстро находить корневой DOM-узел компонента и одинаково подключать внешний className к реальному корню.
user-card/ui/user-status/user-status.tsx
import cl from 'clsx'
import type { UserStatusProps } from './types/user-status-props.type'
import styles from './styles/user-status.module.css'
/**
* Статус пользователя в карточке профиля.
*
* Используется для:
* - отображения текущей доступности пользователя
* - визуального выделения онлайн- и офлайн-состояний
*/
export const UserStatus = (props: UserStatusProps) => {
const { label, isOnline, className, ...rootAttrs } = props
return (
<span
{...rootAttrs}
className={cl(styles.root, isOnline && styles.online, className)}
>
{label}
</span>
)
}
Стили
user-card/ui/user-status/styles/user-status.module.css
.root {
display: inline-flex;
align-items: center;
gap: 6px;
color: var(--color-text-muted);
}
.root::before {
content: '';
width: 6px;
height: 6px;
border-radius: 50%;
background: currentColor;
}
.online {
color: var(--color-success);
}
Локальный экспорт
user-card/ui/user-status/index.ts
export { UserStatus } from './user-status'
export type { UserStatusProps } from './types/user-status-props.type'