mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-29 18:13:47 +00:00
feat(ui): implement Bento Grid design system
- Add Urbanist font (replace Inter) - Add CSS variables: --bento-radius, --bento-gap, --bento-padding - Add Tailwind extend: rounded-bento, rounded-4xl, spacing.bento - Create BentoCard component with size variants (sm/md/lg/xl) - Add .bento-card, .bento-card-hover, .bento-card-glow classes - Add .bento-grid container with responsive columns - Implement floating TabBar (margin 16px, shadow, pill active state) - Apply bento styles to Dashboard cards - Support both dark and light themes
This commit is contained in:
150
.ai/BENTO_REFACTOR.md
Normal file
150
.ai/BENTO_REFACTOR.md
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
# Bento Grids Refactor
|
||||||
|
|
||||||
|
> **Ветка:** `bento-grids`
|
||||||
|
> **Статус:** В работе
|
||||||
|
> **Последнее обновление:** 2026-01-20
|
||||||
|
|
||||||
|
## Референс
|
||||||
|
|
||||||
|
- **Стиль:** Bento Grids (карточки разных размеров в сетке)
|
||||||
|
- **Цветовая схема:** Зеленый неон на темном фоне, чистота
|
||||||
|
- **Шрифт:** Urbanist (современный гротеск)
|
||||||
|
- **Скругления:** Крупные (24-32px)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## План рефакторинга
|
||||||
|
|
||||||
|
### Этап 1: Фундамент (Vibe Check)
|
||||||
|
> Цель: Пустая страница уже выглядит "секси"
|
||||||
|
|
||||||
|
| # | Задача | Статус | Заметки |
|
||||||
|
|---|--------|--------|---------|
|
||||||
|
| 1.1 | Подключить Urbanist шрифт | `[x]` | Google Fonts, заменить Inter |
|
||||||
|
| 1.2 | Tailwind: bento radius/spacing | `[x]` | `rounded-bento`, `rounded-4xl`, `spacing.bento` |
|
||||||
|
| 1.3 | globals.css: CSS переменные Bento | `[x]` | `--bento-radius`, `--bento-gap`, `--bento-padding` |
|
||||||
|
|
||||||
|
**Файлы:**
|
||||||
|
- `src/styles/globals.css`
|
||||||
|
- `tailwind.config.js`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Этап 2: Атом (BentoCard)
|
||||||
|
> Цель: Один идеальный компонент-карточка
|
||||||
|
|
||||||
|
| # | Задача | Статус | Заметки |
|
||||||
|
|---|--------|--------|---------|
|
||||||
|
| 2.1 | Создать BentoCard компонент | `[x]` | С вариантами размеров |
|
||||||
|
| 2.2 | Обновить .card в globals.css | `[x]` | Новые классы .bento-card, .bento-card-hover, .bento-card-glow |
|
||||||
|
|
||||||
|
**Файлы:**
|
||||||
|
- `src/components/ui/BentoCard.tsx` (новый)
|
||||||
|
- `src/styles/globals.css`
|
||||||
|
|
||||||
|
**API компонента:**
|
||||||
|
```tsx
|
||||||
|
type BentoSize = 'sm' | 'md' | 'lg' | 'xl' // 1x1, 2x1, 1x2, 2x2
|
||||||
|
|
||||||
|
interface BentoCardProps {
|
||||||
|
size?: BentoSize
|
||||||
|
children: React.ReactNode
|
||||||
|
className?: string
|
||||||
|
hover?: boolean
|
||||||
|
as?: 'div' | 'Link' | 'button'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Этап 3: Скелет (Floating TabBar)
|
||||||
|
> Цель: Bottom navigation как "парящий остров"
|
||||||
|
|
||||||
|
| # | Задача | Статус | Заметки |
|
||||||
|
|---|--------|--------|---------|
|
||||||
|
| 3.1 | Floating island стиль | `[x]` | margin 16px от краев, shadow |
|
||||||
|
| 3.2 | Active state с pill | `[x]` | rounded-2xl фон под активной иконкой |
|
||||||
|
| 3.3 | Убрать border-top | `[x]` | Заменено на shadow |
|
||||||
|
|
||||||
|
**Файлы:**
|
||||||
|
- `src/components/layout/Layout.tsx` (секция bottom-nav)
|
||||||
|
- `src/styles/globals.css` (`.bottom-nav` классы)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Этап 4: Мясо (Dashboard Grid)
|
||||||
|
> Цель: Главная страница в стиле Bento
|
||||||
|
|
||||||
|
| # | Задача | Статус | Заметки |
|
||||||
|
|---|--------|--------|---------|
|
||||||
|
| 4.1 | Создать .bento-grid контейнер | `[x]` | CSS Grid с gap, 2 колонки mobile, 4 desktop |
|
||||||
|
| 4.2 | Subscription Status → bento-card | `[x]` | Главная карточка подписки |
|
||||||
|
| 4.3 | Stats Grid → bento-grid + bento-card-hover | `[x]` | Balance, Subscription, Referrals, Earnings |
|
||||||
|
| 4.4 | Quick Actions → bento-card | `[x]` | Контейнер для кнопок |
|
||||||
|
| 4.5 | Trial + Wheel Banner → bento-card-glow/hover | `[x]` | Акцентные карточки |
|
||||||
|
|
||||||
|
**Файлы:**
|
||||||
|
- `src/pages/Dashboard.tsx`
|
||||||
|
- `src/styles/globals.css`
|
||||||
|
|
||||||
|
**Правило:** Логику JS/TS НЕ трогаем — только UI обёртки.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Решения и обоснования
|
||||||
|
|
||||||
|
### Почему Urbanist, а не Inter?
|
||||||
|
- Urbanist более геометричный, лучше подходит под Bento-эстетику
|
||||||
|
- Хорошая читаемость на мобильных
|
||||||
|
- Бесплатный, Google Fonts
|
||||||
|
|
||||||
|
### Почему rounded-3xl (24px)?
|
||||||
|
- Стандарт Bento — крупные скругления
|
||||||
|
- 16px (текущий rounded-2xl) выглядит слишком "приложенечно"
|
||||||
|
- 32px (rounded-4xl) для особо крупных элементов
|
||||||
|
|
||||||
|
### Floating TabBar vs прилипший
|
||||||
|
- Floating выглядит премиально
|
||||||
|
- Отделяет навигацию от контента визуально
|
||||||
|
- Работает с safe-area на iOS
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Что НЕ делаем
|
||||||
|
|
||||||
|
- ❌ Модалки (ConnectionModal, TopUpModal) — вторично
|
||||||
|
- ❌ Страницы кроме Dashboard — после MVP
|
||||||
|
- ❌ Header — работает, не ломаем
|
||||||
|
- ❌ Рефакторинг логики — только UI
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Прогресс
|
||||||
|
|
||||||
|
```
|
||||||
|
Этап 1: ██████████ 100%
|
||||||
|
Этап 2: ██████████ 100%
|
||||||
|
Этап 3: ██████████ 100%
|
||||||
|
Этап 4: ██████████ 100%
|
||||||
|
─────────────────────
|
||||||
|
Общий: ██████████ 100%
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Заметки для агентов
|
||||||
|
|
||||||
|
**Контекст:** Это Mini App для Telegram (VPN кабинет). Мобильный фокус.
|
||||||
|
|
||||||
|
**Текущий стек:**
|
||||||
|
- React + Vite + TypeScript
|
||||||
|
- Tailwind CSS
|
||||||
|
- React Query для данных
|
||||||
|
|
||||||
|
**Ключевые файлы:**
|
||||||
|
- `tailwind.config.js` — цвета через CSS переменные
|
||||||
|
- `src/styles/globals.css` — компонентные классы (.card, .btn, etc)
|
||||||
|
- `src/components/layout/Layout.tsx` — шапка + таббар
|
||||||
|
- `src/pages/Dashboard.tsx` — главный экран (монстр, но логику не трогаем)
|
||||||
|
|
||||||
|
**Темы:** Есть dark и light (champagne). Bento-стили должны работать в обеих.
|
||||||
115
src/components/ui/BentoCard.tsx
Normal file
115
src/components/ui/BentoCard.tsx
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import { forwardRef } from 'react'
|
||||||
|
|
||||||
|
export type BentoSize = 'sm' | 'md' | 'lg' | 'xl'
|
||||||
|
|
||||||
|
interface BentoCardBaseProps {
|
||||||
|
size?: BentoSize
|
||||||
|
children: React.ReactNode
|
||||||
|
className?: string
|
||||||
|
hover?: boolean
|
||||||
|
glow?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BentoCardDivProps extends BentoCardBaseProps {
|
||||||
|
as?: 'div'
|
||||||
|
onClick?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BentoCardLinkProps extends BentoCardBaseProps {
|
||||||
|
as: 'link'
|
||||||
|
to: string
|
||||||
|
state?: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BentoCardButtonProps extends BentoCardBaseProps {
|
||||||
|
as: 'button'
|
||||||
|
onClick?: () => void
|
||||||
|
disabled?: boolean
|
||||||
|
type?: 'button' | 'submit'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BentoCardProps = BentoCardDivProps | BentoCardLinkProps | BentoCardButtonProps
|
||||||
|
|
||||||
|
const sizeClasses: Record<BentoSize, string> = {
|
||||||
|
sm: '',
|
||||||
|
md: 'col-span-2',
|
||||||
|
lg: 'row-span-2',
|
||||||
|
xl: 'col-span-2 row-span-2',
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseClasses = `
|
||||||
|
bento-card
|
||||||
|
rounded-[var(--bento-radius)]
|
||||||
|
p-[var(--bento-padding)]
|
||||||
|
bg-dark-900/70
|
||||||
|
border border-dark-700/40
|
||||||
|
transition-all duration-300 ease-smooth
|
||||||
|
`
|
||||||
|
|
||||||
|
const hoverClasses = `
|
||||||
|
cursor-pointer
|
||||||
|
hover:bg-dark-800/60
|
||||||
|
hover:border-dark-600/50
|
||||||
|
hover:shadow-lg
|
||||||
|
hover:scale-[1.01]
|
||||||
|
active:scale-[0.99]
|
||||||
|
`
|
||||||
|
|
||||||
|
const glowClasses = `
|
||||||
|
hover:shadow-glow
|
||||||
|
hover:border-accent-500/30
|
||||||
|
`
|
||||||
|
|
||||||
|
export const BentoCard = forwardRef<HTMLDivElement, BentoCardProps>((props, ref) => {
|
||||||
|
const {
|
||||||
|
size = 'sm',
|
||||||
|
children,
|
||||||
|
className = '',
|
||||||
|
hover = false,
|
||||||
|
glow = false,
|
||||||
|
} = props
|
||||||
|
|
||||||
|
const classes = [
|
||||||
|
baseClasses,
|
||||||
|
sizeClasses[size],
|
||||||
|
hover && hoverClasses,
|
||||||
|
glow && glowClasses,
|
||||||
|
className,
|
||||||
|
].filter(Boolean).join(' ')
|
||||||
|
|
||||||
|
if (props.as === 'link') {
|
||||||
|
const { to, state } = props as BentoCardLinkProps
|
||||||
|
return (
|
||||||
|
<Link to={to} state={state} className={classes}>
|
||||||
|
{children}
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.as === 'button') {
|
||||||
|
const { onClick, disabled, type = 'button' } = props as BentoCardButtonProps
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
ref={ref as React.Ref<HTMLButtonElement>}
|
||||||
|
type={type}
|
||||||
|
onClick={onClick}
|
||||||
|
disabled={disabled}
|
||||||
|
className={classes}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { onClick } = props as BentoCardDivProps
|
||||||
|
return (
|
||||||
|
<div ref={ref} onClick={onClick} className={classes}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
BentoCard.displayName = 'BentoCard'
|
||||||
|
|
||||||
|
export default BentoCard
|
||||||
@@ -254,7 +254,7 @@ export default function Dashboard() {
|
|||||||
|
|
||||||
{/* Subscription Status - Main Card */}
|
{/* Subscription Status - Main Card */}
|
||||||
{subscription && (
|
{subscription && (
|
||||||
<div className="card">
|
<div className="bento-card">
|
||||||
<div className="flex items-center justify-between mb-6">
|
<div className="flex items-center justify-between mb-6">
|
||||||
<h2 className="text-lg font-semibold text-dark-100">{t('subscription.status')}</h2>
|
<h2 className="text-lg font-semibold text-dark-100">{t('subscription.status')}</h2>
|
||||||
<span className={subscription.is_active ? 'badge-success' : 'badge-error'}>
|
<span className={subscription.is_active ? 'badge-success' : 'badge-error'}>
|
||||||
@@ -336,9 +336,9 @@ export default function Dashboard() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Stats Grid */}
|
{/* Stats Grid */}
|
||||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
<div className="bento-grid">
|
||||||
{/* Balance */}
|
{/* Balance */}
|
||||||
<Link to="/balance" className="card-hover group" data-onboarding="balance">
|
<Link to="/balance" className="bento-card-hover group" data-onboarding="balance">
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<span className="text-dark-400 text-sm">{t('balance.currentBalance')}</span>
|
<span className="text-dark-400 text-sm">{t('balance.currentBalance')}</span>
|
||||||
<span className="text-dark-600 group-hover:text-accent-400 transition-colors">
|
<span className="text-dark-600 group-hover:text-accent-400 transition-colors">
|
||||||
@@ -352,7 +352,7 @@ export default function Dashboard() {
|
|||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{/* Subscription */}
|
{/* Subscription */}
|
||||||
<Link to="/subscription" className="card-hover group" data-onboarding="subscription-status">
|
<Link to="/subscription" className="bento-card-hover group" data-onboarding="subscription-status">
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<span className="text-dark-400 text-sm">{t('subscription.title')}</span>
|
<span className="text-dark-400 text-sm">{t('subscription.title')}</span>
|
||||||
<span className="text-dark-600 group-hover:text-accent-400 transition-colors">
|
<span className="text-dark-600 group-hover:text-accent-400 transition-colors">
|
||||||
@@ -388,7 +388,7 @@ export default function Dashboard() {
|
|||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{/* Referrals */}
|
{/* Referrals */}
|
||||||
<Link to="/referral" className="card-hover group">
|
<Link to="/referral" className="bento-card-hover group">
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<span className="text-dark-400 text-sm">{t('referral.stats.totalReferrals')}</span>
|
<span className="text-dark-400 text-sm">{t('referral.stats.totalReferrals')}</span>
|
||||||
<span className="text-dark-600 group-hover:text-accent-400 transition-colors">
|
<span className="text-dark-600 group-hover:text-accent-400 transition-colors">
|
||||||
@@ -403,7 +403,7 @@ export default function Dashboard() {
|
|||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{/* Earnings */}
|
{/* Earnings */}
|
||||||
<Link to="/referral" className="card-hover group">
|
<Link to="/referral" className="bento-card-hover group">
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<span className="text-dark-400 text-sm">{t('referral.stats.totalEarnings')}</span>
|
<span className="text-dark-400 text-sm">{t('referral.stats.totalEarnings')}</span>
|
||||||
<span className="text-dark-600 group-hover:text-accent-400 transition-colors">
|
<span className="text-dark-600 group-hover:text-accent-400 transition-colors">
|
||||||
@@ -422,7 +422,7 @@ export default function Dashboard() {
|
|||||||
|
|
||||||
{/* Trial Activation */}
|
{/* Trial Activation */}
|
||||||
{hasNoSubscription && !trialLoading && trialInfo?.is_available && (
|
{hasNoSubscription && !trialLoading && trialInfo?.is_available && (
|
||||||
<div className="card border-accent-500/30 bg-gradient-to-br from-accent-500/5 to-transparent">
|
<div className="bento-card-glow border-accent-500/30 bg-gradient-to-br from-accent-500/5 to-transparent">
|
||||||
<div className="flex items-start gap-4">
|
<div className="flex items-start gap-4">
|
||||||
<div className="w-12 h-12 rounded-xl bg-accent-500/20 flex items-center justify-center flex-shrink-0">
|
<div className="w-12 h-12 rounded-xl bg-accent-500/20 flex items-center justify-center flex-shrink-0">
|
||||||
<SparklesIcon />
|
<SparklesIcon />
|
||||||
@@ -483,7 +483,7 @@ export default function Dashboard() {
|
|||||||
{wheelConfig?.is_enabled && (
|
{wheelConfig?.is_enabled && (
|
||||||
<Link
|
<Link
|
||||||
to="/wheel"
|
to="/wheel"
|
||||||
className="group card-hover flex items-center justify-between"
|
className="group bento-card-hover flex items-center justify-between"
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
{/* Emoji */}
|
{/* Emoji */}
|
||||||
@@ -504,7 +504,7 @@ export default function Dashboard() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Quick Actions */}
|
{/* Quick Actions */}
|
||||||
<div className="card" data-onboarding="quick-actions">
|
<div className="bento-card" data-onboarding="quick-actions">
|
||||||
<h3 className="text-lg font-semibold text-dark-100 mb-4">{t('dashboard.quickActions')}</h3>
|
<h3 className="text-lg font-semibold text-dark-100 mb-4">{t('dashboard.quickActions')}</h3>
|
||||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
|
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
|
||||||
<Link to="/balance" className="btn-secondary justify-center text-center text-sm py-2.5">
|
<Link to="/balance" className="btn-secondary justify-center text-center text-sm py-2.5">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Urbanist:wght@400;500;600;700;800&display=swap');
|
||||||
|
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@@ -8,6 +8,14 @@
|
|||||||
:root {
|
:root {
|
||||||
--safe-area-inset-bottom: env(safe-area-inset-bottom, 0px);
|
--safe-area-inset-bottom: env(safe-area-inset-bottom, 0px);
|
||||||
|
|
||||||
|
/* Bento Design System */
|
||||||
|
--bento-radius: 24px;
|
||||||
|
--bento-radius-lg: 32px;
|
||||||
|
--bento-gap: 16px;
|
||||||
|
--bento-gap-lg: 24px;
|
||||||
|
--bento-padding: 24px;
|
||||||
|
--bento-padding-lg: 32px;
|
||||||
|
|
||||||
/* Theme colors - RGB format for opacity support */
|
/* Theme colors - RGB format for opacity support */
|
||||||
/* Dark palette (RGB values) */
|
/* Dark palette (RGB values) */
|
||||||
--color-dark-50: 248, 250, 252;
|
--color-dark-50: 248, 250, 252;
|
||||||
@@ -327,6 +335,63 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
|
/* ========== BENTO DESIGN SYSTEM ========== */
|
||||||
|
|
||||||
|
.bento-card {
|
||||||
|
@apply bg-dark-900/70 border border-dark-700/40
|
||||||
|
transition-all duration-300 ease-smooth;
|
||||||
|
border-radius: var(--bento-radius);
|
||||||
|
padding: var(--bento-padding);
|
||||||
|
transform: translateZ(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.bento-card {
|
||||||
|
@apply bg-dark-900/50 backdrop-blur-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bento-card-hover {
|
||||||
|
@apply bento-card cursor-pointer
|
||||||
|
hover:bg-dark-800/60 hover:border-dark-600/50
|
||||||
|
hover:shadow-lg hover:scale-[1.01] active:scale-[0.99];
|
||||||
|
}
|
||||||
|
|
||||||
|
.bento-card-glow {
|
||||||
|
@apply bento-card hover:shadow-glow hover:border-accent-500/30 hover:scale-[1.01];
|
||||||
|
}
|
||||||
|
|
||||||
|
.bento-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: var(--bento-gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.bento-grid {
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: var(--bento-gap-lg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light .bento-card {
|
||||||
|
@apply bg-white/90 border-champagne-300/50 shadow-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.light .bento-card {
|
||||||
|
@apply bg-white/80 backdrop-blur-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.light .bento-card-hover {
|
||||||
|
@apply hover:bg-white hover:border-champagne-400/50 hover:shadow-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light .bento-card-glow {
|
||||||
|
@apply hover:shadow-lg hover:border-accent-400/40;
|
||||||
|
}
|
||||||
|
|
||||||
/* ========== DARK THEME COMPONENTS (default) ========== */
|
/* ========== DARK THEME COMPONENTS (default) ========== */
|
||||||
|
|
||||||
/* Cards - Dark (optimized for mobile) */
|
/* Cards - Dark (optimized for mobile) */
|
||||||
@@ -493,12 +558,17 @@
|
|||||||
@apply nav-item text-accent-400 bg-accent-500/10;
|
@apply nav-item text-accent-400 bg-accent-500/10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bottom nav - Dark (optimized for mobile) */
|
|
||||||
.bottom-nav {
|
.bottom-nav {
|
||||||
@apply fixed bottom-0 left-0 right-0 z-50
|
@apply fixed z-50 bg-dark-900/95;
|
||||||
bg-dark-900/95 border-t border-dark-800/50
|
bottom: 16px;
|
||||||
safe-area-pb;
|
left: 16px;
|
||||||
|
right: 16px;
|
||||||
|
border-radius: var(--bento-radius);
|
||||||
|
padding: 8px 4px;
|
||||||
|
padding-bottom: calc(8px + var(--safe-area-inset-bottom));
|
||||||
transform: translateZ(0);
|
transform: translateZ(0);
|
||||||
|
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.4),
|
||||||
|
0 0 0 1px rgba(255, 255, 255, 0.05) inset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
@@ -508,12 +578,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bottom-nav-item {
|
.bottom-nav-item {
|
||||||
@apply flex flex-col items-center justify-center py-2 px-2 flex-1 min-w-[60px]
|
@apply flex flex-col items-center justify-center py-2.5 px-3 flex-1 min-w-[56px]
|
||||||
text-dark-500 transition-colors duration-200 shrink-0;
|
text-dark-500 transition-all duration-200 shrink-0 rounded-2xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-nav-item:hover {
|
||||||
|
@apply text-dark-300;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom-nav-item-active {
|
.bottom-nav-item-active {
|
||||||
@apply bottom-nav-item text-accent-400;
|
@apply flex flex-col items-center justify-center py-2.5 px-3 flex-1 min-w-[56px]
|
||||||
|
text-accent-400 bg-accent-500/15 rounded-2xl transition-all duration-200 shrink-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Divider - Dark */
|
/* Divider - Dark */
|
||||||
@@ -668,17 +743,28 @@
|
|||||||
@apply text-champagne-800 bg-champagne-200/70;
|
@apply text-champagne-800 bg-champagne-200/70;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bottom nav - Light */
|
|
||||||
.light .bottom-nav {
|
.light .bottom-nav {
|
||||||
@apply bg-white/90 backdrop-blur-xl border-t border-champagne-200;
|
@apply bg-white/95;
|
||||||
|
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1),
|
||||||
|
0 0 0 1px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.light .bottom-nav {
|
||||||
|
@apply bg-white/80 backdrop-blur-xl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.light .bottom-nav-item {
|
.light .bottom-nav-item {
|
||||||
@apply text-champagne-500;
|
@apply text-champagne-500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.light .bottom-nav-item:hover {
|
||||||
|
@apply text-champagne-700;
|
||||||
|
}
|
||||||
|
|
||||||
.light .bottom-nav-item-active {
|
.light .bottom-nav-item-active {
|
||||||
@apply text-champagne-800;
|
@apply text-champagne-800 bg-champagne-300/40;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Divider - Light */
|
/* Divider - Light */
|
||||||
|
|||||||
@@ -106,7 +106,15 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
sans: ['Inter', 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'],
|
sans: ['Urbanist', 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'],
|
||||||
|
},
|
||||||
|
borderRadius: {
|
||||||
|
'bento': '24px',
|
||||||
|
'4xl': '32px',
|
||||||
|
},
|
||||||
|
spacing: {
|
||||||
|
'bento': '16px',
|
||||||
|
'bento-lg': '24px',
|
||||||
},
|
},
|
||||||
fontSize: {
|
fontSize: {
|
||||||
'2xs': ['0.625rem', { lineHeight: '0.875rem' }],
|
'2xs': ['0.625rem', { lineHeight: '0.875rem' }],
|
||||||
|
|||||||
Reference in New Issue
Block a user