Files
shop-server/docs/superpowers/specs/2026-05-22-auth-redesign-design.md
T
2026-05-22 13:18:21 +05:00

8.2 KiB
Raw Blame History

Auth Page Redesign — Spec

Date: 2026-05-22 Goal: Минималистичный редизайн страницы входа с лёгким брендингом (медведь + слоган), pill-кнопками и Paper-карточкой.

Style: Минималистичный, чистый. Одна колонка по центру.


1. Шрифт Outfit

Проблема: Outfit указан в MUI-теме, но не загружается. Фактически везде системный Segoe UI.

Исправление: Скачать шрифт Outfit (woff2, веса 400/500/600/700) и разместить в client/public/fonts/. Добавить @font-face в client/src/app/styles/global.css:

@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 400;
  src: url('/fonts/Outfit-Regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 500;
  src: url('/fonts/Outfit-Medium.woff2') format('woff2');
}
@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 600;
  src: url('/fonts/Outfit-SemiBold.woff2') format('woff2');
}
@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 700;
  src: url('/fonts/Outfit-Bold.woff2') format('woff2');
}

Файлы woff2 скачать с Google Fonts или из CDN и положить в client/public/fonts/.


2. Фон страницы

  • background.default + лёгкий радиальный градиент
  • Градиент: от центра к краям, primary.main с 3-5% opacity
  • Реализация: sx prop на корневом <Box>: background: radial-gradient(circle at 50% 30%, ${alpha(theme.palette.primary.main, 0.05)} 0%, transparent 70%)

3. Компоновка

┌──────────────────────────────────────────┐
│                   (воздух)               │
│              🐻 BearLogo 72px            │
│       Добро пожаловать в Любимый Креатив  │
│           (subtitle, text.secondary)      │
│                   (воздух)               │
│   ┌─────── Paper 440px max-width ──────┐ │
│   │  [Пароль]  [Код]  [Другой способ]   │ │
│   │                                     │ │
│   │   Вход  /  Регистрация              │ │
│   │                                     │ │
│   │  Email:        __________________   │ │
│   │  Пароль:       __________________   │ │
│   │                                     │ │
│   │  [────────── Войти ──────────]      │ │
│   │                                     │ │
│   └─────────────────────────────────────┘ │
│                   (воздух)               │
└──────────────────────────────────────────┘

Детали:

  • Корневой <Box>: display: flex, alignItems: center, justifyContent: center, minHeight: calc(100vh - header)
  • BearLogo: <Box sx={{ display: 'flex', justifyContent: 'center', mb: 2 }}><BearLogo sx={{ fontSize: 72 }} /></Box>
  • Заголовок: variant="h5", fontWeight: 700, textAlign: center
  • Слоган: variant="body2", color: text.secondary, textAlign: center, mb: 3
  • Paper: maxWidth: 440, mx: auto, p: 4, borderRadius: 3 (12px), border: 1px solid divider, мягкая тень

4. Pill-переключатель методов

Вместо MUI Tabs — три MUI Button в ряд:

<Stack direction="row" spacing={1} sx={{ mb: 3 }}>
  <Button
    variant={tab === 0 ? 'contained' : 'outlined'}
    sx={{ borderRadius: '24px', flex: 1, textTransform: 'none' }}
    onClick={() => setTab(0)}
  >
    Пароль
  </Button>
  <Button
    variant={tab === 1 ? 'contained' : 'outlined'}
    sx={{ borderRadius: '24px', flex: 1, textTransform: 'none' }}
    onClick={() => setTab(1)}
  >
    Код
  </Button>
  <Button
    variant={tab === 2 ? 'contained' : 'outlined'}
    sx={{ borderRadius: '24px', flex: 1, textTransform: 'none' }}
    onClick={() => setTab(2)}
  >
    Другой способ
  </Button>
</Stack>

5. Под-переключатель Вход/Регистрация

Только на вкладке «Пароль»:

<Stack direction="row" justifyContent="center" spacing={3} sx={{ mb: 2 }}>
  <Button
    variant="text"
    size="small"
    sx={{
      color: !isRegister ? 'primary.main' : 'text.secondary',
      borderBottom: !isRegister ? 2 : 0,
      borderColor: 'primary.main',
      borderRadius: 0,
      pb: 0.5,
    }}
    onClick={() => setIsRegister(false)}
  >
    Вход
  </Button>
  <Button
    variant="text"
    size="small"
    sx={{
      color: isRegister ? 'primary.main' : 'text.secondary',
      borderBottom: isRegister ? 2 : 0,
      borderColor: 'primary.main',
      borderRadius: 0,
      pb: 0.5,
    }}
    onClick={() => setIsRegister(true)}
  >
    Регистрация
  </Button>
</Stack>

6. Формы по вкладкам

Пароль (вход)

  • Email TextField
  • Пароль TextField
  • Button contained fullWidth: «Войти»

Пароль (регистрация)

  • Email TextField
  • Имя TextField (опционально, helperText: «Необязательно. Будет использована часть email»)
  • Пароль TextField
  • Подтверждение пароля TextField (с валидацией совпадения)
  • Button contained fullWidth: «Зарегистрироваться»

Код

  • Строка: Email + кнопка «Отправить код»
  • Строка: поле Код + кнопка «Войти»
  • Alert outlined success после успешной отправки

Другой способ

  • OAuthButtons — стилизовать кнопки как outlined pill (borderRadius 24px, fullWidth)
  • Кнопки: «Войти через Яндекс ID», «Войти через VK ID»

7. Alert'ы

  • Все ошибки: Alert severity="error" variant="outlined" внутри Paper, над формой
  • Успешная отправка кода: Alert severity="success" variant="outlined"
  • OAuth-ошибки: так же внутри Paper

8. Иконки в TextField

Добавить InputAdornment с иконками для визуального улучшения:

  • Email: <Mail> иконка (lucide-react)
  • Пароль: <Lock> иконка

Иконки только если это не перегружает минималистичный стиль. Решение — использовать в полях email и пароля startAdornment.


9. Адаптивность

  • min-height вместо height (использовать minHeight: calc(100vh - 64px))
  • Paper: mx: 2 на мобильных, mx: auto на десктопе
  • Pill-кнопки остаются в ряд на всех разрешениях (они и так компактные)
  • Отправка кода: на мобильных поля в столбец (уже есть direction={{ xs: 'column', sm: 'row' }})

10. Плавные переходы

  • Смена вкладок: контент формы — opacity transition 200ms
  • Смена Вход/Регистрация: поля появляются с fade-in

11. Заметки

  • BearLogo уже существует (@/shared/ui/BearLogo)
  • OAuthButtons существует (@/features/auth-oauth)
  • Менять бизнес-логику (хуки, mutations) не нужно — только вёрстку
  • Текущий AuthPage — 232 строки, нужно заменить полностью
  • Все цвета брать из темы (primary.main, text.secondary, divider, background.paper)
  • Для градиента использовать useTheme + alpha из MUI