feat: update UI with new branding, logo, and modern terminal-inspired styling
This commit is contained in:
parent
53c8c27ee7
commit
a87259a2ee
|
|
@ -6,6 +6,13 @@
|
|||
<link rel="icon" type="image/png" href="/logo_xcodereviewer.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>XCodeReviewer</title>
|
||||
|
||||
<!-- Terminal Retro & Cassette Futurism Typography -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Orbitron:wght@400;500;600;700;800&family=Rajdhani:wght@500;600;700&family=Inter:wght@400;500;600;700&display=swap"
|
||||
rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body class="dark:bg-gray-900">
|
||||
|
|
|
|||
|
|
@ -19,9 +19,7 @@ function AppLayout() {
|
|||
className={`transition-all duration-300 min-h-screen ${collapsed ? "md:ml-20" : "md:ml-64"
|
||||
}`}
|
||||
>
|
||||
<div className="container mx-auto px-4 py-6 md:py-8 pt-16 md:pt-8">
|
||||
<Outlet />
|
||||
</div>
|
||||
<Outlet />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,67 +2,110 @@
|
|||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
/*
|
||||
XCodeReviewer Design System
|
||||
Aesthetic: Terminal Retro + Pixel Art + Mechanical + Cassette Futurism
|
||||
Core Palette: Orange, Deep Red, Signal Green, Grey
|
||||
Philosophy: Clean, legible, harmonious - simplified linework for reduced eye strain
|
||||
*/
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 210 20% 98%;
|
||||
--foreground: 220 10% 10%;
|
||||
/* Background & Surface - Soft light grey for comfort */
|
||||
--background: 0 0% 96%;
|
||||
--foreground: 0 0% 15%;
|
||||
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 220 10% 10%;
|
||||
/* Card & Surfaces - Clean white with subtle warmth */
|
||||
--card: 0 0% 98%;
|
||||
--card-foreground: 0 0% 15%;
|
||||
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 220 10% 10%;
|
||||
/* Popover */
|
||||
--popover: 0 0% 98%;
|
||||
--popover-foreground: 0 0% 15%;
|
||||
|
||||
--primary: 220 100% 50%;
|
||||
/* Primary - Vibrant Orange (Core brand color) */
|
||||
--primary: 16 100% 58%;
|
||||
--primary-foreground: 0 0% 100%;
|
||||
|
||||
--secondary: 15 100% 50%;
|
||||
/* Secondary - Deep Red (Accent & warnings) */
|
||||
--secondary: 4 70% 52%;
|
||||
--secondary-foreground: 0 0% 100%;
|
||||
|
||||
--muted: 210 20% 90%;
|
||||
--muted-foreground: 220 10% 40%;
|
||||
/* Success/Active - Signal Green */
|
||||
--success: 145 100% 45%;
|
||||
--success-foreground: 0 0% 100%;
|
||||
|
||||
--accent: 180 100% 40%;
|
||||
/* Muted - Neutral Grey tones */
|
||||
--muted: 0 0% 88%;
|
||||
--muted-foreground: 0 0% 45%;
|
||||
|
||||
/* Accent - Mechanical Grey-Blue */
|
||||
--accent: 210 15% 50%;
|
||||
--accent-foreground: 0 0% 100%;
|
||||
|
||||
--destructive: 0 100% 50%;
|
||||
/* Destructive - Deep Red variant */
|
||||
--destructive: 4 70% 52%;
|
||||
--destructive-foreground: 0 0% 100%;
|
||||
|
||||
--border: 0 0% 0%;
|
||||
--input: 0 0% 0%;
|
||||
--ring: 220 100% 50%;
|
||||
/* Borders & Inputs - Simplified grey */
|
||||
--border: 0 0% 75%;
|
||||
--input: 0 0% 75%;
|
||||
--ring: 16 100% 58%;
|
||||
|
||||
--radius: 0rem;
|
||||
/* Border radius - Sharp pixel aesthetic */
|
||||
--radius: 2px;
|
||||
|
||||
/* Simplified shadows - subtle depth */
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.08);
|
||||
--shadow-md: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
--shadow-focus: 0 0 0 2px rgba(255, 107, 44, 0.25);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 220 10% 10%;
|
||||
--foreground: 210 20% 98%;
|
||||
/* Dark mode - balanced, not too dim */
|
||||
--background: 220 15% 12%;
|
||||
--foreground: 0 0% 92%;
|
||||
|
||||
--card: 220 10% 15%;
|
||||
--card-foreground: 210 20% 98%;
|
||||
/* Surfaces - subtle elevation */
|
||||
--card: 220 15% 16%;
|
||||
--card-foreground: 0 0% 92%;
|
||||
|
||||
--popover: 220 10% 15%;
|
||||
--popover-foreground: 210 20% 98%;
|
||||
--popover: 220 15% 16%;
|
||||
--popover-foreground: 0 0% 92%;
|
||||
|
||||
--primary: 220 100% 50%;
|
||||
--primary-foreground: 0 0% 100%;
|
||||
/* Primary - Orange (slightly desaturated for dark mode) */
|
||||
--primary: 16 95% 60%;
|
||||
--primary-foreground: 0 0% 10%;
|
||||
|
||||
--secondary: 15 100% 50%;
|
||||
--secondary-foreground: 0 0% 100%;
|
||||
/* Secondary - Deep Red */
|
||||
--secondary: 4 65% 55%;
|
||||
--secondary-foreground: 0 0% 10%;
|
||||
|
||||
--muted: 220 10% 20%;
|
||||
--muted-foreground: 210 20% 60%;
|
||||
/* Success - Signal Green (slightly muted) */
|
||||
--success: 145 90% 48%;
|
||||
--success-foreground: 0 0% 10%;
|
||||
|
||||
--accent: 180 100% 40%;
|
||||
--accent-foreground: 0 0% 100%;
|
||||
/* Muted - Darker grey tones */
|
||||
--muted: 220 15% 22%;
|
||||
--muted-foreground: 0 0% 60%;
|
||||
|
||||
--destructive: 0 100% 50%;
|
||||
--destructive-foreground: 0 0% 100%;
|
||||
/* Accent */
|
||||
--accent: 210 15% 45%;
|
||||
--accent-foreground: 0 0% 95%;
|
||||
|
||||
--border: 0 0% 100%;
|
||||
--input: 0 0% 100%;
|
||||
--ring: 220 100% 50%;
|
||||
/* Destructive */
|
||||
--destructive: 4 65% 55%;
|
||||
--destructive-foreground: 0 0% 10%;
|
||||
|
||||
/* Borders - softer in dark mode */
|
||||
--border: 220 15% 28%;
|
||||
--input: 220 15% 28%;
|
||||
--ring: 16 95% 60%;
|
||||
|
||||
/* Dark mode shadows */
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||
--shadow-md: 0 2px 4px rgba(0, 0, 0, 0.4);
|
||||
--shadow-focus: 0 0 0 2px rgba(255, 107, 44, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,45 +116,249 @@
|
|||
|
||||
body {
|
||||
@apply bg-background text-foreground font-mono antialiased;
|
||||
/* Smooth transitions for theme changes */
|
||||
transition: background-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
/* Typography Hierarchy - Clean & Legible */
|
||||
h1 {
|
||||
@apply font-display font-bold tracking-tight text-3xl;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@apply font-display font-bold tracking-tight text-2xl;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@apply font-display font-bold tracking-tight text-xl;
|
||||
}
|
||||
|
||||
h4 {
|
||||
@apply font-display font-semibold tracking-tight text-lg;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
@apply font-display font-bold tracking-tight;
|
||||
@apply font-display font-semibold text-base;
|
||||
}
|
||||
|
||||
/* Improved focus states */
|
||||
button:focus-visible,
|
||||
input:focus-visible,
|
||||
textarea:focus-visible,
|
||||
select:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: var(--shadow-focus);
|
||||
}
|
||||
|
||||
/* Smooth scrolling */
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.retro-border {
|
||||
@apply border-2 border-black;
|
||||
box-shadow: 4px 4px 0px 0px rgba(0, 0, 0, 1);
|
||||
|
||||
/* Simplified Terminal Border - 1px for cleaner look */
|
||||
.terminal-border {
|
||||
@apply border border-border;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.retro-card {
|
||||
@apply bg-white border-2 border-black p-4;
|
||||
box-shadow: 4px 4px 0px 0px rgba(0, 0, 0, 1);
|
||||
/* Enhanced Terminal Border with subtle elevation */
|
||||
.terminal-border-elevated {
|
||||
@apply border border-border;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.retro-btn {
|
||||
@apply bg-primary text-white font-bold py-2 px-4 border-2 border-black transition-all;
|
||||
box-shadow: 4px 4px 0px 0px rgba(0, 0, 0, 1);
|
||||
/* Terminal Card - Clean and minimal */
|
||||
.terminal-card {
|
||||
@apply bg-card border border-border p-4 rounded-sm;
|
||||
box-shadow: var(--shadow-sm);
|
||||
transition: box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.retro-btn:hover {
|
||||
box-shadow: 2px 2px 0px 0px rgba(0, 0, 0, 1);
|
||||
transform: translate(2px, 2px);
|
||||
.terminal-card:hover {
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.retro-btn:active {
|
||||
/* Button Variants - Simplified with 1px borders */
|
||||
.terminal-btn {
|
||||
@apply font-mono font-semibold py-2 px-4 border border-border rounded-sm transition-all duration-150;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.terminal-btn:hover:not(:disabled) {
|
||||
box-shadow: var(--shadow-md);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.terminal-btn:active:not(:disabled) {
|
||||
box-shadow: none;
|
||||
transform: translate(4px, 4px);
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.retro-input {
|
||||
@apply bg-white border-2 border-black p-2 focus:outline-none focus:ring-2 focus:ring-primary shadow-none;
|
||||
.terminal-btn:disabled {
|
||||
@apply opacity-50 cursor-not-allowed;
|
||||
}
|
||||
|
||||
/* Primary Button - Orange */
|
||||
.terminal-btn-primary {
|
||||
@apply terminal-btn bg-primary text-primary-foreground;
|
||||
border-color: hsl(16 100% 50%);
|
||||
}
|
||||
|
||||
.terminal-btn-primary:hover:not(:disabled) {
|
||||
background: hsl(16 100% 52%);
|
||||
}
|
||||
|
||||
/* Secondary Button - Deep Red */
|
||||
.terminal-btn-secondary {
|
||||
@apply terminal-btn bg-secondary text-secondary-foreground;
|
||||
border-color: hsl(4 70% 45%);
|
||||
}
|
||||
|
||||
.terminal-btn-secondary:hover:not(:disabled) {
|
||||
background: hsl(4 70% 56%);
|
||||
}
|
||||
|
||||
/* Success Button - Signal Green */
|
||||
.terminal-btn-success {
|
||||
@apply terminal-btn text-white;
|
||||
background: hsl(var(--success));
|
||||
border-color: hsl(145 100% 38%);
|
||||
}
|
||||
|
||||
.terminal-btn-success:hover:not(:disabled) {
|
||||
background: hsl(145 100% 48%);
|
||||
}
|
||||
|
||||
/* Ghost Button - Outline only */
|
||||
.terminal-btn-ghost {
|
||||
@apply terminal-btn bg-transparent;
|
||||
}
|
||||
|
||||
.terminal-btn-ghost:hover:not(:disabled) {
|
||||
@apply bg-muted;
|
||||
}
|
||||
|
||||
/* Input Fields - Simplified */
|
||||
.terminal-input {
|
||||
@apply bg-background border border-input px-3 py-2 rounded-sm font-mono text-sm;
|
||||
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
||||
}
|
||||
|
||||
.terminal-input:focus {
|
||||
outline: none;
|
||||
border-color: hsl(var(--primary));
|
||||
box-shadow: var(--shadow-focus);
|
||||
}
|
||||
|
||||
.terminal-input::placeholder {
|
||||
@apply text-muted-foreground;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
/* Badge Components */
|
||||
.terminal-badge {
|
||||
@apply inline-flex items-center px-2 py-0.5 rounded-sm text-xs font-mono font-semibold;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.terminal-badge-orange {
|
||||
@apply terminal-badge bg-primary text-primary-foreground;
|
||||
border-color: hsl(16 100% 50%);
|
||||
}
|
||||
|
||||
.terminal-badge-red {
|
||||
@apply terminal-badge bg-secondary text-secondary-foreground;
|
||||
border-color: hsl(4 70% 45%);
|
||||
}
|
||||
|
||||
.terminal-badge-green {
|
||||
@apply terminal-badge text-white;
|
||||
background: hsl(var(--success));
|
||||
border-color: hsl(145 100% 38%);
|
||||
}
|
||||
|
||||
.terminal-badge-grey {
|
||||
@apply terminal-badge bg-muted text-muted-foreground;
|
||||
border-color: hsl(var(--border));
|
||||
}
|
||||
|
||||
/* Code Block Styling */
|
||||
.terminal-code {
|
||||
@apply bg-muted border border-border rounded-sm p-3 font-mono text-sm overflow-x-auto;
|
||||
}
|
||||
|
||||
/* Scanline Effect - Subtle CRT aesthetic */
|
||||
.terminal-scanline {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.terminal-scanline::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(to bottom,
|
||||
transparent 50%,
|
||||
rgba(0, 0, 0, 0.02) 50%);
|
||||
background-size: 100% 4px;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Pixel Grid Background - Very subtle */
|
||||
.terminal-pixel-grid {
|
||||
background-image:
|
||||
linear-gradient(rgba(0, 0, 0, 0.02) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(0, 0, 0, 0.02) 1px, transparent 1px);
|
||||
background-size: 8px 8px;
|
||||
}
|
||||
|
||||
/* Status Indicators */
|
||||
.status-indicator {
|
||||
@apply w-2 h-2 rounded-full inline-block;
|
||||
}
|
||||
|
||||
.status-active {
|
||||
background: hsl(var(--success));
|
||||
box-shadow: 0 0 4px hsl(var(--success));
|
||||
}
|
||||
|
||||
.status-warning {
|
||||
background: hsl(var(--primary));
|
||||
box-shadow: 0 0 4px hsl(var(--primary));
|
||||
}
|
||||
|
||||
.status-error {
|
||||
background: hsl(var(--secondary));
|
||||
box-shadow: 0 0 4px hsl(var(--secondary));
|
||||
}
|
||||
|
||||
.status-inactive {
|
||||
@apply bg-muted-foreground;
|
||||
}
|
||||
|
||||
/* Divider */
|
||||
.terminal-divider {
|
||||
@apply border-t border-border my-4;
|
||||
}
|
||||
|
||||
/* Panel - For sections/containers */
|
||||
.terminal-panel {
|
||||
@apply bg-card border border-border rounded-sm p-6;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
/* Smooth transitions */
|
||||
.terminal-transition {
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
}
|
||||
|
|
@ -13,8 +13,7 @@ import {
|
|||
FileText,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Github,
|
||||
Terminal
|
||||
Github
|
||||
} from "lucide-react";
|
||||
import routes from "@/app/routes";
|
||||
|
||||
|
|
@ -46,7 +45,7 @@ export default function Sidebar({ collapsed, setCollapsed }: SidebarProps) {
|
|||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="fixed top-4 left-4 z-50 md:hidden bg-white border-2 border-black shadow-retro text-black hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-retro-hover transition-all"
|
||||
className="fixed top-4 left-4 z-50 md:hidden terminal-btn-ghost text-black"
|
||||
onClick={() => setMobileOpen(!mobileOpen)}
|
||||
>
|
||||
{mobileOpen ? <X className="w-5 h-5" /> : <Menu className="w-5 h-5" />}
|
||||
|
|
@ -64,7 +63,7 @@ export default function Sidebar({ collapsed, setCollapsed }: SidebarProps) {
|
|||
<aside
|
||||
className={`
|
||||
fixed top-0 left-0 h-screen bg-background
|
||||
border-r-2 border-black
|
||||
border-r border-border
|
||||
z-40 transition-all duration-300 ease-in-out
|
||||
${collapsed ? "w-20" : "w-64"}
|
||||
${mobileOpen ? "translate-x-0" : "-translate-x-full md:translate-x-0"}
|
||||
|
|
@ -75,17 +74,17 @@ export default function Sidebar({ collapsed, setCollapsed }: SidebarProps) {
|
|||
<div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none" />
|
||||
|
||||
{/* Logo Section */}
|
||||
<div className="relative flex items-center h-[72px] px-4 border-b-2 border-black bg-white z-10">
|
||||
<div className={`relative flex items-center h-[72px] border-b border-border bg-card z-10 ${collapsed ? 'px-3 justify-center' : 'px-4 pr-6'}`}>
|
||||
<Link
|
||||
to="/"
|
||||
className={`flex items-center space-x-3 group overflow-hidden transition-all duration-300 ${collapsed ? 'justify-center w-full' : ''}`}
|
||||
className={`flex items-center space-x-3 group transition-all duration-300 ${collapsed ? 'justify-center' : 'flex-1 min-w-0'}`}
|
||||
onClick={() => setMobileOpen(false)}
|
||||
>
|
||||
<div className="relative flex-shrink-0 border-2 border-black bg-primary p-1 shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]">
|
||||
<Terminal className="w-6 h-6 text-white" />
|
||||
<div className="relative flex-shrink-0 border border-primary bg-white p-1 shadow-sm rounded-sm overflow-hidden">
|
||||
<img src="/logo_xcodereviewer.png" alt="XCodeReviewer" className="w-7 h-7 object-contain" />
|
||||
</div>
|
||||
<div className={`transition-all duration-300 ${collapsed ? 'w-0 opacity-0 overflow-hidden' : 'w-auto opacity-100'}`}>
|
||||
<span className="text-lg font-display font-bold text-black tracking-tighter uppercase">
|
||||
<div className={`transition-all duration-300 ${collapsed ? 'w-0 opacity-0 overflow-hidden' : 'flex-1 min-w-0 opacity-100'}`}>
|
||||
<span className="text-lg font-display font-bold text-black tracking-tighter uppercase whitespace-nowrap">
|
||||
XCode<span className="text-primary">Reviewer</span>
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -93,8 +92,9 @@ export default function Sidebar({ collapsed, setCollapsed }: SidebarProps) {
|
|||
|
||||
{/* Collapse button for desktop */}
|
||||
<button
|
||||
className="hidden md:flex absolute -right-3 top-1/2 -translate-y-1/2 w-6 h-6 bg-white border-2 border-black items-center justify-center hover:bg-primary hover:text-white transition-colors z-50 shadow-[2px_2px_0px_0px_rgba(0,0,0,1)] active:translate-x-[1px] active:translate-y-[1px] active:shadow-none"
|
||||
className="hidden md:flex absolute -right-3 top-1/2 -translate-y-1/2 w-6 h-6 bg-card border border-border items-center justify-center hover:bg-primary hover:text-white transition-all shadow-sm rounded-sm"
|
||||
onClick={() => setCollapsed(!collapsed)}
|
||||
style={{ zIndex: 100 }}
|
||||
>
|
||||
{collapsed ? (
|
||||
<ChevronRight className="w-3 h-3" />
|
||||
|
|
@ -115,11 +115,11 @@ export default function Sidebar({ collapsed, setCollapsed }: SidebarProps) {
|
|||
to={route.path}
|
||||
className={`
|
||||
flex items-center space-x-3 px-3 py-3
|
||||
transition-all duration-200 group relative
|
||||
border-2
|
||||
transition-all duration-200 group relative rounded-sm
|
||||
border
|
||||
${isActive
|
||||
? "bg-primary border-black shadow-retro text-white"
|
||||
: "bg-transparent border-transparent hover:border-black hover:bg-white hover:shadow-retro-hover text-gray-600 hover:text-black"
|
||||
? "bg-primary border-primary/30 shadow-md text-white"
|
||||
: "bg-transparent border-transparent hover:border-border hover:bg-card hover:shadow-sm text-gray-600 hover:text-foreground"
|
||||
}
|
||||
`}
|
||||
onClick={() => setMobileOpen(false)}
|
||||
|
|
@ -153,14 +153,14 @@ export default function Sidebar({ collapsed, setCollapsed }: SidebarProps) {
|
|||
</nav>
|
||||
|
||||
{/* Footer with GitHub Link */}
|
||||
<div className="p-4 border-t-2 border-black bg-white z-10">
|
||||
<div className="p-4 border-t border-border bg-card z-10">
|
||||
<a
|
||||
href="https://github.com/lintsinghua/XCodeReviewer"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`
|
||||
flex items-center space-x-3 px-3 py-2.5
|
||||
text-black border-2 border-transparent hover:border-black hover:shadow-retro-hover hover:bg-white
|
||||
flex items-center space-x-3 px-3 py-2.5 rounded-sm
|
||||
text-foreground border border-transparent hover:border-border hover:shadow-sm hover:bg-muted
|
||||
transition-all duration-200 group
|
||||
`}
|
||||
title={collapsed ? "GitHub 仓库" : undefined}
|
||||
|
|
|
|||
|
|
@ -5,25 +5,25 @@ import { cva, type VariantProps } from "class-variance-authority";
|
|||
import { cn } from "@/shared/utils/utils";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-sm text-sm font-mono font-semibold transition-all duration-150 focus-visible:outline-none focus-visible:shadow-focus disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
||||
"bg-primary text-primary-foreground border border-primary/30 shadow-sm hover:shadow-md hover:-translate-y-px",
|
||||
destructive:
|
||||
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
||||
"bg-secondary text-secondary-foreground border border-secondary/30 shadow-sm hover:shadow-md hover:-translate-y-px",
|
||||
outline:
|
||||
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
||||
"border border-border bg-transparent shadow-sm hover:bg-muted hover:shadow-md",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
"bg-accent text-accent-foreground border border-accent/30 shadow-sm hover:shadow-md hover:-translate-y-px",
|
||||
ghost: "border border-transparent hover:bg-muted hover:border-border",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-9 px-4 py-2",
|
||||
sm: "h-8 rounded-md px-3 text-xs",
|
||||
lg: "h-10 rounded-md px-8",
|
||||
sm: "h-8 rounded-sm px-3 text-xs",
|
||||
lg: "h-10 rounded-sm px-8",
|
||||
icon: "h-9 w-9",
|
||||
},
|
||||
},
|
||||
|
|
@ -36,7 +36,7 @@ const buttonVariants = cva(
|
|||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
|||
type={type}
|
||||
data-slot="input"
|
||||
className={cn(
|
||||
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
||||
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground font-mono flex h-9 w-full min-w-0 rounded-sm border border-input bg-background px-3 py-2 text-sm shadow-none transition-[border-color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"focus:border-primary focus:shadow-focus",
|
||||
"aria-invalid:border-secondary",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export default function AdminDashboard() {
|
|||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen bg-gray-100">
|
||||
<div className="flex items-center justify-center min-h-screen bg-background">
|
||||
<div className="space-y-4 text-center">
|
||||
<div className="animate-spin rounded-none h-16 w-16 border-8 border-black border-t-transparent mx-auto"></div>
|
||||
<p className="text-black font-mono font-bold uppercase">加载数据库信息...</p>
|
||||
|
|
@ -105,9 +105,12 @@ export default function AdminDashboard() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6 pb-8">
|
||||
<div className="space-y-6 px-6 py-4 bg-background min-h-screen font-mono relative overflow-hidden">
|
||||
{/* Decorative Background */}
|
||||
<div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none" />
|
||||
|
||||
{/* 页面标题 */}
|
||||
<div className="flex items-center justify-between border-b-4 border-black pb-6 bg-white/50 backdrop-blur-sm p-4 retro-border">
|
||||
<div className="relative z-10 flex items-center justify-between border-b-4 border-black pb-6 bg-white/50 backdrop-blur-sm p-4 retro-border">
|
||||
<div>
|
||||
<h1 className="text-3xl font-display font-bold text-black uppercase tracking-tighter flex items-center gap-3">
|
||||
<Settings className="h-8 w-8 text-black" />
|
||||
|
|
|
|||
|
|
@ -121,16 +121,19 @@ export default function AuditTasks() {
|
|||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen bg-gray-100">
|
||||
<div className="flex items-center justify-center min-h-screen bg-background">
|
||||
<div className="animate-spin rounded-none h-32 w-32 border-8 border-primary border-t-transparent"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6 animate-fade-in font-mono">
|
||||
<div className="space-y-6 px-6 py-4 bg-background min-h-screen font-mono relative overflow-hidden">
|
||||
{/* Decorative Background */}
|
||||
<div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none" />
|
||||
|
||||
{/* 页面标题 */}
|
||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 border-b-4 border-black pb-6 bg-white/50 backdrop-blur-sm p-4 retro-border">
|
||||
<div className="relative z-10 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 border-b-4 border-black pb-6 bg-white/50 backdrop-blur-sm p-4 retro-border">
|
||||
<div>
|
||||
<h1 className="text-3xl font-display font-bold text-black uppercase tracking-tighter">审计任务</h1>
|
||||
<p className="text-gray-600 mt-1 font-mono border-l-2 border-primary pl-2">查看和管理所有代码审计任务的执行状态</p>
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ export default function Dashboard() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6 p-6 bg-background min-h-screen font-mono relative overflow-hidden">
|
||||
<div className="space-y-6 px-6 py-4 bg-background min-h-screen font-mono relative overflow-hidden">
|
||||
{/* Decorative Background */}
|
||||
<div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none" />
|
||||
|
||||
|
|
@ -622,30 +622,6 @@ export default function Dashboard() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* 使用技巧 */}
|
||||
{/* 使用技巧 */}
|
||||
<div className="retro-card bg-white border-2 border-black shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] p-4">
|
||||
<div className="pb-3 border-b-2 border-black mb-4">
|
||||
<h3 className="flex items-center text-lg font-display font-bold uppercase">
|
||||
<Target className="w-5 h-5 mr-2 text-purple-600" />
|
||||
使用技巧
|
||||
</h3>
|
||||
</div>
|
||||
<div className="space-y-3 font-mono text-sm">
|
||||
<div className="flex items-start space-x-2">
|
||||
<div className="w-2 h-2 bg-black mt-2 flex-shrink-0"></div>
|
||||
<p className="text-gray-700">定期运行代码审计可以及早发现潜在问题</p>
|
||||
</div>
|
||||
<div className="flex items-start space-x-2">
|
||||
<div className="w-2 h-2 bg-black mt-2 flex-shrink-0"></div>
|
||||
<p className="text-gray-700">使用即时分析功能快速检查代码片段</p>
|
||||
</div>
|
||||
<div className="flex items-start space-x-2">
|
||||
<div className="w-2 h-2 bg-black mt-2 flex-shrink-0"></div>
|
||||
<p className="text-gray-700">关注质量评分趋势,持续改进代码质量</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -535,9 +535,12 @@ class UserManager {
|
|||
);
|
||||
|
||||
return (
|
||||
<div className="space-y-6 animate-fade-in font-mono">
|
||||
<div className="space-y-6 px-6 py-4 bg-background min-h-screen font-mono relative overflow-hidden">
|
||||
{/* Decorative Background */}
|
||||
<div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none" />
|
||||
|
||||
{/* 页面标题 */}
|
||||
<div className="border-b-4 border-black pb-6 bg-white/50 backdrop-blur-sm p-4 retro-border">
|
||||
<div className="relative z-10 border-b-4 border-black pb-6 bg-white/50 backdrop-blur-sm p-4 retro-border">
|
||||
<h1 className="text-3xl font-display font-bold text-black uppercase tracking-tighter">即时代码分析</h1>
|
||||
<p className="text-gray-600 mt-1 font-mono border-l-2 border-primary pl-2">快速分析代码片段,发现潜在问题并获得修复建议</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { Input } from '@/components/ui/input';
|
|||
import { Label } from '@/components/ui/label';
|
||||
|
||||
import { toast } from 'sonner';
|
||||
import { Terminal, Lock, Cpu } from 'lucide-react';
|
||||
import { Lock, Cpu } from 'lucide-react';
|
||||
|
||||
export default function Login() {
|
||||
const [email, setEmail] = useState('');
|
||||
|
|
@ -69,8 +69,8 @@ export default function Login() {
|
|||
{/* Main Card */}
|
||||
<div className="w-full max-w-md relative z-10 p-4">
|
||||
<div className="mb-8 text-center">
|
||||
<div className="inline-flex items-center justify-center p-4 bg-primary border-2 border-black shadow-retro mb-4">
|
||||
<Terminal className="w-8 h-8 text-white" />
|
||||
<div className="inline-flex items-center justify-center p-4 bg-white border border-border shadow-md mb-4 rounded-sm">
|
||||
<img src="/logo_xcodereviewer.png" alt="XCodeReviewer" className="w-16 h-16 object-contain" />
|
||||
</div>
|
||||
<h1 className="text-4xl font-display font-bold tracking-tighter uppercase">
|
||||
XCode<span className="text-primary">Reviewer</span>
|
||||
|
|
@ -78,12 +78,12 @@ export default function Login() {
|
|||
<p className="text-sm font-mono text-gray-500 mt-2">输入凭据以继续</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white border-2 border-black shadow-retro p-8 relative">
|
||||
{/* Decorative Corner Markers */}
|
||||
<div className="absolute top-2 left-2 w-2 h-2 bg-black" />
|
||||
<div className="absolute top-2 right-2 w-2 h-2 bg-black" />
|
||||
<div className="absolute bottom-2 left-2 w-2 h-2 bg-black" />
|
||||
<div className="absolute bottom-2 right-2 w-2 h-2 bg-black" />
|
||||
<div className="terminal-card p-8 relative">
|
||||
{/* Decorative Corner Markers - Subtle */}
|
||||
<div className="absolute top-3 left-3 w-1.5 h-1.5 bg-primary/20 rounded-sm" />
|
||||
<div className="absolute top-3 right-3 w-1.5 h-1.5 bg-primary/20 rounded-sm" />
|
||||
<div className="absolute bottom-3 left-3 w-1.5 h-1.5 bg-primary/20 rounded-sm" />
|
||||
<div className="absolute bottom-3 right-3 w-1.5 h-1.5 bg-primary/20 rounded-sm" />
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6 mt-4">
|
||||
<div className="space-y-2">
|
||||
|
|
@ -96,7 +96,7 @@ export default function Login() {
|
|||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
className="retro-input font-mono pl-10"
|
||||
className="terminal-input font-mono pl-10"
|
||||
/>
|
||||
<Cpu className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
|
||||
</div>
|
||||
|
|
@ -112,7 +112,7 @@ export default function Login() {
|
|||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
required
|
||||
className="retro-input font-mono pl-10"
|
||||
className="terminal-input font-mono pl-10"
|
||||
/>
|
||||
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
|
||||
</div>
|
||||
|
|
@ -120,7 +120,7 @@ export default function Login() {
|
|||
|
||||
<Button
|
||||
type="submit"
|
||||
className="w-full retro-btn text-lg h-12 mt-4"
|
||||
className="w-full terminal-btn-primary text-lg h-12 mt-4"
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
|
|
@ -131,7 +131,7 @@ export default function Login() {
|
|||
</Button>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 pt-6 border-t-2 border-dashed border-gray-200 text-center">
|
||||
<div className="mt-6 pt-6 terminal-divider text-center">
|
||||
<div className="text-xs font-mono text-gray-500">
|
||||
没有访问令牌? <span className="text-primary font-bold cursor-pointer hover:underline" onClick={() => navigate('/register')}>申请访问</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -313,9 +313,12 @@ export default function ProjectDetail() {
|
|||
|
||||
|
||||
return (
|
||||
<div className="space-y-6 font-mono">
|
||||
<div className="space-y-6 px-6 py-4 bg-background min-h-screen font-mono relative overflow-hidden">
|
||||
{/* Decorative Background */}
|
||||
<div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none" />
|
||||
|
||||
{/* 页面标题 */}
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4 border-b-4 border-black pb-6 bg-white/50 backdrop-blur-sm p-4 retro-border">
|
||||
<div className="relative z-10 flex flex-col md:flex-row md:items-center justify-between gap-4 border-b-4 border-black pb-6 bg-white/50 backdrop-blur-sm p-4 retro-border">
|
||||
<div className="flex items-start space-x-4">
|
||||
<Link to="/projects">
|
||||
<Button variant="outline" size="sm" className="retro-btn bg-white text-black hover:bg-gray-100 h-10 w-10 p-0 flex items-center justify-center">
|
||||
|
|
|
|||
|
|
@ -361,7 +361,7 @@ export default function Projects() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-8 p-6 bg-background min-h-screen font-mono relative overflow-hidden">
|
||||
<div className="space-y-6 px-6 py-4 bg-background min-h-screen font-mono relative overflow-hidden">
|
||||
{/* Decorative Background */}
|
||||
<div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none" />
|
||||
|
||||
|
|
@ -379,12 +379,12 @@ export default function Projects() {
|
|||
|
||||
<Dialog open={showCreateDialog} onOpenChange={setShowCreateDialog}>
|
||||
<DialogTrigger asChild>
|
||||
<Button className="retro-btn h-12 text-lg">
|
||||
<Button className="terminal-btn-primary h-12 text-lg">
|
||||
<Plus className="w-5 h-5 mr-2" />
|
||||
初始化项目
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-3xl retro-card border-4 border-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] bg-white p-0 overflow-hidden">
|
||||
<DialogContent className="max-w-3xl terminal-card border-2 border-primary/20 shadow-lg bg-white p-0 overflow-hidden">
|
||||
<DialogHeader className="bg-black text-white p-4 border-b-4 border-black">
|
||||
<DialogTitle className="font-mono text-xl uppercase tracking-widest flex items-center gap-2">
|
||||
<Terminal className="w-5 h-5" />
|
||||
|
|
@ -394,7 +394,7 @@ export default function Projects() {
|
|||
|
||||
<div className="p-6">
|
||||
<Tabs defaultValue="repository" className="w-full">
|
||||
<TabsList className="grid w-full grid-cols-2 bg-gray-100 border-2 border-black p-1 h-auto">
|
||||
<TabsList className="grid w-full grid-cols-2 bg-gray-100 border border-border p-1 h-auto">
|
||||
<TabsTrigger
|
||||
value="repository"
|
||||
className="data-[state=active]:bg-primary data-[state=active]:text-white font-mono font-bold uppercase py-2 border-2 border-transparent data-[state=active]:border-black data-[state=active]:shadow-sm transition-all"
|
||||
|
|
@ -418,7 +418,7 @@ export default function Projects() {
|
|||
value={createForm.name}
|
||||
onChange={(e) => setCreateForm({ ...createForm, name: e.target.value })}
|
||||
placeholder="输入项目名称"
|
||||
className="retro-input"
|
||||
className="terminal-input"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
|
|
@ -427,10 +427,10 @@ export default function Projects() {
|
|||
value={createForm.repository_type}
|
||||
onValueChange={(value: any) => setCreateForm({ ...createForm, repository_type: value })}
|
||||
>
|
||||
<SelectTrigger className="retro-input">
|
||||
<SelectTrigger className="terminal-input">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="retro-card border-2 border-black">
|
||||
<SelectContent className="retro-card border border-border">
|
||||
<SelectItem value="github">GITHUB</SelectItem>
|
||||
<SelectItem value="gitlab">GITLAB</SelectItem>
|
||||
<SelectItem value="other">OTHER</SelectItem>
|
||||
|
|
@ -447,7 +447,7 @@ export default function Projects() {
|
|||
onChange={(e) => setCreateForm({ ...createForm, description: e.target.value })}
|
||||
placeholder="// 项目描述..."
|
||||
rows={3}
|
||||
className="retro-input min-h-[100px]"
|
||||
className="terminal-input min-h-[100px]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -459,7 +459,7 @@ export default function Projects() {
|
|||
value={createForm.repository_url}
|
||||
onChange={(e) => setCreateForm({ ...createForm, repository_url: e.target.value })}
|
||||
placeholder="https://github.com/user/repo"
|
||||
className="retro-input"
|
||||
className="terminal-input"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
|
|
@ -469,7 +469,7 @@ export default function Projects() {
|
|||
value={createForm.default_branch}
|
||||
onChange={(e) => setCreateForm({ ...createForm, default_branch: e.target.value })}
|
||||
placeholder="main"
|
||||
className="retro-input"
|
||||
className="terminal-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -479,7 +479,7 @@ export default function Projects() {
|
|||
<div className="grid grid-cols-3 gap-3">
|
||||
{supportedLanguages.map((lang) => (
|
||||
<label key={lang} className={`flex items-center space-x-3 p-2 border-2 cursor-pointer transition-all ${createForm.programming_languages.includes(lang)
|
||||
? 'border-black bg-primary/10 shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]'
|
||||
? 'border-black bg-primary/10 shadow-sm'
|
||||
: 'border-gray-200 hover:border-black'
|
||||
}`}>
|
||||
<input
|
||||
|
|
@ -498,7 +498,7 @@ export default function Projects() {
|
|||
});
|
||||
}
|
||||
}}
|
||||
className="rounded border-2 border-black w-4 h-4 text-primary focus:ring-0"
|
||||
className="rounded border border-border w-4 h-4 text-primary focus:ring-0"
|
||||
/>
|
||||
<span className="text-sm font-mono font-bold uppercase">{lang}</span>
|
||||
</label>
|
||||
|
|
@ -507,10 +507,10 @@ export default function Projects() {
|
|||
</div>
|
||||
|
||||
<div className="flex justify-end space-x-4 pt-4 border-t-2 border-dashed border-gray-200">
|
||||
<Button variant="outline" onClick={() => setShowCreateDialog(false)} className="retro-btn bg-white text-black hover:bg-gray-100">
|
||||
<Button variant="outline" onClick={() => setShowCreateDialog(false)} className="terminal-btn-primary bg-white text-black hover:bg-gray-100">
|
||||
取消
|
||||
</Button>
|
||||
<Button onClick={handleCreateProject} className="retro-btn">
|
||||
<Button onClick={handleCreateProject} className="terminal-btn-primary">
|
||||
执行创建
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -525,7 +525,7 @@ export default function Projects() {
|
|||
value={createForm.name}
|
||||
onChange={(e) => setCreateForm({ ...createForm, name: e.target.value })}
|
||||
placeholder="输入项目名称"
|
||||
className="retro-input"
|
||||
className="terminal-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -537,7 +537,7 @@ export default function Projects() {
|
|||
onChange={(e) => setCreateForm({ ...createForm, description: e.target.value })}
|
||||
placeholder="// 项目描述..."
|
||||
rows={3}
|
||||
className="retro-input min-h-[100px]"
|
||||
className="terminal-input min-h-[100px]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -546,7 +546,7 @@ export default function Projects() {
|
|||
<div className="grid grid-cols-3 gap-3">
|
||||
{supportedLanguages.map((lang) => (
|
||||
<label key={lang} className={`flex items-center space-x-3 p-2 border-2 cursor-pointer transition-all ${createForm.programming_languages.includes(lang)
|
||||
? 'border-black bg-primary/10 shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]'
|
||||
? 'border-black bg-primary/10 shadow-sm'
|
||||
: 'border-gray-200 hover:border-black'
|
||||
}`}>
|
||||
<input
|
||||
|
|
@ -565,7 +565,7 @@ export default function Projects() {
|
|||
});
|
||||
}
|
||||
}}
|
||||
className="rounded border-2 border-black w-4 h-4 text-primary focus:ring-0"
|
||||
className="rounded border border-border w-4 h-4 text-primary focus:ring-0"
|
||||
/>
|
||||
<span className="text-sm font-mono font-bold uppercase">{lang}</span>
|
||||
</label>
|
||||
|
|
@ -592,7 +592,7 @@ export default function Projects() {
|
|||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="retro-btn bg-white text-black"
|
||||
className="terminal-btn-primary bg-white text-black"
|
||||
disabled={uploading || !createForm.name.trim()}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
|
|
@ -610,11 +610,11 @@ export default function Projects() {
|
|||
<span>上传并分析中...</span>
|
||||
<span>{uploadProgress}%</span>
|
||||
</div>
|
||||
<Progress value={uploadProgress} className="h-4 border-2 border-black rounded-none bg-white [&>div]:bg-primary" />
|
||||
<Progress value={uploadProgress} className="h-4 border border-border rounded-none bg-white [&>div]:bg-primary" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="bg-yellow-50 border-2 border-black p-4 shadow-[4px_4px_0px_0px_rgba(0,0,0,1)]">
|
||||
<div className="bg-yellow-50 border border-border p-4 shadow-md">
|
||||
<div className="flex items-start space-x-3">
|
||||
<AlertCircle className="w-5 h-5 text-black mt-0.5" />
|
||||
<div className="text-xs font-mono text-black">
|
||||
|
|
@ -631,7 +631,7 @@ export default function Projects() {
|
|||
</div>
|
||||
|
||||
<div className="flex justify-end space-x-4 pt-4 border-t-2 border-dashed border-gray-200">
|
||||
<Button variant="outline" onClick={() => setShowCreateDialog(false)} disabled={uploading} className="retro-btn bg-white text-black hover:bg-gray-100">
|
||||
<Button variant="outline" onClick={() => setShowCreateDialog(false)} disabled={uploading} className="terminal-btn-primary bg-white text-black hover:bg-gray-100">
|
||||
取消
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -645,49 +645,49 @@ export default function Projects() {
|
|||
{/* Stats Section */}
|
||||
{projects.length > 0 && (
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 relative z-10">
|
||||
<div className="retro-card p-4 bg-white border-2 border-black shadow-[4px_4px_0px_0px_rgba(0,0,0,1)]">
|
||||
<div className="retro-card p-4 bg-white border border-border shadow-md">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="font-mono text-xs font-bold uppercase text-gray-500">项目总数</p>
|
||||
<p className="font-display text-2xl font-bold">{projects.length}</p>
|
||||
</div>
|
||||
<div className="w-10 h-10 border-2 border-black bg-primary flex items-center justify-center text-white shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]">
|
||||
<div className="w-10 h-10 border border-border bg-primary flex items-center justify-center text-white shadow-sm">
|
||||
<Code className="w-5 h-5" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="retro-card p-4 bg-white border-2 border-black shadow-[4px_4px_0px_0px_rgba(0,0,0,1)]">
|
||||
<div className="retro-card p-4 bg-white border border-border shadow-md">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="font-mono text-xs font-bold uppercase text-gray-500">活跃</p>
|
||||
<p className="font-display text-2xl font-bold">{projects.filter(p => p.is_active).length}</p>
|
||||
</div>
|
||||
<div className="w-10 h-10 border-2 border-black bg-green-500 flex items-center justify-center text-white shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]">
|
||||
<div className="w-10 h-10 border border-border bg-green-500 flex items-center justify-center text-white shadow-sm">
|
||||
<Activity className="w-5 h-5" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="retro-card p-4 bg-white border-2 border-black shadow-[4px_4px_0px_0px_rgba(0,0,0,1)]">
|
||||
<div className="retro-card p-4 bg-white border border-border shadow-md">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="font-mono text-xs font-bold uppercase text-gray-500">GitHub</p>
|
||||
<p className="font-display text-2xl font-bold">{projects.filter(p => p.repository_type === 'github').length}</p>
|
||||
</div>
|
||||
<div className="w-10 h-10 border-2 border-black bg-gray-800 flex items-center justify-center text-white shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]">
|
||||
<div className="w-10 h-10 border border-border bg-gray-800 flex items-center justify-center text-white shadow-sm">
|
||||
<GitBranch className="w-5 h-5" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="retro-card p-4 bg-white border-2 border-black shadow-[4px_4px_0px_0px_rgba(0,0,0,1)]">
|
||||
<div className="retro-card p-4 bg-white border border-border shadow-md">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="font-mono text-xs font-bold uppercase text-gray-500">GitLab</p>
|
||||
<p className="font-display text-2xl font-bold">{projects.filter(p => p.repository_type === 'gitlab').length}</p>
|
||||
</div>
|
||||
<div className="w-10 h-10 border-2 border-black bg-orange-500 flex items-center justify-center text-white shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]">
|
||||
<div className="w-10 h-10 border border-border bg-orange-500 flex items-center justify-center text-white shadow-sm">
|
||||
<Shield className="w-5 h-5" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -696,17 +696,17 @@ export default function Projects() {
|
|||
)}
|
||||
|
||||
{/* Search and Filter */}
|
||||
<div className="retro-card p-4 flex items-center gap-4 bg-white border-2 border-black shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] relative z-10">
|
||||
<div className="retro-card p-4 flex items-center gap-4 bg-white border border-border shadow-md relative z-10">
|
||||
<div className="flex-1 relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-black w-4 h-4" />
|
||||
<Input
|
||||
placeholder="搜索项目..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="retro-input pl-10 w-full"
|
||||
className="terminal-input pl-10 w-full"
|
||||
/>
|
||||
</div>
|
||||
<Button variant="outline" className="retro-btn bg-white text-black hover:bg-gray-100">
|
||||
<Button variant="outline" className="terminal-btn-primary bg-white text-black hover:bg-gray-100">
|
||||
<Settings className="w-4 h-4 mr-2" />
|
||||
筛选选项
|
||||
</Button>
|
||||
|
|
@ -716,10 +716,10 @@ export default function Projects() {
|
|||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 relative z-10">
|
||||
{filteredProjects.length > 0 ? (
|
||||
filteredProjects.map((project) => (
|
||||
<div key={project.id} className="retro-card bg-white border-2 border-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] hover:translate-x-[-2px] hover:translate-y-[-2px] hover:shadow-[10px_10px_0px_0px_rgba(0,0,0,1)] transition-all group flex flex-col h-full">
|
||||
<div key={project.id} className="retro-card bg-white border border-border shadow-md hover:shadow-lg transition-all group flex flex-col h-full">
|
||||
<div className="p-4 border-b-2 border-black bg-gray-50 flex justify-between items-start">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="w-10 h-10 border-2 border-black bg-white flex items-center justify-center text-2xl shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]">
|
||||
<div className="w-10 h-10 border border-border bg-white flex items-center justify-center text-2xl shadow-sm">
|
||||
{getRepositoryIcon(project.repository_type)}
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -783,20 +783,20 @@ export default function Projects() {
|
|||
|
||||
<div className="p-4 border-t-2 border-black bg-gray-50 grid grid-cols-2 gap-2">
|
||||
<Link to={`/projects/${project.id}`} className="col-span-2">
|
||||
<Button variant="outline" className="w-full retro-btn bg-white text-black h-8 text-xs">
|
||||
<Button variant="outline" className="w-full terminal-btn-primary bg-white text-black h-8 text-xs">
|
||||
<Code className="w-3 h-3 mr-2" />
|
||||
查看详情
|
||||
</Button>
|
||||
</Link>
|
||||
<Button size="sm" className="retro-btn h-8 text-xs" onClick={() => handleCreateTask(project.id)}>
|
||||
<Button size="sm" className="terminal-btn-primary h-8 text-xs" onClick={() => handleCreateTask(project.id)}>
|
||||
<Shield className="w-3 h-3 mr-2" />
|
||||
审计
|
||||
</Button>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<Button size="sm" variant="outline" className="retro-btn bg-white text-black h-8 px-0" onClick={() => handleEditClick(project)}>
|
||||
<Button size="sm" variant="outline" className="terminal-btn-primary bg-white text-black h-8 px-0" onClick={() => handleEditClick(project)}>
|
||||
<Edit className="w-3 h-3" />
|
||||
</Button>
|
||||
<Button size="sm" variant="outline" className="retro-btn bg-white text-red-600 border-red-600 h-8 px-0 hover:bg-red-50" onClick={() => handleDeleteClick(project)}>
|
||||
<Button size="sm" variant="outline" className="terminal-btn-primary bg-white text-red-600 border-red-600 h-8 px-0 hover:bg-red-50" onClick={() => handleDeleteClick(project)}>
|
||||
<Trash2 className="w-3 h-3" />
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -805,7 +805,7 @@ export default function Projects() {
|
|||
))
|
||||
) : (
|
||||
<div className="col-span-full">
|
||||
<div className="retro-card border-2 border-black p-16 text-center bg-white border-dashed">
|
||||
<div className="retro-card border border-border p-16 text-center bg-white border-dashed">
|
||||
<Code className="w-16 h-16 text-gray-300 mx-auto mb-4" />
|
||||
<h3 className="text-xl font-display font-bold text-gray-900 mb-2">
|
||||
{searchTerm ? '未找到匹配项' : '未初始化项目'}
|
||||
|
|
@ -814,7 +814,7 @@ export default function Projects() {
|
|||
{searchTerm ? '调整搜索参数' : '初始化第一个项目以开始'}
|
||||
</p>
|
||||
{!searchTerm && (
|
||||
<Button onClick={() => setShowCreateDialog(true)} className="retro-btn">
|
||||
<Button onClick={() => setShowCreateDialog(true)} className="terminal-btn-primary">
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
初始化项目
|
||||
</Button>
|
||||
|
|
@ -834,7 +834,7 @@ export default function Projects() {
|
|||
|
||||
{/* Edit Dialog */}
|
||||
<Dialog open={showEditDialog} onOpenChange={setShowEditDialog}>
|
||||
<DialogContent className="max-w-2xl retro-card border-4 border-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] bg-white p-0">
|
||||
<DialogContent className="max-w-2xl terminal-card border-2 border-primary/20 shadow-lg bg-white p-0">
|
||||
<DialogHeader className="bg-black text-white p-4 border-b-4 border-black">
|
||||
<DialogTitle className="font-mono text-xl uppercase tracking-widest flex items-center gap-2">
|
||||
<Edit className="w-5 h-5" />
|
||||
|
|
@ -850,7 +850,7 @@ export default function Projects() {
|
|||
id="edit-name"
|
||||
value={editForm.name}
|
||||
onChange={(e) => setEditForm({ ...editForm, name: e.target.value })}
|
||||
className="retro-input"
|
||||
className="terminal-input"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -860,7 +860,7 @@ export default function Projects() {
|
|||
value={editForm.description}
|
||||
onChange={(e) => setEditForm({ ...editForm, description: e.target.value })}
|
||||
rows={3}
|
||||
className="retro-input"
|
||||
className="terminal-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -874,7 +874,7 @@ export default function Projects() {
|
|||
id="edit-repo-url"
|
||||
value={editForm.repository_url}
|
||||
onChange={(e) => setEditForm({ ...editForm, repository_url: e.target.value })}
|
||||
className="retro-input"
|
||||
className="terminal-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -885,10 +885,10 @@ export default function Projects() {
|
|||
value={editForm.repository_type}
|
||||
onValueChange={(value: any) => setEditForm({ ...editForm, repository_type: value })}
|
||||
>
|
||||
<SelectTrigger id="edit-repo-type" className="retro-input">
|
||||
<SelectTrigger id="edit-repo-type" className="terminal-input">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="retro-card border-2 border-black">
|
||||
<SelectContent className="retro-card border border-border">
|
||||
<SelectItem value="github">GITHUB</SelectItem>
|
||||
<SelectItem value="gitlab">GITLAB</SelectItem>
|
||||
<SelectItem value="other">OTHER</SelectItem>
|
||||
|
|
@ -902,7 +902,7 @@ export default function Projects() {
|
|||
id="edit-default-branch"
|
||||
value={editForm.default_branch}
|
||||
onChange={(e) => setEditForm({ ...editForm, default_branch: e.target.value })}
|
||||
className="retro-input"
|
||||
className="terminal-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -915,7 +915,7 @@ export default function Projects() {
|
|||
<div
|
||||
key={lang}
|
||||
className={`flex items-center space-x-2 p-2 border-2 cursor-pointer transition-all ${editForm.programming_languages?.includes(lang)
|
||||
? 'border-black bg-primary/10 shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]'
|
||||
? 'border-black bg-primary/10 shadow-sm'
|
||||
: 'border-gray-200 hover:border-black'
|
||||
}`}
|
||||
onClick={() => handleToggleLanguage(lang)}
|
||||
|
|
@ -938,10 +938,10 @@ export default function Projects() {
|
|||
</div>
|
||||
|
||||
<div className="flex justify-end space-x-3 p-4 border-t-2 border-black bg-gray-50">
|
||||
<Button variant="outline" onClick={() => setShowEditDialog(false)} className="retro-btn bg-white text-black hover:bg-gray-100">
|
||||
<Button variant="outline" onClick={() => setShowEditDialog(false)} className="terminal-btn-primary bg-white text-black hover:bg-gray-100">
|
||||
取消
|
||||
</Button>
|
||||
<Button onClick={handleSaveEdit} className="retro-btn">
|
||||
<Button onClick={handleSaveEdit} className="terminal-btn-primary">
|
||||
保存更改
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -950,7 +950,7 @@ export default function Projects() {
|
|||
|
||||
{/* Delete Dialog */}
|
||||
<AlertDialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
|
||||
<AlertDialogContent className="retro-card border-4 border-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] bg-white p-0">
|
||||
<AlertDialogContent className="terminal-card border-2 border-primary/20 shadow-lg bg-white p-0">
|
||||
<AlertDialogHeader className="bg-red-600 text-white p-4 border-b-4 border-black">
|
||||
<AlertDialogTitle className="font-mono text-xl uppercase tracking-widest flex items-center gap-2">
|
||||
<Trash2 className="w-5 h-5" />
|
||||
|
|
@ -962,7 +962,7 @@ export default function Projects() {
|
|||
</AlertDialogHeader>
|
||||
|
||||
<div className="p-6">
|
||||
<div className="bg-blue-50 border-2 border-black p-4 shadow-[4px_4px_0px_0px_rgba(0,0,0,1)]">
|
||||
<div className="bg-blue-50 border border-border p-4 shadow-md">
|
||||
<p className="text-blue-900 font-bold mb-2 font-mono uppercase">系统通知:</p>
|
||||
<ul className="list-disc list-inside text-blue-800 space-y-1 text-xs font-mono">
|
||||
<li>> 项目移至回收站</li>
|
||||
|
|
@ -974,10 +974,10 @@ export default function Projects() {
|
|||
</div>
|
||||
|
||||
<AlertDialogFooter className="p-4 border-t-2 border-black bg-gray-50">
|
||||
<AlertDialogCancel className="retro-btn bg-white text-black hover:bg-gray-100 border-2 border-black">取消</AlertDialogCancel>
|
||||
<AlertDialogCancel className="terminal-btn-primary bg-white text-black hover:bg-gray-100 border border-border">取消</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={handleConfirmDelete}
|
||||
className="retro-btn bg-red-600 text-white hover:bg-red-700 border-2 border-black"
|
||||
className="terminal-btn-primary bg-red-600 text-white hover:bg-red-700 border border-border"
|
||||
>
|
||||
确认删除
|
||||
</AlertDialogAction>
|
||||
|
|
|
|||
|
|
@ -113,19 +113,22 @@ export default function RecycleBin() {
|
|||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen bg-gray-100">
|
||||
<div className="flex items-center justify-center min-h-screen bg-background">
|
||||
<div className="text-center">
|
||||
<div className="animate-spin rounded-none h-12 w-12 border-4 border-black border-t-transparent mx-auto mb-4"></div>
|
||||
<p className="text-black font-mono font-bold uppercase">加载中...</p>
|
||||
<div className="animate-spin rounded-none h-12 w-12 border-4 border-border border-t-transparent mx-auto mb-4"></div>
|
||||
<p className="text-foreground font-mono font-bold uppercase">加载中...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6 animate-fade-in">
|
||||
<div className="space-y-6 px-6 py-4 bg-background min-h-screen font-mono relative overflow-hidden">
|
||||
{/* Decorative Background */}
|
||||
<div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none" />
|
||||
|
||||
{/* 页面标题 */}
|
||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 border-b-4 border-black pb-6 bg-white/50 backdrop-blur-sm p-4 retro-border">
|
||||
<div className="relative z-10 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 border-b-4 border-black pb-6 bg-white/50 backdrop-blur-sm p-4 retro-border">
|
||||
<div>
|
||||
<h1 className="text-3xl font-display font-bold text-black uppercase tracking-tighter flex items-center gap-2">
|
||||
<Trash2 className="w-8 h-8 text-black" />
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ export default function Register() {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50 px-4">
|
||||
<div className="min-h-screen flex items-center justify-center bg-background px-4">
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader className="space-y-1">
|
||||
<CardTitle className="text-2xl font-bold text-center">注册账号</CardTitle>
|
||||
|
|
|
|||
|
|
@ -414,7 +414,7 @@ export default function TaskDetail() {
|
|||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen bg-gray-100">
|
||||
<div className="flex items-center justify-center min-h-screen bg-background">
|
||||
<div className="animate-spin rounded-none h-32 w-32 border-8 border-primary border-t-transparent"></div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -18,11 +18,22 @@ export default {
|
|||
},
|
||||
},
|
||||
extend: {
|
||||
// Typography - Pixel-perfect monospace for terminal aesthetic
|
||||
fontFamily: {
|
||||
mono: ['"Space Mono"', '"Courier New"', 'monospace'],
|
||||
mono: ['"JetBrains Mono"', '"Roboto Mono"', '"Courier New"', 'monospace'],
|
||||
sans: ['"Inter"', 'system-ui', 'sans-serif'],
|
||||
display: ['"Orbitron"', 'sans-serif'],
|
||||
display: ['"Orbitron"', '"Rajdhani"', 'sans-serif'],
|
||||
},
|
||||
fontSize: {
|
||||
'xs': ['0.75rem', { lineHeight: '1rem', letterSpacing: '0.01em' }],
|
||||
'sm': ['0.875rem', { lineHeight: '1.25rem', letterSpacing: '0.01em' }],
|
||||
'base': ['1rem', { lineHeight: '1.5rem', letterSpacing: '0' }],
|
||||
'lg': ['1.125rem', { lineHeight: '1.75rem', letterSpacing: '-0.01em' }],
|
||||
'xl': ['1.25rem', { lineHeight: '1.75rem', letterSpacing: '-0.01em' }],
|
||||
'2xl': ['1.5rem', { lineHeight: '2rem', letterSpacing: '-0.02em' }],
|
||||
'3xl': ['1.875rem', { lineHeight: '2.25rem', letterSpacing: '-0.02em' }],
|
||||
},
|
||||
// Extended Color System
|
||||
colors: {
|
||||
border: 'hsl(var(--border))',
|
||||
input: 'hsl(var(--input))',
|
||||
|
|
@ -37,6 +48,10 @@ export default {
|
|||
DEFAULT: 'hsl(var(--secondary))',
|
||||
foreground: 'hsl(var(--secondary-foreground))',
|
||||
},
|
||||
success: {
|
||||
DEFAULT: 'hsl(var(--success))',
|
||||
foreground: 'hsl(var(--success-foreground))',
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: 'hsl(var(--destructive))',
|
||||
foreground: 'hsl(var(--destructive-foreground))',
|
||||
|
|
@ -57,27 +72,50 @@ export default {
|
|||
DEFAULT: 'hsl(var(--card))',
|
||||
foreground: 'hsl(var(--card-foreground))',
|
||||
},
|
||||
// Cassette Futurism Palette
|
||||
retro: {
|
||||
orange: '#FF3D00',
|
||||
teal: '#00E5FF',
|
||||
pink: '#FF00FF',
|
||||
yellow: '#FFEA00',
|
||||
dark: '#1A1A1A',
|
||||
light: '#F5F7FA',
|
||||
// Core Palette - Direct color access
|
||||
terminal: {
|
||||
orange: '#FF6B2C', // Vibrant Orange
|
||||
'orange-dark': '#E55A1F',
|
||||
red: '#D32F2F', // Deep Red
|
||||
'red-dark': '#B71C1C',
|
||||
green: '#00E676', // Signal Green
|
||||
'green-dark': '#00C853',
|
||||
grey: {
|
||||
50: '#F5F5F5',
|
||||
100: '#E0E0E0',
|
||||
200: '#BDBDBD',
|
||||
300: '#9E9E9E',
|
||||
400: '#757575',
|
||||
500: '#616161',
|
||||
600: '#424242',
|
||||
700: '#303030',
|
||||
800: '#212121',
|
||||
900: '#1A1A1A',
|
||||
}
|
||||
}
|
||||
},
|
||||
// Simplified Border Radius
|
||||
borderRadius: {
|
||||
lg: 'var(--radius)',
|
||||
md: 'calc(var(--radius) - 2px)',
|
||||
sm: 'calc(var(--radius) - 4px)',
|
||||
md: 'var(--radius)',
|
||||
sm: 'var(--radius)',
|
||||
none: '0',
|
||||
},
|
||||
// Refined Shadows - Subtle and clean
|
||||
boxShadow: {
|
||||
'retro': '4px 4px 0px 0px rgba(0,0,0,1)',
|
||||
'retro-hover': '2px 2px 0px 0px rgba(0,0,0,1)',
|
||||
'neon': '0 0 5px theme("colors.primary.DEFAULT"), 0 0 20px theme("colors.primary.DEFAULT")',
|
||||
'sm': 'var(--shadow-sm)',
|
||||
'md': 'var(--shadow-md)',
|
||||
'lg': '0 4px 6px rgba(0, 0, 0, 0.12)',
|
||||
'focus': 'var(--shadow-focus)',
|
||||
// Minimal retro effect for special cases
|
||||
'terminal': '1px 1px 0px rgba(0, 0, 0, 0.15)',
|
||||
'terminal-md': '2px 2px 0px rgba(0, 0, 0, 0.15)',
|
||||
// Glow effects for status indicators
|
||||
'glow-orange': '0 0 8px rgba(255, 107, 44, 0.4)',
|
||||
'glow-red': '0 0 8px rgba(211, 47, 47, 0.4)',
|
||||
'glow-green': '0 0 8px rgba(0, 230, 118, 0.4)',
|
||||
},
|
||||
// Refined Animations
|
||||
keyframes: {
|
||||
'accordion-down': {
|
||||
from: { height: '0' },
|
||||
|
|
@ -87,28 +125,45 @@ export default {
|
|||
from: { height: 'var(--radix-accordion-content-height)' },
|
||||
to: { height: '0' },
|
||||
},
|
||||
'glitch': {
|
||||
'0%, 100%': { transform: 'translate(0)' },
|
||||
'20%': { transform: 'translate(-2px, 2px)' },
|
||||
'40%': { transform: 'translate(-2px, -2px)' },
|
||||
'60%': { transform: 'translate(2px, 2px)' },
|
||||
'80%': { transform: 'translate(2px, -2px)' },
|
||||
// Subtle fade in
|
||||
'fade-in': {
|
||||
'0%': { opacity: '0' },
|
||||
'100%': { opacity: '1' },
|
||||
},
|
||||
// Slide in from bottom
|
||||
'slide-up': {
|
||||
'0%': { transform: 'translateY(10px)', opacity: '0' },
|
||||
'100%': { transform: 'translateY(0)', opacity: '1' },
|
||||
},
|
||||
// Subtle pulse for status indicators
|
||||
'pulse-glow': {
|
||||
'0%, 100%': { opacity: '1' },
|
||||
'50%': { opacity: '0.7' },
|
||||
},
|
||||
// Terminal cursor blink
|
||||
'blink': {
|
||||
'0%, 100%': { opacity: '1' },
|
||||
'50%': { opacity: '0' },
|
||||
},
|
||||
// Simplified scanline
|
||||
'scanline': {
|
||||
'0%': { transform: 'translateY(-100%)' },
|
||||
'100%': { transform: 'translateY(100%)' },
|
||||
},
|
||||
'pulse-slow': {
|
||||
'0%, 100%': { opacity: '1' },
|
||||
'50%': { opacity: '0.5' },
|
||||
}
|
||||
},
|
||||
animation: {
|
||||
'accordion-down': 'accordion-down 0.2s ease-out',
|
||||
'accordion-up': 'accordion-up 0.2s ease-out',
|
||||
'glitch': 'glitch 0.3s cubic-bezier(.25, .46, .45, .94) both infinite',
|
||||
'fade-in': 'fade-in 0.15s ease-out',
|
||||
'slide-up': 'slide-up 0.2s ease-out',
|
||||
'pulse-glow': 'pulse-glow 2s ease-in-out infinite',
|
||||
'blink': 'blink 1s step-end infinite',
|
||||
'scanline': 'scanline 8s linear infinite',
|
||||
'pulse-slow': 'pulse-slow 3s ease-in-out infinite',
|
||||
},
|
||||
// Spacing adjustments for pixel-perfect layouts
|
||||
spacing: {
|
||||
'18': '4.5rem',
|
||||
'88': '22rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue