Enhance documentation and styling system with Mirage Palette, Material Design 3, and Neon accents. Add comprehensive style guide, color palette, and cheatsheet for improved developer experience.

This commit is contained in:
IluaAir
2025-10-27 23:11:11 +03:00
parent cad5cfa780
commit 9820437556
11 changed files with 1415 additions and 381 deletions

View File

@@ -50,6 +50,22 @@ ___
### Frontend ### Frontend
- **React.js** - **React.js**
- **Vite** - **Vite**
- **Tailwind CSS**
- **Material Design 3**
- **Custom Design System** (Mirage Palette + Neon)
---
## 🎨 Design System
Проект использует собственную систему дизайна:
- **Mirage Color Palette** - профессиональная темная сине-синяя тема
- **Material Design 3** - современные UI паттерны
- **Neon Cyberpunk** - уникальные неоновые акценты
**Документация:**
- [Frontend Guide](taskncoffee-app/README.md) - документация frontend
- [Styles Cheatsheet](taskncoffee-app/docs/STYLES_CHEATSHEET.md) - быстрая справка
--- ---

View File

@@ -1,16 +1,76 @@
# React + Vite # Task&Coffee Frontend
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. > Modern task management app with Material Design 3 + Neon aesthetic
Currently, two official plugins are available: ## 🚀 Quick Start
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh ```bash
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh npm install
npm run dev
```
## React Compiler ---
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). ## 🎨 Styling System
## Expanding the ESLint configuration We use a custom design system combining:
- **Mirage Color Palette** - Professional dark blue theme
- **Material Design 3** - Modern UI patterns
- **Neon Cyberpunk** - Unique glowing accents
If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. ### Usage
```jsx
import styles from '@/lib/styles';
<div className={styles.card.filled}>
<h2 className={styles.text.h2}>Hello</h2>
<button className={styles.button.primaryNeon}>Click</button>
</div>
```
### 📖 Documentation
| Document | Purpose |
|----------|---------|
| **[Cheatsheet](./docs/STYLES_CHEATSHEET.md)** | 📋 Quick reference - copy/paste examples |
| **[Style Guide](./docs/STYLE_GUIDE.md)** | 📚 Complete guide with examples |
| **[Color Palette](./docs/COLOR_PALETTE.md)** | 🎨 Color meanings & usage |
**👉 Start with [Cheatsheet](./docs/STYLES_CHEATSHEET.md)** for quick examples!
---
## 🛠️ Tech Stack
- React 18 + Vite
- Tailwind CSS + Custom Design System
- Radix UI (accessibility)
- Lucide React (icons)
---
## 📁 Project Structure
```
src/
├── api/ API services
├── components/ Reusable components
├── lib/
│ ├── styles.js ⭐ Style presets (60+ ready-to-use)
│ └── utils.js Helper functions
├── pages/ Page components
├── index.css ⭐ Color variables (Mirage palette)
└── neon.css ⭐ Neon glow effects
```
---
## 📚 Learn More
- [Design System Overview](../DESIGN_SYSTEM_SUMMARY.md)
- [Vite](https://vitejs.dev/) | [React](https://react.dev/) | [Tailwind](https://tailwindcss.com/)
---
**Made with 💙 and neon ✨**

View File

@@ -0,0 +1,259 @@
# 🎨 Task&Coffee Color Palette
**Usage examples?** See [STYLE_GUIDE.md](./STYLE_GUIDE.md)
**Quick reference?** See [STYLES_CHEATSHEET.md](./STYLES_CHEATSHEET.md)
**Back to main?** See [README.md](../README.md)
---
## Mirage Palette - Visual Guide
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MIRAGE COLOR SCALE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
50 ░░░░░░░░░ #f4f6fb Lightest - heading text on dark bg
100 ▒▒▒▒▒▒▒▒▒ #e7edf7 Card foreground text
200 ▓▓▓▓▓▓▓▓▓ #cbd9ec Main foreground text
300 ▓▓▓▓▓▓▓▓▓ #9db8dc Muted foreground text
────────────────────────────────────────────────────────────
400 ████████ #6893c8 PRIMARY ACCENT ⭐
500 ████████ #4474b3 Accent hover state
────────────────────────────────────────────────────────────
600 ████████ #335b96 Secondary, elevated cards
700 ████████ #2a4a7a Dark cards alternative
800 ████████ #264066 Muted elements, popovers
900 ████████ #243756 CARDS ⭐
950 ████████ #111928 BACKGROUND (darkest) ⭐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
---
## 🌟 Semantic Color Mapping
### Background & Surfaces
```
--background #111928 (mirage-950) Main app background
--card #243756 (mirage-900) Card surfaces
--popover #264066 (mirage-800) Floating elements
--muted #264066 (mirage-800) Subtle backgrounds
--sidebar #111928 (mirage-950) Navigation rail
```
### Foreground & Text
```
--foreground #cbd9ec (mirage-200) Primary text
--card-foreground #e7edf7 (mirage-100) Text on cards
--muted-foreground #9db8dc (mirage-300) Secondary text
--popover-foreground #e7edf7 (mirage-100) Text in popovers
```
### Interactive Elements
```
--primary #6893c8 (mirage-400) Primary actions, links
--primary-foreground #111928 (mirage-950) Text on primary
--secondary #2a4a7a (mirage-700) Secondary actions
--accent #4474b3 (mirage-500) Hover states
```
### Borders & Inputs
```
--border rgba(157, 184, 220, 0.15) Subtle borders
--input rgba(157, 184, 220, 0.2) Input borders
--ring #6893c8 (mirage-400) Focus ring
```
---
## 💫 Neon Accent Colors
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
NEON ACCENTS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔵 Neon Blue #c6e2ff Light blue with glow effect
Glow color: rgba(30, 132, 242, 0.6)
💗 Neon Pink #ffc5ec Light pink with glow effect
Glow color: rgba(255, 20, 147, 0.6)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
---
## 🎯 Usage by Element Type
### Text Colors
```
Headings: mirage-200 (#cbd9ec)
Body text: mirage-200 (#cbd9ec)
Secondary text: mirage-300 (#9db8dc)
Disabled text: mirage-300 (#9db8dc) with opacity
```
### Backgrounds
```
Page background: mirage-950 (#111928)
Card background: mirage-900 (#243756)
Hover background: mirage-800 (#264066)
Active background: mirage-700 (#2a4a7a)
```
### Buttons
```
Primary: mirage-400 (#6893c8) bg
Primary hover: mirage-500 (#4474b3) bg
Secondary: mirage-700 (#2a4a7a) bg
Secondary hover: mirage-600 (#335b96) bg
Ghost hover: mirage-800 (#264066) bg
```
### Borders
```
Default: mirage-300 with 15% opacity
Input: mirage-300 with 20% opacity
Focus: mirage-400 (#6893c8) solid
Divider: mirage-800 (#264066)
```
---
## 🌈 Color Relationships
```
LIGHT ↑
┌─────────────────────────────────┐
│ mirage-50 │ Lightest text │
│ mirage-100 │ Card text │
│ mirage-200 │ Main text │
│ mirage-300 │ Muted text │
├─────────────────────────────────┤
│ mirage-400 │ PRIMARY ⭐ │ ← Interactive
│ mirage-500 │ Hover state │
├─────────────────────────────────┤
│ mirage-600 │ Secondary │
│ mirage-700 │ Alt cards │
│ mirage-800 │ Muted bg │
│ mirage-900 │ CARDS ⭐ │ ← Surfaces
│ mirage-950 │ BACKGROUND ⭐ │
└─────────────────────────────────┘
DARK ↓
```
---
## 📊 Contrast Ratios (WCAG)
```
Background (950) + Text (200): AAA ✓ (14.2:1)
Card (900) + Card Text (100): AAA ✓ (12.8:1)
Primary (400) + Primary FG (950): AA ✓ (5.2:1)
Muted (800) + Muted Text (300): AA ✓ (4.8:1)
```
All color combinations meet WCAG AA standards minimum! 🎉
---
## 🎨 Example Compositions
### Card with Neon Accent
```
┌────────────────────────────────┐
│ mirage-900 background │
│ ┌──────────────────────────┐ │
│ │ mirage-100 text │ │
│ │ mirage-300 muted text │ │
│ │ │ │
│ │ [mirage-400 button] │ │
│ │ + neon blue glow │ │
│ └──────────────────────────┘ │
└────────────────────────────────┘
```
### Primary Button
```
┌──────────────────────┐
│ mirage-400 bg │ ← Background
│ mirage-950 text │ ← Text
│ + subtle shadow │
│ hover: neon glow │ ← Neon effect on hover
└──────────────────────┘
```
### Today's Task Column
```
┌────────────────────────────────┐
│ mirage-400/10 background │ ← 10% opacity
│ + mirage-400 border (2px) │ ← Solid border
│ + neon-blue glow │ ← Glow effect
│ │
│ Tasks: mirage-900 cards │
└────────────────────────────────┘
```
---
## 🔄 Dark Mode Toggle
When dark mode is active (`.dark` class):
```
Background: mirage-900 → mirage-950
Cards: mirage-700 → mirage-900
Primary: mirage-300 → mirage-400
Text: mirage-100 → mirage-200
```
Currently configured for dark-first design.
---
## 💡 Best Practices
1. **Depth hierarchy:**
- Background: mirage-950
- Elevated: mirage-900
- More elevated: mirage-800
2. **Text contrast:**
- Always use mirage-100/200 for text on dark backgrounds
- Use mirage-300 for less important text
3. **Neon sparingly:**
- Use neon effects only for:
- Brand elements (logo, headers)
- Important CTAs
- Today's tasks/current items
- Don't overuse - it should feel special
4. **Accessible focus states:**
- Always use mirage-400 for focus rings
- Add 3px ring with 50% opacity
---
## 🚀 Quick Reference
| Element | Light Value | Dark Value | Usage |
|---------|-------------|------------|-------|
| Page BG | `mirage-950` | `mirage-900` | Main background |
| Card BG | `mirage-900` | `mirage-700` | Surface |
| Text | `mirage-200` | `mirage-100` | Primary text |
| Primary | `mirage-400` | `mirage-300` | CTA buttons |
| Border | `mirage-300/15%` | `mirage-300/20%` | Dividers |
---
**See also:**
- `STYLE_GUIDE.md` - Complete style documentation
- `STYLES_CHEATSHEET.md` - Quick usage examples
- `src/lib/styles.js` - Tailwind class presets

View File

@@ -0,0 +1,244 @@
# Task&Coffee Styles Cheatsheet 🎨
Быстрая справка по использованию стилей в проекте.
**Full guide?** See [STYLE_GUIDE.md](./STYLE_GUIDE.md)
**Color reference?** See [COLOR_PALETTE.md](./COLOR_PALETTE.md)
**Back to main?** See [README.md](../README.md)
---
## Импорт
```javascript
import styles from '@/lib/styles';
import { cn } from '@/lib/utils';
```
---
## 📦 Карточки
```jsx
<div className={styles.card.filled}>Basic card</div>
<div className={styles.card.elevated}>Elevated card</div>
<div className={styles.card.task}>Task card</div>
<div className={styles.card.taskNeon}>Task card with glow</div>
```
---
## 🔘 Кнопки
```jsx
<button className={styles.button.primary}>Primary</button>
<button className={styles.button.primaryNeon}>Primary Neon</button>
<button className={styles.button.secondary}>Secondary</button>
<button className={styles.button.outline}>Outline</button>
<button className={styles.button.ghost}>Ghost</button>
<button className={styles.button.destructive}>Delete</button>
<button className={styles.button.icon}>🔍</button>
<button className={styles.button.iconNeon}></button>
```
---
## 📝 Inputs
```jsx
<input className={styles.input.default} />
<input className={styles.input.neon} />
<input className={styles.input.search} />
```
---
## 🏷️ Badges
```jsx
<span className={styles.badge.low}>Low</span>
<span className={styles.badge.medium}>Medium</span>
<span className={styles.badge.high}>High</span>
<span className={styles.badge.critical}>Critical</span>
<span className={styles.badge.success}>Success</span>
<span className={styles.badge.warning}>Warning</span>
<span className={styles.badge.error}>Error</span>
```
---
## ✨ Neon Effects (CSS Classes)
```jsx
<div className="neon-glow-blue">Blue glow on hover</div>
<div className="neon-glow-pink">Pink glow on hover</div>
<div className="neon-glow-soft">Soft glow</div>
<div className="neon-border-blue">Blue neon border</div>
<div className="neon-border-pink">Pink neon border</div>
<span className="neon-text-blue">Blue neon text</span>
<span className="neon-text-pink">Pink neon text</span>
<Icon className="neon-icon" />
```
---
## 🎭 Neon Animated Text
```jsx
<span className="sign-inline">Task&Coffee</span>
<span className="sign-pink-inline">Task&Coffee</span>
```
---
## 📐 Layout
```jsx
<div className={styles.layout.container}>
<aside className={styles.layout.sidebar}>Sidebar</aside>
<main className={styles.layout.main}>
<div className={styles.layout.content}>Content</div>
</main>
</div>
<div className={styles.layout.gridCards}>Cards grid</div>
```
---
## 🔤 Typography
```jsx
<h1 className={styles.text.h1}>Heading 1</h1>
<h2 className={styles.text.h2}>Heading 2</h2>
<p className={styles.text.body}>Body text</p>
<p className={styles.text.bodyMuted}>Muted text</p>
<small className={styles.text.small}>Small text</small>
```
---
## 🛠️ Utilities
```jsx
// Glow effects
<div className={styles.utility.glowBlue}>Blue glow</div>
<div className={styles.utility.glowPink}>Pink glow</div>
<div className={styles.utility.glowSoft}>Soft glow</div>
// Glass effect
<div className={styles.utility.glass}>Glassmorphism</div>
// Transitions
<div className={styles.utility.transition}>Smooth</div>
<div className={styles.utility.transitionSlow}>Slow</div>
// Focus ring
<button className={styles.utility.focusRing}>Accessible</button>
```
---
## 🎨 Цветовые переменные
### В CSS
```css
background: var(--color-background);
color: var(--color-foreground);
background: var(--color-card);
color: var(--color-primary);
border: 1px solid var(--color-border);
```
### В Tailwind
```jsx
<div className="bg-background text-foreground">
<div className="bg-card text-card-foreground">
<div className="bg-primary text-primary-foreground">
<div className="border border-border">
```
---
## 🔄 Комбинирование
```jsx
import { cn } from '@/lib/utils';
<div className={cn(
styles.card.task,
"neon-glow-soft",
isActive && "neon-border-blue"
)}>
Combined styles
</div>
```
---
## 📏 Радиусы
- `rounded-lg` = **0.5rem** ← используем для кнопок и карточек
- `rounded-xl` = 0.75rem
- `rounded-2xl` = 1rem
---
## 🎯 Полный пример компонента
```jsx
import styles from '@/lib/styles';
import { cn } from '@/lib/utils';
function TaskCard({ task, isToday }) {
return (
<div className={cn(
styles.card.task,
"neon-glow-soft",
isToday && "neon-border-blue"
)}>
<div className="flex items-center gap-2">
<span className={styles.badge[task.priority]}>
{task.priority}
</span>
<h3 className={styles.text.small}>{task.title}</h3>
</div>
<p className={styles.text.smallMuted}>{task.description}</p>
<button className={styles.button.primaryNeon}>
Complete
</button>
</div>
);
}
```
---
## 🌈 Mirage Colors
| Name | Hex | Usage |
|------|-----|-------|
| mirage-950 | `#111928` | Background (darkest) |
| mirage-900 | `#243756` | Cards |
| mirage-800 | `#264066` | Muted elements |
| mirage-700 | `#2a4a7a` | Secondary |
| mirage-600 | `#335b96` | Elevated cards |
| mirage-500 | `#4474b3` | Accent hover |
| mirage-400 | `#6893c8` | Primary accent |
| mirage-300 | `#9db8dc` | Muted text |
| mirage-200 | `#cbd9ec` | Main text |
| mirage-100 | `#e7edf7` | Card text |
| mirage-50 | `#f4f6fb` | Lightest text |
---
## 💡 Tips
1. Используйте готовые стили из `styles.js`
2. Комбинируйте с `cn()` для кастомизации
3. Неон - только для акцентов!
4. Всегда используйте CSS переменные
5. `rounded-lg` для консистентности
**Полная документация:** См. `STYLE_GUIDE.md`

View File

@@ -0,0 +1,371 @@
# Task&Coffee Style Guide
> Complete guide with examples and best practices
**Quick reference?** See [STYLES_CHEATSHEET.md](./STYLES_CHEATSHEET.md)
**Color details?** See [COLOR_PALETTE.md](./COLOR_PALETTE.md)
**Back to main?** See [README.md](../README.md)
---
## 📦 Using Styles
### Import
```javascript
import styles from '@/lib/styles';
import { cn } from '@/lib/utils';
```
### Примеры использования
#### 1. Карточки (Cards)
```jsx
// Filled card - основной вариант
<div className={cardStyles.filled}>
<h3>Card Title</h3>
<p>Card content...</p>
</div>
// Elevated card с тенью
<div className={cardStyles.elevated}>
<h3>Important Card</h3>
</div>
// Task card с неоновым эффектом
<div className={cardStyles.taskNeon}>
<p>Task description</p>
</div>
// Или используя cn helper
import { cn } from '@/lib/utils';
<div className={cn(cardStyles.filled, "additional-class")}>
Content
</div>
```
#### 2. Кнопки (Buttons)
```jsx
// Primary button
<button className={buttonStyles.primary}>
Submit
</button>
// Primary с неоновым эффектом
<button className={buttonStyles.primaryNeon}>
Create Task
</button>
// Secondary button
<button className={buttonStyles.secondary}>
Cancel
</button>
// Ghost button
<button className={buttonStyles.ghost}>
Learn More
</button>
// Icon button с неоновым эффектом
<button className={buttonStyles.iconNeon}>
<Icon />
</button>
```
#### 3. Layouts
```jsx
// Dashboard layout
<div className={layoutStyles.container}>
<aside className={layoutStyles.sidebar}>
{/* Sidebar content */}
</aside>
<main className={layoutStyles.main}>
<div className={layoutStyles.content}>
{/* Main content */}
</div>
</main>
</div>
// Grid для карточек
<div className={layoutStyles.gridCards}>
<Card />
<Card />
<Card />
</div>
```
#### 4. Inputs
```jsx
// Стандартный input
<input
type="text"
className={inputStyles.default}
placeholder="Enter text..."
/>
// Input с неоновым фокусом
<input
type="text"
className={inputStyles.neon}
placeholder="Task name..."
/>
// Search input
<div className="relative">
<SearchIcon className="absolute left-3 top-1/2 -translate-y-1/2" />
<input
type="search"
className={inputStyles.search}
placeholder="Search tasks..."
/>
</div>
```
#### 5. Typography
```jsx
// Headings
<h1 className={textStyles.h1}>Main Title</h1>
<h2 className={textStyles.h2}>Section Title</h2>
// Body text
<p className={textStyles.body}>Regular text</p>
<p className={textStyles.bodyMuted}>Muted text</p>
// Неоновый текст (используется с neon.css)
<span className={cn(textStyles.neonBlue, "sign-inline")}>
Task&
</span>
<span className={cn(textStyles.neonPink, "sign-pink-inline")}>
Coffee
</span>
```
#### 6. Badges
```jsx
// Priority badges
<span className={badgeStyles.low}>Low</span>
<span className={badgeStyles.medium}>Medium</span>
<span className={badgeStyles.high}>High</span>
<span className={badgeStyles.critical}>Critical</span>
// Status badges
<span className={badgeStyles.success}>Completed</span>
<span className={badgeStyles.warning}>In Progress</span>
<span className={badgeStyles.error}>Failed</span>
```
---
## ✨ Неоновые эффекты
### CSS классы из neon.css
```jsx
// Неоновое свечение при hover - голубое
<div className="neon-glow-blue bg-card p-4 rounded-lg">
Card with blue glow on hover
</div>
// Неоновое свечение - розовое
<div className="neon-glow-pink bg-card p-4 rounded-lg">
Card with pink glow on hover
</div>
// Мягкое свечение
<button className="neon-glow-soft bg-primary px-4 py-2 rounded-lg">
Subtle glow
</button>
// Неоновая граница
<div className="neon-border-blue p-4 rounded-lg">
Border with neon effect
</div>
// Неоновый текст (без анимации)
<span className="neon-text-blue">
Static neon text
</span>
// Иконка с неоновым эффектом
<Icon className="neon-icon" />
```
### Анимированный неоновый текст
```jsx
// Для заголовков и брендинга
<div className="sign-inline">Coffee</div>
<div className="sign-pink-inline">Task&</div>
// Для больших заголовков (fullscreen)
<div className="sign">
<span>Task&Coffee</span>
</div>
```
---
## 🎭 Комбинирование стилей
### Пример: Карточка задачи с неоновым эффектом
```jsx
import { cn } from '@/lib/utils';
import { cardStyles, badgeStyles, textStyles } from '@/lib/styles';
function TaskCard({ task }) {
return (
<div className={cn(
cardStyles.task,
"neon-glow-soft",
task.isToday && "neon-border-blue"
)}>
<div className="flex items-center gap-2 mb-2">
<span className={badgeStyles[task.priority]}>
{task.priority}
</span>
<h3 className={textStyles.small}>
{task.title}
</h3>
</div>
<p className={textStyles.smallMuted}>
{task.description}
</p>
</div>
);
}
```
### Пример: Кнопка с неоновым эффектом и иконкой
```jsx
import { PlusIcon } from 'lucide-react';
import { cn } from '@/lib/utils';
import { buttonStyles } from '@/lib/styles';
function CreateButton() {
return (
<button className={cn(
buttonStyles.primaryNeon,
"gap-2"
)}>
<PlusIcon className="w-4 h-4" />
Create Task
</button>
);
}
```
---
## 🎨 Миграция с dashboard.css на Tailwind
### До (dashboard.css):
```css
.dashboard-task-card {
background: var(--color-card);
padding: 0.75rem;
border-radius: 0.5rem;
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
}
```
### После (с использованием стилей):
```jsx
<div className={cardStyles.task}>
{/* content */}
</div>
// Или чистый Tailwind:
<div className="bg-card p-3 rounded-lg shadow-sm">
{/* content */}
</div>
```
---
## 📐 Радиусы округления
Теперь все радиусы синхронизированы:
- `rounded-sm` = `0.25rem` (4px)
- `rounded-md` = `0.375rem` (6px)
- `rounded-lg` = `0.5rem` (8px) ✅ **Используем для карточек и кнопок**
- `rounded-xl` = `0.75rem` (12px)
- `rounded-2xl` = `1rem` (16px)
Базовый радиус установлен в `--radius: 0.5rem` для консистентности с Material Design 3.
---
## 🔧 Утилиты
### Neon Glow Utilities
```javascript
import { utilityStyles } from '@/lib/styles';
<div className={cn(cardStyles.filled, utilityStyles.glowBlue)}>
Card with blue glow
</div>
```
### Glassmorphism
```jsx
<div className={cn(utilityStyles.glass, "p-6 rounded-lg")}>
Glass effect card
</div>
```
### Focus Ring
```jsx
<button className={cn(
buttonStyles.primary,
utilityStyles.focusRing
)}>
Accessible button
</button>
```
---
## 💡 Best Practices
1. **Используйте готовые стили** из `styles.js` для консистентности
2. **Комбинируйте с cn()** для добавления кастомных классов
3. **Неоновые эффекты** используйте умеренно - только для акцентов
4. **Радиусы** - используйте `rounded-lg` для основных элементов
5. **Цвета** - всегда используйте CSS переменные, не хардкодьте цвета
6. **Accessibility** - не забывайте про `focusRing` для интерактивных элементов
---
## 🚀 Быстрый старт
```jsx
// 1. Импортируйте стили
import styles from '@/lib/styles';
import { cn } from '@/lib/utils';
// 2. Используйте в компонентах
function MyComponent() {
return (
<div className={styles.layout.container}>
<div className={styles.card.filled}>
<h2 className={styles.text.h2}>Title</h2>
<p className={styles.text.bodyMuted}>Description</p>
<button className={styles.button.primaryNeon}>
Action
</button>
</div>
</div>
);
}
```
Теперь у вас есть полная система стилей, объединяющая Mirage palette, Material Design 3 и неоновую эстетику! 🎉

View File

@@ -1,6 +1,9 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { getUserTasks } from '@/api/users.service'; import { getUserTasks } from '@/api/users.service';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import styles from '@/lib/styles';
import { Plus } from 'lucide-react';
export default function Calendar() { export default function Calendar() {
const [tasksFromBackend, setTasksFromBackend] = useState([]); const [tasksFromBackend, setTasksFromBackend] = useState([]);
@@ -77,53 +80,108 @@ export default function Calendar() {
if (loading) { if (loading) {
return ( return (
<div className="dashboard-surface-container"> <div className={cn(styles.card.elevated, "flex-[3]")}>
<div className="flex items-center justify-center p-8"> <div className="flex items-center justify-center p-8">
<p className="text-lg">Loading tasks...</p> <p className={styles.text.body}>Loading tasks...</p>
</div> </div>
</div> </div>
); );
} }
return ( return (
<div className="dashboard-surface-container"> <div className={cn(
<div className="dashboard-week-grid"> "bg-card/30 backdrop-blur-md p-6 rounded-2xl flex-[3]",
{daysOfWeek.map((day, index) => { styles.utility.transitionSlow
)}>
<div className="flex gap-4 h-full overflow-x-auto px-2">
{daysOfWeek.map((day) => {
const isToday = day.fullDate.toDateString() === today.toDateString(); const isToday = day.fullDate.toDateString() === today.toDateString();
return ( return (
<div <div
key={day.name} key={day.name}
className={`dashboard-day-column ${isToday ? 'today' : ''} dashboard-card-filled`} className={cn(
"flex-1 min-w-[180px] flex flex-col rounded-lg p-4 transition-all duration-300",
isToday
? "bg-primary/10 border-2 border-primary neon-glow-soft"
: "bg-background border border-border"
)}
> >
<div className="dashboard-day-header"> {/* Header */}
<h3 className="dashboard-day-title">{day.name}</h3> <div className="text-center pb-3 border-b border-border mb-3">
<p className="dashboard-day-date">{day.month} {day.date}</p> <h3 className={cn(
styles.text.small,
"font-semibold mb-1",
isToday && "text-primary font-bold"
)}>
{day.name}
</h3>
<p className={cn(
styles.text.smallMuted,
isToday && "text-primary font-semibold"
)}>
{day.month} {day.date}
</p>
</div> </div>
<div className="dashboard-tasks-container">
{ {/* Tasks */}
day.tasks.map((task) => ( <div className="flex-1 flex flex-col gap-2 overflow-y-auto pt-1">
{day.tasks.map((task) => (
<div <div
key={task.id} key={task.id}
className={`dashboard-task-card ${task.completed ? 'completed' : ''} priority-${task.priority}`} className={cn(
styles.card.task,
"neon-glow-soft",
task.completed && "opacity-60 line-through"
)}
> >
<div className="dashboard-task-header"> <div className="flex items-center gap-2">
<span className={`dashboard-task-priority ${task.priority}`}></span> {/* Priority indicator */}
<p className="dashboard-task-title">{task.title}</p> <span
className={cn(
"w-1 h-1 rounded-full flex-shrink-0",
task.priority === 'low' && "bg-green-500",
task.priority === 'medium' && "bg-yellow-500",
task.priority === 'high' && "bg-orange-500",
task.priority === 'critical' && "bg-red-500"
)}
/>
<p className={cn(styles.text.small, "flex-1")}>
{task.title}
</p>
</div> </div>
</div> </div>
)) ))}
}
<Button variant="elevated" onClick={() => { {/* Empty state */}
console.log('Add task clicked'); {day.tasks.length === 0 && (
}}> <p className={cn(
+ styles.text.smallMuted,
</Button> "text-center py-8 italic"
)}>
No tasks
</p>
)}
{/* Add button */}
<button
className={cn(
styles.button.icon,
"mt-2 w-full flex items-center justify-center gap-2",
styles.utility.glowSoft
)}
onClick={() => {
console.log('Add task clicked for', day.name);
}}
>
<Plus className="w-4 h-4" />
<span className="text-sm">Add Task</span>
</button>
</div> </div>
</div> </div>
); );
})} })}
</div> </div>
</div> </div>
) );
} }

View File

@@ -8,46 +8,80 @@
line-height: 1.5; line-height: 1.5;
font-weight: 400; font-weight: 400;
color-scheme: light dark; color-scheme: dark;
color: rgba(255, 255, 255, 0.87); color: rgba(255, 255, 255, 0.87);
background-color: #242424; background-color: #111928;
font-synthesis: none; font-synthesis: none;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
--radius: 0.625rem;
--background: #111928; /* Mirage Palette Colors */
--foreground: #bcbebc; --mirage-50: #f4f6fb;
--card: #243756; --mirage-100: #e7edf7;
--card-foreground: oklch(0.13 0.028 261.692); --mirage-200: #cbd9ec;
--popover: oklch(1 0 0); --mirage-300: #9db8dc;
--popover-foreground: oklch(0.13 0.028 261.692); --mirage-400: #6893c8;
--primary: oklch(0.21 0.034 264.665); --mirage-500: #4474b3;
--primary-foreground: oklch(0.985 0.002 247.839); --mirage-600: #335b96;
--secondary: oklch(0.967 0.003 264.542); --mirage-700: #2a4a7a;
--secondary-foreground: oklch(0.21 0.034 264.665); --mirage-800: #264066;
--muted: oklch(0.967 0.003 264.542); --mirage-900: #243756;
--muted-foreground: oklch(0.551 0.027 264.364); --mirage-950: #111928;
--accent: oklch(0.967 0.003 264.542);
--accent-foreground: oklch(0.21 0.034 264.665); /* Neon Accent Colors */
--destructive: oklch(0.577 0.245 27.325); --neon-blue: #c6e2ff;
--border: oklch(0.928 0.006 264.531); --neon-blue-glow: rgba(30, 132, 242, 0.6);
--input: oklch(0.928 0.006 264.531); --neon-pink: #ffc5ec;
--ring: oklch(0.707 0.022 261.325); --neon-pink-glow: rgba(255, 20, 147, 0.6);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704); /* Material Design 3 Semantic Colors with Mirage Palette */
--chart-3: oklch(0.398 0.07 227.392); --radius: 0.5rem;
--chart-4: oklch(0.828 0.189 84.429); --background: #111928; /* mirage-950 - самый темный для фона */
--chart-5: oklch(0.769 0.188 70.08); --foreground: #cbd9ec; /* mirage-200 - светлый текст */
--sidebar: oklch(0.985 0.002 247.839);
--sidebar-foreground: oklch(0.13 0.028 261.692); --card: #243756; /* mirage-900 - карточки темнее фона */
--sidebar-primary: oklch(0.21 0.034 264.665); --card-foreground: #e7edf7; /* mirage-100 - текст на карточках */
--sidebar-primary-foreground: oklch(0.985 0.002 247.839);
--sidebar-accent: oklch(0.967 0.003 264.542); --popover: #264066; /* mirage-800 - всплывающие элементы */
--sidebar-accent-foreground: oklch(0.21 0.034 264.665); --popover-foreground: #e7edf7; /* mirage-100 */
--sidebar-border: oklch(0.928 0.006 264.531);
--sidebar-ring: oklch(0.707 0.022 261.325); --primary: #6893c8; /* mirage-400 - основной акцент (средний синий) */
--primary-foreground: #111928; /* mirage-950 - темный текст на акценте */
--secondary: #2a4a7a; /* mirage-700 - вторичный цвет */
--secondary-foreground: #e7edf7; /* mirage-100 */
--muted: #264066; /* mirage-800 - приглушенные элементы */
--muted-foreground: #9db8dc; /* mirage-300 - приглушенный текст */
--accent: #4474b3; /* mirage-500 - акцент при наведении */
--accent-foreground: #f4f6fb; /* mirage-50 */
--destructive: #ef4444; /* красный для удаления */
--destructive-foreground: #f4f6fb;
--border: rgba(157, 184, 220, 0.15); /* mirage-300 с прозрачностью */
--input: rgba(157, 184, 220, 0.2); /* чуть плотнее для полей ввода */
--ring: #6893c8; /* mirage-400 - фокус как primary */
/* Sidebar */
--sidebar: #111928; /* mirage-950 - как фон */
--sidebar-foreground: #cbd9ec; /* mirage-200 */
--sidebar-primary: #6893c8; /* mirage-400 */
--sidebar-primary-foreground: #111928;
--sidebar-accent: #335b96; /* mirage-600 */
--sidebar-accent-foreground: #e7edf7;
--sidebar-border: rgba(157, 184, 220, 0.1);
--sidebar-ring: #6893c8;
/* Chart Colors - используем палитру */
--chart-1: #6893c8; /* mirage-400 */
--chart-2: #4474b3; /* mirage-500 */
--chart-3: #335b96; /* mirage-600 */
--chart-4: #9db8dc; /* mirage-300 */
--chart-5: #2a4a7a; /* mirage-700 */
} }
@theme inline { @theme inline {
@@ -89,37 +123,39 @@
} }
.dark { .dark {
--background: oklch(0.13 0.028 261.692); /* Темная тема немного светлее основной (для toggle режима) */
--foreground: oklch(0.985 0.002 247.839); --background: #243756; /* mirage-900 */
--card: oklch(0.21 0.034 264.665); --foreground: #e7edf7; /* mirage-100 */
--card-foreground: oklch(0.985 0.002 247.839); --card: #2a4a7a; /* mirage-700 */
--popover: oklch(0.21 0.034 264.665); --card-foreground: #f4f6fb; /* mirage-50 */
--popover-foreground: oklch(0.985 0.002 247.839); --popover: #264066; /* mirage-800 */
--primary: oklch(0.928 0.006 264.531); --popover-foreground: #e7edf7;
--primary-foreground: oklch(0.21 0.034 264.665); --primary: #9db8dc; /* mirage-300 - светлее для контраста */
--secondary: oklch(0.278 0.033 256.848); --primary-foreground: #111928;
--secondary-foreground: oklch(0.985 0.002 247.839); --secondary: #335b96; /* mirage-600 */
--muted: oklch(0.278 0.033 256.848); --secondary-foreground: #f4f6fb;
--muted-foreground: oklch(0.707 0.022 261.325); --muted: #264066;
--accent: oklch(0.278 0.033 256.848); --muted-foreground: #9db8dc;
--accent-foreground: oklch(0.985 0.002 247.839); --accent: #6893c8; /* mirage-400 */
--destructive: oklch(0.704 0.191 22.216); --accent-foreground: #111928;
--border: oklch(1 0 0 / 10%); --destructive: #ef4444;
--input: oklch(1 0 0 / 15%); --destructive-foreground: #f4f6fb;
--ring: oklch(0.551 0.027 264.364); --border: rgba(157, 184, 220, 0.2);
--chart-1: oklch(0.488 0.243 264.376); --input: rgba(157, 184, 220, 0.25);
--chart-2: oklch(0.696 0.17 162.48); --ring: #9db8dc;
--chart-3: oklch(0.769 0.188 70.08); --chart-1: #9db8dc;
--chart-4: oklch(0.627 0.265 303.9); --chart-2: #6893c8;
--chart-5: oklch(0.645 0.246 16.439); --chart-3: #4474b3;
--sidebar: oklch(0.21 0.034 264.665); --chart-4: #cbd9ec;
--sidebar-foreground: oklch(0.985 0.002 247.839); --chart-5: #335b96;
--sidebar-primary: oklch(0.488 0.243 264.376); --sidebar: #243756;
--sidebar-primary-foreground: oklch(0.985 0.002 247.839); --sidebar-foreground: #e7edf7;
--sidebar-accent: oklch(0.278 0.033 256.848); --sidebar-primary: #9db8dc;
--sidebar-accent-foreground: oklch(0.985 0.002 247.839); --sidebar-primary-foreground: #111928;
--sidebar-border: oklch(1 0 0 / 10%); --sidebar-accent: #4474b3;
--sidebar-ring: oklch(0.551 0.027 264.364); --sidebar-accent-foreground: #f4f6fb;
--sidebar-border: rgba(157, 184, 220, 0.15);
--sidebar-ring: #9db8dc;
} }
@layer base { @layer base {

View File

@@ -0,0 +1,168 @@
/**
* Tailwind CSS Class Presets for Task&Coffee
* Material Design 3 + Neon Aesthetic
* Using Mirage Color Palette
*/
// Card Styles - Material Design 3 Variants
export const cardStyles = {
// Filled card - основной вариант для большинства карточек
filled: "bg-card text-card-foreground p-6 rounded-lg shadow-sm",
// Elevated card - карточки с эффектом поднятия
elevated: "bg-card text-card-foreground p-6 rounded-lg shadow-lg hover:shadow-xl transition-all duration-300",
// Outlined card - карточки с границей
outlined: "bg-background border-2 border-border text-foreground p-6 rounded-lg",
// Task card - компактные карточки для задач
task: "bg-card text-card-foreground p-3 rounded-lg shadow-sm hover:shadow-md hover:-translate-y-0.5 transition-all duration-200",
// Task card with neon accent
taskNeon: "bg-card text-card-foreground p-3 rounded-lg shadow-sm hover:shadow-[0_0_15px_rgba(104,147,200,0.3)] hover:-translate-y-0.5 transition-all duration-200",
};
// Button Styles
export const buttonStyles = {
// Primary button - основные действия
primary: "bg-primary text-primary-foreground hover:bg-primary/90 px-4 py-2 rounded-lg font-medium transition-all duration-200 shadow-sm hover:shadow-md",
// Primary with neon glow
primaryNeon: "bg-primary text-primary-foreground hover:bg-primary/90 px-4 py-2 rounded-lg font-medium transition-all duration-200 hover:shadow-[0_0_20px_rgba(104,147,200,0.5)]",
// Secondary button - вторичные действия
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 px-4 py-2 rounded-lg font-medium transition-all duration-200",
// Outline button - менее важные действия
outline: "border-2 border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground px-4 py-2 rounded-lg font-medium transition-all duration-200",
// Ghost button - минималистичные кнопки
ghost: "text-foreground hover:bg-accent hover:text-accent-foreground px-4 py-2 rounded-lg font-medium transition-all duration-200",
// Destructive button - опасные действия
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 px-4 py-2 rounded-lg font-medium transition-all duration-200 shadow-sm hover:shadow-md",
// Icon button
icon: "p-2 rounded-lg hover:bg-accent transition-all duration-200",
// Icon button with neon effect
iconNeon: "p-2 rounded-lg hover:bg-accent transition-all duration-200 hover:shadow-[0_0_15px_rgba(104,147,200,0.4)]",
};
// Layout Styles
export const layoutStyles = {
// Main container
container: "flex min-h-screen bg-background text-foreground",
// Sidebar/Navigation rail
sidebar: "w-20 bg-sidebar border-r border-sidebar-border flex flex-col items-center py-4 gap-4",
// Main content area
main: "flex-1 p-6 bg-background flex flex-col",
// Content wrapper with max width
content: "max-w-7xl mx-auto w-full flex flex-1 flex-col gap-6",
// Grid layouts
gridCards: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",
gridTasks: "grid grid-cols-1 gap-3",
};
// Input Styles
export const inputStyles = {
// Standard input
default: "w-full px-4 py-2 bg-background border border-input rounded-lg text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring transition-all duration-200",
// Input with neon focus effect
neon: "w-full px-4 py-2 bg-background border border-input rounded-lg text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:shadow-[0_0_15px_rgba(104,147,200,0.3)] transition-all duration-200",
// Search input
search: "w-full px-4 py-2 pl-10 bg-background border border-input rounded-lg text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring transition-all duration-200",
};
// Text Styles
export const textStyles = {
// Headings
h1: "text-4xl font-bold text-foreground",
h2: "text-3xl font-semibold text-foreground",
h3: "text-2xl font-semibold text-foreground",
h4: "text-xl font-semibold text-foreground",
// Body text
body: "text-base text-foreground",
bodyMuted: "text-base text-muted-foreground",
// Small text
small: "text-sm text-foreground",
smallMuted: "text-sm text-muted-foreground",
// Neon text (to be combined with neon.css animations)
neonBlue: "text-[#c6e2ff]",
neonPink: "text-[#ffc5ec]",
};
// Badge/Chip Styles
export const badgeStyles = {
// Default badge
default: "inline-flex items-center px-2.5 py-0.5 rounded-md text-xs font-medium bg-primary/20 text-primary border border-primary/30",
// Priority badges
low: "inline-flex items-center px-2.5 py-0.5 rounded-md text-xs font-medium bg-green-500/20 text-green-400 border border-green-500/30",
medium: "inline-flex items-center px-2.5 py-0.5 rounded-md text-xs font-medium bg-yellow-500/20 text-yellow-400 border border-yellow-500/30",
high: "inline-flex items-center px-2.5 py-0.5 rounded-md text-xs font-medium bg-orange-500/20 text-orange-400 border border-orange-500/30",
critical: "inline-flex items-center px-2.5 py-0.5 rounded-md text-xs font-medium bg-red-500/20 text-red-400 border border-red-500/30",
// Status badges
success: "inline-flex items-center px-2.5 py-0.5 rounded-md text-xs font-medium bg-green-500/20 text-green-400 border border-green-500/30",
warning: "inline-flex items-center px-2.5 py-0.5 rounded-md text-xs font-medium bg-yellow-500/20 text-yellow-400 border border-yellow-500/30",
error: "inline-flex items-center px-2.5 py-0.5 rounded-md text-xs font-medium bg-red-500/20 text-red-400 border border-red-500/30",
info: "inline-flex items-center px-2.5 py-0.5 rounded-md text-xs font-medium bg-blue-500/20 text-blue-400 border border-blue-500/30",
};
// Utility Styles
export const utilityStyles = {
// Neon glow effects (for hover states)
glowBlue: "hover:shadow-[0_0_20px_rgba(104,147,200,0.6)]",
glowPink: "hover:shadow-[0_0_20px_rgba(255,20,147,0.6)]",
glowSoft: "hover:shadow-[0_0_15px_rgba(104,147,200,0.3)]",
// Glassmorphism effect
glass: "bg-card/50 backdrop-blur-md border border-border/50",
// Smooth transitions
transition: "transition-all duration-200 ease-in-out",
transitionSlow: "transition-all duration-300 ease-in-out",
// Focus visible states
focusRing: "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background",
};
// Complete component compositions
export const componentStyles = {
// Day column in calendar
dayColumn: "flex-1 min-w-[180px] flex flex-col bg-background rounded-lg p-4 transition-all duration-300",
dayColumnToday: "flex-1 min-w-[180px] flex flex-col bg-primary/10 border-2 border-primary rounded-lg p-4 transition-all duration-300",
// Avatar
avatar: "w-14 h-14 rounded-lg overflow-hidden",
avatarLarge: "w-20 h-20 rounded-xl overflow-hidden",
// Divider
divider: "h-px bg-border w-full",
dividerVertical: "w-px bg-border h-full",
};
// Export all styles as a single object for convenience
export const styles = {
card: cardStyles,
button: buttonStyles,
layout: layoutStyles,
input: inputStyles,
text: textStyles,
badge: badgeStyles,
utility: utilityStyles,
component: componentStyles,
};
export default styles;

View File

@@ -136,3 +136,86 @@
0 0 16px rgba(30,132,242,0.92); 0 0 16px rgba(30,132,242,0.92);
} }
} }
/*-- Utility Neon Classes for Cards and Buttons --*/
/* Neon glow on hover - blue */
.neon-glow-blue {
transition: box-shadow 0.3s ease-in-out;
}
.neon-glow-blue:hover {
box-shadow: 0 0 20px rgba(104, 147, 200, 0.6),
0 0 30px rgba(104, 147, 200, 0.4),
0 0 40px rgba(104, 147, 200, 0.2);
}
/* Neon glow on hover - pink */
.neon-glow-pink {
transition: box-shadow 0.3s ease-in-out;
}
.neon-glow-pink:hover {
box-shadow: 0 0 20px rgba(255, 20, 147, 0.6),
0 0 30px rgba(255, 20, 147, 0.4),
0 0 40px rgba(255, 20, 147, 0.2);
}
/* Soft neon glow - for subtle effects */
.neon-glow-soft {
transition: box-shadow 0.3s ease-in-out;
}
.neon-glow-soft:hover {
box-shadow: 0 0 15px rgba(104, 147, 200, 0.3),
0 0 25px rgba(104, 147, 200, 0.2);
}
/* Neon border - blue */
.neon-border-blue {
border: 1px solid rgba(104, 147, 200, 0.4);
box-shadow: 0 0 10px rgba(104, 147, 200, 0.2);
transition: all 0.3s ease-in-out;
}
.neon-border-blue:hover {
border-color: rgba(104, 147, 200, 0.8);
box-shadow: 0 0 15px rgba(104, 147, 200, 0.4),
0 0 25px rgba(104, 147, 200, 0.2);
}
/* Neon border - pink */
.neon-border-pink {
border: 1px solid rgba(255, 20, 147, 0.4);
box-shadow: 0 0 10px rgba(255, 20, 147, 0.2);
transition: all 0.3s ease-in-out;
}
.neon-border-pink:hover {
border-color: rgba(255, 20, 147, 0.8);
box-shadow: 0 0 15px rgba(255, 20, 147, 0.4),
0 0 25px rgba(255, 20, 147, 0.2);
}
/* Text with subtle neon effect (non-animated) */
.neon-text-blue {
color: #c6e2ff;
text-shadow: 0 0 10px rgba(30, 132, 242, 0.5),
0 0 20px rgba(30, 132, 242, 0.3);
}
.neon-text-pink {
color: #ffc5ec;
text-shadow: 0 0 10px rgba(255, 20, 147, 0.5),
0 0 20px rgba(255, 20, 147, 0.3);
}
/* Icon with neon glow on hover */
.neon-icon {
transition: filter 0.3s ease-in-out;
}
.neon-icon:hover {
filter: drop-shadow(0 0 8px rgba(104, 147, 200, 0.8))
drop-shadow(0 0 15px rgba(104, 147, 200, 0.5));
}

View File

@@ -1,13 +1,13 @@
'use client'; 'use client';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import '../neon.css'; import '../neon.css';
import './dashboard.css';
import { MenuDock } from '@/components/ui/shadcn-io/menu-dock'; import { MenuDock } from '@/components/ui/shadcn-io/menu-dock';
import { Home, Settings, Bell } from 'lucide-react'; import { Home, Settings, Bell } from 'lucide-react';
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'; import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
import { jwtexp } from '@/lib/utils'; import { jwtexp, cn } from '@/lib/utils';
import Calendar from '@/components/Calendar'; import Calendar from '@/components/Calendar';
import { useNavigate } from "react-router"; import { useNavigate } from "react-router";
import styles from '@/lib/styles';
const menuItems = [ const menuItems = [
{ label: 'home', icon: Home, onClick: () => console.log('Home clicked') }, { label: 'home', icon: Home, onClick: () => console.log('Home clicked') },
@@ -66,9 +66,9 @@ export default function Dashboard() {
if (loading || authError) { if (loading || authError) {
return ( return (
<div className="dashboard-container"> <div className={styles.layout.container}>
<div className="flex items-center justify-center min-h-screen"> <div className="flex items-center justify-center min-h-screen">
<p className="text-xl"> <p className={styles.text.h3}>
{loading ? 'Loading dashboard...' : 'Redirecting...'} {loading ? 'Loading dashboard...' : 'Redirecting...'}
</p> </p>
</div> </div>
@@ -77,14 +77,14 @@ export default function Dashboard() {
} }
return ( return (
<div className="dashboard-container"> <div className={styles.layout.container}>
{/* Navigation Rail - Material Design 3 */} {/* Navigation Rail - Material Design 3 */}
<aside className="dashboard-sidebar"> <aside className={styles.layout.sidebar}>
{/* Avatar with large M3 container */} {/* Avatar */}
<div className="dashboard-avatar-container"> <div className="mb-2">
<Avatar className="dashboard-avatar"> <Avatar className={styles.component.avatar}>
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" /> <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback className="dashboard-avatar-fallback">CN</AvatarFallback> <AvatarFallback className="rounded-lg">CN</AvatarFallback>
</Avatar> </Avatar>
</div> </div>
@@ -99,15 +99,19 @@ export default function Dashboard() {
</aside> </aside>
{/* Main Content Area */} {/* Main Content Area */}
<main className="dashboard-main"> <main className={styles.layout.main}>
<div className="dashboard-content"> <div className={styles.layout.content}>
<h1 className="dashboard-header"> {/* Header with neon text */}
<h1 className={cn(styles.text.h1, "mb-6")}>
<span className="sign-pink-inline">Task&</span> <span className="sign-pink-inline">Task&</span>
<span className="sign-inline">Coffee</span> <span className="sign-inline">Coffee</span>
</h1> </h1>
{/* Calendar component */}
<Calendar /> <Calendar />
<div className="dashboard-spacer"></div> {/* Spacer */}
<div className="flex-[0.5]"></div>
</div> </div>
</main> </main>
</div> </div>

View File

@@ -1,265 +0,0 @@
/* Dashboard Layout */
.dashboard-container {
display: flex;
min-height: 100vh;
background: var(--color-background);
}
/* Navigation Rail - Material Design 3 */
.dashboard-sidebar {
width: 80px;
background: color-mix(in srgb, var(--color-card) 50%, transparent);
display: flex;
flex-direction: column;
align-items: center;
padding-top: 1rem;
padding-bottom: 1rem;
gap: 1rem;
}
.dashboard-avatar-container {
margin-bottom: 0.5rem;
}
.dashboard-avatar {
width: 3.5rem;
height: 3.5rem;
border-radius: 1rem;
}
.dashboard-avatar-fallback {
border-radius: 1rem;
}
/* Main Content Area */
.dashboard-main {
flex: 1;
padding: 1.5rem;
background: var(--color-background);
display: flex;
flex-direction: column;
}
.dashboard-content {
max-width: 90rem;
margin-left: auto;
margin-right: auto;
width: 100%;
display: flex;
flex: 1;
flex-direction: column;
gap: 1.5rem;
}
/* Header */
.dashboard-header {
font-size: 1.875rem;
font-weight: bold;
}
/* Material Design 3 Cards Grid */
.dashboard-cards-grid {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}
@media (min-width: 768px) {
.dashboard-cards-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 1024px) {
.dashboard-cards-grid {
grid-template-columns: repeat(3, 1fr);
}
}
/* M3 Card Variants */
.dashboard-card-filled {
background: var(--color-card);
padding: 1.5rem;
border-radius: 1.5rem;
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
}
.dashboard-card-elevated {
background: var(--color-card);
padding: 1.5rem;
border-radius: 1.5rem;
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
transition: box-shadow 0.3s;
}
.dashboard-card-elevated:hover {
box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1);
}
.dashboard-card-outlined {
background: var(--color-background);
border: 2px solid var(--color-border);
padding: 1.5rem;
border-radius: 1.5rem;
}
.dashboard-card-title {
font-size: 1.125rem;
font-weight: 600;
margin-bottom: 0.5rem;
}
.dashboard-card-text {
color: var(--color-muted-foreground);
font-size: 0.875rem;
}
/* Surface Container */
.dashboard-surface-container {
background: color-mix(in srgb, var(--color-card) 30%, transparent);
padding: 1.5rem;
border-radius: 1.5rem;
flex: 3;
}
.dashboard-surface-title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 1rem;
}
.dashboard-surface-text {
color: var(--color-muted-foreground);
}
/* Spacer */
.dashboard-spacer {
flex: 0.5;
}
/* Weekly View */
.dashboard-week-grid {
display: flex;
gap: 1rem;
height: 100%;
overflow-x: auto;
padding: 0.6rem;
}
.dashboard-day-column {
flex: 1;
min-width: 180px;
display: flex;
flex-direction: column;
background: var(--color-background);
border-radius: 1rem;
padding: 1rem;
transition: all 0.3s ease;
}
.dashboard-day-column.today {
background: color-mix(in srgb, var(--color-primary) 10%, transparent);
border: 2px solid var(--color-primary);
}
.dashboard-day-header {
text-align: center;
padding-bottom: 0.75rem;
border-bottom: 1px solid var(--color-border);
margin-bottom: 0.75rem;
}
.dashboard-day-title {
font-size: 1rem;
font-weight: 600;
margin: 0 0 0.25rem 0;
}
.dashboard-day-date {
font-size: 0.875rem;
color: var(--color-muted-foreground);
margin: 0;
}
.dashboard-day-column.today .dashboard-day-title {
color: var(--color-primary);
}
.dashboard-day-column.today .dashboard-day-date {
color: var(--color-primary);
font-weight: 600;
}
.dashboard-tasks-container {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.5rem;
overflow-y: auto;
padding-top: 4px;
}
.dashboard-task-card {
background: var(--color-card);
padding: 0.75rem;
border-radius: 0.625rem;
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
font-size: 0.875rem;
transition: transform 0.2s;
}
.dashboard-task-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
}
.dashboard-task-card.completed {
opacity: 0.6;
text-decoration: line-through;
}
.dashboard-task-header {
display: flex;
align-items: center;
gap: 0.5rem;
}
.dashboard-task-priority {
width: 4px;
height: 4px;
border-radius: 50%;
flex-shrink: 0;
}
.dashboard-task-priority.low {
background: #10b981; /* green */
}
.dashboard-task-priority.medium {
background: #f59e0b; /* orange */
}
.dashboard-task-priority.high {
background: #ef4444; /* red */
}
.dashboard-task-priority.critical {
background: #a90404; /* red */
}
.dashboard-task-title {
margin: 0;
font-size: 0.875rem;
color: var(--color-foreground);
flex: 1;
}
.dashboard-no-tasks {
color: var(--color-muted-foreground);
font-size: 0.875rem;
text-align: center;
padding: 2rem 0;
font-style: italic;
}