PhotoPlaces First Style — Дизайн-система
photoplaces_first_style — документация текущих стилевых решений проекта PhotoPlaces. Описывает то, что уже реализовано в коде.
1. ОБЩИЙ ПОДХОД
Архитектура стилей
- Tailwind-only — стили задаются исключительно utility-классами прямо в JSX
- CSS-переменные в
globals.css объявлены, но фактически не используются в компонентах
- Конфигурация Tailwind не расширена — только стандартные классы
- Нет модульного CSS, CSS-in-JS или отдельных файлов стилей компонентов
Тема оформления
- Полностью тёмная тема — нет светлого режима
- Glassmorphism — активно используется
bg-white/10 backdrop-blur-md
- Brand-цвет — зелёный (
#22c55e / #16a34a)
2. ЦВЕТОВАЯ ПАЛИТРА
Фоны (иерархия)
| Значение |
Tailwind-класс |
Назначение |
#060606 |
bg-[#060606] |
Фон страницы (body) |
#0f172a |
bg-[#0f172a] |
Фон страниц (формы, списки) |
#1e293b |
bg-[#1e293b] |
Поверхности (карточки, модалки, панели) |
#15291C |
bg-[#15291C] |
Select в RegisterModal |
Brand-цвета (зелёный)
| Класс |
Hex |
Назначение |
bg-green-700 |
#15803d |
Кнопки "Восстановить", "Удалить навсегда" |
bg-green-600 |
#16a34a |
CTA кнопки, активные фильтры, теги |
bg-green-600/70 |
#16a34a (70%) |
Кнопка "Регистрация" в Header |
bg-green-600/20 |
#16a34a (20%) |
Активный пункт навигации в admin sidebar |
bg-green-600/15 |
#16a34a (15%) |
Фон модалки RegisterModal |
bg-green-500 |
#22c55e |
Hover-состояния кнопок |
bg-green-500/20 |
#22c55e (20%) |
Badge "Активен" |
bg-green-500/10 |
#22c55e (10%) |
Сообщения-уведомления |
text-green-400 |
#4ade80 |
Ссылки, статусы, успешные сообщения |
text-green-300 |
#86efac |
Hover ссылки, badge "это вы" |
focus:border-green-500 |
#22c55e |
Focus-состояние всех инпутов |
Прозрачный белый (glassmorphism)
| Класс |
Назначение |
bg-white/5 |
Фон инпутов |
bg-white/10 |
Вторичные кнопки, навигация, теги, фильтры, Header блок |
bg-white/20 |
Hover вторичных кнопок |
text-white |
Основной текст, кнопки |
text-white/80 |
Приглушённый текст |
text-white/60 |
Подписи, лейблы, placeholder |
text-white/40 |
Статусы, неактивные элементы |
text-white/30 |
Версия в футере |
text-white/20 |
Копирайт в футере |
border-white/10 |
Стандартный бордер инпутов |
border-white/20 |
Бордер кнопки "Сохранить черновик" |
placeholder-white/40 |
Placeholder инпутов |
Функциональные цвета
| Цвет |
Классы |
Назначение |
| Красный |
bg-red-600, bg-red-600/80, bg-red-700, bg-red-500/10, bg-red-500/5, bg-red-500/20, bg-red-900/90, text-red-400, text-red-300/60, border-red-500/20 |
Ошибки, удаление, блокировка |
| Жёлтый |
bg-yellow-500/10, bg-yellow-500/20, bg-yellow-600, bg-yellow-600/80, text-yellow-400, focus:border-yellow-500 |
Предупреждения, модерация, доработка |
| Синий |
bg-blue-500/20, text-blue-400 |
Информационные сообщения, тип "Место" |
| Фиолетовый |
bg-purple-500/20, text-purple-400 |
Тип "Студия" |
| Оранжевый |
bg-orange-600/80, text-orange-400 |
Статус "На доработке", кнопка "Отозвать" |
Красный (кнопка "Выйти")
| Класс |
Hex |
hover:bg-[#ff5656] |
#ff5656 |
SVG-иконки
| Класс |
Hex |
Назначение |
#FF4B4B |
#FF4B4B |
Маркер на карте (Leaflet) |
3. ТИПОГРАФИКА
Шрифт
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
Системный стек — без подгрузки внешних шрифтов.
Размеры шрифтов
| Класс |
Размер |
Назначение |
text-2xl |
24px |
Заголовки страниц (h1), модальные заголовки |
text-xl |
20px |
Заголовки карточек, заголовки секций |
text-lg |
18px |
Заголовок "PhotoPlaces" в Header |
text-sm |
14px |
Основной размер текста (лейблы, кнопки, описания, статусы) |
text-xs |
12px |
Бейджи, теги, ID, копирайт, версия |
Веса шрифтов
| Класс |
Назначение |
font-bold |
Заголовки h1, h2, h3, название бренда |
font-semibold |
Заголовки карточек мест |
font-medium |
Текст кнопок, текст в навигации |
4. ОТСТУПЫ
Padding элементов
| Класс |
Значение |
Назначение |
p-8 |
32px |
Модальные окна (LoginModal, RegisterModal), пустые состояния |
p-6 |
24px |
PlaceForm, PlaceCardModal, модальные окна подтверждения |
p-4 |
16px |
PlaceCard, ErrorReporter, admin sidebar, карточки admin places |
px-4 py-3 |
16/12px |
Стандартный padding инпутов и кнопок CTA |
px-3 py-2 |
12/8px |
Вторичные кнопки, small inputs, теги в админке |
px-3 py-1.5 |
12/6px |
Теги (tags), кнопки фильтров |
px-3 py-1 |
12/4px |
Кнопки в Header |
px-6 py-3 |
24/12px |
Баннер гостя на карте |
px-6 py-2 |
24/8px |
Кнопка "На карту" |
px-4 py-2 |
16/8px |
Кнопки в MapPicker, кнопки в модалках |
Gap (расстояние между элементами)
| Класс |
Значение |
Назначение |
gap-8 |
32px |
Две колонки в admin/tags |
gap-4 |
16px |
Grid координат, grid цена/час, flex кнопки действий |
gap-3 |
12px |
Flex-группы кнопок, Header nav items |
gap-2 |
8px |
Теги, фильтры, flex-группы |
gap-1 |
4px |
Admin nav items |
Space-y (вертикальный gap)
| Класс |
Значение |
Назначение |
space-y-6 |
24px |
PlaceForm секции, admin sidebar |
space-y-4 |
16px |
Модальные окна, список мест |
space-y-3 |
12px |
Форма CreateUserModal |
space-y-2 |
8px |
Успешные сообщения, список пользователей |
space-y-1 |
4px |
Список тегов/характеристик |
Margin
| Класс |
Значение |
Назначение |
mb-6 |
24px |
Заголовки секций перед контентом |
mb-4 |
16px |
Элементы перед списками, кнопками |
mb-2 |
8px |
Текст перед группами |
mb-1 |
4px |
Лейблы перед инпутами |
mt-2 |
8px |
Preview изображения |
mt-4 |
16px |
Кнопка "На карту" в пустом состоянии |
pt-16 |
64px |
Отступ сверху на страницах с формами |
pt-20 |
80px |
Отступ сверху на страницах my/edit |
pt-10 |
40px |
Модалка EditModal |
5. BORDER RADIUS
| Класс |
Значение |
Назначение |
rounded-2xl |
16px |
Модальные окна (LoginModal, RegisterModal, AddLocationModal) |
rounded-t-2xl |
16px (верх) |
PlaceCardModal в MapView |
rounded-xl |
12px |
Карточки мест (PlaceCard), модальные окна подтверждения, EditModal |
rounded-lg |
8px |
Самый частый — инпуты, кнопки, теги-фильтры, навигация, бейджи |
rounded-full |
9999px |
Теги при выборе, бейджи статусов/типов |
rounded |
4px |
Кнопка "Закрыть" в ErrorReporter |
6. ТЕНИ
| Класс/стиль |
Назначение |
shadow-xl |
Все модальные окна (EditModal, DeleteModal, ReworkModal, CreateUserModal, PlaceCardModal, admin modals) |
drop-shadow(0 1px 3px rgba(0,0,0,0.5)) |
SVG-иконка маркера на карте (MapPicker) |
Тени используются только на всплывающих/модальных элементах.
7. СТАНДАРТНЫЕ ПАТТЕРНЫ
7.1. Паттерн инпута
<input
className="w-full rounded-lg border border-white/10 bg-white/5 px-4 py-3 text-white
placeholder-white/40 outline-none focus:border-green-500"
placeholder="..."
/>
7.2. Паттерн кнопки CTA
<button className="rounded-lg bg-green-600 px-4 py-3 font-medium text-white hover:bg-green-500 transition">
Текст кнопки
</button>
7.3. Паттерн кнопки вторичной
<button className="rounded-lg bg-white/10 px-4 py-2 text-sm text-white hover:bg-white/20 transition">
Текст кнопки
</button>
7.4. Паттерн фильтра/тега
Активный:
<button className="rounded-lg bg-green-600 px-3 py-1.5 text-sm text-white">
Тег
</button>
Неактивный:
<button className="rounded-lg bg-white/10 px-3 py-1.5 text-sm text-white/60 hover:bg-white/20">
Тег
</button>
7.5. Паттерн модалки
<!-- Overlay -->
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm">
<!-- Контент -->
<div
className="w-full max-w-md rounded-2xl bg-[#1e293b] p-8"
onClick={(e) => e.stopPropagation()}
>
<!-- Заголовок -->
<h2 className="text-center text-2xl font-bold text-white">Заголовок</h2>
<!-- Форма / Содержимое -->
<!-- Кнопки -->
<div className="mt-6 flex justify-end gap-3">
<button className="secondary">Отмена</button>
<button className="primary">Подтвердить</button>
</div>
</div>
</div>
7.6. Паттерн ошибки
<div className="rounded-lg bg-red-500/10 p-3 text-sm text-red-400">
Текст ошибки
</div>
7.7. Паттерн пустого состояния
<div className="flex flex-col items-center justify-center py-16 text-center">
<p className="text-white/40">Нет данных</p>
</div>
7.8. Disabled state
<button disabled className="... disabled:opacity-50">
7.9. Transition
<!-- Стандартный переход -->
<button className="... transition">
<!-- Переход только цветов -->
<button className="... transition-colors">
8. Z-INDEX ИЕРАРХИЯ
| Z-index |
Элемент |
z-0 |
Карта |
z-10 |
Баннер гостя |
z-20 |
PlaceCardModal (bottom sheet) |
z-30 |
Header |
z-40 |
Футер |
z-50 |
Модальные окна |
z-[60] |
MapPicker (полноэкранный) |
9. РАЗМЕРЫ КОНТЕЙНЕРОВ
| Класс |
Ширина |
Назначение |
max-w-sm |
384px |
Модалки авторизации (Login, Register) |
max-w-md |
448px |
Модалки подтверждения (Delete, Rework) |
max-w-2xl |
672px |
Формы создания/редактирования (PlaceForm, ServiceForm, EditModal, AddLocationModal) |
max-w-3xl |
768px |
Список мест (MyPlaces) |
10. КОМПОНЕНТЫ
Header
- Позиционирование:
absolute top-0, z-30
- Логотип:
text-lg font-bold text-white — текст "PhotoPlaces"
- Навигация авторизованного пользователя:
inline-flex items-center gap-3 rounded-lg bg-white/10 backdrop-blur-md px-4 py-2
- Кнопка "+" для добавления локации:
rounded-lg bg-white/10 backdrop-blur-md px-3 py-1
- Кнопка "Выйти":
hover:bg-[#ff5656]
- Ссылки:
text-sm text-white hover:text-green-400
LoginModal
- Overlay:
bg-black/40
- Контейнер:
rounded-2xl bg-white/10 backdrop-blur-md p-8
- Заголовок:
text-center text-2xl font-bold text-white
- Инпуты: стандартный паттерн
- Максимальная ширина:
max-w-sm
RegisterModal
- Overlay:
bg-black/40
- Контейнер:
rounded-2xl bg-green-600/15 backdrop-blur-md p-8 — зеленоватый оттенок
- Select:
bg-[#15291C] — темно-зелёный фон
- Три роли: Заказчик, Арендодатель, Исполнитель
AddLocationModal
- Overlay:
bg-black/60 backdrop-blur-sm
- Контейнер:
rounded-2xl bg-[#1e293b] без padding
- Форма внутри: PlaceForm
PlaceCard
- Контейнер:
rounded-xl bg-[#1e293b] overflow-hidden
- Изображение:
aspect-[4/3] object-cover
- Hover:
hover:shadow-xl hover:-translate-y-1 transition-all duration-300
- Заголовок:
text-lg font-semibold text-white
- Описание:
text-sm text-white/60 line-clamp-2
- Действия:
text-green-400 hover:text-green-300
PlaceCardModal (Bottom Sheet)
- Позиционирование:
fixed bottom-0 left-0 right-0 z-20
- Контейнер:
rounded-t-2xl bg-[#1e293b]
- Max-height:
max-h-[70vh] overflow-y-auto
MapView
- Контейнер:
fixed inset-0 z-0
- Кнопка "На карту":
rounded-lg bg-green-600 px-6 py-2
- Баннер гостя:
rounded-xl bg-white/10 backdrop-blur-md px-6 py-3
MapPicker (Полноэкранный)
- Позиционирование:
fixed inset-0 z-[60]
- Фон:
bg-[#0f172a]
- Заголовок:
bg-[#1e293b] border-b border-white/10
- Кнопки:
bg-white/10 hover:bg-white/20
Admin Sidebar
- Ширина:
w-64
- Фон:
bg-[#1e293b] border-r border-white/10
- Навигация:
rounded-lg hover:bg-white/10
- Активный:
bg-green-600/20 text-green-400
Admin Page
- Фон:
bg-[#0f172a]
- Статистика:
rounded-xl bg-[#1e293b] p-6
- Кнопки модерации:
bg-yellow-600, bg-red-600/80, bg-green-600
ErrorBoundary
- Контейнер:
min-h-screen bg-red-500/5 flex items-center justify-center
- Карточка:
rounded-xl border border-red-500/20 bg-[#1e293b] p-8
- Заголовок:
text-red-300/60
- Кнопка:
bg-red-600 hover:bg-red-700
ErrorReporter
- Позиционирование:
fixed bottom-4 right-4 z-50
- Контейнер:
rounded bg-red-900/90 p-4
- Максимальная ширина:
max-w-md
Footer
- Фон:
bg-[#0f172a]
- Граница:
border-t border-white/10
- Ссылки:
text-white/60 hover:text-white/80
- Копирайт:
text-white/20
- Версия:
text-white/30
11. КАРТЫ (Leaflet)
- Тайлы: CartoDB Dark All (
basemaps.cartocdn.com/dark_all) с opacity: 0.92
- Маркер: SVG
#FF4B4B с drop-shadow(0 1px 3px rgba(0,0,0,0.5))
- Контейнер карты:
fixed inset-0 z-0
12. CSS-ПЕРЕМЕННЫЕ (объявлены, но не используются)
:root {
--color-primary: #22c55e;
--color-primary-dark: #16a34a;
--color-bg: #060606;
--color-surface: #1e293b;
--color-text: #f1f5f9;
--color-text-muted: #94a3b8;
--color-border: #334155;
}
13. TAILWIND CONFIG (текущий)
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{ts,tsx}'],
theme: {
extend: {}, // Без расширений
},
plugins: [], // Без плагинов
}
14. РЕКОМЕНДАЦИИ ПО УЛУЧШЕНИЮ
Что стоит сделать
- Использовать CSS-переменные — они объявлены, но не применяются
- Расширить Tailwind config — вынести повторяющиеся паттерны в кастомные классы
- Добавить светлую тему — сейчас только тёмная
- Стандартизировать компоненты — создать переиспользуемые UI-компоненты
- ДобавитьGLIGENCE-анимации — сейчас
transition без параметров
- Оптимизировать z-index — использовать CSS-переменные для иерархии
Паттерны для выноса в компоненты
Button (primary, secondary, ghost, danger)
Input (с лейблом, ошибкой)
Modal (overlay + контент)
Badge (статусы, типы)
Card (для локаций)
Alert (ошибки, успех)