docs(design-system): add foundation implementation plan

This commit is contained in:
Sergey Krylov 2026-06-21 09:13:19 +03:00
parent e8dcb27a03
commit ec13fa8ca2
3 changed files with 712 additions and 1 deletions

View File

@ -0,0 +1,643 @@
# Design System Foundation Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Создать внутренний пакет `@moex-vibe/design-system` с трёхуровневыми токенами, MUI light theme, согласованным UI-каталогом, Storybook и опубликованными правилами.
**Architecture:** Platform-neutral токены хранятся как JSON-compatible TypeScript records и разрешаются собственным проверяемым resolver. MUI-адаптер переводит semantic/component tokens в CSS-variable theme; React-компоненты доступны только через public exports пакета. Storybook служит локальным/CI workbench, Docusaurus — единственной опубликованной документацией.
**Tech Stack:** TypeScript 5, React 18, MUI 6.5, TanStack Table 8, Vitest 4 browser mode, Storybook 10.2 (`@storybook/react-vite`), Playwright Chromium, Docusaurus 3.7.
---
## Зафиксированные интерфейсы
Пакет предоставляет subpath exports:
```json
{
".": "./dist/index.js",
"./tokens": "./dist/tokens/index.js",
"./theme": "./dist/theme/index.js"
}
```
Token source использует плоские DTCG-подобные записи:
```ts
type TokenType = 'color' | 'dimension' | 'fontFamily' | 'fontWeight' | 'duration' | 'cubicBezier' | 'shadow';
type TokenValue = string | number | readonly number[] | readonly string[];
type TokenDefinition = { readonly $type: TokenType; readonly $value: TokenValue };
type TokenCollection = Readonly<Record<string, TokenDefinition>>;
// Primitive содержит абсолютное значение.
'color.green.700': { $type: 'color', $value: '#176747' }
// Semantic/component содержит alias и никогда не дублирует primitive.
'color.action.primary': { $type: 'color', $value: '{color.green.700}' }
```
Публичный React API:
```ts
type Tone = 'default' | 'secondary' | 'positive' | 'negative' | 'muted';
type Density = 'balanced' | 'compact';
type ActionVariant = 'primary' | 'secondary' | 'tertiary' | 'danger';
type TextProps = { variant?: 'body' | 'caption' | 'label' | 'numeric'; tone?: Tone };
type HeadingProps = { level: 1 | 2 | 3 | 4 | 5 | 6; size?: 'display' | 'title' | 'section' | 'subsection' };
type ButtonProps = { variant?: ActionVariant; size?: 'small' | 'medium'; loading?: boolean };
type IconButtonProps = { label: string; size?: 'small' | 'medium' };
type SurfaceProps = { padding?: 'none' | 'sm' | 'md' | 'lg'; elevation?: 'none' | 'sm' | 'md' };
type DataTableProps<T> = { table: Table<T>; density?: Density; loading?: boolean; empty?: ReactNode; caption: string };
type MoneyProps = { value: number; currency?: string; locale?: string; signDisplay?: 'auto' | 'always' | 'never' };
type PriceChangeProps = { value: number; format?: 'percent' | 'money'; currency?: string; locale?: string };
type MetricProps = { label: string; value: ReactNode; supportingText?: ReactNode; trend?: ReactNode };
```
Остальные контракты фиксированы так:
- `Link`: MUI Link без `color`, `variant`, `sx`; добавляет `tone` и сохраняет polymorphic `component`.
- `TextField`: MUI TextField без `color`, `variant`, `size`, `sx`; всегда `variant="outlined"` и
`size="medium"`.
- `Select`: `label`, `value`, `onChange(value: string)`, `options: { value; label; disabled? }[]`,
`error?`, `helperText?`, `disabled?`.
- `Checkbox`: `label`, `checked`, `onChange(checked: boolean)`, `disabled?`, `error?`.
- `Card`: Surface props плюс `header?`, `actions?`, `children`; не знает маршруты и домен.
- `Chip`: `label`, `tone: neutral|info|success|warning|error`, `onDelete?`.
- `Badge`: `value`, `max?`, `label`; decorative badge запрещён без accessible label.
- `Alert`: `severity: info|success|warning|error`, `title?`, `children`, `action?`.
- `Dialog`: `open`, `onClose`, обязательные `title`, `children`, `actions?`.
- `Skeleton`: `width?`, `height?`, `shape: text|rectangular|rounded|circular`.
- `Progress`: `label`, `value?`; отсутствие value означает indeterminate.
- `FormField`: `label`, `htmlFor`, `helperText?`, `error?`, `required?`, `children`.
- `FilterBar`: `children`, `actions?`; отвечает только за responsive layout.
- Page states: обязательный `title`, optional `description/action`; `LoadingState` дополнительно имеет
`label` и `size: section|page`.
Все wrappers запрещают произвольные `color`, `variant`, `size` и `sx`, где они обходят контракт.
`Box`, `Stack`, `Grid` остаются полным и единственным прямым MUI allowlist во frontend.
## Карта файлов
- `packages/design-system/src/tokens/` — schema, три token collections, resolver и guards.
- `packages/design-system/src/theme/` — MUI augmentation, theme factory, provider, component overrides.
- `packages/design-system/src/components/` — Core UI и product patterns; один каталог на компонент.
- `packages/design-system/.storybook/` — единый provider, a11y и browser-test annotations.
- `apps/frontend/src/app/providers/AppProviders.tsx` — подключение provider пакета без миграции страниц.
- `apps/docs/docs/design-system/` — канонические правила; `apps/docs/docs/adr/ADR-016-design-system.md` — архитектурное решение.
### Task 1: Pre-flight и workspace shell
**Files:**
- Modify: `package.json`
- Create: `packages/design-system/package.json`
- Create: `packages/design-system/tsconfig.json`
- Create: `packages/design-system/vitest.config.ts`
- Create: `packages/design-system/.eslintrc.cjs`
- Create: `packages/design-system/src/test/setup.ts`
- Create: `packages/design-system/src/index.ts`
- [ ] **Step 1: Проверить pre-flight до любых implementation edits**
Run:
```bash
git branch --show-current
git status --short
npm run test:backend
npm run test:frontend
npm run lint
npm run build:backend
npm run build:frontend
```
Expected: ветка `codex/design-system-foundation`, чистый worktree и все команды PASS. При сбое
остановиться и классифицировать его до изменения кода.
- [ ] **Step 2: Добавить workspace и root scripts**
В `package.json` добавить `packages/design-system` в `workspaces` и scripts:
```json
{
"build:design-system": "npm run build -w packages/design-system",
"test:design-system": "npm run test -w packages/design-system",
"lint:design-system": "npm run lint -w packages/design-system",
"storybook": "npm run storybook -w packages/design-system",
"build:storybook": "npm run build-storybook -w packages/design-system",
"test:storybook": "npm run test:storybook -w packages/design-system"
}
```
- [ ] **Step 3: Создать package manifest и TypeScript build**
`packages/design-system/package.json` должен быть private ESM package версии `0.1.0`, иметь `files:
["dist"]`, exports из раздела выше, peer dependencies на React 18, MUI 6 и TanStack Table 8, dev
dependencies Storybook `^10.2.9`, `@vitest/browser-playwright`/Vitest `^4.1.8` и Playwright, scripts
`build: tsc -p tsconfig.json`, `test: vitest run --project unit`, `storybook: storybook dev -p 6006
--no-open`, `build-storybook: storybook build`, `test:storybook: vitest run --project storybook`,
`lint: eslint "src/**/*.{ts,tsx}"`.
`tsconfig.json` компилирует `src` в `dist`, включает declarations, `jsx: react-jsx`, strict и
`moduleResolution: bundler`. `vitest.config.ts` сначала содержит unit project с jsdom и
`passWithNoTests: true`; флаг удаляется после Task 2. Test setup подключает jest-dom и matchMedia mock.
Package ESLint config проверяет TypeScript/React hooks, но не включает frontend FSD zones. Root `lint`
дополняется `lint:design-system`.
- [ ] **Step 4: Установить зависимости и проверить пустой пакет**
Run:
```bash
npm install
npm run build:design-system
npm run test:design-system
```
Expected: package-lock обновлён, build PASS, Vitest PASS с `passWithNoTests: true`.
- [ ] **Step 5: Commit**
```bash
git add package.json package-lock.json packages/design-system
git commit -m "build(design-system): add workspace package"
```
### Task 2: Token schema и resolver (TDD)
**Files:**
- Create: `packages/design-system/src/tokens/types.ts`
- Create: `packages/design-system/src/tokens/resolveToken.ts`
- Test: `packages/design-system/src/tokens/resolveToken.test.ts`
- [ ] **Step 1: Написать failing tests**
```ts
it('resolves an alias chain and preserves the declared type', () => {
const tokens = {
base: { $type: 'color', $value: '#176747' },
semantic: { $type: 'color', $value: '{base}' },
component: { $type: 'color', $value: '{semantic}' },
} satisfies TokenCollection;
expect(resolveToken(tokens, 'component')).toEqual({ type: 'color', value: '#176747' });
});
it.each([
['missing alias', { a: { $type: 'color', $value: '{missing}' } }, /Unknown token/],
['cycle', { a: { $type: 'color', $value: '{b}' }, b: { $type: 'color', $value: '{a}' } }, /cycle/i],
['type mismatch', { a: { $type: 'color', $value: '#fff' }, b: { $type: 'dimension', $value: '{a}' } }, /type/i],
])('rejects %s', (_name, tokens, error) => expect(() => resolveToken(tokens, 'a')).toThrow(error));
```
- [ ] **Step 2: Запустить тест и подтвердить RED**
Run: `npm run test:design-system -- resolveToken.test.ts`
Expected: FAIL, module/functions отсутствуют.
- [ ] **Step 3: Реализовать schema и resolver**
Resolver распознаёт только полную alias-строку `/^\{([^}]+)\}$/`, хранит visited path, проверяет
существование target и равенство `$type`, возвращает `{ type, value }`. Смешанные строки вроде
`calc({space.2} * 2)` запрещены.
- [ ] **Step 4: Запустить тест и commit**
Run: `npm run test:design-system -- resolveToken.test.ts`
Expected: PASS.
```bash
git add packages/design-system/src/tokens
git commit -m "feat(design-system): add token contracts"
```
### Task 3: Три уровня токенов
**Files:**
- Create: `packages/design-system/src/tokens/primitives.ts`
- Create: `packages/design-system/src/tokens/semantic.light.ts`
- Create: `packages/design-system/src/tokens/components.ts`
- Create: `packages/design-system/src/tokens/index.ts`
- Test: `packages/design-system/src/tokens/tokens.test.ts`
- [ ] **Step 1: Написать token integrity tests**
Тест объединяет три collections, резолвит каждый token, проверяет уникальные имена и инварианты:
```ts
expect(Object.keys(primitiveTokens).every((name) => !isAlias(primitiveTokens[name].$value))).toBe(true);
expect(Object.keys(semanticLightTokens).every((name) => isAlias(semanticLightTokens[name].$value))).toBe(true);
expect(Object.keys(componentTokens).every((name) => isAlias(componentTokens[name].$value))).toBe(true);
for (const name of Object.keys(allTokens)) expect(() => resolveToken(allTokens, name)).not.toThrow();
```
- [ ] **Step 2: Запустить тест и подтвердить RED**
Run: `npm run test:design-system -- tokens.test.ts`
Expected: FAIL, collections отсутствуют.
- [ ] **Step 3: Добавить минимальный полный набор foundations**
Primitive groups: `color.neutral.{0,50,100,200,400,600,800,900}`, `color.green.{50,100,600,700,800}`,
`color.red.{50,600,700}`, `color.amber.{50,600}`, `color.blue.{50,600}`, `space.{0,1,2,3,4,5,6,8,10,12}`
на 4px grid, `radius.{none,sm,md,lg,pill}`, `font.family.{sans,mono}`, `font.size.{100..700}`,
`font.weight.{regular,medium,semibold,bold}`, `lineHeight.{tight,normal,relaxed}`, `shadow.{none,sm,md}`,
`duration.{instant,fast,normal}`, `easing.standard`, `size.control.{sm,md}`.
`font.family.sans` использует Inter с system-ui fallback. Webfont weights 400/500/600/700 подключаются
один раз во frontend shell в Task 10; Roboto не становится частью нового foundation.
Semantic groups: `color.canvas`, `color.surface.{default,subtle,raised}`, `color.text.{primary,secondary,
disabled,inverse}`, `color.border.{subtle,default,strong,focus}`, `color.action.{primary,primaryHover,
secondary,danger}`, `color.feedback.{info,success,warning,error}`, `color.finance.{positive,negative,
neutral}`, plus semantic typography, focus ring, spacing and control sizes.
Component groups cover только API v1: button, iconButton, field, checkbox, surface, card, chip, badge,
alert, dialog, skeleton, progress, table, metric и pageState.
- [ ] **Step 4: Проверить GREEN и запрет hardcoded values вне primitives**
Run: `npm run test:design-system -- tokens.test.ts`
Expected: PASS. Дополнительный test scan подтверждает, что `semantic.light.ts` и `components.ts` не
содержат hex/rgb/px literals.
- [ ] **Step 5: Commit**
```bash
git add packages/design-system/src/tokens
git commit -m "feat(design-system): define three-level tokens"
```
### Task 4: MUI adapter и provider (TDD)
**Files:**
- Create: `packages/design-system/src/theme/createMoexVibeTheme.ts`
- Create: `packages/design-system/src/theme/MoexVibeThemeProvider.tsx`
- Create: `packages/design-system/src/theme/mui.d.ts`
- Create: `packages/design-system/src/theme/index.ts`
- Test: `packages/design-system/src/theme/createMoexVibeTheme.test.ts`
- [ ] **Step 1: Написать failing theme contract tests**
```ts
const theme = createMoexVibeTheme();
expect(theme.cssVarPrefix).toBe('mv');
expect(theme.colorSchemes.light.palette.primary.main).toBe(resolveValue('color.action.primary'));
expect(theme.typography.body1.fontFamily).toContain('Inter');
expect(theme.shape.borderRadius).toBe(resolveValue('radius.md'));
expect(theme.components?.MuiButton?.defaultProps).toMatchObject({ disableElevation: true });
```
- [ ] **Step 2: Подтвердить RED**
Run: `npm run test:design-system -- createMoexVibeTheme.test.ts`
Expected: FAIL, factory отсутствует.
- [ ] **Step 3: Реализовать adapter**
Использовать `createTheme({ cssVariables: { cssVarPrefix: 'mv' }, colorSchemes: { light: ... } })`.
Theme получает palette, typography, spacing, shape, shadows, transitions и component overrides только
через `resolveValue`. `mui.d.ts` включает `themeCssVarsAugmentation` и добавляет `finance` palette roles.
- [ ] **Step 4: Реализовать provider**
`MoexVibeThemeProvider` оборачивает MUI `ThemeProvider` и `CssBaseline`, принимает только `children`;
mode API в v1 не экспортируется.
- [ ] **Step 5: Проверить и commit**
Run: `npm run test:design-system -- createMoexVibeTheme.test.ts && npm run build:design-system`
Expected: PASS.
```bash
git add packages/design-system/src/theme packages/design-system/src/tokens
git commit -m "feat(design-system): add MUI theme adapter"
```
### Task 5: Storybook и automated story checks
**Files:**
- Create: `packages/design-system/.storybook/main.ts`
- Create: `packages/design-system/.storybook/preview.tsx`
- Create: `packages/design-system/.storybook/vitest.setup.ts`
- Modify: `packages/design-system/vitest.config.ts`
- Modify: `packages/design-system/package.json`
- [ ] **Step 1: Настроить Storybook 10.2**
```ts
const config: StorybookConfig = {
framework: '@storybook/react-vite',
stories: ['../src/**/*.stories.@(ts|tsx)'],
addons: ['@storybook/addon-a11y', '@storybook/addon-vitest'],
};
```
`preview.tsx` добавляет decorator `MoexVibeThemeProvider`, background `color.canvas` и параметры
`a11y.test = 'error'`, layout `centered` по умолчанию.
- [ ] **Step 2: Добавить Storybook Vitest browser project**
Использовать `storybookTest`, `@vitest/browser-playwright` и headless Chromium; setup регистрирует
`@storybook/addon-a11y/preview` и project annotations через `setProjectAnnotations`.
- [ ] **Step 3: Проверить стенд**
Run:
```bash
npx playwright install chromium
npm run build:storybook
```
Expected: static Storybook build PASS. Первый `test:storybook` запускается после появления stories в
Task 6.
- [ ] **Step 4: Commit**
```bash
git add package.json package-lock.json packages/design-system
git commit -m "build(design-system): configure Storybook workbench"
```
### Task 6: Typography и actions (TDD)
**Files:**
- Create: `packages/design-system/src/components/{Text,Heading,Link,Button,IconButton}/`
- Test: colocated `*.test.tsx`
- Stories: colocated `*.stories.tsx`
- [ ] **Step 1: Написать failing interaction/type tests**
Проверить semantic heading level, tone mapping, external link rel, loading button disabled state и
progress label, обязательный accessible label IconButton. Type tests отклоняют `color`, произвольный
`variant` и `sx`.
- [ ] **Step 2: Подтвердить RED**
Run: `npm run test:design-system -- Text Heading Link Button IconButton`
Expected: FAIL, exports отсутствуют.
- [ ] **Step 3: Реализовать компоненты по public contracts**
Каждый каталог содержит component, props и index. `Button loading` сохраняет ширину, блокирует повторный
click и имеет `aria-busy`; `IconButton` всегда устанавливает `aria-label={label}`.
- [ ] **Step 4: Добавить stories и проверить GREEN**
Stories: все variants/sizes/tones, disabled, loading, long Russian label, keyboard focus reference.
Run: `npm run test:design-system && npm run test:storybook && npm run build:storybook`
Expected: PASS без a11y violations.
- [ ] **Step 5: Commit**
```bash
git add packages/design-system/src
git commit -m "feat(design-system): add typography and actions"
```
### Task 7: Inputs, surfaces и feedback (TDD)
**Files:**
- Create: `packages/design-system/src/components/{TextField,Select,Checkbox,Surface,Card,Chip,Badge,Alert,Dialog,Skeleton,Progress}/`
- Test/Stories: colocated `*.test.tsx`, `*.stories.tsx`
- [ ] **Step 1: Написать failing contract tests**
Проверить label/helper/error association, Select options и keyboard opening, Checkbox label click,
Surface padding/elevation mapping, Dialog focus/escape/label, Alert role, determinate/indeterminate
Progress accessible name и Skeleton `aria-hidden`.
- [ ] **Step 2: Подтвердить RED**
Run: `npm run test:design-system -- TextField Select Checkbox Surface Card Chip Badge Alert Dialog Skeleton Progress`
Expected: FAIL, components отсутствуют.
- [ ] **Step 3: Реализовать ограниченные wrappers**
`Select` принимает `{ value: string; label: string; disabled?: boolean }[]`; `Checkbox` требует `label`;
`Dialog` требует `title` и управляется через `open/onClose`; Surface/Card не принимают raw elevation.
- [ ] **Step 4: Stories, GREEN и commit**
Stories покрывают default/focus/disabled/error/loading, длинный русский текст и narrow viewport.
Run: `npm run test:design-system && npm run test:storybook && npm run build:storybook`
Expected: PASS.
```bash
git add packages/design-system/src
git commit -m "feat(design-system): add controls and feedback"
```
### Task 8: Финансовые data patterns (TDD)
**Files:**
- Create: `packages/design-system/src/components/{DataTable,Metric,Money,PriceChange}/`
- Test/Stories: colocated `*.test.tsx`, `*.stories.tsx`
- Test: `packages/design-system/src/visual/financial-patterns.visual.test.ts`
- [ ] **Step 1: Написать failing tests**
Проверить table caption, semantic headers, sortable button `aria-sort`, balanced/compact density, loading
и empty states; `Money` через `Intl.NumberFormat`; `PriceChange` знак, текстовое направление и не только
цвет; `Metric` composition.
- [ ] **Step 2: Подтвердить RED**
Run: `npm run test:design-system -- DataTable Metric Money PriceChange`
Expected: FAIL.
- [ ] **Step 3: Реализовать patterns**
`DataTable` принимает готовый TanStack `Table<T>` и не владеет server pagination/sorting. Defaults:
`density="balanced"`, locale `ru-RU`, currency `RUB`. Negative/positive output включает видимый знак и
screen-reader label.
- [ ] **Step 4: Stories, visual baselines и commit**
Canonical screenshot cases: balanced table, compact table, positive/negative metrics, empty/loading.
Browser test запускает portable stories через `composeStories`, затем делает
`expect(page.getByTestId('visual-root')).toMatchScreenshot('<stable-name>.png')`; baselines коммитятся
рядом с visual test. Обновление baseline допустимо только вместе с объяснением визуального изменения.
Run: `npm run test:design-system && npm run test:storybook`
Expected: interaction, a11y и screenshot checks PASS.
```bash
git add packages/design-system/src
git commit -m "feat(design-system): add financial data patterns"
```
### Task 9: Form и page-state patterns (TDD)
**Files:**
- Create: `packages/design-system/src/components/{FormField,FilterBar,EmptyState,ErrorState,LoadingState}/`
- Test/Stories: colocated `*.test.tsx`, `*.stories.tsx`
- [ ] **Step 1: Написать failing tests**
Проверить `htmlFor`/description/error association FormField, wrapping and action placement FilterBar,
semantic heading/action для Empty/Error, `aria-live="polite"` LoadingState и reduced-motion rendering.
- [ ] **Step 2: RED, implementation, GREEN**
Run before: `npm run test:design-system -- FormField FilterBar EmptyState ErrorState LoadingState`
Expected before: FAIL. Реализовать только layout/semantics без API/domain knowledge.
Run after: `npm run test:design-system && npm run test:storybook`
Expected after: PASS.
- [ ] **Step 3: Commit**
```bash
git add packages/design-system/src
git commit -m "feat(design-system): add form and page-state patterns"
```
### Task 10: Frontend integration и MUI boundary
**Files:**
- Modify: `apps/frontend/package.json`
- Modify: `apps/frontend/tsconfig.json`
- Modify: `apps/frontend/vite.config.ts`
- Modify: `apps/frontend/src/app/providers/AppProviders.tsx`
- Modify: `apps/frontend/.eslintrc.cjs`
- Delete: `apps/frontend/src/app/styles/theme.ts`
- Test: `apps/frontend/src/app/providers/AppProviders.test.tsx`
- [ ] **Step 1: Написать failing provider test**
Render `AppProviders`, assert generated `--mv-palette-primary-main` exists and Query/Session providers
по-прежнему доступны. Test не проверяет редизайн страниц.
- [ ] **Step 2: Подключить workspace package**
Добавить dependency, `@fontsource/inter` и aliases к source для dev/test; заменить MUI
ThemeProvider/CssBaseline на `MoexVibeThemeProvider`. Удалить старый локальный theme и импортировать
Inter 400/500/600/700 в provider entry ровно один раз.
- [ ] **Step 3: Зафиксировать ESLint allowlist**
Во frontend запретить root import `@mui/material` и subpaths через `no-restricted-imports`; исключить
только `@mui/material/Box`, `Stack`, `Grid`. Сам пакет design-system использует отдельный lint config.
- [ ] **Step 4: Проверить отсутствие визуальной миграции**
Run:
```bash
npm run test:frontend
npm run lint -w apps/frontend
npm run build:design-system
npm run build:frontend
```
Expected: PASS; legacy `styles.css` и product component markup не изменены.
- [ ] **Step 5: Commit**
```bash
git add apps/frontend packages/design-system package.json package-lock.json
git commit -m "feat(frontend): connect design system foundation"
```
### Task 11: Docusaurus и ADR
**Files:**
- Create: `apps/docs/docs/design-system/{overview,foundations,tokens,components,patterns,accessibility,governance}.md`
- Create: `apps/docs/docs/adr/ADR-016-design-system.md`
- Create: `packages/design-system/CHANGELOG.md`
- Modify: `apps/docs/sidebars.ts`
- Modify: `apps/docs/docs/adr/index.md`
- Modify: `apps/docs/docs/frontend/styling.md`
- [ ] **Step 1: Написать канонические правила**
Документы фиксируют light-only v1, balanced density, три token levels, MUI allowlist, каталог,
component-card template, WCAG 2.2 AA и promotion/change process. Components page содержит матрицу
«задача → компонент → не использовать» и полную карточку обязательного шаблона для каждого public
export. `CHANGELOG.md` начинается с `0.1.0` и документирует public API foundation; governance описывает
обязательную migration note для будущих breaking changes.
- [ ] **Step 2: Добавить ADR-016**
ADR содержит Context, варианты theme-only/hybrid/full-wrapper, решение hybrid, последствия, Storybook
роль и будущие DTCG/Android adapters.
- [ ] **Step 3: Обновить sidebar и проверить docs**
Run: `npm run build:docs`
Expected: PASS без broken links; новый раздел виден как отдельная категория «Дизайн-система».
- [ ] **Step 4: Commit**
```bash
git add apps/docs packages/design-system/CHANGELOG.md
git commit -m "docs(design-system): publish usage guidelines"
```
### Task 12: CI, visual checks и финальная верификация
**Files:**
- Modify: `.gitea/workflows/ci.yml`
- Modify: `README.md`
- Modify: `docs/features/design-system-foundation/tasks.md`
- [ ] **Step 1: Добавить CI gates**
После `npm ci` установить Chromium `npx playwright install --with-deps chromium`; добавить design-system
unit/story tests, Storybook build, design-system build и docs build. Сохранять Storybook static build и
visual diff через `actions/upload-artifact@v4` с `if: failure()`.
- [ ] **Step 2: Обновить команды README**
Добавить `npm run storybook`, `build:storybook`, `test:design-system`, `test:storybook`,
`build:design-system` и пояснить, что Docusaurus — published docs, Storybook — engineering workbench.
- [ ] **Step 3: Запустить полный DoD**
```bash
npm run format:check
npm run lint
npm run test:backend
npm run test:frontend
npm run test:design-system
npm run test:storybook
npm run build:backend
npm run build:design-system
npm run build:storybook
npm run build:frontend
npm run build:docs
git diff --check
git status --short
```
Expected: все команды PASS; status содержит только намеренные изменения до финального commit.
- [ ] **Step 4: Обновить SDD tasks и запросить code review**
Отметить выполненные checkbox в `tasks.md`, применить `superpowers:requesting-code-review`, исправить
только подтверждённые scope issues и повторить полный DoD.
- [ ] **Step 5: Final commit**
```bash
git add .gitea/workflows/ci.yml README.md docs/features/design-system-foundation
git commit -m "ci(design-system): enforce foundation quality gates"
```

View File

@ -2,7 +2,7 @@
## Статус
Draft — ожидает ревью пользователя.
Approved — утверждена пользователем 2026-06-21.
## Цель

View File

@ -0,0 +1,68 @@
# Design System Foundation — Tasks
Исполнять по `plan.md` последовательно, используя TDD и отмечая checkbox только после успешной
проверки соответствующего шага.
## 1. Pre-flight и workspace
- [ ] Подтвердить ветку, чистый worktree и зелёные baseline tests/lint/build.
- [ ] Добавить `packages/design-system` в npm workspaces и root scripts.
- [ ] Создать package manifest, TypeScript/Vitest/ESLint configs и test setup.
- [ ] Установить зависимости; проверить пустой package build/test/lint.
- [ ] Закоммитить workspace shell.
## 2. Tokens
- [ ] Написать RED-тесты alias resolver: chain, missing target, cycle, type mismatch.
- [ ] Реализовать token schema и resolver; получить GREEN.
- [ ] Написать RED-тесты целостности трёх token levels.
- [ ] Добавить primitive/reference tokens.
- [ ] Добавить light semantic tokens только через aliases.
- [ ] Добавить component tokens только через semantic aliases.
- [ ] Проверить guards, build и отсутствие hardcoded values вне primitives.
- [ ] Закоммитить token foundation.
## 3. MUI adapter и Storybook
- [ ] Написать RED-тесты MUI theme contract.
- [ ] Реализовать `createMoexVibeTheme`, type augmentation и provider; получить GREEN.
- [ ] Настроить Storybook React/Vite с общим theme decorator.
- [ ] Подключить addon-a11y и Vitest browser project с Playwright Chromium.
- [ ] Проверить package и static Storybook build.
- [ ] Закоммитить theme adapter и Storybook workbench.
## 4. Core UI
- [ ] Реализовать через TDD `Text`, `Heading`, `Link`, `Button`, `IconButton`.
- [ ] Добавить их stories, type checks и a11y checks.
- [ ] Реализовать через TDD `TextField`, `Select`, `Checkbox`.
- [ ] Реализовать через TDD `Surface`, `Card`, `Chip`, `Badge`.
- [ ] Реализовать через TDD `Alert`, `Dialog`, `Skeleton`, `Progress`.
- [ ] Добавить обязательные states, responsive stories и visual baselines.
- [ ] Проверить unit/story/a11y/build gates и закоммитить Core UI.
## 5. Product patterns
- [ ] Реализовать через TDD `DataTable`, включая caption, sorting semantics и density variants.
- [ ] Реализовать через TDD `Metric`, `Money`, `PriceChange` без color-only semantics.
- [ ] Добавить financial stories и стабильные screenshot baselines.
- [ ] Реализовать через TDD `FormField` и `FilterBar`.
- [ ] Реализовать через TDD `EmptyState`, `ErrorState`, `LoadingState`.
- [ ] Проверить unit/story/a11y/visual gates и закоммитить patterns.
## 6. Интеграция и governance
- [ ] Написать RED-тест frontend provider integration.
- [ ] Подключить workspace package и Inter во frontend shell; удалить локальную MUI theme.
- [ ] Enforce ESLint allowlist для `Box`, `Stack`, `Grid`.
- [ ] Подтвердить, что product pages и legacy CSS не мигрированы.
- [ ] Создать Docusaurus-раздел с foundations, catalog, rules и accessibility.
- [ ] Создать ADR-016 и changelog `0.1.0`.
- [ ] Обновить sidebar, styling docs и README; собрать docs.
## 7. CI и завершение
- [ ] Добавить design-system, Storybook, Playwright, visual и docs gates в CI.
- [ ] Запустить полный DoD из Task 12 `plan.md`.
- [ ] Запросить code review и устранить подтверждённые scope issues.
- [ ] Повторить полный DoD, отметить все tasks и сделать финальный commit.