Enhance VibeTunnel web interface with modern visual design

- Implement modern color scheme with cyan/teal primary colors
- Redesign sidebar with card-based sessions and enhanced status indicators
- Create unified header design with gradient backgrounds
- Add JetBrains Mono font and improve typography throughout
- Implement smooth micro-interactions and animations
- Enhance terminal area with better focus states and loading overlays
- Update all buttons and inputs with consistent hover/focus effects
This commit is contained in:
Peter Steinberger 2025-07-01 15:17:50 +01:00
parent 9e862f96d5
commit a09563ec62
6 changed files with 360 additions and 111 deletions

View file

@ -365,6 +365,9 @@ export class SessionCard extends LitElement {
}
private getStatusColor(): string {
if (this.killing) {
return 'text-status-error';
}
if (this.session.active === false) {
return 'text-dark-text-muted';
}
@ -372,6 +375,9 @@ export class SessionCard extends LitElement {
}
private getStatusDotColor(): string {
if (this.killing) {
return 'bg-status-error animate-pulse';
}
if (this.session.active === false) {
return 'bg-dark-text-muted';
}

View file

@ -237,45 +237,57 @@ export class SessionList extends LitElement {
${
this.compactMode
? html`
<!-- Compact list item for sidebar -->
<!-- Enhanced compact list item for sidebar -->
<div
class="group flex items-center gap-3 p-3 rounded-md cursor-pointer transition-all hover:bg-dark-bg-tertiary hover:shadow-md ${
class="group flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all duration-200 animate-fade-in ${
session.id === this.selectedSessionId
? 'bg-dark-bg-tertiary border border-accent-green shadow-sm'
: 'border border-transparent hover:border-dark-border'
? 'bg-dark-bg-elevated border border-accent-primary shadow-card-hover'
: 'bg-dark-bg-secondary border border-dark-border hover:bg-dark-bg-tertiary hover:border-dark-border-light hover:shadow-card'
}"
@click=${() =>
this.handleSessionSelect({ detail: session } as CustomEvent)}
>
<!-- Activity indicator on the left -->
<div
class="w-2 h-2 rounded-full flex-shrink-0 ${
session.status === 'running'
? session.activityStatus?.specificStatus
? 'bg-status-warning' // Claude active - orange, no pulse
: session.activityStatus?.isActive
? 'bg-status-success' // Generic active
: 'bg-status-success ring-1 ring-status-success' // Idle (outline)
: 'bg-status-warning'
}"
title="${
session.status === 'running' && session.activityStatus
? session.activityStatus.specificStatus
? `Active: ${session.activityStatus.specificStatus.app}`
: session.activityStatus.isActive
? 'Active'
: 'Idle'
: session.status
}"
></div>
<!-- Enhanced activity indicator with pulse animation -->
<div class="relative flex-shrink-0">
<div
class="w-2.5 h-2.5 rounded-full ${
session.status === 'running'
? session.activityStatus?.specificStatus
? 'bg-status-warning animate-pulse-primary' // Claude active - amber with pulse
: session.activityStatus?.isActive
? 'bg-status-success' // Generic active
: 'bg-status-success ring-1 ring-status-success ring-opacity-50' // Idle (subtle outline)
: 'bg-status-error'
}"
title="${
session.status === 'running' && session.activityStatus
? session.activityStatus.specificStatus
? `Active: ${session.activityStatus.specificStatus.app}`
: session.activityStatus.isActive
? 'Active'
: 'Idle'
: session.status
}"
></div>
<!-- Pulse ring for active sessions -->
${
session.status === 'running' && session.activityStatus?.isActive
? html`<div class="absolute inset-0 w-2.5 h-2.5 rounded-full bg-status-success opacity-30 animate-ping"></div>`
: ''
}
</div>
<!-- Divider line -->
<div class="w-px h-8 bg-dark-border"></div>
<!-- Elegant divider line -->
<div class="w-px h-8 bg-gradient-to-b from-transparent via-dark-border to-transparent"></div>
<!-- Session content -->
<div class="flex-1 min-w-0">
<div
class="text-sm font-mono text-accent-green truncate"
class="text-sm font-mono truncate ${
session.id === this.selectedSessionId
? 'text-accent-primary font-medium'
: 'text-dark-text group-hover:text-accent-primary transition-colors'
}"
title="${
session.name ||
(Array.isArray(session.command)
@ -332,11 +344,11 @@ export class SessionList extends LitElement {
session.status === 'running' || session.status === 'exited'
? html`
<button
class="btn-ghost text-status-error p-1 rounded transition-opacity absolute right-0 ${
class="btn-ghost text-status-error p-1.5 rounded-md transition-all absolute right-0 ${
'ontouchstart' in window
? 'opacity-100 static ml-2'
: 'opacity-0 group-hover:opacity-100'
} hover:bg-dark-bg hover:shadow-sm"
} hover:bg-dark-bg-elevated hover:shadow-sm hover:scale-110"
@click=${async (e: Event) => {
e.stopPropagation();
// Kill the session

View file

@ -1064,30 +1064,30 @@ export class SessionView extends LitElement {
}}
></session-header>
<!-- Terminal Container -->
<!-- Enhanced Terminal Container -->
<div
class="${this.terminalContainerHeight === '100%' ? 'flex-1' : ''} bg-black overflow-hidden min-h-0 relative ${
this.session?.status === 'exited' ? 'session-exited' : ''
class="${this.terminalContainerHeight === '100%' ? 'flex-1' : ''} bg-black overflow-hidden min-h-0 relative border-t border-dark-border shadow-inner ${
this.session?.status === 'exited' ? 'session-exited opacity-90' : ''
}"
id="terminal-container"
style="${this.terminalContainerHeight !== '100%' ? `height: ${this.terminalContainerHeight}; flex: none; max-height: ${this.terminalContainerHeight};` : ''} transition: height 0.3s ease-out;"
style="${this.terminalContainerHeight !== '100%' ? `height: ${this.terminalContainerHeight}; flex: none; max-height: ${this.terminalContainerHeight};` : ''} transition: all 0.3s ease-out;"
>
${
this.loadingAnimationManager.isLoading()
? html`
<!-- Loading overlay -->
<!-- Enhanced Loading overlay -->
<div
class="absolute inset-0 bg-dark-bg bg-opacity-80 flex items-center justify-center z-10"
class="absolute inset-0 bg-dark-bg bg-opacity-90 backdrop-filter backdrop-blur-sm flex items-center justify-center z-10 animate-fade-in"
>
<div class="text-dark-text font-mono text-center">
<div class="text-2xl mb-2">${this.loadingAnimationManager.getLoadingText()}</div>
<div class="text-2xl mb-3 text-accent-primary animate-pulse-primary">${this.loadingAnimationManager.getLoadingText()}</div>
<div class="text-sm text-dark-text-muted">Connecting to session...</div>
</div>
</div>
`
: ''
}
<!-- Terminal Component -->
<!-- Enhanced Terminal Component -->
<vibe-terminal
.sessionId=${this.session?.id || ''}
.sessionStatus=${this.session?.status || 'running'}
@ -1100,7 +1100,7 @@ export class SessionView extends LitElement {
.initialRows=${this.session?.initialRows || 0}
.disableClick=${this.isMobile && this.useDirectKeyboard}
.hideScrollButton=${this.showQuickKeys}
class="w-full h-full p-0 m-0"
class="w-full h-full p-0 m-0 terminal-container"
@click=${this.handleTerminalClick}
@terminal-input=${this.handleTerminalInput}
></vibe-terminal>
@ -1114,9 +1114,12 @@ export class SessionView extends LitElement {
class="fixed inset-0 flex items-center justify-center pointer-events-none z-[25]"
>
<div
class="bg-dark-bg-secondary border border-dark-border text-status-warning font-medium text-sm tracking-wide px-4 py-2 rounded-lg shadow-lg"
class="bg-dark-bg-elevated border border-status-warning text-status-warning font-medium text-sm tracking-wide px-6 py-3 rounded-lg shadow-elevated animate-scale-in"
>
SESSION EXITED
<span class="flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-status-warning"></span>
SESSION EXITED
</span>
</div>
</div>
`

View file

@ -75,10 +75,10 @@ export class SessionHeader extends LitElement {
if (!this.session) return null;
return html`
<!-- Compact Header -->
<!-- Enhanced Header with gradient background -->
<div
class="flex items-center justify-between border-b border-dark-border text-sm min-w-0 bg-dark-bg-secondary p-3"
style="padding-top: max(0.75rem, calc(0.75rem + env(safe-area-inset-top))); padding-left: max(0.75rem, env(safe-area-inset-left)); padding-right: max(0.75rem, env(safe-area-inset-right));"
class="flex items-center justify-between border-b border-dark-border text-sm min-w-0 bg-gradient-to-r from-dark-bg-secondary to-dark-bg-tertiary p-4 shadow-sm"
style="padding-top: max(1rem, calc(1rem + env(safe-area-inset-top))); padding-left: max(1rem, env(safe-area-inset-left)); padding-right: max(1rem, env(safe-area-inset-right));"
>
<div class="flex items-center gap-3 min-w-0 flex-1">
<!-- Sidebar Toggle and Create Session Buttons (shown when sidebar is collapsed) -->
@ -87,7 +87,7 @@ export class SessionHeader extends LitElement {
? html`
<div class="flex items-center gap-2">
<button
class="bg-dark-bg-tertiary border border-dark-border rounded-lg p-1.5 font-mono text-dark-text-muted transition-all duration-300 hover:text-dark-text hover:bg-dark-bg hover:border-accent-green flex-shrink-0"
class="bg-dark-bg-elevated border border-dark-border rounded-lg p-2 font-mono text-dark-text-muted transition-all duration-200 hover:text-accent-primary hover:bg-dark-surface-hover hover:border-accent-primary hover:shadow-sm flex-shrink-0"
@click=${() => this.onSidebarToggle?.()}
title="Show sidebar (⌘B)"
aria-label="Show sidebar"
@ -100,9 +100,9 @@ export class SessionHeader extends LitElement {
</svg>
</button>
<!-- Create Session button -->
<!-- Create Session button with primary color -->
<button
class="bg-dark-bg-tertiary border border-accent-green text-accent-green rounded-lg p-1.5 font-mono transition-all duration-300 hover:bg-accent-green hover:text-dark-bg flex-shrink-0"
class="bg-accent-primary bg-opacity-10 border border-accent-primary text-accent-primary rounded-lg p-2 font-mono transition-all duration-200 hover:bg-accent-primary hover:text-dark-bg hover:shadow-glow-primary-sm flex-shrink-0"
@click=${() => this.onCreateSession?.()}
title="Create New Session (⌘K)"
>
@ -128,7 +128,7 @@ export class SessionHeader extends LitElement {
}
<div class="text-dark-text min-w-0 flex-1 overflow-hidden max-w-[50vw] sm:max-w-none">
<div
class="text-accent-green text-xs sm:text-sm overflow-hidden text-ellipsis whitespace-nowrap"
class="text-dark-text-bright font-medium text-xs sm:text-sm overflow-hidden text-ellipsis whitespace-nowrap"
title="${
this.session.name ||
(Array.isArray(this.session.command)
@ -153,7 +153,7 @@ export class SessionHeader extends LitElement {
</div>
<div class="flex items-center gap-2 text-xs flex-shrink-0 ml-2 relative">
<button
class="btn-secondary font-mono text-xs p-1 flex-shrink-0"
class="bg-dark-bg-elevated border border-dark-border rounded-lg p-2 font-mono text-dark-text-muted transition-all duration-200 hover:text-accent-primary hover:bg-dark-surface-hover hover:border-accent-primary hover:shadow-sm flex-shrink-0"
@click=${() => this.onOpenFileBrowser?.()}
title="Browse Files (⌘O)"
>
@ -164,7 +164,7 @@ export class SessionHeader extends LitElement {
</svg>
</button>
<button
class="btn-secondary font-mono text-xs p-1 flex-shrink-0"
class="bg-dark-bg-elevated border border-dark-border rounded-lg p-2 font-mono text-dark-text-muted transition-all duration-200 hover:text-accent-primary hover:bg-dark-surface-hover hover:border-accent-primary hover:shadow-sm flex-shrink-0"
@click=${() => this.onOpenImagePicker?.()}
title="Upload File"
>
@ -174,7 +174,7 @@ export class SessionHeader extends LitElement {
</svg>
</button>
<button
class="btn-secondary font-mono text-xs px-2 py-1 flex-shrink-0 width-selector-button"
class="bg-dark-bg-elevated border border-dark-border rounded-lg px-3 py-2 font-mono text-xs text-dark-text-muted transition-all duration-200 hover:text-accent-primary hover:bg-dark-surface-hover hover:border-accent-primary hover:shadow-sm flex-shrink-0 width-selector-button"
@click=${() => this.onMaxWidthToggle?.()}
title="${this.widthTooltip}"
>
@ -190,8 +190,17 @@ export class SessionHeader extends LitElement {
.onClose=${() => this.handleCloseWidthSelector()}
></width-selector>
<div class="flex flex-col items-end gap-0">
<span class="${this.getStatusColor()} text-xs flex items-center gap-1">
<div class="w-2 h-2 rounded-full ${this.getStatusDotColor()}"></div>
<span class="text-xs flex items-center gap-2 font-medium ${
this.getStatusText() === 'running' ? 'text-status-success' : 'text-status-warning'
}">
<div class="relative">
<div class="w-2.5 h-2.5 rounded-full ${this.getStatusDotColor()}"></div>
${
this.getStatusText() === 'running'
? html`<div class="absolute inset-0 w-2.5 h-2.5 rounded-full bg-status-success animate-ping opacity-50"></div>`
: ''
}
</div>
${this.getStatusText().toUpperCase()}
</span>
${

View file

@ -99,23 +99,50 @@
@apply hover:text-dark-text hover:bg-dark-bg-tertiary;
}
/* Card styles */
/* Enhanced card styles */
.card {
@apply bg-black border border-dark-border rounded-lg p-0;
@apply transition-all duration-200 ease-in-out;
@apply hover:border-accent-green-darker hover:shadow-glow-green-sm;
@apply bg-dark-bg-secondary border border-dark-border rounded-lg p-0;
@apply transition-all duration-200 ease-in-out shadow-sm;
@apply hover:bg-dark-bg-tertiary hover:border-dark-border-light hover:shadow-card-hover;
}
.card-elevated {
@apply bg-dark-bg-elevated rounded-xl p-6 shadow-card;
@apply hover:shadow-elevated hover:bg-dark-surface-hover;
@apply transition-all duration-200;
}
/* Status badges */
.status-badge {
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium;
}
.status-badge-success {
@apply bg-accent-green bg-opacity-20 text-accent-green;
}
.status-badge-warning {
@apply bg-status-warning bg-opacity-20 text-status-warning;
}
.status-badge-error {
@apply bg-status-error bg-opacity-20 text-status-error;
}
.status-badge-info {
@apply bg-status-info bg-opacity-20 text-status-info;
}
/* Quick start buttons */
.quick-start-btn {
@apply bg-dark-bg-tertiary border border-dark-border rounded-lg px-4 py-3 h-12;
@apply transition-all duration-200 ease-in-out text-dark-text-muted;
@apply hover:border-accent-green hover:text-accent-green hover:shadow-glow-green-sm;
@apply hover:border-accent-primary hover:text-accent-primary hover:shadow-glow-primary-sm;
@apply active:scale-95;
}
.quick-start-btn.active {
@apply bg-accent-green text-dark-bg border-accent-green shadow-glow-green-sm;
@apply bg-accent-primary text-dark-bg border-accent-primary shadow-glow-primary-sm;
}
/* Modal backdrop */
@ -135,13 +162,13 @@
@apply text-dark-text-muted text-sm font-medium mb-2 flex items-center gap-2;
}
/* Responsive session grid layout */
/* Enhanced responsive session grid layout */
.session-flex-responsive {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
grid-auto-rows: 380px;
gap: 1rem;
padding: 0 0.5rem;
grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
grid-auto-rows: 400px;
gap: 1.25rem;
padding: 0 0.75rem;
/* Enable smooth grid transitions */
transition: grid-template-columns 0.3s ease-out;
}
@ -153,15 +180,16 @@
@media (max-width: 420px) {
.session-flex-responsive {
padding: 0;
padding: 0 0.5rem;
grid-template-columns: 1fr;
grid-auto-rows: 300px;
grid-auto-rows: 320px;
gap: 1rem;
}
}
/* Authentication styles */
/* Enhanced authentication styles */
.auth-container {
@apply bg-dark-bg flex items-center justify-center p-4;
@apply bg-gradient-to-br from-dark-bg to-dark-bg-secondary flex items-center justify-center p-4;
min-height: 100vh;
min-height: 100dvh; /* Dynamic viewport height for mobile */
}
@ -181,7 +209,9 @@
}
.auth-title {
@apply text-2xl font-mono font-bold text-dark-text;
@apply text-3xl font-mono font-bold text-dark-text-bright;
font-family: 'JetBrains Mono', monospace;
letter-spacing: -0.02em;
}
.auth-subtitle {
@ -189,7 +219,7 @@
}
.auth-form {
@apply bg-dark-bg-secondary border border-dark-border rounded-lg p-0 w-full;
@apply bg-dark-bg-elevated border border-dark-border rounded-xl shadow-card p-0 w-full;
}
.auth-divider {
@ -225,6 +255,100 @@
}
}
/* Micro-interactions and animations */
@layer utilities {
/* Smooth transitions for interactive elements */
.interactive {
@apply transition-all duration-200 ease-out;
}
.interactive-fast {
@apply transition-all duration-150 ease-out;
}
.interactive-slow {
@apply transition-all duration-300 ease-out;
}
/* Hover lift effect for cards */
.hover-lift {
@apply transition-transform duration-200 ease-out;
}
.hover-lift:hover {
@apply -translate-y-0.5 shadow-elevated;
}
/* Hover glow effect */
.hover-glow-primary:hover {
@apply shadow-glow-primary;
}
.hover-glow-green:hover {
@apply shadow-glow-green;
}
/* Focus within styles */
.focus-within-glow:focus-within {
@apply shadow-glow-primary-sm ring-2 ring-accent-primary ring-opacity-50;
}
/* Smooth color transitions */
.transition-colors-all {
@apply transition-colors duration-200 ease-out;
}
/* Scale on click */
.active-scale:active {
@apply scale-95;
}
/* Pulse animation for activity indicators */
.pulse-slow {
animation: pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: .7;
}
}
/* Slide animations */
.slide-in-from-right {
animation: slideInFromRight 0.3s ease-out;
}
.slide-in-from-bottom {
animation: slideInFromBottom 0.3s ease-out;
}
@keyframes slideInFromRight {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes slideInFromBottom {
from {
transform: translateY(100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
}
/* Fira Code Variable Font */
@font-face {
font-family: 'Fira Code';
@ -570,28 +694,31 @@ body.initial-session-load .session-flex-responsive > session-card:nth-child(n +
touch-action: pan-x pan-y;
}
/* XTerm terminal styling */
/* Enhanced XTerm terminal styling */
.xterm {
padding: 0 !important;
font-family:
'Hack Nerd Font Mono', 'Fira Code', ui-monospace, SFMono-Regular, 'SF Mono', Consolas,
'JetBrains Mono', 'Hack Nerd Font Mono', 'Fira Code', ui-monospace, SFMono-Regular, 'SF Mono', Consolas,
'Liberation Mono', Menlo, monospace !important;
font-variant-ligatures: none;
font-variant-ligatures: contextual;
font-feature-settings:
'liga' 0,
'clig' 0,
'calt' 0;
'liga' 1,
'clig' 1,
'calt' 1;
text-rendering: optimizeSpeed;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
line-height: 1.4;
}
/* Terminal container styling */
/* Enhanced terminal container styling */
.terminal-container {
color: #e4e4e4;
white-space: pre;
overflow: hidden;
background-color: #000000;
background-color: #0a0a0a;
border-radius: 0.5rem;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.5);
}
/* Terminal line styling */
@ -643,19 +770,23 @@ body.initial-session-load .session-flex-responsive > session-card:nth-child(n +
opacity: 0;
}
/* Cursor styling */
/* Enhanced cursor styling */
.terminal-char.cursor {
animation: cursor-blink 1s infinite;
background-color: #00D9FF;
color: #0a0a0a;
}
@keyframes cursor-blink {
0%,
50% {
opacity: 1;
background-color: #00D9FF;
}
51%,
100% {
opacity: 0.3;
opacity: 0.4;
background-color: #00D9FF;
}
}
@ -671,24 +802,40 @@ body.initial-session-load .session-flex-responsive > session-card:nth-child(n +
width: 100%;
}
/* Terminal focus indicator */
/* Enhanced terminal focus indicator */
.terminal-focused {
box-shadow: 0 0 0 2px #00ff88;
border-color: #00ff88 !important;
box-shadow: 0 0 0 2px #00D9FF, 0 0 20px rgba(0, 217, 255, 0.3);
border-color: #00D9FF !important;
transition: all 0.2s ease-out;
}
/* Keyboard capture indicator */
/* Enhanced keyboard capture indicator */
.keyboard-capture-indicator {
position: fixed;
top: 10px;
right: 10px;
background: rgba(0, 255, 136, 0.1);
border: 1px solid #00ff88;
color: #00ff88;
padding: 4px 8px;
border-radius: 4px;
background: rgba(0, 217, 255, 0.1);
backdrop-filter: blur(8px);
border: 1px solid #00D9FF;
color: #00D9FF;
padding: 6px 12px;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
z-index: 1000;
animation: slideInFromTop 0.3s ease-out;
box-shadow: 0 2px 8px rgba(0, 217, 255, 0.2);
}
@keyframes slideInFromTop {
from {
transform: translateY(-100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
/* Force XTerm terminal to fit within session card bounds */

View file

@ -4,34 +4,47 @@ module.exports = {
theme: {
extend: {
colors: {
// Dark theme colors
// Enhanced Dark theme colors with better depth
"dark-bg": "#0a0a0a",
"dark-bg-secondary": "#1a1a1a",
"dark-bg-tertiary": "#242424",
"dark-surface": "#1f1f1f",
"dark-bg-secondary": "#141414",
"dark-bg-tertiary": "#1f1f1f",
"dark-bg-elevated": "#262626",
"dark-surface": "#1a1a1a",
"dark-surface-hover": "#2a2a2a",
"dark-border": "#2a2a2a",
"dark-border-light": "#3a3a3a",
"dark-border-focus": "#4a4a4a",
// Text colors
// Enhanced Text colors
"dark-text": "#e4e4e4",
"dark-text-muted": "#7a7a7a",
"dark-text-dim": "#5a5a5a",
"dark-text-bright": "#ffffff",
"dark-text-muted": "#888888",
"dark-text-dim": "#666666",
// Green accent colors (multiple shades)
"accent-green": "#00ff88",
"accent-green-dark": "#00cc66",
"accent-green-darker": "#009944",
"accent-green-light": "#44ffaa",
"accent-green-glow": "#00ff8866",
// Modern accent colors - Cyan/Teal primary
"accent-primary": "#00D9FF",
"accent-primary-dark": "#00B8E6",
"accent-primary-darker": "#0096CC",
"accent-primary-light": "#33E1FF",
"accent-primary-glow": "#00D9FF66",
// Green accent colors (success/active)
"accent-green": "#4ADE80",
"accent-green-dark": "#22C55E",
"accent-green-darker": "#16A34A",
"accent-green-light": "#86EFAC",
"accent-green-glow": "#4ADE8066",
// Secondary accent colors
"accent-cyan": "#00ffcc",
"accent-teal": "#00ccaa",
"accent-purple": "#A78BFA",
"accent-blue": "#60A5FA",
"accent-amber": "#FFA726",
// Status colors
"status-error": "#cc3333",
"status-warning": "#cc8833",
"status-success": "#00cc66",
// Enhanced Status colors
"status-error": "#FF6B6B",
"status-warning": "#FFA726",
"status-success": "#4ADE80",
"status-info": "#60A5FA",
// Legacy VS Code theme colors (for compatibility)
"vs-bg": "#0a0a0a",
@ -52,12 +65,25 @@ module.exports = {
"vs-highlight": "#8b6914",
},
boxShadow: {
'glow-green': '0 0 20px rgba(0, 255, 136, 0.4)',
'glow-green-sm': '0 0 10px rgba(0, 255, 136, 0.3)',
'glow-green-lg': '0 0 30px rgba(0, 255, 136, 0.5)',
// Updated glow effects with new colors
'glow-primary': '0 0 20px rgba(0, 217, 255, 0.4)',
'glow-primary-sm': '0 0 10px rgba(0, 217, 255, 0.3)',
'glow-primary-lg': '0 0 30px rgba(0, 217, 255, 0.5)',
'glow-green': '0 0 20px rgba(74, 222, 128, 0.4)',
'glow-green-sm': '0 0 10px rgba(74, 222, 128, 0.3)',
'glow-green-lg': '0 0 30px rgba(74, 222, 128, 0.5)',
// New subtle shadows
'card': '0 1px 3px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.4)',
'card-hover': '0 4px 6px rgba(0, 0, 0, 0.3), 0 2px 4px rgba(0, 0, 0, 0.4)',
'elevated': '0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2)',
},
animation: {
'pulse-green': 'pulseGreen 2s cubic-bezier(0.4, 0, 0.6, 1) infinite',
'pulse-primary': 'pulsePrimary 2s cubic-bezier(0.4, 0, 0.6, 1) infinite',
'slide-in-right': 'slideInRight 0.3s ease-out',
'slide-in-bottom': 'slideInBottom 0.3s ease-out',
'fade-in': 'fadeIn 0.2s ease-out',
'scale-in': 'scaleIn 0.2s ease-out',
},
keyframes: {
pulseGreen: {
@ -68,6 +94,52 @@ module.exports = {
opacity: '.8',
},
},
pulsePrimary: {
'0%, 100%': {
opacity: '1',
},
'50%': {
opacity: '.7',
},
},
slideInRight: {
'0%': {
transform: 'translateX(100%)',
opacity: '0',
},
'100%': {
transform: 'translateX(0)',
opacity: '1',
},
},
slideInBottom: {
'0%': {
transform: 'translateY(100%)',
opacity: '0',
},
'100%': {
transform: 'translateY(0)',
opacity: '1',
},
},
fadeIn: {
'0%': {
opacity: '0',
},
'100%': {
opacity: '1',
},
},
scaleIn: {
'0%': {
transform: 'scale(0.95)',
opacity: '0',
},
'100%': {
transform: 'scale(1)',
opacity: '1',
},
},
},
},
},