mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-03-25 09:25:50 +00:00
Tailwind 4 migration
This commit is contained in:
parent
5611b58789
commit
78bd4d79e9
31 changed files with 906 additions and 561 deletions
|
|
@ -77,6 +77,8 @@
|
|||
"test:e2e:parallel": "PLAYWRIGHT_PARALLEL=true playwright test",
|
||||
"test:e2e:parallel:headed": "PLAYWRIGHT_PARALLEL=true playwright test --headed",
|
||||
"test:e2e:parallel:workers": "PLAYWRIGHT_PARALLEL=true PLAYWRIGHT_WORKERS=4 playwright test",
|
||||
"test:e2e:fast": "./scripts/test-fast.sh",
|
||||
"test:e2e:perf": "playwright test --config=playwright.config.performance.ts",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"pnpm": {
|
||||
|
|
@ -123,6 +125,7 @@
|
|||
"@open-wc/testing": "^4.0.0",
|
||||
"@playwright/test": "^1.54.1",
|
||||
"@prettier/plugin-oxc": "^0.0.4",
|
||||
"@tailwindcss/postcss": "^4.1.11",
|
||||
"@testing-library/dom": "^10.4.1",
|
||||
"@types/compression": "^1.8.1",
|
||||
"@types/express": "^5.0.3",
|
||||
|
|
@ -146,10 +149,11 @@
|
|||
"lint-staged": "^16.1.2",
|
||||
"node-fetch": "^3.3.2",
|
||||
"postcss": "^8.5.6",
|
||||
"postcss-cli": "^11.0.1",
|
||||
"prettier": "^3.6.2",
|
||||
"puppeteer": "^24.15.0",
|
||||
"supertest": "^7.1.4",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"tailwindcss": "^4.1.11",
|
||||
"tsx": "^4.20.3",
|
||||
"typescript": "^5.8.3",
|
||||
"uuid": "^11.1.0",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,5 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
'@tailwindcss/postcss': {},
|
||||
},
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ execSync('node scripts/copy-assets.js', { stdio: 'inherit' });
|
|||
|
||||
// Build CSS
|
||||
console.log('Building CSS...');
|
||||
execSync('pnpm exec tailwindcss -i ./src/client/styles.css -o ./public/bundle/styles.css --minify', { stdio: 'inherit' });
|
||||
execSync('pnpm exec postcss ./src/client/styles.css -o ./public/bundle/styles.css', { stdio: 'inherit' });
|
||||
|
||||
// Bundle client JavaScript
|
||||
console.log('Bundling client JavaScript...');
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ async function build() {
|
|||
|
||||
// Build CSS
|
||||
console.log('Building CSS...');
|
||||
execSync('pnpm exec tailwindcss -i ./src/client/styles.css -o ./public/bundle/styles.css --minify', { stdio: 'inherit' });
|
||||
execSync('pnpm exec postcss ./src/client/styles.css -o ./public/bundle/styles.css', { stdio: 'inherit' });
|
||||
|
||||
// Bundle client JavaScript
|
||||
console.log('Bundling client JavaScript...');
|
||||
|
|
|
|||
|
|
@ -109,12 +109,12 @@ for (let i = 0; i < allArgs.length; i++) {
|
|||
console.log('Initial build...');
|
||||
require('child_process').execSync('node scripts/ensure-dirs.js', { stdio: 'inherit' });
|
||||
require('child_process').execSync('node scripts/copy-assets.js', { stdio: 'inherit' });
|
||||
require('child_process').execSync('pnpm exec tailwindcss -i ./src/client/styles.css -o ./public/bundle/styles.css', { stdio: 'inherit' });
|
||||
require('child_process').execSync('pnpm exec postcss ./src/client/styles.css -o ./public/bundle/styles.css', { stdio: 'inherit' });
|
||||
|
||||
// Build the command parts
|
||||
const commands = [
|
||||
// Watch CSS
|
||||
['pnpm', ['exec', 'tailwindcss', '-i', './src/client/styles.css', '-o', './public/bundle/styles.css', '--watch']],
|
||||
['pnpm', ['exec', 'postcss', './src/client/styles.css', '-o', './public/bundle/styles.css', '--watch']],
|
||||
// Watch assets
|
||||
['pnpm', ['exec', 'chokidar', 'src/client/assets/**/*', '-c', 'node scripts/copy-assets.js']],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1757,7 +1757,7 @@ export class VibeTunnelApp extends LitElement {
|
|||
<div
|
||||
class="fixed inset-0 sm:hidden transition-all ${
|
||||
this.isInSidebarDismissMode
|
||||
? 'bg-bg bg-opacity-50 backdrop-blur-sm'
|
||||
? 'bg-bg/50 backdrop-blur-sm'
|
||||
: 'bg-transparent pointer-events-none'
|
||||
}"
|
||||
style="z-index: ${Z_INDEX.MOBILE_OVERLAY}; transition-duration: ${TRANSITIONS.MOBILE_SLIDE}ms;"
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ export class AuthLogin extends LitElement {
|
|||
<div class="auth-container">
|
||||
<!-- Settings button in top right corner -->
|
||||
<button
|
||||
class="absolute top-4 right-4 p-2 text-muted hover:text-primary transition-colors"
|
||||
class="absolute top-4 right-4 p-2 text-text-muted hover:text-primary transition-colors"
|
||||
@click=${this.handleOpenSettings}
|
||||
title="Settings"
|
||||
>
|
||||
|
|
@ -187,7 +187,7 @@ export class AuthLogin extends LitElement {
|
|||
this.error
|
||||
? html`
|
||||
<div
|
||||
class="bg-status-error text-base px-3 py-1.5 rounded mb-3 font-mono text-xs sm:text-sm"
|
||||
class="bg-status-error text-bg px-3 py-1.5 rounded mb-3 font-mono text-xs sm:text-sm"
|
||||
data-testid="error-message"
|
||||
>
|
||||
${this.error}
|
||||
|
|
@ -195,7 +195,7 @@ export class AuthLogin extends LitElement {
|
|||
@click=${() => {
|
||||
this.error = '';
|
||||
}}
|
||||
class="ml-2 text-base hover:text-primary"
|
||||
class="ml-2 text-bg hover:text-primary"
|
||||
data-testid="error-close"
|
||||
>
|
||||
✕
|
||||
|
|
@ -208,14 +208,14 @@ export class AuthLogin extends LitElement {
|
|||
this.success
|
||||
? html`
|
||||
<div
|
||||
class="bg-status-success text-base px-3 py-1.5 rounded mb-3 font-mono text-xs sm:text-sm"
|
||||
class="bg-status-success text-bg px-3 py-1.5 rounded mb-3 font-mono text-xs sm:text-sm"
|
||||
>
|
||||
${this.success}
|
||||
<button
|
||||
@click=${() => {
|
||||
this.success = '';
|
||||
}}
|
||||
class="ml-2 text-base hover:text-primary"
|
||||
class="ml-2 text-bg hover:text-primary"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
|
@ -248,10 +248,10 @@ export class AuthLogin extends LitElement {
|
|||
`
|
||||
: html`
|
||||
<div
|
||||
class="w-full h-full bg-secondary flex items-center justify-center"
|
||||
class="w-full h-full bg-bg-secondary flex items-center justify-center"
|
||||
>
|
||||
<svg
|
||||
class="w-12 h-12 sm:w-14 sm:h-14 text-muted"
|
||||
class="w-12 h-12 sm:w-14 sm:h-14 text-text-muted"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
|
|
@ -300,7 +300,7 @@ export class AuthLogin extends LitElement {
|
|||
<div class="ssh-key-item p-6 sm:p-8">
|
||||
<div class="flex flex-col items-center mb-4 sm:mb-6">
|
||||
<div
|
||||
class="w-16 h-16 sm:w-20 sm:h-20 rounded-full mb-2 sm:mb-3 overflow-hidden border-2 border-base"
|
||||
class="w-16 h-16 sm:w-20 sm:h-20 rounded-full mb-2 sm:mb-3 overflow-hidden border-2 border-border"
|
||||
>
|
||||
${
|
||||
this.userAvatar
|
||||
|
|
@ -315,10 +315,10 @@ export class AuthLogin extends LitElement {
|
|||
`
|
||||
: html`
|
||||
<div
|
||||
class="w-full h-full bg-secondary flex items-center justify-center"
|
||||
class="w-full h-full bg-bg-secondary flex items-center justify-center"
|
||||
>
|
||||
<svg
|
||||
class="w-8 h-8 sm:w-10 sm:h-10 text-muted"
|
||||
class="w-8 h-8 sm:w-10 sm:h-10 text-text-muted"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
|
|
@ -335,7 +335,7 @@ export class AuthLogin extends LitElement {
|
|||
: 'Please authenticate to continue'
|
||||
}
|
||||
</p>
|
||||
<p class="text-muted text-xs mt-1 sm:mt-2">
|
||||
<p class="text-text-muted text-xs mt-1 sm:mt-2">
|
||||
SSH key authentication required
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -374,11 +374,11 @@ export class AuthLogin extends LitElement {
|
|||
</div>
|
||||
|
||||
<div class="space-y-3">
|
||||
<div class="bg-base border border-base rounded p-3">
|
||||
<p class="text-muted text-xs mb-2">
|
||||
<div class="bg-bg border border-border rounded p-3">
|
||||
<p class="text-text-muted text-xs mb-2">
|
||||
Generate SSH keys for browser-based authentication
|
||||
</p>
|
||||
<p class="text-muted text-xs">
|
||||
<p class="text-text-muted text-xs">
|
||||
💡 SSH keys work in both browser and terminal
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -33,13 +33,13 @@ export class AuthQuickKeys extends LitElement {
|
|||
|
||||
render() {
|
||||
return html`
|
||||
<div class="quick-keys-bar bg-secondary border-t border-base p-2">
|
||||
<div class="quick-keys-bar bg-bg-secondary border-t border-border p-2">
|
||||
<div class="flex gap-1 overflow-x-auto scrollbar-hide">
|
||||
${QUICK_KEYS.map(
|
||||
({ key, label }) => html`
|
||||
<button
|
||||
type="button"
|
||||
class="quick-key-btn px-3 py-1.5 bg-tertiary text-primary text-xs font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap flex-shrink-0"
|
||||
class="quick-key-btn px-3 py-1.5 bg-bg-tertiary text-primary text-xs font-mono rounded border border-border hover:bg-surface hover:border-primary transition-all whitespace-nowrap flex-shrink-0"
|
||||
@click=${() => this.handleKeyPress(key)}
|
||||
>
|
||||
${label}
|
||||
|
|
|
|||
|
|
@ -405,7 +405,7 @@ export class FileBrowser extends LitElement {
|
|||
private renderPreview() {
|
||||
if (this.previewLoading) {
|
||||
return html`
|
||||
<div class="flex items-center justify-center h-full text-muted">
|
||||
<div class="flex items-center justify-center h-full text-text-muted">
|
||||
Loading preview...
|
||||
</div>
|
||||
`;
|
||||
|
|
@ -417,7 +417,7 @@ export class FileBrowser extends LitElement {
|
|||
|
||||
if (!this.preview) {
|
||||
return html`
|
||||
<div class="flex flex-col items-center justify-center h-full text-muted">
|
||||
<div class="flex flex-col items-center justify-center h-full text-text-muted">
|
||||
${UIIcons.preview}
|
||||
<div>Select a file to preview</div>
|
||||
</div>
|
||||
|
|
@ -451,11 +451,11 @@ export class FileBrowser extends LitElement {
|
|||
|
||||
case 'binary':
|
||||
return html`
|
||||
<div class="flex flex-col items-center justify-center h-full text-muted">
|
||||
<div class="flex flex-col items-center justify-center h-full text-text-muted">
|
||||
${UIIcons.binary}
|
||||
<div class="text-lg mb-2">Binary File</div>
|
||||
<div class="text-sm">${this.preview.humanSize || `${this.preview.size} bytes`}</div>
|
||||
<div class="text-sm text-muted mt-2">
|
||||
<div class="text-sm text-text-muted mt-2">
|
||||
${this.preview.mimeType || 'Unknown type'}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -467,7 +467,7 @@ export class FileBrowser extends LitElement {
|
|||
// For new files (added or untracked), we might not have a diff but we have diffContent
|
||||
if (!this.diffContent && (!this.diff || !this.diff.diff)) {
|
||||
return html`
|
||||
<div class="flex items-center justify-center h-full text-muted">
|
||||
<div class="flex items-center justify-center h-full text-text-muted">
|
||||
No changes in this file
|
||||
</div>
|
||||
`;
|
||||
|
|
@ -496,7 +496,7 @@ export class FileBrowser extends LitElement {
|
|||
return html`
|
||||
<div class="overflow-auto h-full p-4 font-mono text-xs">
|
||||
${lines.map((line) => {
|
||||
let className = 'text-muted';
|
||||
let className = 'text-text-muted';
|
||||
if (line.startsWith('+')) className = 'text-status-success bg-status-success/10';
|
||||
else if (line.startsWith('-')) className = 'text-status-error bg-status-error/10';
|
||||
else if (line.startsWith('@@')) className = 'text-status-info font-semibold';
|
||||
|
|
@ -518,7 +518,7 @@ export class FileBrowser extends LitElement {
|
|||
${
|
||||
this.isMobile && this.mobileView === 'preview'
|
||||
? html`
|
||||
<div class="absolute top-1/2 left-2 -translate-y-1/2 text-muted opacity-50">
|
||||
<div class="absolute top-1/2 left-2 -translate-y-1/2 text-text-muted opacity-50">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
|
|
@ -537,12 +537,12 @@ export class FileBrowser extends LitElement {
|
|||
>
|
||||
<!-- Compact Header (like session-view) -->
|
||||
<div
|
||||
class="flex items-center justify-between px-3 py-2 border-b border-border/50 text-sm min-w-0 bg-secondary"
|
||||
class="flex items-center justify-between px-3 py-2 border-b border-border/50 text-sm min-w-0 bg-bg-secondary"
|
||||
style="padding-top: max(0.5rem, 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));"
|
||||
>
|
||||
<div class="flex items-center gap-3 min-w-0 flex-1">
|
||||
<button
|
||||
class="text-muted hover:text-primary font-mono text-xs px-2 py-1 flex-shrink-0 transition-colors flex items-center gap-1"
|
||||
class="text-text-muted hover:text-primary font-mono text-xs px-2 py-1 flex-shrink-0 transition-colors flex items-center gap-1"
|
||||
@click=${this.handleCancel}
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
|
|
@ -585,7 +585,7 @@ export class FileBrowser extends LitElement {
|
|||
${
|
||||
this.gitStatus?.branch
|
||||
? html`
|
||||
<span class="text-muted text-xs flex items-center gap-1 font-mono flex-shrink-0">
|
||||
<span class="text-text-muted text-xs flex items-center gap-1 font-mono flex-shrink-0">
|
||||
${UIIcons.git} ${this.gitStatus.branch}
|
||||
</span>
|
||||
`
|
||||
|
|
@ -614,16 +614,16 @@ export class FileBrowser extends LitElement {
|
|||
<div
|
||||
class="${this.isMobile && this.mobileView === 'preview' ? 'hidden' : ''} ${
|
||||
this.isMobile ? 'w-full' : 'w-80'
|
||||
} bg-secondary border-r border-border/50 flex flex-col"
|
||||
} bg-bg-secondary border-r border-border/50 flex flex-col"
|
||||
>
|
||||
<!-- File list header with toggles -->
|
||||
<div
|
||||
class="bg-secondary border-b border-border/50 p-3 flex items-center justify-between"
|
||||
class="bg-bg-secondary border-b border-border/50 p-3 flex items-center justify-between"
|
||||
>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
class="btn-secondary text-xs px-2 py-1 font-mono ${
|
||||
this.gitFilter === 'changed' ? 'bg-primary text-text-bright' : ''
|
||||
this.gitFilter === 'changed' ? 'bg-primary text-bg' : ''
|
||||
}"
|
||||
@click=${this.toggleGitFilter}
|
||||
title="Show only Git changes"
|
||||
|
|
@ -632,7 +632,7 @@ export class FileBrowser extends LitElement {
|
|||
</button>
|
||||
<button
|
||||
class="btn-secondary text-xs px-2 py-1 font-mono ${
|
||||
this.showHidden ? 'bg-primary text-text-bright' : ''
|
||||
this.showHidden ? 'bg-primary text-bg' : ''
|
||||
}"
|
||||
@click=${this.toggleHidden}
|
||||
title="Show hidden files"
|
||||
|
|
@ -649,7 +649,7 @@ export class FileBrowser extends LitElement {
|
|||
${
|
||||
this.loading
|
||||
? html`
|
||||
<div class="flex items-center justify-center h-full text-muted">
|
||||
<div class="flex items-center justify-center h-full text-text-muted">
|
||||
Loading...
|
||||
</div>
|
||||
`
|
||||
|
|
@ -662,7 +662,7 @@ export class FileBrowser extends LitElement {
|
|||
@click=${this.handleParentClick}
|
||||
>
|
||||
${getParentDirectoryIcon()}
|
||||
<span class="text-muted">..</span>
|
||||
<span class="text-text-muted">..</span>
|
||||
</div>
|
||||
`
|
||||
: ''
|
||||
|
|
@ -684,7 +684,7 @@ export class FileBrowser extends LitElement {
|
|||
file.isSymlink
|
||||
? html`
|
||||
<svg
|
||||
class="w-3 h-3 text-muted absolute -bottom-1 -right-1"
|
||||
class="w-3 h-3 text-text-muted absolute -bottom-1 -right-1">
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
|
|
@ -726,7 +726,7 @@ export class FileBrowser extends LitElement {
|
|||
this.selectedFile
|
||||
? html`
|
||||
<div
|
||||
class="bg-secondary border-b border-border/50 p-3 ${
|
||||
class="bg-bg-secondary border-b border-border/50 p-3 ${
|
||||
this.isMobile ? 'space-y-2' : 'flex items-center justify-between'
|
||||
}"
|
||||
>
|
||||
|
|
@ -738,7 +738,7 @@ export class FileBrowser extends LitElement {
|
|||
@click=${() => {
|
||||
this.mobileView = 'list';
|
||||
}}
|
||||
class="text-muted hover:text-primary transition-colors flex-shrink-0"
|
||||
class="text-text-muted hover:text-primary transition-colors flex-shrink-0"
|
||||
title="Back to files"
|
||||
>
|
||||
<svg
|
||||
|
|
@ -821,7 +821,7 @@ export class FileBrowser extends LitElement {
|
|||
? html`
|
||||
<button
|
||||
class="btn-secondary text-xs px-2 py-1 font-mono ${
|
||||
this.showDiff ? 'bg-primary text-text-bright' : ''
|
||||
this.showDiff ? 'bg-primary text-bg' : ''
|
||||
} ${
|
||||
this.isMobile &&
|
||||
this.selectedFile.type === 'file' &&
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ export class FilePicker extends LitElement {
|
|||
}
|
||||
|
||||
return html`
|
||||
<div class="fixed inset-0 bg-bg bg-opacity-80 backdrop-blur-sm flex items-center justify-center animate-fade-in" style="z-index: ${Z_INDEX.FILE_PICKER};" @click=${this.handleCancel}>
|
||||
<div class="fixed inset-0 bg-bg/80 backdrop-blur-sm flex items-center justify-center animate-fade-in" style="z-index: ${Z_INDEX.FILE_PICKER};" @click=${this.handleCancel}>
|
||||
<div class="bg-elevated border border-border/50 rounded-xl shadow-2xl p-8 m-4 max-w-sm w-full animate-scale-in" @click=${(e: Event) => e.stopPropagation()}>
|
||||
<h3 class="text-xl font-bold text-primary mb-6">
|
||||
Select File
|
||||
|
|
@ -258,10 +258,10 @@ export class FilePicker extends LitElement {
|
|||
? html`
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<span class="text-sm text-muted font-mono">Uploading...</span>
|
||||
<span class="text-sm text-text-muted font-mono">Uploading...</span>
|
||||
<span class="text-sm text-primary font-mono font-medium">${Math.round(this.uploadProgress)}%</span>
|
||||
</div>
|
||||
<div class="w-full bg-secondary rounded-full h-2 overflow-hidden">
|
||||
<div class="w-full bg-bg-secondary rounded-full h-2 overflow-hidden">
|
||||
<div
|
||||
class="bg-gradient-to-r from-primary to-primary-light h-2 rounded-full transition-all duration-300 shadow-glow-sm"
|
||||
style="width: ${this.uploadProgress}%"
|
||||
|
|
@ -289,7 +289,7 @@ export class FilePicker extends LitElement {
|
|||
<button
|
||||
id="file-picker-cancel-button"
|
||||
@click=${this.handleCancel}
|
||||
class="w-full bg-secondary border border-border/50 text-primary font-mono py-3 px-6 rounded-lg transition-all duration-200 hover:bg-surface hover:border-primary active:scale-95"
|
||||
class="w-full bg-bg-secondary border border-border/50 text-primary font-mono py-3 px-6 rounded-lg transition-all duration-200 hover:bg-surface hover:border-primary active:scale-95"
|
||||
?disabled=${this.uploading}
|
||||
>
|
||||
Cancel
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ export class LogViewer extends LitElement {
|
|||
|
||||
if (this.loading) {
|
||||
return html`
|
||||
<div class="flex items-center justify-center h-screen bg-base text-primary">
|
||||
<div class="flex items-center justify-center h-screen bg-bg text-primary">
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="animate-spin rounded-full h-12 w-12 border-4 border-primary border-t-transparent mb-4 mx-auto"
|
||||
|
|
@ -297,16 +297,16 @@ export class LogViewer extends LitElement {
|
|||
|
||||
return html`
|
||||
${scrollbarStyles}
|
||||
<div class="flex flex-col h-full bg-base text-primary font-mono">
|
||||
<div class="flex flex-col h-full bg-bg text-primary font-mono">
|
||||
<!-- Header - single row on desktop, two rows on mobile -->
|
||||
<div class="bg-secondary border-b border-border/50 p-3 sm:p-4">
|
||||
<div class="bg-bg-secondary border-b border-border/50 p-3 sm:p-4">
|
||||
<!-- Mobile layout (two rows) -->
|
||||
<div class="sm:hidden">
|
||||
<!-- Top row with back button and title -->
|
||||
<div class="flex items-center gap-2 mb-3">
|
||||
<!-- Back button -->
|
||||
<button
|
||||
class="p-2 bg-base border border-border/50 rounded text-sm text-primary hover:border-primary hover:text-primary transition-colors flex items-center gap-1 flex-shrink-0"
|
||||
class="p-2 bg-bg border border-border/50 rounded text-sm text-primary hover:border-primary hover:text-primary transition-colors flex items-center gap-1 flex-shrink-0"
|
||||
@click=${() => {
|
||||
window.location.href = '/';
|
||||
}}
|
||||
|
|
@ -335,8 +335,8 @@ export class LogViewer extends LitElement {
|
|||
<button
|
||||
class="p-2 text-xs uppercase font-bold rounded transition-colors ${
|
||||
this.autoScroll
|
||||
? 'bg-primary text-base'
|
||||
: 'bg-tertiary text-muted border border-border/50'
|
||||
? 'bg-primary text-bg'
|
||||
: 'bg-bg-tertiary text-text-muted border border-border/50'
|
||||
}"
|
||||
@click=${() => {
|
||||
this.autoScroll = !this.autoScroll;
|
||||
|
|
@ -362,7 +362,7 @@ export class LogViewer extends LitElement {
|
|||
<!-- Search input -->
|
||||
<input
|
||||
type="text"
|
||||
class="px-3 py-1.5 bg-base border border-border/50 rounded text-sm text-primary placeholder-muted focus:outline-none focus:border-primary transition-colors w-full"
|
||||
class="px-3 py-1.5 bg-bg border border-border/50 rounded text-sm text-primary placeholder-text-muted focus:outline-none focus:border-primary transition-colors w-full"
|
||||
placeholder="Filter logs..."
|
||||
.value=${this.filter}
|
||||
@input=${(e: Event) => {
|
||||
|
|
@ -380,12 +380,12 @@ export class LogViewer extends LitElement {
|
|||
class="px-1.5 py-1 text-xs uppercase font-bold rounded transition-colors ${
|
||||
this.levelFilter.has(level)
|
||||
? level === 'error'
|
||||
? 'bg-status-error bg-opacity-20 text-status-error border border-status-error'
|
||||
? 'bg-status-error/20 text-status-error border border-status-error'
|
||||
: level === 'warn'
|
||||
? 'bg-status-warning bg-opacity-20 text-status-warning border border-status-warning'
|
||||
? 'bg-status-warning/20 text-status-warning border border-status-warning'
|
||||
: level === 'debug'
|
||||
? 'bg-bg-tertiary text-text-muted border border-border'
|
||||
: 'bg-primary bg-opacity-20 text-primary border border-primary'
|
||||
: 'bg-primary/20 text-primary border border-primary'
|
||||
: 'bg-bg-tertiary text-text-muted border border-border'
|
||||
}"
|
||||
@click=${() => this.toggleLevel(level)}
|
||||
|
|
@ -410,7 +410,7 @@ export class LogViewer extends LitElement {
|
|||
<button
|
||||
class="px-1.5 py-1 text-xs uppercase font-bold rounded transition-colors ${
|
||||
this.showClient
|
||||
? 'bg-status-warning bg-opacity-20 text-status-warning border border-status-warning'
|
||||
? 'bg-status-warning/20 text-status-warning border border-status-warning'
|
||||
: 'bg-bg-tertiary text-text-muted border border-border'
|
||||
}"
|
||||
@click=${() => {
|
||||
|
|
@ -423,7 +423,7 @@ export class LogViewer extends LitElement {
|
|||
<button
|
||||
class="px-1.5 py-1 text-xs uppercase font-bold rounded transition-colors ${
|
||||
this.showServer
|
||||
? 'bg-primary bg-opacity-20 text-primary border border-primary'
|
||||
? 'bg-primary/20 text-primary border border-primary'
|
||||
: 'bg-bg-tertiary text-text-muted border border-border'
|
||||
}"
|
||||
@click=${() => {
|
||||
|
|
@ -485,12 +485,12 @@ export class LogViewer extends LitElement {
|
|||
class="px-2 py-1 text-xs uppercase font-bold rounded transition-colors ${
|
||||
this.levelFilter.has(level)
|
||||
? level === 'error'
|
||||
? 'bg-status-error bg-opacity-20 text-status-error border border-status-error'
|
||||
? 'bg-status-error/20 text-status-error border border-status-error'
|
||||
: level === 'warn'
|
||||
? 'bg-status-warning bg-opacity-20 text-status-warning border border-status-warning'
|
||||
? 'bg-status-warning/20 text-status-warning border border-status-warning'
|
||||
: level === 'debug'
|
||||
? 'bg-bg-tertiary text-text-muted border border-border'
|
||||
: 'bg-primary bg-opacity-20 text-primary border border-primary'
|
||||
: 'bg-primary/20 text-primary border border-primary'
|
||||
: 'bg-bg-tertiary text-text-muted border border-border'
|
||||
}"
|
||||
@click=${() => this.toggleLevel(level)}
|
||||
|
|
@ -506,7 +506,7 @@ export class LogViewer extends LitElement {
|
|||
<button
|
||||
class="px-2 py-1 text-xs uppercase font-bold rounded transition-colors ${
|
||||
this.showClient
|
||||
? 'bg-status-warning bg-opacity-20 text-status-warning border border-status-warning'
|
||||
? 'bg-status-warning/20 text-status-warning border border-status-warning'
|
||||
: 'bg-bg-tertiary text-text-muted border border-border'
|
||||
}"
|
||||
@click=${() => {
|
||||
|
|
@ -518,7 +518,7 @@ export class LogViewer extends LitElement {
|
|||
<button
|
||||
class="px-2 py-1 text-xs uppercase font-bold rounded transition-colors ${
|
||||
this.showServer
|
||||
? 'bg-primary bg-opacity-20 text-primary border border-primary'
|
||||
? 'bg-primary/20 text-primary border border-primary'
|
||||
: 'bg-bg-tertiary text-text-muted border border-border'
|
||||
}"
|
||||
@click=${() => {
|
||||
|
|
@ -533,7 +533,7 @@ export class LogViewer extends LitElement {
|
|||
<button
|
||||
class="px-3 py-1 text-xs uppercase font-bold rounded transition-colors ${
|
||||
this.autoScroll
|
||||
? 'bg-primary bg-opacity-20 text-primary border border-primary'
|
||||
? 'bg-primary/20 text-primary border border-primary'
|
||||
: 'bg-bg-tertiary text-text-muted border border-border'
|
||||
}"
|
||||
@click=${() => {
|
||||
|
|
|
|||
|
|
@ -373,7 +373,7 @@ export class SessionCard extends LitElement {
|
|||
>
|
||||
<!-- Compact Header -->
|
||||
<div
|
||||
class="flex justify-between items-center px-3 py-2 border-b border-base bg-gradient-to-r from-secondary to-tertiary"
|
||||
class="flex justify-between items-center px-3 py-2 border-b border-border bg-gradient-to-r from-bg-secondary to-bg-tertiary"
|
||||
>
|
||||
<div class="text-xs font-mono pr-2 flex-1 min-w-0 text-primary">
|
||||
<div class="flex items-center gap-2">
|
||||
|
|
@ -421,8 +421,8 @@ export class SessionCard extends LitElement {
|
|||
<button
|
||||
class="p-1 rounded-full transition-all duration-200 disabled:opacity-50 flex-shrink-0 ${
|
||||
this.session.status === 'running'
|
||||
? 'text-status-error hover:bg-status-error hover:bg-opacity-20'
|
||||
: 'text-status-warning hover:bg-status-warning hover:bg-opacity-20'
|
||||
? 'text-status-error hover:bg-status-error/20'
|
||||
: 'text-status-warning hover:bg-status-warning/20'
|
||||
}"
|
||||
@click=${this.handleKillClick}
|
||||
?disabled=${this.killing}
|
||||
|
|
@ -491,7 +491,7 @@ export class SessionCard extends LitElement {
|
|||
|
||||
<!-- Compact Footer -->
|
||||
<div
|
||||
class="px-3 py-2 text-muted text-xs border-t border-base bg-gradient-to-r from-tertiary to-secondary"
|
||||
class="px-3 py-2 text-text-muted text-xs border-t border-border bg-gradient-to-r from-bg-tertiary to-bg-secondary"
|
||||
>
|
||||
<div class="flex justify-between items-center min-w-0">
|
||||
<span
|
||||
|
|
@ -601,7 +601,7 @@ export class SessionCard extends LitElement {
|
|||
return 'text-status-error';
|
||||
}
|
||||
if (this.session.active === false) {
|
||||
return 'text-muted';
|
||||
return 'text-text-muted';
|
||||
}
|
||||
if (this.session.status === 'running' && this.session.activityStatus?.specificStatus) {
|
||||
return 'text-status-warning';
|
||||
|
|
@ -622,7 +622,7 @@ export class SessionCard extends LitElement {
|
|||
} else if (this.session.activityStatus?.isActive || this.isActive) {
|
||||
return 'bg-status-success'; // Generic active - solid green
|
||||
} else {
|
||||
return 'bg-status-success ring-1 ring-status-success ring-opacity-50'; // Idle - green with ring
|
||||
return 'bg-status-success ring-1 ring-status-success/50'; // Idle - green with ring
|
||||
}
|
||||
}
|
||||
return 'bg-status-warning';
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ export class QuickStartSection extends LitElement {
|
|||
@click=${() => this.handleQuickStartClick(command)}
|
||||
class="${
|
||||
this.selectedCommand === command
|
||||
? 'px-2 py-1.5 sm:px-3 sm:py-2 lg:px-4 lg:py-3 rounded-lg border text-left transition-all bg-primary bg-opacity-10 border-primary/50 text-primary hover:bg-opacity-20 font-medium text-[10px] sm:text-xs lg:text-sm'
|
||||
? 'px-2 py-1.5 sm:px-3 sm:py-2 lg:px-4 lg:py-3 rounded-lg border text-left transition-all bg-primary/10 border-primary/50 text-primary hover:bg-primary/20 font-medium text-[10px] sm:text-xs lg:text-sm'
|
||||
: 'px-2 py-1.5 sm:px-3 sm:py-2 lg:px-4 lg:py-3 rounded-lg border text-left transition-all bg-bg-elevated border-border/50 text-text hover:bg-hover hover:border-primary/50 hover:text-primary text-[10px] sm:text-xs lg:text-sm'
|
||||
}"
|
||||
?disabled=${this.disabled || this.isCreating}
|
||||
|
|
|
|||
|
|
@ -1102,7 +1102,7 @@ export class SessionList extends LitElement {
|
|||
!this.hideExited && exitedSessions.length > 0
|
||||
? html`
|
||||
<button
|
||||
class="font-mono text-xs px-3 py-1.5 rounded-md border transition-all duration-200 border-status-warning bg-status-warning bg-opacity-10 text-status-warning hover:bg-opacity-20 hover:shadow-glow-warning-sm active:scale-95 disabled:opacity-50"
|
||||
class="font-mono text-xs px-3 py-1.5 rounded-md border transition-all duration-200 border-status-warning bg-status-warning/10 text-status-warning hover:bg-status-warning/20 hover:shadow-glow-warning-sm active:scale-95 disabled:opacity-50"
|
||||
id="clean-exited-button"
|
||||
@click=${this.handleCleanupExited}
|
||||
?disabled=${this.cleaningExited}
|
||||
|
|
@ -1128,7 +1128,7 @@ export class SessionList extends LitElement {
|
|||
runningSessions.length > 0
|
||||
? html`
|
||||
<button
|
||||
class="font-mono text-xs px-3 py-1.5 rounded-md border transition-all duration-200 border-status-error bg-status-error bg-opacity-10 text-status-error hover:bg-opacity-20 hover:shadow-glow-error-sm active:scale-95"
|
||||
class="font-mono text-xs px-3 py-1.5 rounded-md border transition-all duration-200 border-status-error bg-status-error/10 text-status-error hover:bg-status-error/20 hover:shadow-glow-error-sm active:scale-95"
|
||||
id="kill-all-button"
|
||||
@click=${() => this.dispatchEvent(new CustomEvent('kill-all-sessions'))}
|
||||
data-testid="kill-all-button"
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ export class CompactSessionCard extends LitElement {
|
|||
|
||||
if (session.activityStatus?.isActive === false) {
|
||||
// Idle
|
||||
return html`<div class="w-2.5 h-2.5 rounded-full bg-status-success ring-1 ring-status-success ring-opacity-50"></div>`;
|
||||
return html`<div class="w-2.5 h-2.5 rounded-full bg-status-success ring-1 ring-status-success/50"></div>`;
|
||||
}
|
||||
|
||||
// Active
|
||||
|
|
|
|||
|
|
@ -955,10 +955,10 @@ export class SessionView extends LitElement {
|
|||
render() {
|
||||
if (!this.session) {
|
||||
return html`
|
||||
<div class="fixed inset-0 bg-base flex items-center justify-center">
|
||||
<div class="fixed inset-0 bg-bg flex items-center justify-center">
|
||||
<div class="text-primary font-mono text-center">
|
||||
<div class="text-2xl mb-2">${this.loadingAnimationManager.getLoadingText()}</div>
|
||||
<div class="text-sm text-muted">Waiting for session...</div>
|
||||
<div class="text-sm text-text-muted">Waiting for session...</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
|
@ -1130,11 +1130,11 @@ export class SessionView extends LitElement {
|
|||
? html`
|
||||
<!-- Enhanced Loading overlay -->
|
||||
<div
|
||||
class="absolute inset-0 bg-bg bg-opacity-90 backdrop-filter backdrop-blur-sm flex items-center justify-center z-10 animate-fade-in"
|
||||
class="absolute inset-0 bg-bg/90 backdrop-filter backdrop-blur-sm flex items-center justify-center z-10 animate-fade-in"
|
||||
>
|
||||
<div class="text-primary font-mono text-center">
|
||||
<div class="text-2xl mb-3 text-primary animate-pulse-primary">${this.loadingAnimationManager.getLoadingText()}</div>
|
||||
<div class="text-sm text-muted">Connecting to session...</div>
|
||||
<div class="text-sm text-text-muted">Connecting to session...</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
|
|
@ -1179,7 +1179,7 @@ export class SessionView extends LitElement {
|
|||
${
|
||||
uiState.isMobile && !uiState.showMobileInput && !uiState.useDirectKeyboard
|
||||
? html`
|
||||
<div class="p-4 bg-secondary">
|
||||
<div class="p-4 bg-bg-secondary">
|
||||
<!-- First row: Arrow keys -->
|
||||
<div class="flex gap-2 mb-2">
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ export class CompactMenu extends LitElement {
|
|||
return html`
|
||||
<div class="relative w-[44px] flex-shrink-0">
|
||||
<button
|
||||
class="p-2 ${this.showMenu ? 'text-primary border-primary' : 'text-primary border-base'} hover:border-primary hover:text-primary rounded-lg"
|
||||
class="p-2 bg-bg-tertiary border ${this.showMenu ? 'text-primary border-primary' : 'text-primary border-border'} hover:border-primary hover:text-primary hover:bg-surface-hover rounded-lg transition-all duration-200"
|
||||
@click=${this.toggleMenu}
|
||||
@keydown=${this.handleMenuButtonKeyDown}
|
||||
title="More actions"
|
||||
|
|
@ -235,13 +235,13 @@ export class CompactMenu extends LitElement {
|
|||
let menuItemIndex = 0;
|
||||
return html`
|
||||
<div
|
||||
class="absolute right-0 top-full mt-2 bg-surface border border-base rounded-lg shadow-xl py-1 min-w-[250px]"
|
||||
class="absolute right-0 top-full mt-2 bg-surface border border-border rounded-lg shadow-xl py-1 min-w-[250px]"
|
||||
style="z-index: ${Z_INDEX.WIDTH_SELECTOR_DROPDOWN};"
|
||||
>
|
||||
|
||||
<!-- New Session -->
|
||||
<button
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-surface-hover hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-surface-hover text-primary' : ''}"
|
||||
@click=${() => this.handleAction(this.onCreateSession)}
|
||||
data-testid="compact-new-session"
|
||||
tabindex="${this.showMenu ? '0' : '-1'}"
|
||||
|
|
@ -252,11 +252,11 @@ export class CompactMenu extends LitElement {
|
|||
New Session
|
||||
</button>
|
||||
|
||||
<div class="border-t border-base my-1"></div>
|
||||
<div class="border-t border-border my-1"></div>
|
||||
|
||||
<!-- File Browser -->
|
||||
<button
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-surface-hover hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-surface-hover text-primary' : ''}"
|
||||
@click=${() => this.handleAction(this.onOpenFileBrowser)}
|
||||
data-testid="compact-file-browser"
|
||||
tabindex="${this.showMenu ? '0' : '-1'}"
|
||||
|
|
@ -269,7 +269,7 @@ export class CompactMenu extends LitElement {
|
|||
|
||||
<!-- Upload Image -->
|
||||
<button
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-surface-hover hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-surface-hover text-primary' : ''}"
|
||||
@click=${() => this.handleAction(this.onUploadImage)}
|
||||
data-testid="compact-upload-image"
|
||||
tabindex="${this.showMenu ? '0' : '-1'}"
|
||||
|
|
@ -282,7 +282,7 @@ export class CompactMenu extends LitElement {
|
|||
|
||||
<!-- Width Settings -->
|
||||
<button
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-surface-hover hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-surface-hover text-primary' : ''}"
|
||||
@click=${() => this.handleAction(this.onMaxWidthToggle)}
|
||||
data-testid="compact-width-settings"
|
||||
tabindex="${this.showMenu ? '0' : '-1'}"
|
||||
|
|
@ -298,7 +298,7 @@ export class CompactMenu extends LitElement {
|
|||
this.hasGitRepo
|
||||
? html`
|
||||
<button
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-surface-hover hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-surface-hover text-primary' : ''}"
|
||||
@click=${() => this.handleAction(this.onToggleViewMode)}
|
||||
data-testid="compact-worktree-toggle"
|
||||
tabindex="${this.showMenu ? '0' : '-1'}"
|
||||
|
|
@ -314,7 +314,7 @@ export class CompactMenu extends LitElement {
|
|||
|
||||
<!-- Theme Toggle -->
|
||||
<button
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-surface-hover hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-surface-hover text-primary' : ''}"
|
||||
@click=${() => this.handleThemeChange()}
|
||||
data-testid="compact-theme-toggle"
|
||||
tabindex="${this.showMenu ? '0' : '-1'}"
|
||||
|
|
@ -325,7 +325,7 @@ export class CompactMenu extends LitElement {
|
|||
|
||||
<!-- Settings -->
|
||||
<button
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-primary hover:bg-surface-hover hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-surface-hover text-primary' : ''}"
|
||||
@click=${() => this.handleAction(this.onOpenSettings)}
|
||||
data-testid="compact-settings"
|
||||
tabindex="${this.showMenu ? '0' : '-1'}"
|
||||
|
|
@ -339,14 +339,14 @@ export class CompactMenu extends LitElement {
|
|||
${
|
||||
this.session
|
||||
? html`
|
||||
<div class="border-t border-base my-1"></div>
|
||||
<div class="border-t border-border my-1"></div>
|
||||
|
||||
<!-- Session Actions -->
|
||||
${
|
||||
this.session.status === 'running'
|
||||
? html`
|
||||
<button
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-status-error hover:bg-secondary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary' : ''}"
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-status-error hover:bg-surface-hover flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-surface-hover' : ''}"
|
||||
@click=${() => this.handleAction(this.onTerminateSession)}
|
||||
data-testid="compact-terminate-session"
|
||||
tabindex="${this.showMenu ? '0' : '-1'}"
|
||||
|
|
@ -359,7 +359,7 @@ export class CompactMenu extends LitElement {
|
|||
`
|
||||
: html`
|
||||
<button
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-muted hover:bg-secondary hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-secondary text-primary' : ''}"
|
||||
class="w-full text-left px-4 py-3 text-sm font-mono text-text-muted hover:bg-surface-hover hover:text-primary flex items-center gap-3 ${this.focusedIndex === menuItemIndex++ ? 'bg-surface-hover text-primary' : ''}"
|
||||
@click=${() => this.handleAction(this.onClearSession)}
|
||||
data-testid="compact-clear-session"
|
||||
tabindex="${this.showMenu ? '0' : '-1'}"
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export class CtrlAlphaOverlay extends LitElement {
|
|||
<div class="text-primary text-center mb-2 font-bold">Ctrl + Key</div>
|
||||
|
||||
<!-- Help text -->
|
||||
<div class="text-xs text-muted text-center mb-3 opacity-70">
|
||||
<div class="text-xs text-text-muted text-center mb-3 opacity-70">
|
||||
Build sequences like ctrl+c ctrl+c
|
||||
</div>
|
||||
|
||||
|
|
@ -58,8 +58,8 @@ export class CtrlAlphaOverlay extends LitElement {
|
|||
${
|
||||
this.ctrlSequence.length > 0
|
||||
? html`
|
||||
<div class="text-center mb-4 p-2 border border-base rounded bg-base">
|
||||
<div class="text-xs text-muted mb-1">Current sequence:</div>
|
||||
<div class="text-center mb-4 p-2 border border-border rounded bg-bg">
|
||||
<div class="text-xs text-text-muted mb-1">Current sequence:</div>
|
||||
<div class="text-sm text-primary font-bold">
|
||||
${this.ctrlSequence.map((letter) => `Ctrl+${letter}`).join(' ')}
|
||||
</div>
|
||||
|
|
@ -110,7 +110,7 @@ export class CtrlAlphaOverlay extends LitElement {
|
|||
</div>
|
||||
|
||||
<!-- Common shortcuts info -->
|
||||
<div class="text-xs text-muted text-center mb-3">
|
||||
<div class="text-xs text-text-muted text-center mb-3">
|
||||
<div>Common: C=interrupt, X=exit, O=save, W=search</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ export class ImageUploadMenu extends LitElement {
|
|||
<div class="relative">
|
||||
<vt-tooltip content="Upload Image (⌘U)" .show=${!this.isMobile}>
|
||||
<button
|
||||
class="bg-bg-tertiary border border-border rounded-lg p-2 font-mono text-muted transition-all duration-200 hover:text-primary hover:bg-surface-hover hover:border-primary hover:shadow-sm flex-shrink-0"
|
||||
class="bg-bg-tertiary border border-border rounded-lg p-2 font-mono text-text-muted transition-all duration-200 hover:text-primary hover:bg-surface-hover hover:border-primary hover:shadow-sm flex-shrink-0"
|
||||
@click=${this.toggleMenu}
|
||||
@keydown=${this.handleMenuButtonKeyDown}
|
||||
title="Upload Image"
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ export class OverlaysContainer extends LitElement {
|
|||
${
|
||||
this.uiState.isDragOver
|
||||
? html`
|
||||
<div class="fixed inset-0 bg-bg bg-opacity-90 backdrop-blur-sm flex items-center justify-center z-50 pointer-events-none animate-fade-in">
|
||||
<div class="fixed inset-0 bg-bg/90 backdrop-blur-sm flex items-center justify-center z-50 pointer-events-none animate-fade-in">
|
||||
<div class="bg-elevated border-2 border-dashed border-primary rounded-xl p-10 text-center max-w-md mx-4 shadow-2xl animate-scale-in">
|
||||
<div class="relative mb-6">
|
||||
<div class="w-24 h-24 mx-auto bg-gradient-to-br from-primary to-primary-light rounded-full flex items-center justify-center shadow-glow">
|
||||
|
|
@ -192,10 +192,10 @@ export class OverlaysContainer extends LitElement {
|
|||
<div class="absolute -bottom-2 left-1/2 transform -translate-x-1/2 w-32 h-1 bg-gradient-to-r from-transparent via-primary to-transparent opacity-50"></div>
|
||||
</div>
|
||||
<h3 class="text-2xl font-bold text-primary mb-3">Drop files here</h3>
|
||||
<p class="text-sm text-muted mb-4">Files will be uploaded and the path sent to terminal</p>
|
||||
<div class="inline-flex items-center gap-2 text-xs text-dim bg-secondary px-4 py-2 rounded-lg">
|
||||
<p class="text-sm text-text-muted mb-4">Files will be uploaded and the path sent to terminal</p>
|
||||
<div class="inline-flex items-center gap-2 text-xs text-text-dim bg-bg-secondary px-4 py-2 rounded-lg">
|
||||
<span class="opacity-75">Or press</span>
|
||||
<kbd class="px-2 py-1 bg-tertiary border border-base rounded text-primary font-mono text-xs">⌘V</kbd>
|
||||
<kbd class="px-2 py-1 bg-bg-tertiary border border-border rounded text-primary font-mono text-xs">⌘V</kbd>
|
||||
<span class="opacity-75">to paste from clipboard</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -152,9 +152,9 @@ export class SessionHeader extends LitElement {
|
|||
}
|
||||
|
||||
private getStatusDotColor(): string {
|
||||
if (!this.session) return 'bg-muted';
|
||||
if (!this.session) return 'bg-bg-muted';
|
||||
if ('active' in this.session && this.session.active === false) {
|
||||
return 'bg-muted';
|
||||
return 'bg-bg-muted';
|
||||
}
|
||||
return this.session.status === 'running' ? 'bg-status-success' : 'bg-status-warning';
|
||||
}
|
||||
|
|
@ -418,7 +418,7 @@ export class SessionHeader extends LitElement {
|
|||
|
||||
<!-- Terminal size button -->
|
||||
<button
|
||||
class="bg-bg-tertiary border border-border rounded-lg px-3 py-2 font-mono text-xs text-muted transition-all duration-200 hover:text-primary hover:bg-surface-hover hover:border-primary hover:shadow-sm flex-shrink-0 width-selector-button"
|
||||
class="bg-bg-tertiary border border-border rounded-lg px-3 py-2 font-mono text-xs text-text-muted transition-all duration-200 hover:text-primary hover:bg-surface-hover hover:border-primary hover:shadow-sm flex-shrink-0 width-selector-button"
|
||||
@click=${() => this.onMaxWidthToggle?.()}
|
||||
title="${this.widthTooltip}"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ export class SessionStatusDropdown extends LitElement {
|
|||
height="10"
|
||||
viewBox="0 0 10 10"
|
||||
fill="currentColor"
|
||||
class="transition-transform text-muted ${this.showMenu ? 'rotate-180' : ''}"
|
||||
class="transition-transform text-text-muted ${this.showMenu ? 'rotate-180' : ''}"
|
||||
>
|
||||
<path d="M5 7L1 3h8z" />
|
||||
</svg>
|
||||
|
|
@ -235,7 +235,7 @@ export class SessionStatusDropdown extends LitElement {
|
|||
`
|
||||
: html`
|
||||
<button
|
||||
class="w-full text-left px-6 py-3 text-sm font-mono text-muted hover:bg-bg-secondary hover:text-primary flex items-center gap-3 ${
|
||||
class="w-full text-left px-6 py-3 text-sm font-mono text-text-muted hover:bg-bg-secondary hover:text-primary flex items-center gap-3 ${
|
||||
this.focusedIndex === menuItemIndex++ ? 'bg-bg-secondary text-primary' : ''
|
||||
}"
|
||||
@click=${() => this.handleAction(this.onClear)}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export class TerminalDimensions extends LitElement {
|
|||
|
||||
return html`
|
||||
<span
|
||||
class="hidden sm:inline text-muted text-xs opacity-60"
|
||||
class="hidden sm:inline text-text-muted text-xs opacity-60"
|
||||
style="font-size: 10px; line-height: 1;"
|
||||
>
|
||||
${this.cols}×${this.rows}
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ export class TerminalSettingsModal extends LitElement {
|
|||
<div class="flex items-center justify-between mb-6">
|
||||
<h2 id="terminal-settings-title" class="text-lg font-semibold text-text-bright">Terminal Settings</h2>
|
||||
<button
|
||||
class="text-muted hover:text-primary transition-colors p-1"
|
||||
class="text-text-muted hover:text-primary transition-colors p-1"
|
||||
@click=${() => this.handleClose()}
|
||||
title="Close"
|
||||
aria-label="Close terminal settings"
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ export class Settings extends LitElement {
|
|||
<div class="p-4 pb-4 border-b border-border/50 relative flex-shrink-0">
|
||||
<h2 class="text-primary text-lg font-bold">Settings</h2>
|
||||
<button
|
||||
class="absolute top-4 right-4 text-muted hover:text-primary transition-colors p-1"
|
||||
class="absolute top-4 right-4 text-text-muted hover:text-primary transition-colors p-1"
|
||||
@click=${this.handleClose}
|
||||
title="Close"
|
||||
aria-label="Close settings"
|
||||
|
|
@ -431,7 +431,7 @@ export class Settings extends LitElement {
|
|||
${
|
||||
!this.isNotificationsSupported
|
||||
? html`
|
||||
<div class="p-4 bg-status-warning bg-opacity-10 border border-status-warning rounded-lg">
|
||||
<div class="p-4 bg-status-warning/10 border border-status-warning rounded-lg">
|
||||
${
|
||||
isIOSSafari && !isStandalone
|
||||
? html`
|
||||
|
|
@ -452,7 +452,7 @@ export class Settings extends LitElement {
|
|||
`
|
||||
: html`
|
||||
<!-- Main toggle -->
|
||||
<div class="flex items-center justify-between p-4 bg-tertiary rounded-lg border border-border/50">
|
||||
<div class="flex items-center justify-between p-4 bg-bg-tertiary rounded-lg border border-border/50">
|
||||
<div class="flex-1">
|
||||
<label class="text-primary font-medium">Enable Notifications</label>
|
||||
<p class="text-muted text-xs mt-1">
|
||||
|
|
@ -482,8 +482,8 @@ export class Settings extends LitElement {
|
|||
<!-- Notification types -->
|
||||
<div class="mt-4 space-y-4">
|
||||
<div>
|
||||
<h4 class="text-sm font-medium text-muted mb-3">Notification Types</h4>
|
||||
<div class="space-y-2 bg-base rounded-lg p-3">
|
||||
<h4 class="text-sm font-medium text-text-muted mb-3">Notification Types</h4>
|
||||
<div class="space-y-2 bg-bg rounded-lg p-3">
|
||||
${this.renderNotificationToggle('sessionExit', 'Session Exit', 'When a session terminates or crashes (shows exit code)')}
|
||||
${this.renderNotificationToggle('sessionStart', 'Session Start', 'When a new session starts (useful for shared terminals)')}
|
||||
${this.renderNotificationToggle('commandError', 'Session Errors', 'When commands fail with non-zero exit codes')}
|
||||
|
|
@ -495,8 +495,8 @@ export class Settings extends LitElement {
|
|||
|
||||
<!-- Sound and vibration -->
|
||||
<div>
|
||||
<h4 class="text-sm font-medium text-muted mb-3">Notification Behavior</h4>
|
||||
<div class="space-y-2 bg-base rounded-lg p-3">
|
||||
<h4 class="text-sm font-medium text-text-muted mb-3">Notification Behavior</h4>
|
||||
<div class="space-y-2 bg-bg rounded-lg p-3">
|
||||
${this.renderNotificationToggle('soundEnabled', 'Sound', 'Play a notification sound when alerts are triggered')}
|
||||
${this.renderNotificationToggle('vibrationEnabled', 'Vibration', 'Vibrate device with notifications (mobile devices only)')}
|
||||
</div>
|
||||
|
|
@ -562,7 +562,7 @@ export class Settings extends LitElement {
|
|||
${
|
||||
this.mediaState.isMobile
|
||||
? html`
|
||||
<div class="flex items-center justify-between p-4 bg-tertiary rounded-lg border border-border/50">
|
||||
<div class="flex items-center justify-between p-4 bg-bg-tertiary rounded-lg border border-border/50">
|
||||
<div class="flex-1">
|
||||
<label class="text-primary font-medium">
|
||||
Use Direct Keyboard
|
||||
|
|
@ -592,7 +592,7 @@ export class Settings extends LitElement {
|
|||
|
||||
|
||||
<!-- Repository Base Path -->
|
||||
<div class="p-4 bg-tertiary rounded-lg border border-border/50">
|
||||
<div class="p-4 bg-bg-tertiary rounded-lg border border-border/50">
|
||||
<div class="mb-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="text-primary font-medium">Repository Base Path</label>
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ export class SSHKeyManager extends LitElement {
|
|||
|
||||
return html`
|
||||
<div
|
||||
class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-[1000]"
|
||||
class="fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-[1000]"
|
||||
@click=${this.handleBackdropClick}
|
||||
>
|
||||
<div
|
||||
|
|
@ -190,7 +190,7 @@ export class SSHKeyManager extends LitElement {
|
|||
<h2 class="text-2xl font-mono text-primary text-center">🔑 SSH Key Manager</h2>
|
||||
<button
|
||||
@click=${this.handleClose}
|
||||
class="absolute top-0 right-0 w-8 h-8 flex items-center justify-center text-muted hover:text-primary hover:bg-surface rounded transition-colors"
|
||||
class="absolute top-0 right-0 w-8 h-8 flex items-center justify-center text-text-muted hover:text-primary hover:bg-surface rounded transition-colors"
|
||||
title="Close"
|
||||
>
|
||||
✕
|
||||
|
|
@ -277,7 +277,7 @@ export class SSHKeyManager extends LitElement {
|
|||
<div>
|
||||
<label class="form-label">Algorithm</label>
|
||||
<div
|
||||
class="input-field bg-secondary text-muted cursor-not-allowed"
|
||||
class="input-field bg-bg-secondary text-text-muted cursor-not-allowed"
|
||||
>
|
||||
Ed25519 (recommended)
|
||||
</div>
|
||||
|
|
@ -296,7 +296,7 @@ export class SSHKeyManager extends LitElement {
|
|||
}}
|
||||
?disabled=${this.loading}
|
||||
/>
|
||||
<p class="text-muted text-xs mt-1">
|
||||
<p class="text-text-muted text-xs mt-1">
|
||||
💡 Leave empty for unencrypted key. Password is required when using the
|
||||
key for signing.
|
||||
</p>
|
||||
|
|
@ -346,7 +346,7 @@ export class SSHKeyManager extends LitElement {
|
|||
}}
|
||||
?disabled=${this.loading}
|
||||
></textarea>
|
||||
<p class="text-muted text-xs mt-1">
|
||||
<p class="text-text-muted text-xs mt-1">
|
||||
💡 If the key is password-protected, you'll be prompted for the password
|
||||
when using it for authentication.
|
||||
</p>
|
||||
|
|
@ -383,7 +383,7 @@ export class SSHKeyManager extends LitElement {
|
|||
@click=${() => {
|
||||
this.showInstructions = false;
|
||||
}}
|
||||
class="w-8 h-8 flex items-center justify-center text-muted hover:text-primary hover:bg-bg rounded transition-colors"
|
||||
class="w-8 h-8 flex items-center justify-center text-text-muted hover:text-primary hover:bg-bg rounded transition-colors"
|
||||
title="Close instructions"
|
||||
>
|
||||
✕
|
||||
|
|
@ -391,7 +391,7 @@ export class SSHKeyManager extends LitElement {
|
|||
</div>
|
||||
<div class="space-y-6">
|
||||
<div class="bg-bg border border-border rounded-lg p-4">
|
||||
<p class="text-muted text-sm mb-3 font-medium">
|
||||
<p class="text-text-muted text-sm mb-3 font-medium">
|
||||
1. Add the public key to your authorized_keys file:
|
||||
</p>
|
||||
<div class="relative">
|
||||
|
|
@ -415,7 +415,7 @@ echo "${this.sshAgent.getPublicKey(this.instructionsKeyId)}" >> ~/.ssh/authorize
|
|||
</div>
|
||||
</div>
|
||||
<div class="bg-bg border border-border rounded-lg p-4">
|
||||
<p class="text-muted text-sm mb-3 font-medium">2. Or copy the public key:</p>
|
||||
<p class="text-text-muted text-sm mb-3 font-medium">2. Or copy the public key:</p>
|
||||
<div class="relative">
|
||||
<pre
|
||||
class="bg-secondary p-3 rounded-lg text-xs overflow-x-auto text-primary pr-20 font-mono"
|
||||
|
|
@ -437,8 +437,8 @@ ${this.sshAgent.getPublicKey(this.instructionsKeyId)}</pre
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-blue-50 border border-blue-200 rounded-lg p-3">
|
||||
<p class="text-blue-700 text-sm font-mono flex items-center gap-2">
|
||||
<div class="bg-status-info/10 border border-status-info/30 rounded-lg p-3">
|
||||
<p class="text-status-info text-sm font-mono flex items-center gap-2">
|
||||
💡 <strong>Tip:</strong> Make sure ~/.ssh/authorized_keys has correct permissions (600)
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -453,7 +453,7 @@ ${this.sshAgent.getPublicKey(this.instructionsKeyId)}</pre
|
|||
${
|
||||
this.keys.length === 0
|
||||
? html`
|
||||
<div class="text-center py-12 text-muted border border-border rounded-lg bg-surface">
|
||||
<div class="text-center py-12 text-text-muted border border-border rounded-lg bg-surface">
|
||||
<div class="text-4xl mb-4">🔑</div>
|
||||
<p class="font-mono text-lg mb-2 text-primary">No SSH keys found</p>
|
||||
<p class="text-sm">Generate or import a key to get started</p>
|
||||
|
|
@ -473,7 +473,7 @@ ${this.sshAgent.getPublicKey(this.instructionsKeyId)}</pre
|
|||
: ''
|
||||
}
|
||||
</div>
|
||||
<div class="text-sm text-muted font-mono space-y-1">
|
||||
<div class="text-sm text-text-muted font-mono space-y-1">
|
||||
<div>ID: ${key.id}</div>
|
||||
<div>Fingerprint: ${key.fingerprint}</div>
|
||||
<div>Created: ${new Date(key.createdAt).toLocaleString()}</div>
|
||||
|
|
|
|||
|
|
@ -418,7 +418,7 @@ export class TerminalQuickKeys extends LitElement {
|
|||
<button
|
||||
type="button"
|
||||
tabindex="-1"
|
||||
class="quick-key-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-tertiary text-primary font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${modifier ? 'modifier-key' : ''} ${arrow ? 'arrow-key' : ''} ${toggle ? 'toggle-key' : ''} ${toggle && ((key === 'CtrlExpand' && this.showCtrlKeys) || (key === 'F' && this.showFunctionKeys)) ? 'active' : ''} ${modifier && key === 'Option' && this.activeModifiers.has('Option') ? 'active' : ''}"
|
||||
class="quick-key-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-bg-tertiary text-primary font-mono rounded border border-border hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${modifier ? 'modifier-key' : ''} ${arrow ? 'arrow-key' : ''} ${toggle ? 'toggle-key' : ''} ${toggle && ((key === 'CtrlExpand' && this.showCtrlKeys) || (key === 'F' && this.showFunctionKeys)) ? 'active' : ''} ${modifier && key === 'Option' && this.activeModifiers.has('Option') ? 'active' : ''}"
|
||||
@mousedown=${(e: Event) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
|
@ -470,7 +470,7 @@ export class TerminalQuickKeys extends LitElement {
|
|||
<button
|
||||
type="button"
|
||||
tabindex="-1"
|
||||
class="ctrl-shortcut-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-tertiary text-primary font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${combo ? 'combo-key' : ''} ${special ? 'special-key' : ''}"
|
||||
class="ctrl-shortcut-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-bg-tertiary text-primary font-mono rounded border border-border hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${combo ? 'combo-key' : ''} ${special ? 'special-key' : ''}"
|
||||
@mousedown=${(e: Event) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
|
@ -505,7 +505,7 @@ export class TerminalQuickKeys extends LitElement {
|
|||
<button
|
||||
type="button"
|
||||
tabindex="-1"
|
||||
class="func-key-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-tertiary text-primary font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap"
|
||||
class="func-key-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-bg-tertiary text-primary font-mono rounded border border-border hover:bg-surface hover:border-primary transition-all whitespace-nowrap"
|
||||
@mousedown=${(e: Event) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
|
@ -539,7 +539,7 @@ export class TerminalQuickKeys extends LitElement {
|
|||
<button
|
||||
type="button"
|
||||
tabindex="-1"
|
||||
class="quick-key-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-tertiary text-primary font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${modifier ? 'modifier-key' : ''} ${combo ? 'combo-key' : ''} ${special ? 'special-key' : ''} ${toggle ? 'toggle-key' : ''} ${toggle && this.showFunctionKeys ? 'active' : ''}"
|
||||
class="quick-key-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-bg-tertiary text-primary font-mono rounded border border-border hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${modifier ? 'modifier-key' : ''} ${combo ? 'combo-key' : ''} ${special ? 'special-key' : ''} ${toggle ? 'toggle-key' : ''} ${toggle && this.showFunctionKeys ? 'active' : ''}"
|
||||
@mousedown=${(e: Event) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
|
@ -578,7 +578,7 @@ export class TerminalQuickKeys extends LitElement {
|
|||
<button
|
||||
type="button"
|
||||
tabindex="-1"
|
||||
class="quick-key-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-tertiary text-primary font-mono rounded border border-base hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${modifier ? 'modifier-key' : ''} ${combo ? 'combo-key' : ''} ${special ? 'special-key' : ''} ${modifier && key === 'Option' && this.activeModifiers.has('Option') ? 'active' : ''}"
|
||||
class="quick-key-btn ${this.getButtonFontClass(label)} min-w-0 ${this.getButtonSizeClass(label)} bg-bg-tertiary text-primary font-mono rounded border border-border hover:bg-surface hover:border-primary transition-all whitespace-nowrap ${modifier ? 'modifier-key' : ''} ${combo ? 'combo-key' : ''} ${special ? 'special-key' : ''} ${modifier && key === 'Option' && this.activeModifiers.has('Option') ? 'active' : ''}"
|
||||
@mousedown=${(e: Event) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ export class VibeTerminalBuffer extends LitElement {
|
|||
this.error
|
||||
? html`
|
||||
<div class="absolute inset-0 flex items-center justify-center">
|
||||
<div class="text-red-500 text-sm">${this.error}</div>
|
||||
<div class="text-status-error text-sm">${this.error}</div>
|
||||
</div>
|
||||
`
|
||||
: html`
|
||||
|
|
|
|||
|
|
@ -1,36 +1,141 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@import "tailwindcss";
|
||||
|
||||
|
||||
/* Define CSS variables first */
|
||||
:root {
|
||||
/* Light mode colors (default) */
|
||||
--color-bg: rgb(250 250 250);
|
||||
--color-bg-secondary: rgb(245 245 245);
|
||||
--color-bg-tertiary: rgb(237 237 237);
|
||||
--color-bg-elevated: rgb(255 255 255);
|
||||
--color-surface: rgb(245 245 245);
|
||||
--color-surface-hover: rgb(237 237 237);
|
||||
--color-border: rgb(226 226 226);
|
||||
--color-border-light: rgb(237 237 237);
|
||||
--color-border-focus: rgb(200 200 200);
|
||||
--color-text: rgb(23 23 23);
|
||||
--color-text-bright: rgb(0 0 0);
|
||||
--color-text-muted: rgb(75 75 75);
|
||||
--color-text-dim: rgb(115 115 115);
|
||||
--color-primary: #10B981;
|
||||
--color-primary-hover: #059669;
|
||||
--color-primary-dark: #047857;
|
||||
--color-primary-light: #34D399;
|
||||
--color-primary-muted: #10B98133;
|
||||
--color-primary-glow: #10B98166;
|
||||
--color-status-error: #EF4444;
|
||||
--color-status-warning: #F59E0B;
|
||||
--color-status-success: #10B981;
|
||||
--color-status-info: #3B82F6;
|
||||
}
|
||||
|
||||
/* Tailwind v4 Theme Configuration */
|
||||
@theme {
|
||||
/* Register custom colors using CSS variables */
|
||||
--color-bg: var(--color-bg);
|
||||
--color-bg-secondary: var(--color-bg-secondary);
|
||||
--color-bg-tertiary: var(--color-bg-tertiary);
|
||||
--color-bg-elevated: var(--color-bg-elevated);
|
||||
--color-surface: var(--color-surface);
|
||||
--color-surface-hover: var(--color-surface-hover);
|
||||
--color-border: var(--color-border);
|
||||
--color-border-light: var(--color-border-light);
|
||||
--color-border-focus: var(--color-border-focus);
|
||||
--color-text: var(--color-text);
|
||||
--color-text-bright: var(--color-text-bright);
|
||||
--color-text-muted: var(--color-text-muted);
|
||||
--color-text-dim: var(--color-text-dim);
|
||||
--color-primary: var(--color-primary);
|
||||
--color-primary-hover: var(--color-primary-hover);
|
||||
--color-primary-dark: var(--color-primary-dark);
|
||||
--color-primary-light: var(--color-primary-light);
|
||||
--color-primary-muted: var(--color-primary-muted);
|
||||
--color-primary-glow: var(--color-primary-glow);
|
||||
--color-accent-primary: var(--color-primary);
|
||||
--color-accent-green: var(--color-status-success);
|
||||
--color-accent-red: var(--color-status-error);
|
||||
--color-status-error: var(--color-status-error);
|
||||
--color-status-warning: var(--color-status-warning);
|
||||
--color-status-success: var(--color-status-success);
|
||||
--color-status-info: var(--color-status-info);
|
||||
|
||||
/* Box Shadows */
|
||||
--shadow-glow: 0 0 20px rgb(16 185 129 / 0.4);
|
||||
--shadow-glow-sm: 0 0 10px rgb(16 185 129 / 0.3);
|
||||
--shadow-glow-lg: 0 0 30px rgb(16 185 129 / 0.5);
|
||||
--shadow-glow-intense: 0 0 40px rgb(16 185 129 / 0.6);
|
||||
--shadow-glow-error: 0 0 20px rgb(239 68 68 / 0.4);
|
||||
--shadow-glow-error-sm: 0 0 10px rgb(239 68 68 / 0.3);
|
||||
--shadow-glow-error-lg: 0 0 30px rgb(239 68 68 / 0.5);
|
||||
--shadow-glow-warning: 0 0 20px rgb(245 158 11 / 0.4);
|
||||
--shadow-glow-warning-sm: 0 0 10px rgb(245 158 11 / 0.3);
|
||||
--shadow-glow-warning-lg: 0 0 30px rgb(245 158 11 / 0.5);
|
||||
--shadow-card: 0 1px 3px rgb(0 0 0 / 0.3), 0 1px 2px rgb(0 0 0 / 0.4);
|
||||
--shadow-card-hover: 0 4px 6px rgb(0 0 0 / 0.3), 0 2px 4px rgb(0 0 0 / 0.4);
|
||||
--shadow-elevated: 0 10px 15px -3px rgb(0 0 0 / 0.3), 0 4px 6px -2px rgb(0 0 0 / 0.2);
|
||||
|
||||
/* Animations */
|
||||
--animate-pulse-primary: pulsePrimary 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
--animate-slide-in-right: slideInRight 0.3s ease-out;
|
||||
--animate-slide-in-bottom: slideInBottom 0.3s ease-out;
|
||||
--animate-fade-in: fadeIn 0.2s ease-out;
|
||||
--animate-scale-in: scaleIn 0.2s ease-out;
|
||||
}
|
||||
|
||||
/* Keyframes */
|
||||
@keyframes pulsePrimary {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: .7;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInRight {
|
||||
0% {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInBottom {
|
||||
0% {
|
||||
transform: translateY(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scaleIn {
|
||||
0% {
|
||||
transform: scale(0.95);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* CSS Custom Properties for VibeTunnel constants */
|
||||
:root {
|
||||
/* Theme Colors - Light Mode (Default) */
|
||||
--color-bg: 250 250 250; /* #fafafa - Off-white background */
|
||||
--color-bg-secondary: 245 245 245; /* #f5f5f5 - Subtle gray */
|
||||
--color-bg-tertiary: 237 237 237; /* #ededed - Card backgrounds */
|
||||
--color-bg-elevated: 255 255 255; /* #ffffff - Pure white for elevated surfaces */
|
||||
--color-surface: 245 245 245; /* #f5f5f5 */
|
||||
--color-surface-hover: 237 237 237; /* #ededed */
|
||||
--color-border: 226 226 226; /* #e2e2e2 - Subtle gray borders */
|
||||
--color-border-light: 237 237 237; /* #ededed */
|
||||
--color-border-focus: 200 200 200; /* #c8c8c8 */
|
||||
|
||||
/* Text colors - Light Mode */
|
||||
--color-text: 23 23 23; /* #171717 - Near black for high contrast */
|
||||
--color-text-bright: 0 0 0; /* #000000 - Pure black for emphasis */
|
||||
--color-text-muted: 75 75 75; /* #4b4b4b - Darker muted gray for AAA compliance */
|
||||
--color-text-dim: 115 115 115; /* #737373 - Darker dim gray for AA compliance */
|
||||
|
||||
/* Primary color (same across themes) */
|
||||
--color-primary: 16 185 129; /* #10B981 - VibeTunnel green */
|
||||
--color-primary-hover: 5 150 105; /* #059669 */
|
||||
--color-primary-dark: 4 120 87; /* #047857 */
|
||||
|
||||
/* Status colors */
|
||||
--color-status-error: 239 68 68; /* #EF4444 */
|
||||
--color-status-warning: 245 158 11; /* #F59E0B */
|
||||
--color-status-success: 16 185 129; /* #10B981 */
|
||||
--color-status-info: 59 130 246; /* #3B82F6 */
|
||||
/* Breakpoints */
|
||||
--vt-breakpoint-mobile: 768px;
|
||||
--vt-breakpoint-tablet: 1024px;
|
||||
|
|
@ -60,57 +165,39 @@
|
|||
|
||||
/* Dark mode theme colors */
|
||||
[data-theme="dark"] {
|
||||
--color-bg: 23 23 23; /* #171717 - Lighter neutral dark */
|
||||
--color-bg-secondary: 32 32 32; /* #202020 - Slightly darker for sidebar */
|
||||
--color-bg-tertiary: 40 40 40; /* #282828 - For buttons and cards */
|
||||
--color-bg-elevated: 48 48 48; /* #303030 - Elevated surfaces */
|
||||
--color-surface: 36 36 36; /* #242424 - Surface color */
|
||||
--color-surface-hover: 52 52 52; /* #343434 - Hover states */
|
||||
--color-border: 64 64 64; /* #404040 - Subtle borders */
|
||||
--color-border-light: 72 72 72; /* #484848 - Light borders */
|
||||
--color-border-focus: 80 80 80; /* #505050 - Focus borders */
|
||||
|
||||
/* Text colors - Dark Mode */
|
||||
--color-text: 228 228 228; /* #e4e4e4 */
|
||||
--color-text-bright: 255 255 255; /* #ffffff */
|
||||
--color-text-muted: 163 163 163; /* #a3a3a3 */
|
||||
--color-text-dim: 115 115 115; /* #737373 */
|
||||
|
||||
/* Primary color (same as light mode) */
|
||||
--color-primary: 16 185 129; /* #10B981 */
|
||||
--color-primary-hover: 5 150 105; /* #059669 */
|
||||
--color-primary-dark: 4 120 87; /* #047857 */
|
||||
|
||||
/* Status colors (same as light mode) */
|
||||
--color-status-error: 239 68 68; /* #EF4444 */
|
||||
--color-status-warning: 245 158 11; /* #F59E0B */
|
||||
--color-status-success: 16 185 129; /* #10B981 */
|
||||
--color-status-info: 59 130 246; /* #3B82F6 */
|
||||
/* Override CSS variables for dark mode */
|
||||
--color-bg: rgb(23 23 23);
|
||||
--color-bg-secondary: rgb(32 32 32);
|
||||
--color-bg-tertiary: rgb(40 40 40);
|
||||
--color-bg-elevated: rgb(48 48 48);
|
||||
--color-surface: rgb(36 36 36);
|
||||
--color-surface-hover: rgb(52 52 52);
|
||||
--color-border: rgb(64 64 64);
|
||||
--color-border-light: rgb(72 72 72);
|
||||
--color-border-focus: rgb(80 80 80);
|
||||
--color-text: rgb(228 228 228);
|
||||
--color-text-bright: rgb(255 255 255);
|
||||
--color-text-muted: rgb(163 163 163);
|
||||
--color-text-dim: rgb(115 115 115);
|
||||
/* Primary and status colors remain the same */
|
||||
}
|
||||
|
||||
/* System preference detection */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme="light"]) {
|
||||
--color-bg: 23 23 23;
|
||||
--color-bg-secondary: 32 32 32;
|
||||
--color-bg-tertiary: 40 40 40;
|
||||
--color-bg-elevated: 48 48 48;
|
||||
--color-surface: 36 36 36;
|
||||
--color-surface-hover: 52 52 52;
|
||||
--color-border: 64 64 64;
|
||||
--color-border-light: 72 72 72;
|
||||
--color-border-focus: 80 80 80;
|
||||
--color-text: 228 228 228;
|
||||
--color-text-bright: 255 255 255;
|
||||
--color-text-muted: 163 163 163;
|
||||
--color-text-dim: 115 115 115;
|
||||
--color-primary: 16 185 129;
|
||||
--color-primary-hover: 5 150 105;
|
||||
--color-primary-dark: 4 120 87;
|
||||
--color-status-error: 239 68 68;
|
||||
--color-status-warning: 245 158 11;
|
||||
--color-status-success: 16 185 129;
|
||||
--color-status-info: 59 130 246;
|
||||
--color-bg: rgb(23 23 23);
|
||||
--color-bg-secondary: rgb(32 32 32);
|
||||
--color-bg-tertiary: rgb(40 40 40);
|
||||
--color-bg-elevated: rgb(48 48 48);
|
||||
--color-surface: rgb(36 36 36);
|
||||
--color-surface-hover: rgb(52 52 52);
|
||||
--color-border: rgb(64 64 64);
|
||||
--color-border-light: rgb(72 72 72);
|
||||
--color-border-focus: rgb(80 80 80);
|
||||
--color-text: rgb(228 228 228);
|
||||
--color-text-bright: rgb(255 255 255);
|
||||
--color-text-muted: rgb(163 163 163);
|
||||
--color-text-dim: rgb(115 115 115);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,6 +211,126 @@
|
|||
@apply bg-bg text-text;
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
/* Checkbox styling */
|
||||
input[type="checkbox"] {
|
||||
@apply w-4 h-4 rounded border border-border bg-bg cursor-pointer;
|
||||
@apply transition-all duration-200;
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-primary/50;
|
||||
@apply checked:bg-primary checked:border-primary;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked::before {
|
||||
content: '✓';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: white;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Select element styling */
|
||||
select {
|
||||
@apply w-full rounded border border-border bg-bg cursor-pointer;
|
||||
@apply transition-all duration-200;
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-primary/50;
|
||||
@apply hover:border-primary/50;
|
||||
@apply px-3 py-2 pr-8;
|
||||
appearance: none;
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||
background-position: right 0.5rem center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1.5em 1.5em;
|
||||
}
|
||||
|
||||
/* Dark mode select arrow */
|
||||
[data-theme="dark"] select {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%239ca3af' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
/* Textarea styling */
|
||||
textarea {
|
||||
@apply w-full rounded border border-border bg-bg;
|
||||
@apply transition-all duration-200;
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-primary/50;
|
||||
@apply hover:border-primary/50 focus:border-primary;
|
||||
@apply px-3 py-2;
|
||||
resize: vertical;
|
||||
min-height: 80px;
|
||||
}
|
||||
|
||||
/* Radio button styling */
|
||||
input[type="radio"] {
|
||||
@apply w-4 h-4 border border-border bg-bg cursor-pointer;
|
||||
@apply transition-all duration-200;
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-primary/50;
|
||||
appearance: none;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
input[type="radio"]:checked {
|
||||
@apply bg-primary border-primary;
|
||||
}
|
||||
|
||||
input[type="radio"]:checked::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
/* File input styling */
|
||||
input[type="file"] {
|
||||
@apply w-full rounded border border-border bg-bg cursor-pointer;
|
||||
@apply transition-all duration-200;
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-primary/50;
|
||||
@apply hover:border-primary/50;
|
||||
@apply px-3 py-2;
|
||||
@apply text-sm text-text;
|
||||
}
|
||||
|
||||
input[type="file"]::file-selector-button {
|
||||
@apply mr-3 px-3 py-1 rounded bg-primary text-bg;
|
||||
@apply hover:bg-primary-hover;
|
||||
@apply cursor-pointer transition-colors duration-200;
|
||||
border: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Range input styling */
|
||||
input[type="range"] {
|
||||
@apply w-full h-2 bg-bg-tertiary rounded-lg appearance-none cursor-pointer;
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-primary/50;
|
||||
}
|
||||
|
||||
input[type="range"]::-webkit-slider-thumb {
|
||||
@apply appearance-none w-4 h-4 rounded-full bg-primary cursor-pointer;
|
||||
@apply hover:bg-primary-hover transition-colors duration-200;
|
||||
@apply shadow-sm hover:shadow-md;
|
||||
}
|
||||
|
||||
input[type="range"]::-moz-range-thumb {
|
||||
@apply appearance-none w-4 h-4 rounded-full bg-primary cursor-pointer;
|
||||
@apply hover:bg-primary-hover transition-colors duration-200;
|
||||
@apply shadow-sm hover:shadow-md;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Session toggle checkbox specific styling */
|
||||
.session-toggle-checkbox {
|
||||
@apply w-3 h-3;
|
||||
}
|
||||
|
||||
/* Default focus styles */
|
||||
:focus {
|
||||
|
|
@ -174,31 +381,49 @@
|
|||
}
|
||||
|
||||
.btn-sm {
|
||||
@apply btn px-3 py-1.5 text-sm;
|
||||
@apply font-medium rounded-lg transition-all duration-200 ease-in-out;
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-primary/50;
|
||||
@apply disabled:opacity-50 disabled:cursor-not-allowed;
|
||||
@apply px-3 py-1.5 text-sm;
|
||||
}
|
||||
|
||||
.btn-md {
|
||||
@apply btn px-4 py-2;
|
||||
@apply font-medium rounded-lg transition-all duration-200 ease-in-out;
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-primary/50;
|
||||
@apply disabled:opacity-50 disabled:cursor-not-allowed;
|
||||
@apply px-4 py-2;
|
||||
}
|
||||
|
||||
.btn-lg {
|
||||
@apply btn px-6 py-3 text-lg;
|
||||
@apply font-medium rounded-lg transition-all duration-200 ease-in-out;
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-primary/50;
|
||||
@apply disabled:opacity-50 disabled:cursor-not-allowed;
|
||||
@apply px-6 py-3 text-lg;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
@apply btn-md bg-primary text-bg;
|
||||
@apply font-medium rounded-lg transition-all duration-200 ease-in-out;
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-primary/50;
|
||||
@apply disabled:opacity-50 disabled:cursor-not-allowed;
|
||||
@apply px-4 py-2 bg-primary text-bg;
|
||||
@apply hover:bg-primary-hover hover:shadow-glow;
|
||||
@apply active:scale-95;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@apply btn-md border border-primary text-primary;
|
||||
@apply font-medium rounded-lg transition-all duration-200 ease-in-out;
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-primary/50;
|
||||
@apply disabled:opacity-50 disabled:cursor-not-allowed;
|
||||
@apply px-4 py-2 border border-primary text-primary;
|
||||
@apply hover:bg-primary/10 hover:border-primary-hover hover:shadow-glow-sm;
|
||||
@apply active:scale-95;
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
@apply btn-md text-text-muted;
|
||||
@apply font-medium rounded-lg transition-all duration-200 ease-in-out;
|
||||
@apply focus:outline-none focus:ring-2 focus:ring-primary/50;
|
||||
@apply disabled:opacity-50 disabled:cursor-not-allowed;
|
||||
@apply px-4 py-2 text-text-muted;
|
||||
@apply hover:text-text hover:bg-bg-tertiary;
|
||||
}
|
||||
|
||||
|
|
@ -249,19 +474,19 @@
|
|||
}
|
||||
|
||||
.status-badge-success {
|
||||
@apply bg-status-success bg-opacity-20 text-status-success;
|
||||
@apply bg-status-success/20 text-status-success;
|
||||
}
|
||||
|
||||
.status-badge-warning {
|
||||
@apply bg-status-warning bg-opacity-20 text-status-warning;
|
||||
@apply bg-status-warning/20 text-status-warning;
|
||||
}
|
||||
|
||||
.status-badge-error {
|
||||
@apply bg-status-error bg-opacity-20 text-status-error;
|
||||
@apply bg-status-error/20 text-status-error;
|
||||
}
|
||||
|
||||
.status-badge-info {
|
||||
@apply bg-status-info bg-opacity-20 text-status-info;
|
||||
@apply bg-status-info/20 text-status-info;
|
||||
}
|
||||
|
||||
/* Quick start buttons */
|
||||
|
|
@ -280,7 +505,7 @@
|
|||
|
||||
/* Modal backdrop */
|
||||
.modal-backdrop {
|
||||
@apply fixed inset-0 bg-bg bg-opacity-80;
|
||||
@apply fixed inset-0 bg-bg/80;
|
||||
z-index: 1000;
|
||||
backdrop-filter: blur(4px);
|
||||
/* Disable all transitions and animations */
|
||||
|
|
@ -291,7 +516,7 @@
|
|||
/* Modal content */
|
||||
.modal-content {
|
||||
@apply bg-bg-secondary border border-border rounded-xl;
|
||||
@apply shadow-2xl shadow-black/50;
|
||||
@apply shadow-2xl;
|
||||
position: relative;
|
||||
z-index: 1001;
|
||||
/* Disable all transitions and animations */
|
||||
|
|
@ -521,7 +746,7 @@
|
|||
|
||||
/* Focus within styles */
|
||||
.focus-within-glow:focus-within {
|
||||
@apply shadow-glow-sm ring-2 ring-primary ring-opacity-50;
|
||||
@apply shadow-glow-sm ring-2 ring-primary/50;
|
||||
}
|
||||
|
||||
/* Smooth color transitions */
|
||||
|
|
@ -1660,7 +1885,6 @@ body.initial-session-load .session-flex-responsive > session-card:nth-child(n +
|
|||
|
||||
|
||||
|
||||
|
||||
/* Black hole collapse animation for session removal */
|
||||
@keyframes black-hole-collapse {
|
||||
0% {
|
||||
|
|
@ -1935,4 +2159,4 @@ body.initial-session-load .session-flex-responsive > session-card:nth-child(n +
|
|||
/* Focus visible for keyboard navigation */
|
||||
.session-toggle-checkbox:focus-visible {
|
||||
box-shadow: 0 0 0 2px rgb(var(--color-primary) / 0.4);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
"./src/**/*.{html,js,ts,jsx,tsx}",
|
||||
"./public/**/*.html",
|
||||
"!./node_modules/**/*"
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
// Theme-aware colors using CSS variables
|
||||
"bg": "rgb(var(--color-bg) / <alpha-value>)",
|
||||
"bg-secondary": "rgb(var(--color-bg-secondary) / <alpha-value>)",
|
||||
"bg-tertiary": "rgb(var(--color-bg-tertiary) / <alpha-value>)",
|
||||
"bg-elevated": "rgb(var(--color-bg-elevated) / <alpha-value>)",
|
||||
"surface": "rgb(var(--color-surface) / <alpha-value>)",
|
||||
"surface-hover": "rgb(var(--color-surface-hover) / <alpha-value>)",
|
||||
"border": "rgb(var(--color-border) / <alpha-value>)",
|
||||
"border-light": "rgb(var(--color-border-light) / <alpha-value>)",
|
||||
"border-focus": "rgb(var(--color-border-focus) / <alpha-value>)",
|
||||
|
||||
// Text colors
|
||||
"text": "rgb(var(--color-text) / <alpha-value>)",
|
||||
"text-bright": "rgb(var(--color-text-bright) / <alpha-value>)",
|
||||
"text-muted": "rgb(var(--color-text-muted) / <alpha-value>)",
|
||||
"text-dim": "rgb(var(--color-text-dim) / <alpha-value>)",
|
||||
|
||||
// Unified accent color - Vibrant teal-green (stays the same across themes)
|
||||
"primary": "#10B981",
|
||||
"primary-hover": "#059669",
|
||||
"primary-dark": "#047857",
|
||||
"primary-light": "#34D399",
|
||||
"primary-muted": "#10B98133",
|
||||
"primary-glow": "#10B98166",
|
||||
|
||||
// Status colors
|
||||
"status-error": "#EF4444",
|
||||
"status-warning": "#F59E0B",
|
||||
"status-success": "#10B981",
|
||||
"status-info": "#3B82F6",
|
||||
},
|
||||
boxShadow: {
|
||||
// Unified glow effects with primary color
|
||||
'glow': '0 0 20px rgba(16, 185, 129, 0.4)',
|
||||
'glow-sm': '0 0 10px rgba(16, 185, 129, 0.3)',
|
||||
'glow-lg': '0 0 30px rgba(16, 185, 129, 0.5)',
|
||||
'glow-intense': '0 0 40px rgba(16, 185, 129, 0.6)',
|
||||
// Status-specific glow effects
|
||||
'glow-error': '0 0 20px rgba(239, 68, 68, 0.4)',
|
||||
'glow-error-sm': '0 0 10px rgba(239, 68, 68, 0.3)',
|
||||
'glow-error-lg': '0 0 30px rgba(239, 68, 68, 0.5)',
|
||||
'glow-warning': '0 0 20px rgba(245, 158, 11, 0.4)',
|
||||
'glow-warning-sm': '0 0 10px rgba(245, 158, 11, 0.3)',
|
||||
'glow-warning-lg': '0 0 30px rgba(245, 158, 11, 0.5)',
|
||||
// Subtle shadows for depth
|
||||
'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-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: {
|
||||
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',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
Loading…
Reference in a new issue