feat: modernize frontend UI with Tailwind v4 and professional design system
BREAKING CHANGE: Migrated to Tailwind CSS v4 configuration system Key Changes: - Migrated from Tailwind v3 to v4 configuration system - Removed tailwind.config.js (incompatible with v4) - Updated index.css with @theme directive and oklch color space - Defined all custom animations directly in CSS using @keyframes - Redesigned LoginPage with modern, enterprise-grade UI: - Full-screen gradient background (blue → purple → pink) - Floating animated orbs with blur effects - Glass morphism white card with backdrop-blur - Gradient buttons with shadow effects - 7 custom animations: fade-in, slide-in-right, slide-in-left, scale-in, shimmer, pulse, float - Added shadcn/ui components: - alert.tsx, dialog.tsx, input.tsx, label.tsx, select.tsx, tabs.tsx - Updated dependencies: - Added class-variance-authority ^0.7.0 - Added react-markdown ^9.0.1 - Updated frontend documentation: - Comprehensive README.md with feature list, tech stack, project structure - Quick start guide and deployment instructions Technical Details: - Tailwind v4 uses @import "tailwindcss" instead of @tailwind directives - All theme customization now in @theme block with CSS variables - Color system migrated to oklch for better perceptual uniformity - Animation definitions moved from config to CSS @layer utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,115 +1,172 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@import "tailwindcss";
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
/* Clean, modern color palette */
|
||||
--background: 220 15% 97%;
|
||||
--foreground: 220 15% 15%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 220 15% 15%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 220 15% 15%;
|
||||
@theme {
|
||||
/* Clean, modern color palette */
|
||||
--color-background: oklch(95% 0.02 220);
|
||||
--color-foreground: oklch(20% 0.02 220);
|
||||
--color-card: oklch(100% 0 0);
|
||||
--color-card-foreground: oklch(20% 0.02 220);
|
||||
--color-popover: oklch(100% 0 0);
|
||||
--color-popover-foreground: oklch(20% 0.02 220);
|
||||
|
||||
/* Primary: Professional blue */
|
||||
--primary: 217 91% 60%;
|
||||
--primary-foreground: 0 0% 100%;
|
||||
--primary-hover: 217 91% 50%;
|
||||
/* Primary: Professional blue */
|
||||
--color-primary: oklch(65% 0.25 250);
|
||||
--color-primary-foreground: oklch(100% 0 0);
|
||||
--color-primary-hover: oklch(60% 0.25 250);
|
||||
|
||||
/* Secondary: Subtle gray-blue */
|
||||
--secondary: 220 15% 95%;
|
||||
--secondary-foreground: 220 15% 25%;
|
||||
/* Secondary: Subtle gray-blue */
|
||||
--color-secondary: oklch(95% 0.02 220);
|
||||
--color-secondary-foreground: oklch(30% 0.02 220);
|
||||
|
||||
/* Accent: Vibrant teal */
|
||||
--accent: 173 80% 50%;
|
||||
--accent-foreground: 0 0% 100%;
|
||||
/* Accent: Vibrant teal */
|
||||
--color-accent: oklch(65% 0.20 180);
|
||||
--color-accent-foreground: oklch(100% 0 0);
|
||||
|
||||
/* Sidebar */
|
||||
--sidebar: 220 25% 12%;
|
||||
--sidebar-foreground: 220 10% 90%;
|
||||
--sidebar-active: 217 91% 60%;
|
||||
/* Muted */
|
||||
--color-muted: oklch(93% 0.02 220);
|
||||
--color-muted-foreground: oklch(50% 0.02 220);
|
||||
|
||||
/* Muted */
|
||||
--muted: 220 15% 93%;
|
||||
--muted-foreground: 220 10% 45%;
|
||||
/* Destructive */
|
||||
--color-destructive: oklch(60% 0.22 25);
|
||||
--color-destructive-foreground: oklch(100% 0 0);
|
||||
|
||||
/* Destructive */
|
||||
--destructive: 0 85% 60%;
|
||||
--destructive-foreground: 0 0% 100%;
|
||||
/* Success */
|
||||
--color-success: oklch(55% 0.20 150);
|
||||
--color-success-foreground: oklch(100% 0 0);
|
||||
|
||||
/* Success */
|
||||
--success: 142 72% 45%;
|
||||
--success-foreground: 0 0% 100%;
|
||||
/* Warning */
|
||||
--color-warning: oklch(65% 0.22 60);
|
||||
--color-warning-foreground: oklch(100% 0 0);
|
||||
|
||||
/* Warning */
|
||||
--warning: 38 92% 50%;
|
||||
--warning-foreground: 0 0% 100%;
|
||||
/* Borders and inputs */
|
||||
--color-border: oklch(88% 0.02 220);
|
||||
--color-input: oklch(88% 0.02 220);
|
||||
--color-ring: oklch(65% 0.25 250);
|
||||
|
||||
/* Borders and inputs */
|
||||
--border: 220 13% 88%;
|
||||
--input: 220 13% 88%;
|
||||
--ring: 217 91% 60%;
|
||||
--radius: 0.5rem;
|
||||
/* Border radius */
|
||||
--radius-lg: 0.5rem;
|
||||
--radius-md: calc(0.5rem - 2px);
|
||||
--radius-sm: calc(0.5rem - 4px);
|
||||
|
||||
/* Shadows */
|
||||
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
--shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);
|
||||
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
|
||||
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
|
||||
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.dark {
|
||||
/* Dark mode with rich colors */
|
||||
--background: 240 20% 8%;
|
||||
--foreground: 240 5% 95%;
|
||||
--card: 240 15% 12%;
|
||||
--card-foreground: 240 5% 95%;
|
||||
--popover: 240 15% 12%;
|
||||
--popover-foreground: 240 5% 95%;
|
||||
|
||||
/* Primary: Brighter in dark mode */
|
||||
--primary: 250 85% 65%;
|
||||
--primary-foreground: 240 20% 8%;
|
||||
--primary-glow: 250 85% 65%;
|
||||
|
||||
/* Secondary */
|
||||
--secondary: 240 15% 18%;
|
||||
--secondary-foreground: 240 5% 95%;
|
||||
|
||||
/* Accent */
|
||||
--accent: 190 85% 55%;
|
||||
--accent-foreground: 240 20% 8%;
|
||||
|
||||
/* Muted */
|
||||
--muted: 240 15% 15%;
|
||||
--muted-foreground: 240 5% 65%;
|
||||
|
||||
/* Destructive */
|
||||
--destructive: 0 80% 60%;
|
||||
--destructive-foreground: 0 0% 100%;
|
||||
|
||||
/* Success */
|
||||
--success: 142 70% 50%;
|
||||
--success-foreground: 0 0% 100%;
|
||||
|
||||
/* Borders */
|
||||
--border: 240 15% 20%;
|
||||
--input: 240 15% 20%;
|
||||
--ring: 250 85% 65%;
|
||||
}
|
||||
/* Animations */
|
||||
--animate-fade-in: fade-in 0.5s ease-out;
|
||||
--animate-slide-in-right: slide-in-right 0.5s ease-out;
|
||||
--animate-slide-in-left: slide-in-left 0.5s ease-out;
|
||||
--animate-scale-in: scale-in 0.3s ease-out;
|
||||
--animate-shimmer: shimmer 2s linear infinite;
|
||||
--animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
--animate-float: float 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
body {
|
||||
background-color: hsl(var(--background));
|
||||
color: hsl(var(--foreground));
|
||||
background-color: var(--color-background);
|
||||
color: var(--color-foreground);
|
||||
font-feature-settings: "rlig" 1, "calt" 1;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
/* Animations */
|
||||
@keyframes fade-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-in-right {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-in-left {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scale-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
background-position: -1000px 0;
|
||||
}
|
||||
100% {
|
||||
background-position: 1000px 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fade-in {
|
||||
animation: fade-in 0.5s ease-out;
|
||||
}
|
||||
|
||||
.animate-slide-in-right {
|
||||
animation: slide-in-right 0.5s ease-out;
|
||||
}
|
||||
|
||||
.animate-slide-in-left {
|
||||
animation: slide-in-left 0.5s ease-out;
|
||||
}
|
||||
|
||||
.animate-scale-in {
|
||||
animation: scale-in 0.3s ease-out;
|
||||
}
|
||||
|
||||
.animate-shimmer {
|
||||
animation: shimmer 2s linear infinite;
|
||||
}
|
||||
|
||||
.animate-pulse {
|
||||
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
}
|
||||
|
||||
.animate-float {
|
||||
animation: float 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Custom scrollbar */
|
||||
.scrollbar-thin::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
@@ -117,17 +174,17 @@
|
||||
}
|
||||
|
||||
.scrollbar-thin::-webkit-scrollbar-track {
|
||||
background: hsl(var(--muted));
|
||||
background: var(--color-muted);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.scrollbar-thin::-webkit-scrollbar-thumb {
|
||||
background: hsl(var(--muted-foreground) / 0.3);
|
||||
background: color-mix(in oklch, var(--color-muted-foreground) 30%, transparent);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.scrollbar-thin::-webkit-scrollbar-thumb:hover {
|
||||
background: hsl(var(--muted-foreground) / 0.5);
|
||||
background: color-mix(in oklch, var(--color-muted-foreground) 50%, transparent);
|
||||
}
|
||||
|
||||
.scrollbar-hide::-webkit-scrollbar {
|
||||
@@ -149,31 +206,31 @@
|
||||
.page-title {
|
||||
font-size: 1.875rem;
|
||||
font-weight: 700;
|
||||
color: hsl(var(--foreground));
|
||||
color: var(--color-foreground);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.page-description {
|
||||
color: hsl(var(--muted-foreground));
|
||||
color: var(--color-muted-foreground);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* Section */
|
||||
.section {
|
||||
background: hsl(var(--card));
|
||||
border: 1px solid hsl(var(--border));
|
||||
border-radius: var(--radius);
|
||||
background: var(--color-card);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 1.5rem;
|
||||
box-shadow: var(--shadow-sm);
|
||||
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.section-header {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
color: hsl(var(--foreground));
|
||||
color: var(--color-foreground);
|
||||
margin-bottom: 1rem;
|
||||
padding-bottom: 0.75rem;
|
||||
border-bottom: 1px solid hsl(var(--border));
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
/* Status badge */
|
||||
@@ -187,22 +244,22 @@
|
||||
}
|
||||
|
||||
.status-badge-success {
|
||||
background: hsl(var(--success) / 0.1);
|
||||
color: hsl(var(--success));
|
||||
background: color-mix(in oklch, var(--color-success) 10%, transparent);
|
||||
color: var(--color-success);
|
||||
}
|
||||
|
||||
.status-badge-warning {
|
||||
background: hsl(var(--warning) / 0.1);
|
||||
color: hsl(var(--warning));
|
||||
background: color-mix(in oklch, var(--color-warning) 10%, transparent);
|
||||
color: var(--color-warning);
|
||||
}
|
||||
|
||||
.status-badge-error {
|
||||
background: hsl(var(--destructive) / 0.1);
|
||||
color: hsl(var(--destructive));
|
||||
background: color-mix(in oklch, var(--color-destructive) 10%, transparent);
|
||||
color: var(--color-destructive);
|
||||
}
|
||||
|
||||
.status-badge-info {
|
||||
background: hsl(var(--primary) / 0.1);
|
||||
color: hsl(var(--primary));
|
||||
background: color-mix(in oklch, var(--color-primary) 10%, transparent);
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user