diff --git a/SPRINTS.md b/SPRINTS.md index c31fb97..2649792 100644 --- a/SPRINTS.md +++ b/SPRINTS.md @@ -79,5 +79,18 @@ _заполнить в конце спринта_ - [x] Добавить 5-ю палитру **Бриз** — вариант Лагуны с приглушённым primary `#63BAC3` (яркий `#29AEE3` переехал в p300, warm/accent/success/fg-4 наследуются от Лагуны) - [ ] Визуальная проверка всех экранов в новой палитре: кнопки, чипы, CTA, прогресс восстановления, успех-галочка, таббар-бейджи +--- + +## Спринт 4 · 20 апр 2026 + +**Цель:** служебные экраны для разработчиков — визуализация дизайн-системы прямо в прототипе, чтобы переключая палитру сразу видеть все цвета и их применение. + +### План +- [x] Пробросить текущую палитру через `ctx.palette` (чтобы dev-экраны могли прочитать все поля) +- [x] Экран **DEV · Палитра**: таблица всех цветов (primary / warm / accent / status / neutrals / text), у каждой строки — свотч, название роли, CSS-переменная, hex-код, краткое описание применения +- [x] Экран **DEV · Примеры**: реальные компоненты (кнопки, чипы, карточки, текстовая иерархия, статусы) с подписями «какая CSS-переменная используется» +- [x] Добавить оба экрана в SCREEN_OPTIONS Tweaks +- [x] Динамический рендер: при переключении палитры значения hex обновляются автоматически + ### Итоги _заполнить в конце спринта_ diff --git a/src/App.jsx b/src/App.jsx index 5929e90..65beb2d 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -83,6 +83,8 @@ const SCREEN_OPTIONS = [ { id: 'search', lb: 'Поиск' }, { id: 'contacts', lb: 'Контакты' }, { id: 'prices', lb: 'Цены' }, + { id: 'dev-colors', lb: 'DEV · Палитра' }, + { id: 'dev-examples', lb: 'DEV · Примеры' }, ]; function applyTheme(tw) { @@ -213,7 +215,8 @@ export default function App() { useEffect(() => { applyTheme(tw); }, [tw.accent, tw.font]); - const ctx = { homeVariant: tw.homeVariant, docVariant: tw.docVariant, density: tw.density }; + const palette = ACCENT_OPTIONS.find(a => a.id === tw.accent) || ACCENT_OPTIONS[0]; + const ctx = { homeVariant: tw.homeVariant, docVariant: tw.docVariant, density: tw.density, palette }; const content = useMemo(() => { if (tw.layout === 'home3') { diff --git a/src/PhoneApp.jsx b/src/PhoneApp.jsx index 513be9d..d69e392 100644 --- a/src/PhoneApp.jsx +++ b/src/PhoneApp.jsx @@ -16,6 +16,7 @@ import { import { ChatsListScreen, ChatConversationScreen } from './screens/screens-chats.jsx'; import { ArticlesScreen, ArticleDetailScreen } from './screens/screens-articles.jsx'; import { HomeV2Screen, SearchScreen, ContactsScreen, PricesScreen } from './screens/screens-v2.jsx'; +import { DevColorsScreen, DevExamplesScreen } from './screens/screens-dev.jsx'; function renderScreen(screenId, nav, ctx) { const parts = screenId.split(':'); @@ -51,6 +52,8 @@ function renderScreen(screenId, nav, ctx) { case 'search': return ; case 'contacts': return ; case 'prices': return ; + case 'dev-colors': return ; + case 'dev-examples': return ; default: return
Экран не найден: {screenId}
; } } diff --git a/src/screens/screens-dev.jsx b/src/screens/screens-dev.jsx new file mode 100644 index 0000000..2ff79e2 --- /dev/null +++ b/src/screens/screens-dev.jsx @@ -0,0 +1,411 @@ +import React from 'react'; +import { I } from '../icons.jsx'; +import { Avatar, ScreenHeader } from '../components.jsx'; + +// ───────────────────────────────────────────────────────────── +// DEV · Colors palette reference +// Shows every design-system color with role, CSS var, hex, and usage. +// Dynamic values (primary/accent/warm/etc.) come from ctx.palette and +// update automatically when user switches the accent in Tweaks. +// ───────────────────────────────────────────────────────────── + +function ColorRow({ c }) { + return ( +
+
+
+
{c.name}
+
{c.var}
+
{c.use}
+
+
{c.hex.toUpperCase()}
+
+ ); +} + +function ColorGroup({ title, note, colors }) { + return ( +
+
+
{title} · {colors.length}
+ {note &&
{note}
} +
+
+ {colors.map((c, i) => ( +
+ +
+ ))} +
+
+ ); +} + +export function DevColorsScreen({ nav, ctx }) { + const p = ctx.palette; + + const groups = [ + { + title: 'Primary · динамически', + note: 'Основная brand-гамма. Меняется при переключении палитры в Tweaks.', + colors: [ + { name: 'primary', var: '--c-primary', hex: p.primary, use: 'CTA, активные иконки, прогресс' }, + { name: 'primary-darker', var: '--c-primary-darker', hex: p.darker, use: 'Активное состояние, таббар, hover' }, + { name: 'primary-dark', var: '--c-primary-dark', hex: p.dark, use: 'Глубокие фоны: QR, градиент восстановления' }, + { name: 'primary-50', var: '--c-primary-50', hex: p.p50, use: 'Очень лёгкие подложки, фон AI-чата' }, + { name: 'primary-100', var: '--c-primary-100', hex: p.p100, use: 'Фоны иконок в плитках, чипы, hero статей' }, + { name: 'primary-200', var: '--c-primary-200', hex: p.p200, use: 'Бордеры, hover-стейты, рамки карточек' }, + { name: 'primary-300', var: '--c-primary-300', hex: p.p300, use: 'Промежуточный primary, декоративные бордеры' }, + ], + }, + { + title: 'Accent · динамически', + colors: [ + { name: 'accent', var: '--c-accent', hex: p.accent, use: 'Красная CTA на таймлайне, бейджи непрочитанных, булавка' }, + { name: 'accent-dark', var: '--c-accent-dark', hex: p.accentDark, use: 'Hover accent-кнопок' }, + { name: 'accent-50', var: '--c-accent-50', hex: p.accent50, use: 'Фон hero «Беременность», плашки danger' }, + ], + }, + { + title: 'Warm · динамически', + colors: [ + { name: 'warm-50', var: '--c-warm-50', hex: p.warm50, use: 'Плашки-предупреждения, subtle warm bg' }, + { name: 'warm-100', var: '--c-warm-100', hex: p.warm100, use: 'hero статей «Дети», чип «К.м.н.», профиль' }, + { name: 'warm-200', var: '--c-warm-200', hex: '#E8DCC5', use: 'Акценты beige, не меняется по палитре' }, + { name: 'warm-text', var: '--c-warm-text', hex: '#7A6A2E', use: 'Текст внутри warm-чипов, не меняется' }, + ], + }, + { + title: 'Статус', + colors: [ + { name: 'success', var: '--c-success', hex: '#2E9B6B', use: 'Онлайн-индикаторы, success-иконки' }, + { name: 'success-50', var: '--c-success-50', hex: p.success50, use: 'Фон «Готово» чипов, финал теста слуха · динамически' }, + { name: 'warning', var: '--c-warning', hex: '#E8A13C', use: 'Иконки лекарств, «В работе» статус' }, + { name: 'warning-50', var: '--c-warning-50', hex: '#FBEFD8', use: 'Фон уведомлений-напоминаний' }, + { name: 'danger', var: '--c-danger', hex: '#D94141', use: 'Критические ошибки, аллергии (красные чипы)' }, + ], + }, + { + title: 'Текст', + colors: [ + { name: 'fg-1', var: '--c-fg-1', hex: '#17242E', use: 'Основной текст, заголовки' }, + { name: 'fg-2', var: '--c-fg-2', hex: '#3E4C5D', use: 'Основной текст в body статей' }, + { name: 'fg-3', var: '--c-fg-3', hex: '#6B7A89', use: 'Приглушённый текст, sub-заголовки, подписи' }, + { name: 'fg-4', var: '--c-fg-4', hex: p.fg4, use: 'Плейсхолдеры, disabled, разделители · динамически' }, + ], + }, + { + title: 'Поверхности / бордеры', + colors: [ + { name: 'bg', var: '--c-bg', hex: '#F7F9FB', use: 'Фон приложения (внутри рамки)' }, + { name: 'bg-card', var: '--c-bg-card', hex: '#FFFFFF', use: 'Фон карточек, модалок, инпутов' }, + { name: 'border', var: '--c-border', hex: '#EAF0F3', use: 'Бордер карточек, инпутов, кнопок-ghost' }, + { name: 'border-strong', var: '--c-border-strong', hex: '#D8E1E6', use: 'Усиленный бордер, disabled-точки плана' }, + { name: 'divider', var: '--c-divider', hex: '#F0F4F6', use: 'Разделители строк внутри карточек' }, + ], + }, + ]; + + return ( +
+ nav.pop()} /> + + {/* Header banner with current palette key colors */} +
+
+
Ключевые цвета
+
+ {[p.primary, p.darker, p.dark, p.p100, p.warm100, p.accent, p.success50, p.p300].map((c, i) => ( +
+ ))} +
+
+
+ +
+ {groups.map(g => )} + +
+ +
+ Экран служебный. Переключите палитру в Tweaks — динамические значения (primary / accent / warm / success-50 / fg-4 / p300) пересчитываются автоматически. +
+
+ +
+ +
+
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// DEV · Usage examples +// Real rendered components with labels pointing to CSS vars used. +// ───────────────────────────────────────────────────────────── + +function ExampleBlock({ title, hint, children }) { + return ( +
+
+
{title}
+
+
+ {children} +
+ {hint &&
{hint}
} +
+ ); +} + +function VarTag({ children }) { + return ( + {children} + ); +} + +function ExampleRow({ children, label }) { + return ( +
+
{children}
+
+ {label} +
+
+ ); +} + +export function DevExamplesScreen({ nav }) { + return ( +
+ nav.pop()} /> + +
+ {/* BUTTONS */} + + --c-primary фон · #fff текст}> + + + --c-accent фон · для красной CTA}> + + + --c-primary-100 фон · --c-primary-darker текст}> + + +
+ +
+ #fff фон · --c-border рамка · --c-fg-2 текст +
+
+
+ + {/* CHIPS */} + + --c-primary-100 / --c-primary-darker}> + Обычный + + --c-warm-100 / --c-warm-text}> + К.м.н. + + --c-success-50 / --c-success}> + Готово + + --c-accent-50 / --c-accent}> + Пенициллин + +
+ + добавить +
+ --c-bg / --c-fg-3 / --c-border +
+
+
+ + {/* CARDS / SURFACES */} + + #fff фон · --sh-sm тень}> +
+
Карточка по умолчанию
+
белый фон, лёгкая тень
+
+
+ gradient (--c-primary-100--c-warm-100)}> +
+
Карточка профиля / статистики
+
+
+ solid --c-primary-darker · белый текст}> +
+
CTA-карточка
+
hero записи на главной
+
+
+
+ + {/* STATUS */} + + success — --c-success-50 фон}> +
+ + Успешно +
+
+ warning — --c-warning-50 фон}> +
+ + Напоминание +
+
+
+
+ + Критично +
+
+ danger — --c-accent-50 фон · --c-danger текст +
+
+
+ + {/* TYPOGRAPHY */} + + --c-fg-1 · основной заголовок}> +
Заголовок экрана
+
+ --c-fg-2 · body-текст}> +
Основной параграф, тело статей и объяснений в карточках.
+
+ --c-fg-3 · muted / подписи}> +
Подпись, время, sub-текст
+
+
+
Плейсхолдер, disabled-состояние
+
+ --c-fg-4 · disabled, placeholder +
+
+
+ + {/* AVATARS & BADGES */} + + --c-primary-100 / --c-primary-darker — градиент}> +
+ + + +
+
+ online · --c-success · белая рамка}> +
+ + +
+
+
+
+ 2 + AI +
+
+ unread — --c-accent · AI-бейдж — --c-primary-100 / --c-primary-darker +
+
+
+ + {/* INPUT */} + + #fff фон · --c-border рамка · placeholder --c-fg-4}> +
+ + Найти врача... +
+
+
+
+ + +
+
+ segmented · #EEF2F5 фон · активный #fff / --c-primary-darker +
+
+
+ + {/* Shadow / radius quick reference */} + + --sh-sm · --r-lg = 16px}> +
card (sh-sm)
+
+ --sh-md · --r-xl = 20px}> +
modal (sh-md)
+
+
+
sheet (sh-lg)
+
+ --sh-lg · --r-2xl = 24px +
+
+
+
+
+ ); +}