feat: Add mobile chat interface and command input to footer component
Some checks failed
GBCI / build (push) Failing after 8m35s
Some checks failed
GBCI / build (push) Failing after 8m35s
This commit is contained in:
parent
0908822924
commit
a3c37e31ac
5 changed files with 575 additions and 235 deletions
|
@ -4,6 +4,7 @@ import { usePathname, useRouter } from 'next/navigation';
|
|||
import Image from 'next/image';
|
||||
import { useRef, useEffect, useState } from 'react';
|
||||
import { useTheme } from './theme-provider';
|
||||
import { ChevronLeft, ChevronRight, HardDrive, Terminal } from 'lucide-react';
|
||||
import './client-nav.css'; // Ensure you have the CSS file for styles
|
||||
|
||||
const examples = [
|
||||
|
@ -21,7 +22,7 @@ const examples = [
|
|||
{ name: "Settings", href: "/settings", color: "#6B7280" }, // Gray
|
||||
];
|
||||
|
||||
export function Nav() {
|
||||
export const Nav = ()=> {
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
@ -32,8 +33,35 @@ export function Nav() {
|
|||
const loginMenuRef = useRef<HTMLDivElement>(null);
|
||||
const [showThemeMenu, setShowThemeMenu] = useState(false);
|
||||
const themeMenuRef = useRef<HTMLDivElement>(null);
|
||||
const [currentTime, setCurrentTime] = useState(new Date());
|
||||
const { theme, setTheme, themes } = useTheme();
|
||||
|
||||
// Update time every second
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
setCurrentTime(new Date());
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
const formatTime = (date) => {
|
||||
return date.toLocaleTimeString('en-US', {
|
||||
hour12: false,
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
});
|
||||
};
|
||||
|
||||
const formatDate = (date) => {
|
||||
return date.toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit'
|
||||
});
|
||||
};
|
||||
|
||||
const isActive = (href: string) => {
|
||||
if (href === '/') return pathname === href;
|
||||
return pathname.startsWith(href);
|
||||
|
@ -153,7 +181,36 @@ export function Nav() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="nav-container">
|
||||
{/* Retro System Status Bar */}
|
||||
<div className="fixed top-0 left-0 right-0 z-50 bg-gray-800 text-green-400 font-mono border-b border-green-600 text-xs">
|
||||
<div className="flex items-center justify-between px-4 py-1">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<HardDrive className="w-3 h-3 text-green-400" />
|
||||
<span className="text-green-300">RETRO NAVIGATOR v4.0</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
|
||||
<span className="text-green-400">READY</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-green-300">THEME:</span>
|
||||
<span className="text-yellow-400">{theme.label}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-green-300">{formatDate(currentTime)}</span>
|
||||
<span className="text-green-300">{formatTime(currentTime)}</span>
|
||||
<div className="flex items-center gap-1">
|
||||
<Terminal className="w-3 h-3 text-green-400" />
|
||||
<span className="text-green-400">SYS</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Navigation */}
|
||||
<div className="nav-container" style={{ top: '24px' }}>
|
||||
<div className="nav-inner">
|
||||
<div className="nav-content">
|
||||
<div className="logo-container">
|
||||
|
@ -166,8 +223,12 @@ export function Nav() {
|
|||
</div>
|
||||
|
||||
{showScrollButtons && (
|
||||
<button className="scroll-btn scroll-left" onClick={scrollLeft} aria-label="Scroll left">
|
||||
‹
|
||||
<button
|
||||
className="w-8 h-8 bg-gray-800 border border-green-600 text-green-400 rounded hover:bg-green-900/30 hover:border-green-500 hover:text-green-300 transition-all flex items-center justify-center flex-shrink-0 mx-1"
|
||||
onClick={scrollLeft}
|
||||
aria-label="Scroll left"
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
|
||||
|
@ -182,6 +243,20 @@ export function Nav() {
|
|||
onClick={() => router.push(example.href)}
|
||||
className={`nav-item ${active ? 'active' : ''}`}
|
||||
style={{'--neon-color': example.color} as React.CSSProperties}
|
||||
onMouseEnter={(e) => {
|
||||
e.target.style.boxShadow = `0 0 15px ${example.color}60`;
|
||||
e.target.style.borderColor = example.color;
|
||||
e.target.style.color = example.color;
|
||||
e.target.style.textShadow = `0 0 8px ${example.color}80`;
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
if (!active) {
|
||||
e.target.style.boxShadow = 'none';
|
||||
e.target.style.borderColor = '';
|
||||
e.target.style.color = '';
|
||||
e.target.style.textShadow = 'none';
|
||||
}
|
||||
}}
|
||||
>
|
||||
{example.name}
|
||||
<div className="neon-glow"></div>
|
||||
|
@ -192,8 +267,12 @@ export function Nav() {
|
|||
</div>
|
||||
|
||||
{showScrollButtons && (
|
||||
<button className="scroll-btn scroll-right" onClick={scrollRight} aria-label="Scroll right">
|
||||
›
|
||||
<button
|
||||
className="w-8 h-8 bg-gray-800 border border-green-600 text-green-400 rounded hover:bg-green-900/30 hover:border-green-500 hover:text-green-300 transition-all flex items-center justify-center flex-shrink-0 mx-1"
|
||||
onClick={scrollRight}
|
||||
aria-label="Scroll right"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
|
||||
|
@ -255,8 +334,13 @@ export function Nav() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="nav-spacer"></div>
|
||||
<div className="nav-spacer" style={{ height: '88px' }}></div>
|
||||
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
export default Nav;
|
281
app/footer.tsx
281
app/footer.tsx
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { MessageCircle, Send, X, Minimize2, Maximize2, Monitor, Terminal, Cpu, HardDrive } from 'lucide-react';
|
||||
import { MessageCircle, Send, X, Minimize2, Maximize2, Monitor, Terminal, Cpu, HardDrive, ChevronUp, ChevronDown } from 'lucide-react';
|
||||
import {
|
||||
ResizableHandle,
|
||||
ResizablePanel,
|
||||
|
@ -13,6 +13,8 @@ const Footer = ({ className = "", shortcuts }) => {
|
|||
const [inputValue, setInputValue] = useState('');
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
const [currentTime, setCurrentTime] = useState(new Date());
|
||||
const [isMaximized, setIsMaximized] = useState(false);
|
||||
const [isMinimized, setIsMinimized] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const checkMobile = () => {
|
||||
|
@ -89,6 +91,20 @@ const Footer = ({ className = "", shortcuts }) => {
|
|||
}
|
||||
};
|
||||
|
||||
const toggleMaximize = () => {
|
||||
if (isMinimized) {
|
||||
setIsMinimized(false);
|
||||
}
|
||||
setIsMaximized(!isMaximized);
|
||||
};
|
||||
|
||||
const toggleMinimize = () => {
|
||||
setIsMinimized(!isMinimized);
|
||||
if (isMaximized) {
|
||||
setIsMaximized(false);
|
||||
}
|
||||
};
|
||||
|
||||
const formatTime = (date) => {
|
||||
return date.toLocaleTimeString('en-US', {
|
||||
hour12: false,
|
||||
|
@ -108,34 +124,87 @@ const Footer = ({ className = "", shortcuts }) => {
|
|||
});
|
||||
};
|
||||
|
||||
const getContainerHeight = () => {
|
||||
if (isMinimized) return 'h-4';
|
||||
if (isMaximized) return 'h-screen fixed inset-0 z-50 bg-background';
|
||||
return isMobile ? 'h-64' : 'h-32';
|
||||
};
|
||||
|
||||
const scrollbarStyles = `
|
||||
/* Webkit browsers */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(128, 128, 128, 0.3);
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(128, 128, 128, 0.5);
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(128, 128, 128, 0.3) rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
`;
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<div className={`h-80 bg-background border-t border-border ${className}`}>
|
||||
<ResizablePanelGroup direction="vertical" className="h-full">
|
||||
<ResizablePanel defaultSize={40} minSize={30}>
|
||||
<div className="h-full flex flex-col bg-card border-b border-border">
|
||||
<div className="flex items-center justify-between p-2 bg-muted border-b border-border">
|
||||
<>
|
||||
<style dangerouslySetInnerHTML={{ __html: scrollbarStyles }} />
|
||||
<div className={`${getContainerHeight()} bg-gradient-to-br from-background via-background to-muted/20 border-t border-border shadow-2xl ${className}`}>
|
||||
{isMinimized ? (
|
||||
<div className="h-full flex items-center justify-between px-2 bg-gradient-to-r from-muted/50 to-secondary/50 border-b border-border backdrop-blur-sm cursor-pointer" onClick={toggleMinimize}>
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="w-4 h-4 text-primary" />
|
||||
<span className="text-sm font-mono text-foreground">MOBILE TERMINAL</span>
|
||||
<div className="w-2 h-2 bg-gradient-to-br from-green-400 to-emerald-500 rounded-full animate-pulse shadow-lg" />
|
||||
<span className="text-xs font-mono text-foreground font-medium">TERMINAL</span>
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground font-mono">
|
||||
<div className="text-xs text-muted-foreground font-mono bg-secondary/50 px-1.5 py-0.5 rounded-full">
|
||||
{formatTime(currentTime)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 p-3">
|
||||
<div className="flex items-center gap-2 bg-background border border-input rounded-md">
|
||||
<span className="text-primary text-sm font-mono pl-3">></span>
|
||||
) : (
|
||||
<ResizablePanelGroup direction="vertical" className="h-full">
|
||||
<ResizablePanel defaultSize={40} minSize={30}>
|
||||
<div className="h-full flex flex-col bg-gradient-to-br from-card via-card to-secondary/20 border-b border-border/50 shadow-inner">
|
||||
<div className="flex items-center justify-between p-1.5 bg-gradient-to-r from-muted/80 to-secondary/80 border-b border-border/50 backdrop-blur-sm cursor-pointer" onClick={toggleMaximize}>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1 bg-primary/10 rounded border border-primary/20">
|
||||
<Terminal className="w-3 h-3 text-primary" />
|
||||
</div>
|
||||
<span className="text-xs font-mono text-foreground font-medium">MOBILE TERMINAL</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="text-xs text-muted-foreground font-mono bg-background/50 px-1.5 py-0.5 rounded-full border border-border/50">
|
||||
{formatTime(currentTime)}
|
||||
</div>
|
||||
<div className="w-2 h-2 bg-gradient-to-br from-green-400 to-emerald-500 rounded-full animate-pulse shadow-lg" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 p-2">
|
||||
<div className="flex items-center gap-1 bg-gradient-to-r from-background to-background/80 border border-input/50 rounded shadow-inner backdrop-blur-sm">
|
||||
<span className="text-primary text-xs font-mono pl-2 font-bold">></span>
|
||||
<input
|
||||
placeholder="Enter command..."
|
||||
className="flex-1 bg-transparent text-foreground placeholder:text-muted-foreground border-0 outline-none py-2 pr-3 text-sm font-mono"
|
||||
className="flex-1 bg-transparent text-foreground placeholder:text-muted-foreground border-0 outline-none py-2 pr-2 text-xs font-mono"
|
||||
value={inputValue}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
onKeyPress={handleKeyPress}
|
||||
/>
|
||||
<button
|
||||
onClick={handleSendMessage}
|
||||
className="bg-primary text-primary-foreground hover:bg-primary/90 rounded-r-md px-3 py-2 text-sm font-mono transition-colors flex items-center gap-1"
|
||||
className="bg-gradient-to-r from-primary to-primary/90 text-primary-foreground hover:from-primary/90 hover:to-primary/80 rounded-r px-3 py-2 text-xs font-mono transition-all duration-200 flex items-center gap-1 shadow-lg hover:shadow-xl transform hover:scale-105"
|
||||
>
|
||||
<Send className="w-3 h-3" />
|
||||
</button>
|
||||
|
@ -143,37 +212,38 @@ const Footer = ({ className = "", shortcuts }) => {
|
|||
</div>
|
||||
</div>
|
||||
</ResizablePanel>
|
||||
<ResizableHandle />
|
||||
<ResizableHandle className="bg-gradient-to-r from-border to-primary/20 hover:from-primary/30 hover:to-primary/40 transition-all duration-200" />
|
||||
<ResizablePanel defaultSize={60} minSize={40}>
|
||||
<div className="h-full flex flex-col bg-card">
|
||||
<div className="flex items-center justify-between p-2 bg-muted border-b border-border">
|
||||
<div className="h-full flex flex-col bg-gradient-to-br from-card via-card to-accent/10">
|
||||
<div className="flex items-center justify-between p-1.5 bg-gradient-to-r from-muted/80 to-secondary/80 border-b border-border/50 backdrop-blur-sm cursor-pointer" onClick={toggleMinimize}>
|
||||
<div className="flex items-center gap-2">
|
||||
<Monitor className="w-4 h-4 text-primary" />
|
||||
<span className="text-sm font-mono text-foreground">OUTPUT</span>
|
||||
<div className="p-1 bg-primary/10 rounded border border-primary/20">
|
||||
<Monitor className="w-3 h-3 text-primary" />
|
||||
</div>
|
||||
<span className="text-xs font-mono text-foreground font-medium">OUTPUT</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
|
||||
<span className="text-xs text-muted-foreground font-mono">READY</span>
|
||||
<div className="w-2 h-2 bg-gradient-to-br from-green-400 to-emerald-500 rounded-full animate-pulse shadow-lg" />
|
||||
<span className="text-xs text-muted-foreground font-mono bg-background/50 px-1.5 py-0.5 rounded-full border border-border/50">READY</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 p-3 overflow-y-auto bg-background font-mono text-sm">
|
||||
<div className="flex-1 p-2 overflow-y-auto bg-gradient-to-br from-background/50 to-secondary/20 font-mono text-xs backdrop-blur-sm">
|
||||
{messages.length === 0 ? (
|
||||
<div className="text-muted-foreground text-center py-8">
|
||||
<div className="animate-pulse text-primary">● SYSTEM READY ●</div>
|
||||
<div className="mt-2 text-xs">Awaiting input...</div>
|
||||
<div className="animate-pulse text-primary text-sm font-bold mb-1">● SYSTEM READY ●</div>
|
||||
<div className="mt-1 text-xs bg-secondary/30 px-2 py-0.5 rounded-full inline-block">Awaiting input...</div>
|
||||
</div>
|
||||
) : (
|
||||
messages.map((message, index) => (
|
||||
<div key={index} className="mb-3">
|
||||
<div className="text-xs text-muted-foreground mb-1">
|
||||
<div key={index} className="mb-2 group">
|
||||
<div className="text-xs text-muted-foreground mb-1 bg-secondary/20 px-1.5 py-0.5 rounded-t">
|
||||
[{formatTime(message.timestamp)}] {message.sender.toUpperCase()}:
|
||||
</div>
|
||||
<div className={`p-2 rounded border ${
|
||||
message.sender === 'user'
|
||||
? 'bg-primary/10 border-primary text-foreground'
|
||||
<div className={`p-2 rounded-b rounded-tr shadow-sm transition-all duration-200 group-hover:shadow-md border ${message.sender === 'user'
|
||||
? 'bg-gradient-to-r from-primary/10 to-primary/5 border-primary/30 text-foreground'
|
||||
: message.sender === 'system'
|
||||
? 'bg-accent/50 border-accent text-accent-foreground'
|
||||
: 'bg-secondary/50 border-secondary text-secondary-foreground'
|
||||
? 'bg-gradient-to-r from-accent/50 to-accent/30 border-accent/50 text-accent-foreground'
|
||||
: 'bg-gradient-to-r from-secondary/50 to-secondary/30 border-secondary/50 text-secondary-foreground'
|
||||
}`}>
|
||||
{message.text}
|
||||
</div>
|
||||
|
@ -184,32 +254,74 @@ const Footer = ({ className = "", shortcuts }) => {
|
|||
</div>
|
||||
</ResizablePanel>
|
||||
</ResizablePanelGroup>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`h-48 bg-background border-t border-border ${className}`}>
|
||||
<>
|
||||
<style dangerouslySetInnerHTML={{ __html: scrollbarStyles }} />
|
||||
<div className={`${getContainerHeight()} bg-gradient-to-br from-background via-background to-muted/20 border-t border-border shadow-2xl ${className}`}>
|
||||
{isMinimized ? (
|
||||
<div className="h-full flex items-center justify-between px-3 bg-gradient-to-r from-muted/50 to-secondary/50 border-b border-border backdrop-blur-sm cursor-pointer" onClick={toggleMinimize}>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="w-2 h-2 bg-gradient-to-br from-green-400 to-emerald-500 rounded-full animate-pulse shadow-lg" />
|
||||
<span className="text-xs font-mono text-foreground font-medium">TERMINAL READY</span>
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground font-mono bg-secondary/50 px-1.5 py-0.5 rounded-full">
|
||||
MSG: {messages.length}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground font-mono bg-secondary/50 px-1.5 py-0.5 rounded-full">
|
||||
{formatTime(currentTime)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<ResizablePanelGroup direction="horizontal" className="h-full">
|
||||
<ResizablePanel defaultSize={30} minSize={20} maxSize={50}>
|
||||
<div className="h-full flex flex-col bg-card">
|
||||
<div className="flex items-center justify-between px-3 py-1 bg-muted border-b border-border">
|
||||
<div className="h-full flex flex-col bg-gradient-to-br from-card via-card to-secondary/20 shadow-inner">
|
||||
<div className="flex items-center justify-between px-3 py-1 bg-gradient-to-r from-muted/80 to-secondary/80 border-b border-border/50 backdrop-blur-sm cursor-pointer" onClick={toggleMaximize}>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-0.5 bg-primary/10 rounded border border-primary/20">
|
||||
<Cpu className="w-3 h-3 text-primary" />
|
||||
<span className="text-xs font-mono text-foreground">SYSTEM v3.0</span>
|
||||
</div>
|
||||
<span className="text-xs font-mono text-foreground font-medium">STATUS</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<HardDrive className="w-3 h-3 text-muted-foreground" />
|
||||
<span className="text-xs font-mono text-muted-foreground">{formatTime(currentTime)}</span>
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
|
||||
<div className="flex items-center gap-1 text-xs font-mono text-muted-foreground">
|
||||
<span className="inline-flex items-center gap-0.5">
|
||||
<span className="relative w-1.5 h-1.5 rounded-sm bg-gradient-to-br from-yellow-400 to-orange-500 border border-yellow-600 inline-block shadow-sm">
|
||||
<span className="absolute -top-0.5 -right-0.5 w-1.5 h-1.5 rounded-full bg-primary animate-pulse border border-background shadow-md" />
|
||||
</span>
|
||||
<span className="text-xs">Inbox</span>
|
||||
</span>
|
||||
<span className="mx-0.5 text-border">|</span>
|
||||
<span className="inline-flex items-center gap-0.5">
|
||||
<span className="w-1.5 h-1.5 rounded-sm bg-gradient-to-br from-green-400 to-emerald-500 border border-green-600 inline-block shadow-sm" />
|
||||
<span className="text-xs">Tasks</span>
|
||||
</span>
|
||||
<span className="mx-0.5 text-border">|</span>
|
||||
<span className="inline-flex items-center gap-0.5">
|
||||
<span className="w-1.5 h-1.5 rounded-sm bg-gradient-to-br from-red-400 to-rose-500 border border-red-600 inline-block shadow-sm" />
|
||||
<span className="text-xs">Meet</span>
|
||||
</span>
|
||||
<span className="mx-0.5 text-border">|</span>
|
||||
<span className="inline-flex items-center gap-0.5">
|
||||
<span className="w-1.5 h-1.5 rounded-sm bg-gradient-to-br from-blue-400 to-cyan-500 border border-blue-600 inline-block shadow-sm" />
|
||||
<span className="text-xs">Chat</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 flex items-center px-2 border-b border-border bg-secondary/20">
|
||||
<div className="flex items-center gap-1 overflow-x-auto w-full pb-1">
|
||||
</div>
|
||||
<div className="flex-1 flex items-center px-2 py-0.5 border-b border-border/50 bg-gradient-to-r from-secondary/20 to-accent/10">
|
||||
<div className="flex items-center gap-0.5 overflow-x-auto w-full">
|
||||
{shortcutGroups[0].map((shortcut, index) => (
|
||||
<button
|
||||
key={index}
|
||||
className="flex items-center text-xs cursor-pointer hover:bg-accent hover:text-accent-foreground px-2 py-1 rounded transition-colors min-w-fit border border-border hover:border-primary bg-background"
|
||||
className="flex items-center text-xs cursor-pointer hover:bg-gradient-to-r hover:from-accent/50 hover:to-primary/20 hover:text-accent-foreground px-1.5 py-1 rounded transition-all duration-200 min-w-fit border border-border/50 hover:border-primary/50 bg-gradient-to-r from-background/80 to-background/60 backdrop-blur-sm shadow-sm hover:shadow-md transform hover:scale-105"
|
||||
onClick={shortcut.action}
|
||||
>
|
||||
<span className="font-bold text-primary mr-1">{formatShortcutKey(shortcut.key)}</span>
|
||||
|
@ -218,12 +330,12 @@ const Footer = ({ className = "", shortcuts }) => {
|
|||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 flex items-center px-2 bg-secondary/20">
|
||||
<div className="flex items-center gap-1 overflow-x-auto w-full pb-1">
|
||||
<div className="flex-1 flex items-center px-2 py-0.5 bg-gradient-to-r from-secondary/20 to-accent/10">
|
||||
<div className="flex items-center gap-0.5 overflow-x-auto w-full">
|
||||
{shortcutGroups[1].map((shortcut, index) => (
|
||||
<button
|
||||
key={index}
|
||||
className="flex items-center text-xs cursor-pointer hover:bg-accent hover:text-accent-foreground px-2 py-1 rounded transition-colors min-w-fit border border-border hover:border-primary bg-background"
|
||||
className="flex items-center text-xs cursor-pointer hover:bg-gradient-to-r hover:from-accent/50 hover:to-primary/20 hover:text-accent-foreground px-1.5 py-1 rounded transition-all duration-200 min-w-fit border border-border/50 hover:border-primary/50 bg-gradient-to-r from-background/80 to-background/60 backdrop-blur-sm shadow-sm hover:shadow-md transform hover:scale-105"
|
||||
onClick={shortcut.action}
|
||||
>
|
||||
<span className="font-bold text-primary mr-1">{formatShortcutKey(shortcut.key)}</span>
|
||||
|
@ -234,29 +346,31 @@ const Footer = ({ className = "", shortcuts }) => {
|
|||
</div>
|
||||
</div>
|
||||
</ResizablePanel>
|
||||
<ResizableHandle />
|
||||
<ResizableHandle className="bg-gradient-to-b from-border to-primary/20 hover:from-primary/30 hover:to-primary/40 transition-all duration-200" />
|
||||
<ResizablePanel defaultSize={30} minSize={20} maxSize={50}>
|
||||
<div className="h-full flex flex-col bg-card border-r border-border">
|
||||
<div className="flex items-center justify-between p-2 bg-muted border-b border-border">
|
||||
<div className="h-full flex flex-col bg-gradient-to-br from-card via-card to-secondary/20 border-r border-border/50 shadow-inner">
|
||||
<div className="flex items-center justify-between px-3 py-1 bg-gradient-to-r from-muted/80 to-secondary/80 border-b border-border/50 backdrop-blur-sm cursor-pointer" onClick={toggleMinimize}>
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="w-4 h-4 text-primary" />
|
||||
<span className="text-sm font-mono text-foreground">INPUT</span>
|
||||
<div className="p-0.5 bg-primary/10 rounded border border-primary/20">
|
||||
<Terminal className="w-3 h-3 text-primary" />
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground font-mono">
|
||||
<span className="text-xs font-mono text-foreground font-medium">INPUT</span>
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground font-mono bg-background/50 px-1.5 py-0.5 rounded-full border border-border/50">
|
||||
CMD
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 p-3 bg-background">
|
||||
<div className="flex-1 p-2 bg-gradient-to-br from-background/50 to-secondary/20 backdrop-blur-sm">
|
||||
<div className="h-full flex flex-col">
|
||||
<div className="text-xs text-muted-foreground mb-2 font-mono">
|
||||
<div className="text-xs text-muted-foreground mb-2 font-mono bg-secondary/20 px-1.5 py-0.5 rounded">
|
||||
COMMAND LINE INTERFACE
|
||||
</div>
|
||||
<div className="flex-1 bg-card border border-input rounded-md p-3 font-mono text-sm">
|
||||
<div className="flex items-start gap-2">
|
||||
<span className="text-primary">></span>
|
||||
<div className="flex-1 bg-gradient-to-br from-card to-card/80 border border-input/50 rounded p-2 font-mono text-xs shadow-inner backdrop-blur-sm">
|
||||
<div className="flex items-start gap-1">
|
||||
<span className="text-primary font-bold">></span>
|
||||
<textarea
|
||||
placeholder="Enter your command or query here..."
|
||||
className="flex-1 bg-transparent text-foreground placeholder:text-muted-foreground border-0 outline-none resize-none min-h-20"
|
||||
className="flex-1 bg-transparent text-foreground placeholder:text-muted-foreground border-0 outline-none resize-none min-h-12"
|
||||
value={inputValue}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
onKeyPress={(e) => {
|
||||
|
@ -269,14 +383,14 @@ const Footer = ({ className = "", shortcuts }) => {
|
|||
</div>
|
||||
</div>
|
||||
<div className="mt-2 flex justify-between items-center">
|
||||
<div className="text-xs text-muted-foreground font-mono">
|
||||
<div className="text-xs text-muted-foreground font-mono bg-secondary/20 px-1.5 py-0.5 rounded">
|
||||
Enter to send • Shift+Enter for new line
|
||||
</div>
|
||||
<button
|
||||
onClick={handleSendMessage}
|
||||
className="bg-primary text-primary-foreground hover:bg-primary/90 rounded px-3 py-1 text-xs font-mono transition-colors flex items-center gap-1"
|
||||
className="bg-gradient-to-r from-primary to-primary/90 text-primary-foreground hover:from-primary/90 hover:to-primary/80 rounded px-3 py-1 text-xs font-mono transition-all duration-200 flex items-center gap-1 shadow-lg hover:shadow-xl transform hover:scale-105"
|
||||
>
|
||||
<Send className="w-3 h-3" />
|
||||
<Send className="w-2.5 h-2.5" />
|
||||
SEND
|
||||
</button>
|
||||
</div>
|
||||
|
@ -284,46 +398,47 @@ const Footer = ({ className = "", shortcuts }) => {
|
|||
</div>
|
||||
</div>
|
||||
</ResizablePanel>
|
||||
<ResizableHandle />
|
||||
<ResizableHandle className="bg-gradient-to-b from-border to-primary/20 hover:from-primary/30 hover:to-primary/40 transition-all duration-200" />
|
||||
<ResizablePanel defaultSize={40} minSize={25}>
|
||||
<div className="h-full flex flex-col bg-card">
|
||||
<div className="flex items-center justify-between p-2 bg-muted border-b border-border">
|
||||
<div className="h-full flex flex-col bg-gradient-to-br from-card via-card to-accent/10 shadow-inner">
|
||||
<div className="flex items-center justify-between px-3 py-1 bg-gradient-to-r from-muted/80 to-secondary/80 border-b border-border/50 backdrop-blur-sm cursor-pointer" onClick={toggleMaximize}>
|
||||
<div className="flex items-center gap-2">
|
||||
<Monitor className="w-4 h-4 text-primary" />
|
||||
<span className="text-sm font-mono text-foreground">OUTPUT</span>
|
||||
<div className="p-0.5 bg-primary/10 rounded border border-primary/20">
|
||||
<Monitor className="w-3 h-3 text-primary" />
|
||||
</div>
|
||||
<span className="text-xs font-mono text-foreground font-medium">OUTPUT</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs text-muted-foreground font-mono">
|
||||
<span className="text-xs text-muted-foreground font-mono bg-background/50 px-1.5 py-0.5 rounded-full border border-border/50">
|
||||
MSG: {messages.length}
|
||||
</span>
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
|
||||
<div className="w-2 h-2 bg-gradient-to-br from-green-400 to-emerald-500 rounded-full animate-pulse shadow-lg" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 p-3 overflow-y-auto bg-background font-mono text-sm">
|
||||
<div className="flex-1 p-2 overflow-y-auto bg-gradient-to-br from-background/50 to-secondary/20 font-mono text-xs backdrop-blur-sm">
|
||||
{messages.length === 0 ? (
|
||||
<div className="text-muted-foreground text-center py-8">
|
||||
<div className="animate-pulse text-primary text-lg">● SYSTEM READY ●</div>
|
||||
<div className="mt-2 text-xs">
|
||||
<div>Waiting for input...</div>
|
||||
<div className="mt-1 text-muted-foreground/70">
|
||||
<div className="animate-pulse text-primary text-sm font-bold mb-2">● SYSTEM READY ●</div>
|
||||
<div className="mt-1 text-xs space-y-1">
|
||||
<div className="bg-secondary/30 px-2 py-0.5 rounded-full inline-block">Waiting for input...</div>
|
||||
<div className="text-muted-foreground/70 bg-secondary/20 px-2 py-0.5 rounded-full inline-block">
|
||||
Use F-keys or Ctrl commands
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-2">
|
||||
{messages.map((message, index) => (
|
||||
<div key={index} className="group">
|
||||
<div className="text-xs text-muted-foreground mb-1 flex justify-between">
|
||||
<div className="text-xs text-muted-foreground mb-1 flex justify-between bg-secondary/20 px-1.5 py-0.5 rounded-t">
|
||||
<span>[{formatTime(message.timestamp)}] {message.sender.toUpperCase()}:</span>
|
||||
<span>#{index + 1}</span>
|
||||
<span className="bg-primary/20 px-1 py-0.5 rounded-full text-primary">#{index + 1}</span>
|
||||
</div>
|
||||
<div className={`p-3 rounded border transition-all group-hover:shadow-sm ${
|
||||
message.sender === 'user'
|
||||
? 'bg-primary/10 border-primary text-foreground'
|
||||
<div className={`p-2 rounded-b rounded-tr shadow-sm transition-all duration-200 group-hover:shadow-lg border backdrop-blur-sm ${message.sender === 'user'
|
||||
? 'bg-gradient-to-r from-primary/10 to-primary/5 border-primary/30 text-foreground'
|
||||
: message.sender === 'system'
|
||||
? 'bg-accent/50 border-accent text-accent-foreground'
|
||||
: 'bg-secondary/50 border-secondary text-secondary-foreground'
|
||||
? 'bg-gradient-to-r from-accent/50 to-accent/30 border-accent/50 text-accent-foreground'
|
||||
: 'bg-gradient-to-r from-secondary/50 to-secondary/30 border-secondary/50 text-secondary-foreground'
|
||||
}`}>
|
||||
<div className="whitespace-pre-wrap break-words">
|
||||
{message.text}
|
||||
|
@ -334,21 +449,23 @@ const Footer = ({ className = "", shortcuts }) => {
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center justify-between px-3 py-1 bg-muted border-t border-border">
|
||||
<div className="flex items-center justify-between px-3 py-1 bg-gradient-to-r from-muted/50 to-secondary/50 border-t border-border/50 backdrop-blur-sm">
|
||||
<div className="text-xs text-muted-foreground font-mono">
|
||||
Ready for input
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="text-xs text-muted-foreground font-mono">
|
||||
<div className="text-xs text-muted-foreground font-mono bg-background/50 px-1.5 py-0.5 rounded-full border border-border/50">
|
||||
SCROLL: {messages.length > 10 ? 'AUTO' : 'MANUAL'}
|
||||
</div>
|
||||
<div className="w-1 h-1 bg-primary rounded-full animate-pulse" />
|
||||
<div className="w-1 h-1 bg-gradient-to-br from-primary to-primary/70 rounded-full animate-pulse shadow-sm" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ResizablePanel>
|
||||
</ResizablePanelGroup>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
import { Nav } from './client-nav';
|
||||
import { ReactNode } from 'react';
|
||||
import { ThemeProvider } from './theme-provider';
|
||||
import Nav from './client-nav';
|
||||
|
||||
export default function RootLayout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
Pages
|
||||
=====
|
||||
|
||||
|
||||
|
||||
Should work on mobile also
|
||||
|
||||
|
||||
|
||||
Use themes variables
|
||||
--------------------
|
||||
|
|
|
@ -698,10 +698,18 @@ body {
|
|||
left: -3rem;
|
||||
}
|
||||
|
||||
.-right-1 {
|
||||
right: -0.25rem;
|
||||
}
|
||||
|
||||
.-right-12 {
|
||||
right: -3rem;
|
||||
}
|
||||
|
||||
.-top-1 {
|
||||
top: -0.25rem;
|
||||
}
|
||||
|
||||
.-top-12 {
|
||||
top: -3rem;
|
||||
}
|
||||
|
@ -1017,6 +1025,10 @@ body {
|
|||
display: block;
|
||||
}
|
||||
|
||||
.inline-block {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
@ -1117,6 +1129,10 @@ body {
|
|||
height: 2rem;
|
||||
}
|
||||
|
||||
.h-80 {
|
||||
height: 20rem;
|
||||
}
|
||||
|
||||
.h-9 {
|
||||
height: 2.25rem;
|
||||
}
|
||||
|
@ -1329,6 +1345,10 @@ body {
|
|||
width: 200px;
|
||||
}
|
||||
|
||||
.w-\[280px\] {
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.w-\[40\%\] {
|
||||
width: 40%;
|
||||
}
|
||||
|
@ -1817,6 +1837,11 @@ body {
|
|||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.rounded-r-md {
|
||||
border-top-right-radius: calc(var(--radius) - 2px);
|
||||
border-bottom-right-radius: calc(var(--radius) - 2px);
|
||||
}
|
||||
|
||||
.rounded-t-\[10px\] {
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
|
@ -1883,6 +1908,14 @@ body {
|
|||
border-color: var(--color-border);
|
||||
}
|
||||
|
||||
.border-accent {
|
||||
border-color: hsl(var(--accent));
|
||||
}
|
||||
|
||||
.border-background {
|
||||
border-color: hsl(var(--background));
|
||||
}
|
||||
|
||||
.border-blue-100 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(219 234 254 / var(--tw-border-opacity));
|
||||
|
@ -1933,6 +1966,11 @@ body {
|
|||
border-color: rgb(34 197 94 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-green-600 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(22 163 74 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-input {
|
||||
border-color: hsl(var(--input));
|
||||
}
|
||||
|
@ -1959,6 +1997,15 @@ body {
|
|||
border-color: rgb(239 68 68 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-red-600 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(220 38 38 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-secondary {
|
||||
border-color: hsl(var(--secondary));
|
||||
}
|
||||
|
||||
.border-sidebar-border {
|
||||
border-color: hsl(var(--sidebar-border));
|
||||
}
|
||||
|
@ -1967,6 +2014,11 @@ body {
|
|||
border-color: transparent;
|
||||
}
|
||||
|
||||
.border-yellow-600 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(202 138 4 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-l-blue-500 {
|
||||
--tw-border-opacity: 1;
|
||||
border-left-color: rgb(59 130 246 / var(--tw-border-opacity));
|
||||
|
@ -2007,6 +2059,10 @@ body {
|
|||
background-color: hsl(var(--accent));
|
||||
}
|
||||
|
||||
.bg-accent\/50 {
|
||||
background-color: hsl(var(--accent) / 0.5);
|
||||
}
|
||||
|
||||
.bg-background {
|
||||
background-color: hsl(var(--background));
|
||||
}
|
||||
|
@ -2093,6 +2149,11 @@ body {
|
|||
background-color: rgb(107 114 128 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gray-800 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gray-900 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
|
||||
|
@ -2103,6 +2164,11 @@ body {
|
|||
background-color: rgb(220 252 231 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-green-400 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(74 222 128 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-green-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(34 197 94 / var(--tw-bg-opacity));
|
||||
|
@ -2124,10 +2190,6 @@ body {
|
|||
background-color: hsl(var(--muted-foreground));
|
||||
}
|
||||
|
||||
.bg-muted\/30 {
|
||||
background-color: hsl(var(--muted) / 0.3);
|
||||
}
|
||||
|
||||
.bg-muted\/50 {
|
||||
background-color: hsl(var(--muted) / 0.5);
|
||||
}
|
||||
|
@ -2167,6 +2229,11 @@ body {
|
|||
background-color: rgb(168 85 247 / 0.2);
|
||||
}
|
||||
|
||||
.bg-red-400 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(248 113 113 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
|
@ -2180,6 +2247,14 @@ body {
|
|||
background-color: hsl(var(--secondary));
|
||||
}
|
||||
|
||||
.bg-secondary\/20 {
|
||||
background-color: hsl(var(--secondary) / 0.2);
|
||||
}
|
||||
|
||||
.bg-secondary\/50 {
|
||||
background-color: hsl(var(--secondary) / 0.5);
|
||||
}
|
||||
|
||||
.bg-sidebar {
|
||||
background-color: hsl(var(--sidebar-background));
|
||||
}
|
||||
|
@ -2202,6 +2277,11 @@ body {
|
|||
background-color: rgb(254 249 195 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-yellow-400 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(250 204 21 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gradient-to-br {
|
||||
background-image: linear-gradient(to bottom right, var(--tw-gradient-stops));
|
||||
}
|
||||
|
@ -2387,6 +2467,10 @@ body {
|
|||
padding-bottom: 2rem;
|
||||
}
|
||||
|
||||
.pb-1 {
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.pb-3 {
|
||||
padding-bottom: 0.75rem;
|
||||
}
|
||||
|
@ -2407,6 +2491,10 @@ body {
|
|||
padding-left: 0.625rem;
|
||||
}
|
||||
|
||||
.pl-3 {
|
||||
padding-left: 0.75rem;
|
||||
}
|
||||
|
||||
.pl-4 {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
@ -2431,6 +2519,10 @@ body {
|
|||
padding-right: 0.625rem;
|
||||
}
|
||||
|
||||
.pr-3 {
|
||||
padding-right: 0.75rem;
|
||||
}
|
||||
|
||||
.pr-4 {
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
@ -2621,6 +2713,16 @@ body {
|
|||
color: rgb(31 41 55 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-green-300 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(134 239 172 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-green-400 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(74 222 128 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-green-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(34 197 94 / var(--tw-text-opacity));
|
||||
|
@ -2645,6 +2747,10 @@ body {
|
|||
color: hsl(var(--muted-foreground));
|
||||
}
|
||||
|
||||
.text-muted-foreground\/70 {
|
||||
color: hsl(var(--muted-foreground) / 0.7);
|
||||
}
|
||||
|
||||
.text-pink-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(236 72 153 / var(--tw-text-opacity));
|
||||
|
@ -2708,6 +2814,11 @@ body {
|
|||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-yellow-400 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(250 204 21 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-yellow-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(234 179 8 / var(--tw-text-opacity));
|
||||
|
@ -3102,6 +3213,15 @@ body {
|
|||
border-color: hsl(var(--accent));
|
||||
}
|
||||
|
||||
.hover\:border-green-500:hover {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(34 197 94 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.hover\:border-primary:hover {
|
||||
border-color: hsl(var(--primary));
|
||||
}
|
||||
|
||||
.hover\:bg-accent:hover {
|
||||
background-color: hsl(var(--accent));
|
||||
}
|
||||
|
@ -3110,10 +3230,6 @@ body {
|
|||
background-color: hsl(var(--accent) / 0.1);
|
||||
}
|
||||
|
||||
.hover\:bg-accent\/50:hover {
|
||||
background-color: hsl(var(--accent) / 0.5);
|
||||
}
|
||||
|
||||
.hover\:bg-blue-600:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
|
||||
|
@ -3151,6 +3267,10 @@ body {
|
|||
background-color: rgb(21 128 61 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-green-900\/30:hover {
|
||||
background-color: rgb(20 83 45 / 0.3);
|
||||
}
|
||||
|
||||
.hover\:bg-muted:hover {
|
||||
background-color: hsl(var(--muted));
|
||||
}
|
||||
|
@ -3191,6 +3311,11 @@ body {
|
|||
color: hsl(var(--foreground));
|
||||
}
|
||||
|
||||
.hover\:text-green-300:hover {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(134 239 172 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.hover\:text-muted-foreground:hover {
|
||||
color: hsl(var(--muted-foreground));
|
||||
}
|
||||
|
@ -3385,6 +3510,12 @@ body {
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
.group:hover .group-hover\:shadow-sm {
|
||||
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.group[data-collapsed=true] .group-\[\[data-collapsed\=true\]\]\:justify-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
@ -3608,6 +3739,10 @@ body {
|
|||
background-color: hsl(var(--accent));
|
||||
}
|
||||
|
||||
.data-\[state\=active\]\:bg-accent[data-state=active] {
|
||||
background-color: hsl(var(--accent));
|
||||
}
|
||||
|
||||
.data-\[state\=active\]\:bg-background[data-state=active] {
|
||||
background-color: hsl(var(--background));
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue