166 lines
7.9 KiB
Markdown
166 lines
7.9 KiB
Markdown
|
|
---
|
|||
|
|
title: Компонент
|
|||
|
|
description: Как должен выглядеть сгенерированный React-компонент внутри SLM-модуля.
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Компонент
|
|||
|
|
|
|||
|
|
Как должен выглядеть сгенерированный React-компонент внутри SLM-модуля.
|
|||
|
|
|
|||
|
|
## Назначение
|
|||
|
|
|
|||
|
|
Архитектурное определение компонента описано в разделе [Модули → Компонент](/docs/basics/architecture/modules#компонент), а структура сегмента `ui/` — в разделе [Сегменты → ui/](/docs/basics/architecture/segments#сегмент-ui).
|
|||
|
|
|
|||
|
|
Эта страница не повторяет архитектурные ограничения. Она показывает, каким должен быть результат генерации компонента: структура папки, `.tsx`, типы, стили и локальный экспорт.
|
|||
|
|
|
|||
|
|
::: danger Компоненты не создаются вручную
|
|||
|
|
Компоненты в проекте создаются только через кодогенератор: через [VS Code](/docs/applied/templates/templates-usage#через-vs-code) или [CLI](/docs/applied/templates/templates-usage#через-cli).
|
|||
|
|
|
|||
|
|
Ручное создание компонента запрещено. Это грубое нарушение правил работы в проекте для разработчика и AI-ассистента.
|
|||
|
|
|
|||
|
|
Если в проекте нет шаблона `.templates/component`, сначала создайте шаблон по разделу [Создание шаблонов](/docs/applied/templates/templates-create), и только потом генерируйте компонент на его основе.
|
|||
|
|
:::
|
|||
|
|
|
|||
|
|
## Создание
|
|||
|
|
|
|||
|
|
1. Проверьте, что в проекте есть шаблон `.templates/component`.
|
|||
|
|
2. Если шаблона нет — создайте его по разделу [Создание шаблонов](/docs/applied/templates/templates-create).
|
|||
|
|
3. Сгенерируйте компонент через [VS Code или CLI](/docs/applied/templates/templates-usage).
|
|||
|
|
|
|||
|
|
Структура и код ниже показывают ожидаемый результат генерации. Их нельзя использовать как инструкцию для ручного создания файлов.
|
|||
|
|
|
|||
|
|
## Структура
|
|||
|
|
|
|||
|
|
Компонент размещается в `ui/{component-name}/` родительского модуля.
|
|||
|
|
|
|||
|
|
Для каждого компонента обязательны `.tsx`, типы, стили и локальный `index.ts`.
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
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](/docs/basics/documentation#типы-интерфейсы-enum).
|
|||
|
|
|
|||
|
|
`user-card/ui/user-status/types/user-status-props.type.ts`
|
|||
|
|
|
|||
|
|
```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-комментарий обязателен и пишется по правилам раздела [Документирование → Компоненты](/docs/basics/documentation#компоненты).
|
|||
|
|
- Пропсы деструктурируются в теле компонента, а не в сигнатуре.
|
|||
|
|
- Из пропсов обязательно выделяются `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`
|
|||
|
|
|
|||
|
|
```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`
|
|||
|
|
|
|||
|
|
```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`
|
|||
|
|
|
|||
|
|
```ts
|
|||
|
|
export { UserStatus } from './user-status'
|
|||
|
|
export type { UserStatusProps } from './types/user-status-props.type'
|
|||
|
|
```
|