Files
nick-doc/05 - Design System/Components.md
2026-05-23 20:35:34 +03:30

223 lines
7.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Components
tags: [design-system, components, ui]
created: 2026-05-23
---
# Components
Inventory of reusable components in `frontend/src/components/`. Each component lives in its own folder (`index.ts` + `<name>.tsx` + `classes.ts` + `types.ts`).
> [!info]
> Pattern: components are reusable **and free of business logic**. Page-specific composition lives in `frontend/src/sections/`. Hooks that fetch data live in `frontend/src/hooks/`.
---
## 1. Form components (`components/hook-form/`)
RHF + MUI wrappers. Used inside a `<FormProvider {...methods}>` context. All accept `name`, plus the MUI props of the underlying component.
| Component | Wraps | Notes |
|---|---|---|
| `RHFTextField` | `TextField` | The workhorse text input |
| `RHFSelect` | `Select` + `MenuItem` | Pass `children={<MenuItem value="..."/>...}` |
| `RHFAutocomplete` | `Autocomplete` | Async-loader friendly; pass `options` |
| `RHFCheckbox` | `Checkbox` + `FormControlLabel` | Single boolean |
| `RHFMultiCheckbox` | grid of checkboxes | Returns `string[]` |
| `RHFRadioGroup` | `RadioGroup` | Returns selected value |
| `RHFSwitch` | `Switch` + label | Boolean toggle |
| `RHFEditor` | TipTap wrapper | HTML output |
| `RHFUpload` | `components/upload` Dropzone | Single or multiple |
| `RHFDatePicker` | `@mui/x-date-pickers DatePicker` | Locale-aware |
| `RHFDateTimePicker` | `DateTimePicker` | — |
| `RHFTimePicker` | `TimePicker` | — |
| `RHFPhoneInput` | `react-phone-number-input` | E.164 output |
| `RHFCountrySelect` | `components/country-select` | ISO-2 output |
| `RHFNumberInput` | `components/number-input` | Locale-formatted, accepts min/max/step |
| `RHFRating` | `Rating` | 05 |
| `RHFSlider` | `Slider` | Single or range |
> [!tip]
> Form-level errors render automatically via `formState.errors[name]` — pass `helperText={errors.name?.message}` is **not needed**; the wrapper handles it.
---
## 2. Data display
| Component | Purpose |
|---|---|
| `custom-data-grid/` | MUI DataGrid Pro wrapper — sets density, locale, custom toolbar, RTL support |
| `table/` | Lower-level table utilities (head, pagination, no-data row, skeleton) |
| `chart/` | ApexCharts wrapper with theme-synced palette |
| `markdown/` | `react-markdown` + `remark-gfm` for chat/evidence rendering |
| `lightbox/` | Image gallery (gallery / dispute evidence) |
| `image/` | Next `Image` wrapper with fallback skeleton + error state |
| `file-thumbnail/` | Renders icon by MIME type for non-image files |
| `flag-icon/` | Country flag SVG (used in phone input, locale switcher) |
| `iconify/` | Iconify SVG wrapper — `<Iconify icon="solar:user-bold" />` |
| `svg-color/` | Renders SVG with `color` prop (mask-image trick) |
---
## 3. Navigation
| Component | Purpose |
|---|---|
| `nav-section/` | Sidebar nav with role-filtering, group headers, mini variant |
| `nav-basic/` | Simple horizontal nav for marketing pages |
| `custom-breadcrumbs/` | Page header breadcrumbs + action slot |
| `progress-bar/` | NProgress integration for route transitions |
The sidebar reads from a configuration array — see `src/layouts/dashboard/config-nav-dashboard.ts` (or similar) — where each entry can specify `roles: ['admin']` to hide from other users.
---
## 4. Feedback
| Component | Purpose |
|---|---|
| `snackbar/` | Notistack wrapper — `enqueueSnackbar('Done', { variant: 'success' })` |
| `loading-screen/` | Full-screen splash for boot or guarded routes |
| `empty-content/` | "No results" placeholder with illustration |
| `search-not-found/` | Variant of empty-content for failed searches |
| `email-verification-banner/` | Persistent top banner when email unverified |
---
## 5. Overlays & dialogs
| Component | Purpose |
|---|---|
| `custom-dialog/` | Modal dialog with title/content/actions slots |
| `custom-popover/` | Click-or-hover popover (used for menus, tooltips, info) |
---
## 6. Inputs (raw, non-RHF)
| Component | Purpose |
|---|---|
| `number-input/` | Numeric with +/- buttons + locale format |
| `phone-input/` | Phone with country selector |
| `country-select/` | Country dropdown |
| `incrementer-button/` | Tiny `` / `+` quantity stepper |
| `upload/` | Dropzone with progress, preview, removal |
---
## 7. User & profile
| Component | Purpose |
|---|---|
| `user-avatar/` | Hashes name → color; respects `src` if avatar uploaded |
| `user-profile-card/` | Profile summary card (name, role, level, points) |
| `notifications-drawer/` | Side drawer listing notifications, mark-as-read |
---
## 8. Media
| Component | Purpose |
|---|---|
| `video-player/` | Plyr / video.js wrapper for blog & template videos |
| `map/` | Mapbox + react-map-gl wrapper (delivery addresses) |
| `carousel/` | Embla carousel — multiple variants in `hooks/use-carousel-*` |
---
## 9. Animation
| Component | Purpose |
|---|---|
| `animate/` | Framer-motion presets (fade, slide, scale) for page transitions and lists |
---
## 10. Utility
| Component | Purpose |
|---|---|
| `scrollbar/` | SimpleBar wrapper — themed scrollbar with shadow on overflow |
| `label/` | Tag/badge — variants: filled, outlined, soft |
| `filters-result/` | Active filter chips with × to remove |
| `logo/` | App logo SVG (responsive: full mark + icon-only at small width) |
| `color-utils/` | Color manipulation helpers (alpha, darken, contrast) |
---
## 11. Settings
| Component | Purpose |
|---|---|
| `settings/` | The mounted Settings drawer + provider hooks |
---
## 12. Debug
| Component | Purpose |
|---|---|
| `debug/` | Dev-only diagnostic overlays (only rendered when `NEXT_PUBLIC_ENABLE_DEBUG=true`) |
---
## 13. Editor (`components/editor/`)
TipTap rich-text editor with this extension set:
- `StarterKit` (paragraph, headings, bold/italic, lists, blockquote, history)
- `Link` (URL parsing, target=_blank by default for external)
- `Image` (drag-drop, uploads via `components/upload`)
- `Underline`, `TextAlign`
- `CodeBlock` + `CodeBlockLowlight` (syntax highlighting via `lowlight`)
- `Placeholder`
Output: HTML string. Round-trip safe with `react-markdown` + `turndown` when Markdown storage is preferred.
Used in:
- Blog post editor (`dashboard/post/new`)
- Long-form description fields (request, template)
- Dispute evidence narrative
---
## 14. Payment-specific (`components/payment/`)
| Component | Purpose |
|---|---|
| `<TokenSelector>` | USDT / USDC / BTC / ETH chip selector |
| `<NetworkSelector>` | BSC / TRC20 / Ethereum / Polygon chip selector |
| `<QrInvoice>` | Renders the SHKeeper invoice QR + copy-address button |
| `<PaymentStatus>` | Live status pill that updates from socket events |
(Confirm names against actual exports — these are typical for this stack.)
---
## 15. Adding a new component
1. Create `src/components/<kebab-name>/` with `index.ts`, `<kebab-name>.tsx`, `classes.ts`, `types.ts`.
2. Re-export from `src/components/<kebab-name>/index.ts`: `export * from './<kebab-name>'`.
3. Place ONLY rendering + styling; do NOT call `useQuery` / `useMutation` — pass data via props.
4. Use the `sx` prop, not styled-components, unless the styling is non-trivial.
5. Cover with at least one Jest snapshot test in `__tests__/`.
---
## 16. Component vs Section vs Hook decision
| Question | Where it goes |
|---|---|
| "I want to render a chip with a delete icon." | `components/` |
| "I want a chat sidebar with conversation list + active chat + composer." | `sections/chat/` |
| "I want to subscribe to chat updates and keep the cache in sync." | `hooks/use-chat-socket.ts` |
---
## 17. Related
- [[Design System Overview]] · [[Theme Configuration]] · [[Colors]] · [[Typography]]
- [[Layouts]] · [[Internationalization & RTL]]
- [[Frontend Architecture]] — where these components live in the bigger picture
- [[Coding Standards]] — file layout & import order rules