From bd3341269151368eabe83198456cffdd08323771 Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Sun, 21 Jun 2026 16:57:19 +0300 Subject: [PATCH] feat(frontend): migrate HomePage and SearchBar to design system components - HomePage: replace inline styles with , , - SearchBar: replace with ,
    with ,
  • with ++, hardcoded hex with theme tokens - ESLint no-restricted-imports respected via @mui/material/Box deep import - Logic unchanged, all 111 tests pass --- apps/frontend/src/pages/home/ui/HomePage.tsx | 21 ++-- .../src/widgets/search-bar/ui/SearchBar.tsx | 115 +++++++++--------- docs/features/pilot-migration/plan.md | 60 +++++++++ docs/features/pilot-migration/spec.md | 31 +++++ docs/features/pilot-migration/tasks.md | 27 ++++ 5 files changed, 187 insertions(+), 67 deletions(-) create mode 100644 docs/features/pilot-migration/plan.md create mode 100644 docs/features/pilot-migration/spec.md create mode 100644 docs/features/pilot-migration/tasks.md diff --git a/apps/frontend/src/pages/home/ui/HomePage.tsx b/apps/frontend/src/pages/home/ui/HomePage.tsx index a0f2c52..1977544 100644 --- a/apps/frontend/src/pages/home/ui/HomePage.tsx +++ b/apps/frontend/src/pages/home/ui/HomePage.tsx @@ -1,14 +1,15 @@ +import Box from '@mui/material/Box'; +import { Heading, Text } from '@moex-vibe/design-system'; + export function HomePage() { return ( -
    -

    MoexVibe

    -

    - Анализ акций и облигаций Московской биржи -

    -

    Введите название или тикер в строку поиска выше

    -

    - Данные задерживаются на 15 минут · Бесплатный API MOEX ISS -

    -
    + + + MoexVibe + + Анализ акций и облигаций Московской биржи + Введите название или тикер в строку поиска выше + Данные задерживаются на 15 минут · Бесплатный API MOEX ISS + ); } diff --git a/apps/frontend/src/widgets/search-bar/ui/SearchBar.tsx b/apps/frontend/src/widgets/search-bar/ui/SearchBar.tsx index 240f04b..f41d370 100644 --- a/apps/frontend/src/widgets/search-bar/ui/SearchBar.tsx +++ b/apps/frontend/src/widgets/search-bar/ui/SearchBar.tsx @@ -1,5 +1,7 @@ import { useState, useRef, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; +import Box from '@mui/material/Box'; +import { Chip, Surface, Text, TextField } from '@moex-vibe/design-system'; import { useSearch } from '@/entities/search'; export function SearchBar() { @@ -32,82 +34,81 @@ export function SearchBar() { const showResults = open && debounced.length >= 2; return ( -
    - + { setQuery(e.target.value); setOpen(true); }} onFocus={() => setOpen(true)} - style={{ - width: '100%', - padding: '8px 12px', - border: '1px solid #ccc', - borderRadius: 6, - fontSize: 14, - }} /> {showResults && ( -
      - {isLoading &&
    • Загрузка...
    • } - {!isLoading && results && results.length === 0 && ( -
    • Ничего не найдено
    • - )} - {!isLoading && - results?.map((item) => ( -
    • { - setOpen(false); - setQuery(''); - navigate( - item.type === 'share' ? `/stocks/${item.secid}` : `/bonds/${item.secid}`, - ); - }} - style={{ - padding: '10px 12px', - cursor: 'pointer', - borderBottom: '1px solid #f0f0f0', - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - }} - onMouseEnter={(e) => (e.currentTarget.style.background = '#f5f5f5')} - onMouseLeave={(e) => (e.currentTarget.style.background = '')} - > - - {item.shortName} - {item.secid} - - + {isLoading && ( + + Загрузка... + + )} + {!isLoading && results && results.length === 0 && ( + + Ничего не найдено + + )} + {!isLoading && + results?.map((item) => ( + { + setOpen(false); + setQuery(''); + navigate( + item.type === 'share' ? `/stocks/${item.secid}` : `/bonds/${item.secid}`, + ); + }} + sx={{ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + px: 1.5, + py: 1.25, + cursor: 'pointer', + borderBottom: 1, + borderColor: 'divider', + '&:hover': { bgcolor: 'action.hover' }, + '&:last-child': { borderBottom: 0 }, + }} > - {item.type === 'share' ? 'Акция' : 'Облигация'} - -
    • - ))} -
    + + {item.shortName} + + {item.secid} + + + + + ))} + + )} -
    +
    ); } diff --git a/docs/features/pilot-migration/plan.md b/docs/features/pilot-migration/plan.md new file mode 100644 index 0000000..f53557e --- /dev/null +++ b/docs/features/pilot-migration/plan.md @@ -0,0 +1,60 @@ +# Pilot Migration — Implementation Plan + +## Architecture + +Миграция слоя представления без изменения логики. HomePage меняет JSX на DS-компоненты. SearchBar заменяет inline-стили на DS-компоненты + MUI `Box` (разрешён layout utility). + +## Files + +### Modify +- `apps/frontend/src/pages/home/ui/HomePage.tsx` — замена JSX +- `apps/frontend/src/widgets/search-bar/ui/SearchBar.tsx` — замена JSX + +### No changes +- `apps/frontend/src/widgets/search-bar/ui/SearchBar.test.tsx` — тесты не меняются (те же тексты) +- `apps/frontend/src/styles.css` — CSS-переменные всё ещё используются broker-страницами + +## Step-by-step + +### Step 1: Migrate HomePage + +```tsx +// До +
    +

    MoexVibe

    +

    + Анализ акций и облигаций Московской биржи +

    +

    Введите название или тикер в строку поиска выше

    +

    + Данные задерживаются на 15 минут · Бесплатный API MOEX ISS +

    +
    + +// После +import { Box } from '@mui/material'; +import { Heading, Text } from '@moex-vibe/design-system'; + + + MoexVibe + Анализ акций и облигаций Московской биржи + Введите название или тикер в строку поиска выше + Данные задерживаются на 15 минут · Бесплатный API MOEX ISS + +``` + +### Step 2: Migrate SearchBar + +- `` → `` +- `
      ` dropdown wrapper → `` (с inline-стилями для absolute positioning) +- `
    • ` loading → `Загрузка...` +- `
    • ` empty → `Ничего не найдено` +- `
    • ` result item → `` + `` + `` +- Hover effect (`onMouseEnter/onMouseLeave`) → MUI `sx={{ '&:hover': { bgcolor: 'action.hover' } }}` +- Hardcoded hex colors → MUI theme tokens (`text.disabled`, `divider`, etc.) + +### Step 3: Verify + +- `npm run test:frontend` — все тесты проходят +- `npm run lint -w apps/frontend` — lint чист, нет неразрешённых MUI-импортов +- `npm run build:frontend` — сборка проходит diff --git a/docs/features/pilot-migration/spec.md b/docs/features/pilot-migration/spec.md new file mode 100644 index 0000000..050b42c --- /dev/null +++ b/docs/features/pilot-migration/spec.md @@ -0,0 +1,31 @@ +# Pilot Migration — Design System Adoption + +## Status + +Approved — утверждена пользователем 2026-06-21. + +## Goal + +Пилотная миграция существующих страниц на компоненты `@moex-vibe/design-system`. Подтвердить, что API дизайн-системы покрывает реальные сценарии, и зафиксировать gaps для следующей итерации. + +## Scope + +- `apps/frontend/src/pages/home/ui/HomePage.tsx` — миграция на ``, ``, `` +- `apps/frontend/src/widgets/search-bar/ui/SearchBar.tsx` — миграция на ``, ``, ``, ``, `` + +## Out of scope + +- Рефакторинг логики SearchBar (debounce, click outside, keyboard nav, navigate) +- Миграция других страниц/виджетов +- Добавление новых компонентов в DS +- Удаление всего `styles.css` (только orphaned CSS variables после миграции) +- Изменение поведения компонентов (все acceptance criteria остаются теми же) + +## Acceptance Criteria + +- [ ] HomePage не содержит inline-стилей; все стили — через DS-компоненты и MUI layout utilities +- [ ] SearchBar не содержит hardcoded hex-цветов; палитра — через DS tokens +- [ ] SearchBar states (loading, empty, results) используют соответствующие DS-компоненты +- [ ] Логика SearchBar не изменена — все тесты проходят +- [ ] ESLint `no-restricted-imports` не нарушен (только `Box` из MUI напрямую) +- [ ] `npm run test:frontend && npm run lint -w apps/frontend && npm run build:frontend` проходят diff --git a/docs/features/pilot-migration/tasks.md b/docs/features/pilot-migration/tasks.md new file mode 100644 index 0000000..1d40751 --- /dev/null +++ b/docs/features/pilot-migration/tasks.md @@ -0,0 +1,27 @@ +# Pilot Migration — Tasks + +## 1. HomePage + +- [x] Заменить h1 на `` +- [x] Заменить p с text-secondary на `` +- [x] Заменить p с #888/#aaa на `` +- [x] Заменить div-wrapper на `` +- [x] Удалить все inline-стили + +## 2. SearchBar + +- [x] Заменить `` на `` +- [x] Заменить `
        ` на `` с positioning styles +- [x] Заменить loading text на `` +- [x] Заменить empty text на `` +- [x] Заменить `
      • ` results на `` с flex layout +- [x] Заменить hardcoded hex на theme tokens +- [x] Заменить JS hover handlers на MUI `sx={{ '&:hover': { bgcolor: 'action.hover' } }}` +- [x] Заменить тип "Акция"/"Облигация" на `` + +## 3. Verification + +- [x] `npm run test:frontend` — 23 suites, 111 passed +- [x] `npm run lint -w apps/frontend` — чист, 0 warnings +- [x] `npm run build:frontend` — проходит +- [x] ESLint `no-restricted-imports` не нарушен (использован `@mui/material/Box` deep import)