Sprint 4: developer design-system screens
Two service screens accessible via Tweaks screen selector: - DEV · Палитра — every color role grouped (primary / accent / warm / status / text / surfaces) with swatch, role name, CSS var name, hex code, and usage note. Key-color banner at top. Dynamic values (primary/accent/warm/success-50/fg-4/p300) recompute from ctx.palette when the user flips the color in Tweaks. - DEV · Примеры — rendered components (buttons, chips, surfaces, status blocks, text hierarchy, avatars, badges, inputs, segmented control, shadow/radius scale) each labeled with the CSS vars it uses, so devs can read the theme visually. Plumbed the active palette object via ctx.palette from App.jsx. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+13
@@ -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 обновляются автоматически
|
||||
|
||||
### Итоги
|
||||
_заполнить в конце спринта_
|
||||
|
||||
+4
-1
@@ -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') {
|
||||
|
||||
@@ -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 <SearchScreen nav={nav} />;
|
||||
case 'contacts': return <ContactsScreen nav={nav} />;
|
||||
case 'prices': return <PricesScreen nav={nav} />;
|
||||
case 'dev-colors': return <DevColorsScreen nav={nav} ctx={ctx} />;
|
||||
case 'dev-examples': return <DevExamplesScreen nav={nav} ctx={ctx} />;
|
||||
default: return <div style={{padding: 40, textAlign: 'center'}}>Экран не найден: {screenId}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<div style={{
|
||||
display: 'flex', gap: 12, alignItems: 'center',
|
||||
padding: '10px 14px', borderBottom: '1px solid var(--c-divider)',
|
||||
}}>
|
||||
<div style={{
|
||||
width: 54, height: 40, borderRadius: 8, flexShrink: 0,
|
||||
background: c.hex, border: '1px solid rgba(0,0,0,0.08)',
|
||||
}} />
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<div style={{ fontSize: 13, fontWeight: 700, color: 'var(--c-fg-1)' }}>{c.name}</div>
|
||||
<div style={{ fontSize: 10.5, color: 'var(--c-fg-3)', fontFamily: 'SF Mono, Menlo, Consolas, monospace', marginTop: 1 }}>{c.var}</div>
|
||||
<div style={{ fontSize: 11, color: 'var(--c-fg-3)', marginTop: 2, lineHeight: 1.4 }}>{c.use}</div>
|
||||
</div>
|
||||
<div style={{
|
||||
fontSize: 11, fontFamily: 'SF Mono, Menlo, Consolas, monospace',
|
||||
color: 'var(--c-fg-2)', fontWeight: 700,
|
||||
background: 'var(--c-bg)', padding: '4px 6px', borderRadius: 5,
|
||||
flexShrink: 0,
|
||||
}}>{c.hex.toUpperCase()}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ColorGroup({ title, note, colors }) {
|
||||
return (
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<div style={{ padding: '0 4px 8px' }}>
|
||||
<div style={{ fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: .6, color: 'var(--c-fg-3)' }}>{title} · {colors.length}</div>
|
||||
{note && <div className="sub" style={{ fontSize: 11, marginTop: 3 }}>{note}</div>}
|
||||
</div>
|
||||
<div className="card" style={{ padding: 0 }}>
|
||||
{colors.map((c, i) => (
|
||||
<div key={c.name} style={{ borderBottom: i === colors.length - 1 ? 0 : undefined }}>
|
||||
<ColorRow c={c} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
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 (
|
||||
<div style={{ paddingBottom: 40 }}>
|
||||
<ScreenHeader title="DEV · Палитра" subtitle={`Активна: ${p.lb}`} onBack={() => nav.pop()} />
|
||||
|
||||
{/* Header banner with current palette key colors */}
|
||||
<div style={{ padding: '0 20px 16px' }}>
|
||||
<div className="card" style={{ padding: 14, background: 'var(--c-primary-50)', border: '1px solid var(--c-primary-200)' }}>
|
||||
<div style={{ fontSize: 12, fontWeight: 700, color: 'var(--c-primary-darker)', textTransform: 'uppercase', letterSpacing: .6, marginBottom: 8 }}>Ключевые цвета</div>
|
||||
<div style={{ display: 'flex', gap: 6 }}>
|
||||
{[p.primary, p.darker, p.dark, p.p100, p.warm100, p.accent, p.success50, p.p300].map((c, i) => (
|
||||
<div key={i} style={{
|
||||
flex: 1, height: 36, borderRadius: 6, background: c,
|
||||
border: '1px solid rgba(0,0,0,0.08)',
|
||||
}} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: '0 16px' }}>
|
||||
{groups.map(g => <ColorGroup key={g.title} {...g} />)}
|
||||
|
||||
<div style={{
|
||||
marginTop: 8, padding: 12, borderRadius: 10,
|
||||
background: 'var(--c-warning-50)', display: 'flex', gap: 10, alignItems: 'flex-start',
|
||||
}}>
|
||||
<I.shield size={18} style={{ color: 'var(--c-warning)', flexShrink: 0, marginTop: 1 }} />
|
||||
<div className="sub" style={{ fontSize: 12, lineHeight: 1.5 }}>
|
||||
Экран служебный. Переключите палитру в Tweaks — динамические значения (primary / accent / warm / success-50 / fg-4 / p300) пересчитываются автоматически.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', gap: 10, marginTop: 14 }}>
|
||||
<button onClick={() => nav.push('dev-examples')} className="btn-p" style={{ flex: 1 }}>
|
||||
Примеры применения <I.arrow size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// DEV · Usage examples
|
||||
// Real rendered components with labels pointing to CSS vars used.
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
function ExampleBlock({ title, hint, children }) {
|
||||
return (
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<div style={{ padding: '0 4px 8px' }}>
|
||||
<div style={{ fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: .6, color: 'var(--c-fg-3)' }}>{title}</div>
|
||||
</div>
|
||||
<div className="card" style={{ padding: 14 }}>
|
||||
{children}
|
||||
</div>
|
||||
{hint && <div className="sub" style={{ fontSize: 11, padding: '6px 4px 0', lineHeight: 1.5 }}>{hint}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function VarTag({ children }) {
|
||||
return (
|
||||
<code style={{
|
||||
display: 'inline-block', padding: '1px 6px', borderRadius: 4,
|
||||
background: 'var(--c-bg)', border: '1px solid var(--c-border)',
|
||||
fontFamily: 'SF Mono, Menlo, Consolas, monospace', fontSize: 10.5,
|
||||
color: 'var(--c-fg-2)',
|
||||
}}>{children}</code>
|
||||
);
|
||||
}
|
||||
|
||||
function ExampleRow({ children, label }) {
|
||||
return (
|
||||
<div style={{ padding: '10px 0', borderBottom: '1px solid var(--c-divider)' }}>
|
||||
<div style={{ marginBottom: 8 }}>{children}</div>
|
||||
<div style={{ fontSize: 11, color: 'var(--c-fg-3)', display: 'flex', flexWrap: 'wrap', gap: 5, alignItems: 'center' }}>
|
||||
{label}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function DevExamplesScreen({ nav }) {
|
||||
return (
|
||||
<div style={{ paddingBottom: 40 }}>
|
||||
<ScreenHeader title="DEV · Примеры" subtitle="Где какой цвет" onBack={() => nav.pop()} />
|
||||
|
||||
<div style={{ padding: '0 16px' }}>
|
||||
{/* BUTTONS */}
|
||||
<ExampleBlock title="Кнопки">
|
||||
<ExampleRow label={<><VarTag>--c-primary</VarTag> фон · <VarTag>#fff</VarTag> текст</>}>
|
||||
<button className="btn-p">Записаться на приём</button>
|
||||
</ExampleRow>
|
||||
<ExampleRow label={<><VarTag>--c-accent</VarTag> фон · для красной CTA</>}>
|
||||
<button className="btn-p btn-accent">Записаться · срочно</button>
|
||||
</ExampleRow>
|
||||
<ExampleRow label={<><VarTag>--c-primary-100</VarTag> фон · <VarTag>--c-primary-darker</VarTag> текст</>}>
|
||||
<button className="btn-s"><I.chat size={14} /> Чат</button>
|
||||
</ExampleRow>
|
||||
<div style={{ padding: '10px 0' }}>
|
||||
<button className="btn-g">Отмена</button>
|
||||
<div style={{ fontSize: 11, color: 'var(--c-fg-3)', marginTop: 8, display: 'flex', flexWrap: 'wrap', gap: 5, alignItems: 'center' }}>
|
||||
<VarTag>#fff</VarTag> фон · <VarTag>--c-border</VarTag> рамка · <VarTag>--c-fg-2</VarTag> текст
|
||||
</div>
|
||||
</div>
|
||||
</ExampleBlock>
|
||||
|
||||
{/* CHIPS */}
|
||||
<ExampleBlock title="Чипы">
|
||||
<ExampleRow label={<><VarTag>--c-primary-100</VarTag> / <VarTag>--c-primary-darker</VarTag></>}>
|
||||
<span className="chip">Обычный</span>
|
||||
</ExampleRow>
|
||||
<ExampleRow label={<><VarTag>--c-warm-100</VarTag> / <VarTag>--c-warm-text</VarTag></>}>
|
||||
<span className="chip chip-warm">К.м.н.</span>
|
||||
</ExampleRow>
|
||||
<ExampleRow label={<><VarTag>--c-success-50</VarTag> / <VarTag>--c-success</VarTag></>}>
|
||||
<span className="chip chip-success">Готово</span>
|
||||
</ExampleRow>
|
||||
<ExampleRow label={<><VarTag>--c-accent-50</VarTag> / <VarTag>--c-accent</VarTag></>}>
|
||||
<span className="chip chip-danger">Пенициллин</span>
|
||||
</ExampleRow>
|
||||
<div style={{ padding: '10px 0' }}>
|
||||
<span className="chip chip-soft">+ добавить</span>
|
||||
<div style={{ fontSize: 11, color: 'var(--c-fg-3)', marginTop: 8, display: 'flex', flexWrap: 'wrap', gap: 5, alignItems: 'center' }}>
|
||||
<VarTag>--c-bg</VarTag> / <VarTag>--c-fg-3</VarTag> / <VarTag>--c-border</VarTag>
|
||||
</div>
|
||||
</div>
|
||||
</ExampleBlock>
|
||||
|
||||
{/* CARDS / SURFACES */}
|
||||
<ExampleBlock title="Поверхности">
|
||||
<ExampleRow label={<><VarTag>#fff</VarTag> фон · <VarTag>--sh-sm</VarTag> тень</>}>
|
||||
<div className="card" style={{ padding: 12 }}>
|
||||
<div style={{ fontSize: 13, fontWeight: 700 }}>Карточка по умолчанию</div>
|
||||
<div className="sub" style={{ fontSize: 11 }}>белый фон, лёгкая тень</div>
|
||||
</div>
|
||||
</ExampleRow>
|
||||
<ExampleRow label={<>gradient (<VarTag>--c-primary-100</VarTag> → <VarTag>--c-warm-100</VarTag>)</>}>
|
||||
<div className="card" style={{
|
||||
padding: 12,
|
||||
background: 'linear-gradient(135deg, var(--c-primary-100), var(--c-warm-100))',
|
||||
border: 0,
|
||||
}}>
|
||||
<div style={{ fontSize: 13, fontWeight: 700 }}>Карточка профиля / статистики</div>
|
||||
</div>
|
||||
</ExampleRow>
|
||||
<ExampleRow label={<>solid <VarTag>--c-primary-darker</VarTag> · белый текст</>}>
|
||||
<div style={{
|
||||
padding: 14, borderRadius: 14,
|
||||
background: 'var(--c-primary-darker)', color: '#fff',
|
||||
}}>
|
||||
<div style={{ fontSize: 13, fontWeight: 700 }}>CTA-карточка</div>
|
||||
<div style={{ fontSize: 11, opacity: .85, marginTop: 2 }}>hero записи на главной</div>
|
||||
</div>
|
||||
</ExampleRow>
|
||||
</ExampleBlock>
|
||||
|
||||
{/* STATUS */}
|
||||
<ExampleBlock title="Статусы">
|
||||
<ExampleRow label={<>success — <VarTag>--c-success-50</VarTag> фон</>}>
|
||||
<div style={{ background: 'var(--c-success-50)', padding: 10, borderRadius: 10, display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<I.check size={16} style={{ color: 'var(--c-success)' }} sw={3} />
|
||||
<span style={{ fontSize: 13, color: 'var(--c-success)', fontWeight: 700 }}>Успешно</span>
|
||||
</div>
|
||||
</ExampleRow>
|
||||
<ExampleRow label={<>warning — <VarTag>--c-warning-50</VarTag> фон</>}>
|
||||
<div style={{ background: 'var(--c-warning-50)', padding: 10, borderRadius: 10, display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<I.bell size={16} style={{ color: 'var(--c-warning)' }} />
|
||||
<span style={{ fontSize: 13, color: 'var(--c-warning)', fontWeight: 700 }}>Напоминание</span>
|
||||
</div>
|
||||
</ExampleRow>
|
||||
<div style={{ padding: '10px 0' }}>
|
||||
<div style={{ background: 'var(--c-accent-50)', padding: 10, borderRadius: 10, display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<I.shield size={16} style={{ color: 'var(--c-danger)' }} />
|
||||
<span style={{ fontSize: 13, color: 'var(--c-danger)', fontWeight: 700 }}>Критично</span>
|
||||
</div>
|
||||
<div style={{ fontSize: 11, color: 'var(--c-fg-3)', marginTop: 8, display: 'flex', flexWrap: 'wrap', gap: 5, alignItems: 'center' }}>
|
||||
danger — <VarTag>--c-accent-50</VarTag> фон · <VarTag>--c-danger</VarTag> текст
|
||||
</div>
|
||||
</div>
|
||||
</ExampleBlock>
|
||||
|
||||
{/* TYPOGRAPHY */}
|
||||
<ExampleBlock title="Иерархия текста" hint="fg-1 → fg-2 → fg-3 → fg-4 — по убыванию важности. В Лагуне fg-4 переопределён на серый из скрина.">
|
||||
<ExampleRow label={<><VarTag>--c-fg-1</VarTag> · основной заголовок</>}>
|
||||
<div className="h-screen" style={{ fontSize: 22 }}>Заголовок экрана</div>
|
||||
</ExampleRow>
|
||||
<ExampleRow label={<><VarTag>--c-fg-2</VarTag> · body-текст</>}>
|
||||
<div style={{ fontSize: 14, color: 'var(--c-fg-2)', lineHeight: 1.5 }}>Основной параграф, тело статей и объяснений в карточках.</div>
|
||||
</ExampleRow>
|
||||
<ExampleRow label={<><VarTag>--c-fg-3</VarTag> · muted / подписи</>}>
|
||||
<div className="sub" style={{ fontSize: 13 }}>Подпись, время, sub-текст</div>
|
||||
</ExampleRow>
|
||||
<div style={{ padding: '10px 0' }}>
|
||||
<div style={{ fontSize: 13, color: 'var(--c-fg-4)' }}>Плейсхолдер, disabled-состояние</div>
|
||||
<div style={{ fontSize: 11, color: 'var(--c-fg-3)', marginTop: 8, display: 'flex', flexWrap: 'wrap', gap: 5, alignItems: 'center' }}>
|
||||
<VarTag>--c-fg-4</VarTag> · disabled, placeholder
|
||||
</div>
|
||||
</div>
|
||||
</ExampleBlock>
|
||||
|
||||
{/* AVATARS & BADGES */}
|
||||
<ExampleBlock title="Аватары и бейджи">
|
||||
<ExampleRow label={<><VarTag>--c-primary-100</VarTag> / <VarTag>--c-primary-darker</VarTag> — градиент</>}>
|
||||
<div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
|
||||
<Avatar init="АС" size={48} />
|
||||
<Avatar init="СА" size={40} />
|
||||
<Avatar init="МЛ" size={32} />
|
||||
</div>
|
||||
</ExampleRow>
|
||||
<ExampleRow label={<>online · <VarTag>--c-success</VarTag> · белая рамка</>}>
|
||||
<div style={{ position: 'relative', width: 48, height: 48 }}>
|
||||
<Avatar init="СА" size={48} />
|
||||
<span style={{
|
||||
position: 'absolute', bottom: 1, right: 1,
|
||||
width: 12, height: 12, borderRadius: 999,
|
||||
background: 'var(--c-success)', border: '2px solid #fff',
|
||||
}} />
|
||||
</div>
|
||||
</ExampleRow>
|
||||
<div style={{ padding: '10px 0' }}>
|
||||
<div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
|
||||
<span style={{
|
||||
background: 'var(--c-accent)', color: '#fff',
|
||||
fontSize: 11, fontWeight: 700, padding: '3px 8px', borderRadius: 999,
|
||||
}}>2</span>
|
||||
<span style={{
|
||||
background: 'var(--c-primary-100)', color: 'var(--c-primary-darker)',
|
||||
fontSize: 10, fontWeight: 700, padding: '2px 6px', borderRadius: 5, letterSpacing: .5,
|
||||
}}>AI</span>
|
||||
</div>
|
||||
<div style={{ fontSize: 11, color: 'var(--c-fg-3)', marginTop: 8, display: 'flex', flexWrap: 'wrap', gap: 5, alignItems: 'center' }}>
|
||||
unread — <VarTag>--c-accent</VarTag> · AI-бейдж — <VarTag>--c-primary-100</VarTag> / <VarTag>--c-primary-darker</VarTag>
|
||||
</div>
|
||||
</div>
|
||||
</ExampleBlock>
|
||||
|
||||
{/* INPUT */}
|
||||
<ExampleBlock title="Формы">
|
||||
<ExampleRow label={<><VarTag>#fff</VarTag> фон · <VarTag>--c-border</VarTag> рамка · placeholder <VarTag>--c-fg-4</VarTag></>}>
|
||||
<div style={{
|
||||
background: '#fff', borderRadius: 12, padding: '10px 14px',
|
||||
display: 'flex', alignItems: 'center', gap: 10,
|
||||
border: '1px solid var(--c-border)',
|
||||
}}>
|
||||
<I.search size={16} style={{ color: 'var(--c-fg-4)' }} />
|
||||
<span style={{ color: 'var(--c-fg-4)', fontSize: 14 }}>Найти врача...</span>
|
||||
</div>
|
||||
</ExampleRow>
|
||||
<div style={{ padding: '10px 0' }}>
|
||||
<div className="seg">
|
||||
<button className="on">Активно</button>
|
||||
<button>Неактивно</button>
|
||||
</div>
|
||||
<div style={{ fontSize: 11, color: 'var(--c-fg-3)', marginTop: 8, display: 'flex', flexWrap: 'wrap', gap: 5, alignItems: 'center' }}>
|
||||
segmented · <VarTag>#EEF2F5</VarTag> фон · активный <VarTag>#fff</VarTag> / <VarTag>--c-primary-darker</VarTag>
|
||||
</div>
|
||||
</div>
|
||||
</ExampleBlock>
|
||||
|
||||
{/* Shadow / radius quick reference */}
|
||||
<ExampleBlock title="Тени и радиусы">
|
||||
<ExampleRow label={<><VarTag>--sh-sm</VarTag> · <VarTag>--r-lg</VarTag> = 16px</>}>
|
||||
<div style={{
|
||||
padding: 14, borderRadius: 'var(--r-lg)',
|
||||
background: '#fff', boxShadow: 'var(--sh-sm)',
|
||||
fontSize: 13, fontWeight: 700,
|
||||
}}>card (sh-sm)</div>
|
||||
</ExampleRow>
|
||||
<ExampleRow label={<><VarTag>--sh-md</VarTag> · <VarTag>--r-xl</VarTag> = 20px</>}>
|
||||
<div style={{
|
||||
padding: 14, borderRadius: 'var(--r-xl)',
|
||||
background: '#fff', boxShadow: 'var(--sh-md)',
|
||||
fontSize: 13, fontWeight: 700,
|
||||
}}>modal (sh-md)</div>
|
||||
</ExampleRow>
|
||||
<div style={{ padding: '10px 0' }}>
|
||||
<div style={{
|
||||
padding: 14, borderRadius: 'var(--r-2xl)',
|
||||
background: '#fff', boxShadow: 'var(--sh-lg)',
|
||||
fontSize: 13, fontWeight: 700,
|
||||
}}>sheet (sh-lg)</div>
|
||||
<div style={{ fontSize: 11, color: 'var(--c-fg-3)', marginTop: 8, display: 'flex', flexWrap: 'wrap', gap: 5, alignItems: 'center' }}>
|
||||
<VarTag>--sh-lg</VarTag> · <VarTag>--r-2xl</VarTag> = 24px
|
||||
</div>
|
||||
</div>
|
||||
</ExampleBlock>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user