diff --git a/src/index.css b/src/index.css index dc72e237..21a3e8cb 100644 --- a/src/index.css +++ b/src/index.css @@ -1,5 +1,8 @@ @import './styles/tokens.css'; -@import './styles/components.css'; +@import './styles/utilities.css'; +@import './styles/controls.css'; +@import './styles/messaging.css'; +@import './styles/panels.css'; @import './styles/markdown.css'; @tailwind base; @tailwind components; diff --git a/src/styles/components.css b/src/styles/components.css deleted file mode 100644 index 06442aed..00000000 --- a/src/styles/components.css +++ /dev/null @@ -1,2344 +0,0 @@ -/* Reusable component utilities using tokens */ - -/* Base token utility helpers */ -.text-primary { - color: var(--text-primary); -} - -.text-secondary { - color: var(--text-secondary); -} - -.text-muted { - color: var(--text-muted); -} - -.text-inverted { - color: var(--text-inverted); -} - -.text-accent { - color: var(--accent-primary); -} - -.bg-surface-base { - background-color: var(--surface-base); -} - -.bg-surface-secondary { - background-color: var(--surface-secondary); -} - -.bg-surface-muted { - background-color: var(--surface-muted); -} - -.border-base { - border-color: var(--border-base); -} - -.icon-muted { - color: var(--text-muted); -} - -.icon-accent { - color: var(--accent-primary); -} - -.icon-danger-hover:hover { - color: var(--status-error); -} - -.icon-accent-hover:hover { - color: var(--accent-primary); -} - -.ring-accent-inset { - box-shadow: inset 0 0 0 2px var(--accent-primary); -} - -.button-primary { - @apply inline-flex items-center justify-center gap-2 rounded-lg px-6 py-3 text-base font-medium transition-colors; - background-color: var(--accent-primary); - color: var(--text-inverted); -} - -.button-primary:hover:not(:disabled) { - opacity: 0.9; -} - -.button-primary:focus-visible { - outline: none; - box-shadow: 0 0 0 2px var(--surface-base), 0 0 0 4px var(--accent-primary); -} - -.button-primary:disabled { - @apply cursor-not-allowed opacity-50; -} - -/* Ensure Tailwind base reset on [type="button"] doesn't remove accent styles */ -button.button-primary { - @apply inline-flex items-center justify-center gap-2 px-4 py-2 rounded-md font-medium transition-colors; - color: #fff; - background-color: var(--accent-primary); - border: 1px solid var(--accent-primary); -} - -button.button-primary:hover:not(:disabled) { - background-color: var(--accent-hover); - border-color: var(--accent-hover); -} - -button.button-primary:focus-visible { - outline: none; - box-shadow: 0 0 0 2px var(--surface-base), 0 0 0 4px var(--accent-primary); -} - -button.button-primary:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -/* Message item base styles */ - -.message-item-base { - @apply flex flex-col gap-2 p-3 w-full; -} - - -[data-theme="dark"] button.button-primary { - background-color: #3f3f46; - color: #f5f6f8; -} - -[data-theme="dark"] button.button-primary:hover:not(:disabled) { - background-color: #52525b; - opacity: 1; -} - -.button-secondary { - @apply inline-flex items-center justify-center gap-2 rounded-lg px-6 py-3 text-base font-medium transition-colors; - background-color: var(--surface-secondary); - color: var(--text-primary); - border: 1px solid var(--border-base); -} - -.button-secondary:hover:not(:disabled) { - background-color: var(--surface-hover); -} - -.button-secondary:focus-visible { - outline: none; - box-shadow: 0 0 0 2px var(--surface-base), 0 0 0 4px var(--accent-primary); -} - -.button-secondary:disabled { - @apply cursor-not-allowed opacity-50; -} - -.button-tertiary { - @apply inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors; - background-color: transparent; - color: var(--text-secondary); - border: 1px solid var(--border-base); -} - -.button-tertiary:hover:not(:disabled) { - color: var(--text-primary); - background-color: var(--surface-hover); -} - -.button-tertiary:focus-visible { - outline: none; - box-shadow: 0 0 0 2px var(--surface-base), 0 0 0 4px var(--accent-primary); -} - -.button-tertiary:disabled { - @apply cursor-not-allowed opacity-50; -} - -/* Message item base styles */ - -.message-item-base { - @apply flex flex-col gap-2 p-3 w-full; -} - -.assistant-message { - /* gap: 0.25rem; */ - padding: 0.6rem 0.65rem; -} - -/* Message state badges */ -.message-queued-badge { - @apply inline-block font-bold px-3 py-1 rounded mb-3 text-xs tracking-wide; - background-color: var(--accent-primary); - color: var(--text-inverted); -} - -/* Message error block */ -.message-error-block { - @apply text-sm p-3 rounded border-l-[3px] my-2; - color: var(--status-error); - background-color: rgba(244, 67, 54, 0.1); - border-color: var(--status-error); -} - -[data-theme="dark"] .message-error-block { - background-color: rgba(244, 67, 54, 0.15); -} - -/* Message generating indicator */ -.message-generating { - @apply text-sm italic py-2; - color: var(--text-muted); -} - -/* Message sending indicator */ -.message-sending { - @apply text-xs italic mt-1; - color: var(--text-muted); -} - -/* Message error indicator */ -.message-error { - @apply text-xs mt-1; - color: var(--status-error); -} - -/* Generating spinner animation */ -.generating-spinner { - @apply inline-block; - animation: pulse 1.5s ease-in-out infinite; -} - -@keyframes pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.5; } -} - -/* Prompt input component utilities */ -.prompt-input-container { - @apply flex flex-col border-t; - border-color: var(--border-base); - background-color: var(--surface-base); -} - -.prompt-input-wrapper { - @apply flex items-end gap-2 p-3; -} - -.prompt-input { - @apply flex-1 min-h-[96px] max-h-[200px] p-2.5 border rounded-md text-sm resize-none outline-none transition-colors; - font-family: inherit; - background-color: var(--surface-base); - color: inherit; - border-color: var(--border-base); - line-height: var(--line-height-normal); -} - -.prompt-input:focus { - border-color: var(--accent-primary); -} - -.prompt-input:disabled { - @apply opacity-60 cursor-not-allowed; -} - -.prompt-input::placeholder { - color: var(--text-muted); -} - -.send-button { - @apply w-10 h-10 rounded-md border-none cursor-pointer flex items-center justify-center transition-all flex-shrink-0; - background-color: var(--accent-primary); - color: var(--text-inverted); -} - -.send-button:hover:not(:disabled) { - @apply opacity-90 scale-105; -} - -.send-button:active:not(:disabled) { - @apply scale-95; -} - -.send-button:disabled { - @apply opacity-40 cursor-not-allowed; -} - -.send-icon { - @apply text-base; -} - -.prompt-input-hints { - @apply px-4 pb-2 flex justify-between items-center; -} - -.hint { - @apply text-xs; - color: var(--text-muted); -} - -.hint kbd { - @apply inline-block px-1.5 py-0.5 text-xs font-mono rounded mx-0.5; - background-color: var(--surface-secondary); - border: 1px solid var(--border-base); - border-radius: 3px; -} - -/* Attachment chip utilities */ -.attachment-chip { - @apply inline-flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs font-medium ring-1 ring-inset; - background-color: var(--accent-primary); - color: var(--accent-primary); - --attachment-bg: rgba(0, 102, 255, 0.1); - --attachment-text: #0066ff; - --attachment-ring: rgba(0, 102, 255, 0.1); - background-color: var(--attachment-bg); - color: var(--attachment-text); - ring-color: var(--attachment-ring); -} - -[data-theme="dark"] .attachment-chip { - --attachment-bg: rgba(0, 128, 255, 0.1); - --attachment-text: #0080ff; - --attachment-ring: rgba(0, 128, 255, 0.2); -} - -.attachment-remove { - @apply ml-0.5 flex h-4 w-4 items-center justify-center rounded transition-colors; -} - -.attachment-remove:hover { - background-color: rgba(0, 102, 255, 0.1); -} - -[data-theme="dark"] .attachment-remove:hover { - background-color: rgba(0, 128, 255, 0.2); -} - -/* Neutral badge utilities */ -.neutral-badge { - @apply inline-flex items-center rounded px-1.5 py-0.5 text-xs font-normal; - --badge-bg: rgba(0, 102, 255, 0.05); - --badge-text: #0066ff; - background-color: var(--badge-bg); - color: var(--badge-text); -} - -[data-theme="dark"] .neutral-badge { - --badge-bg: rgba(0, 128, 255, 0.15); - --badge-text: #0080ff; -} - -/* Status badge utilities */ -.status-badge { - @apply inline-flex items-center gap-1.5 rounded px-2 py-1 text-xs font-medium; -} - -.status-badge.ready { - background-color: rgba(34, 197, 94, 0.1); - color: #16a34a; -} - -[data-theme="dark"] .status-badge.ready { - background-color: rgba(34, 197, 94, 0.2); - color: #22c55e; -} - -.status-badge.starting { - background-color: rgba(250, 204, 21, 0.1); - color: #ca8a04; -} - -[data-theme="dark"] .status-badge.starting { - background-color: rgba(250, 204, 21, 0.2); - color: #facc15; -} - -.status-badge.error { - background-color: rgba(239, 68, 68, 0.1); - color: #dc2626; -} - -[data-theme="dark"] .status-badge.error { - background-color: rgba(239, 68, 68, 0.2); - color: #ef4444; -} - -.status-badge.stopped { - background-color: rgba(107, 114, 128, 0.1); - color: #6b7280; -} - -[data-theme="dark"] .status-badge.stopped { - background-color: rgba(107, 114, 128, 0.2); - color: #9ca3af; -} - -.status-dot { - @apply w-1 h-1 rounded-full; -} - -.status-dot.ready { - background-color: #16a34a; -} - -.status-dot.starting { - background-color: #ca8a04; -} - -.status-dot.error { - background-color: #dc2626; -} - -.status-dot.stopped { - background-color: #6b7280; -} - -/* Tab component utilities */ -.tab-bar { - @apply border-b; - border-color: var(--border-base); -} - -.tab-bar-instance { - background-color: var(--surface-secondary); -} - -.tab-bar-session { - background-color: var(--surface-base); -} - -[data-theme="dark"] .tab-bar-session { - background-color: var(--surface-secondary); -} - -.tab-container { - @apply flex items-center justify-between gap-1 px-2 py-1 overflow-x-auto; -} - -.tab-base { - @apply inline-flex items-center gap-2 px-3 py-2 rounded-t-md max-w-[200px] transition-colors text-sm font-medium; - font-family: var(--font-family-sans); - outline: none; -} - -.tab-base:focus-visible { - @apply ring-2 ring-offset-1; - ring-color: var(--accent-primary); - ring-offset-color: var(--surface-base); -} - -.tab-active { - background-color: var(--accent-primary); - color: var(--text-inverted); -} - -.tab-inactive { - background-color: var(--surface-secondary); - color: var(--text-secondary); -} - -.tab-inactive:hover { - background-color: var(--surface-hover); -} - -[data-theme="dark"] .tab-active { - background-color: #3f3f46; - color: #f5f6f8; -} - -[data-theme="dark"] .tab-active:hover { - background-color: #52525b; -} - -[data-theme="dark"] .tab-inactive { - background-color: #2a2a31; - color: #d4d4d8; -} - -[data-theme="dark"] .tab-inactive:hover { - background-color: #3f3f46; - color: #f5f6f8; -} - -.tab-label { - @apply truncate; -} - -.tab-close { - @apply opacity-0 group-hover:opacity-100 hover:bg-red-500 hover:text-white rounded p-0.5 transition-all cursor-pointer; -} - -.tab-close:focus-visible { - @apply ring-2 ring-offset-1; - ring-color: var(--accent-primary); - ring-offset-color: inherit; -} - -.new-tab-button { - @apply inline-flex items-center justify-center w-8 h-8 rounded-md transition-colors; - background-color: var(--surface-secondary); - color: var(--text-muted); -} - -.new-tab-button:hover { - background-color: var(--surface-hover); -} - -[data-theme="dark"] .new-tab-button { - background-color: #3f3f46; - color: #f5f6f8; -} - -[data-theme="dark"] .new-tab-button:hover { - background-color: #52525b; -} - -.new-tab-button:focus-visible { - @apply ring-2 ring-offset-1; - ring-color: var(--accent-primary); - ring-offset-color: var(--surface-base); -} - -/* Session tab specific styles */ -.session-tab-base { - @apply inline-flex items-center gap-2 px-3 py-1.5 rounded-t-md max-w-[150px] transition-colors text-sm; - font-family: var(--font-family-sans); - outline: none; - border-bottom: 2px solid transparent; -} - -.session-tab-base:focus-visible { - @apply ring-2 ring-offset-1; - ring-color: var(--accent-primary); - ring-offset-color: var(--surface-base); -} - -.session-tab-active { - background-color: var(--surface-base); - border-bottom-color: var(--accent-primary); - color: var(--text-primary); - font-weight: var(--font-weight-medium); -} - -[data-theme="dark"] .session-tab-active { - background-color: var(--surface-muted); -} - -.session-tab-inactive { - color: var(--text-muted); -} - -.session-tab-inactive:hover { - background-color: var(--surface-hover); -} - -.session-tab-special { - color: var(--text-muted); -} - -/* Message stream component utilities */ -.message-stream-container { - @apply relative flex-1 min-h-0 flex flex-col overflow-hidden; -} - -.connection-status { - @apply grid items-center px-4 py-2 gap-4; - grid-template-columns: 1fr auto 1fr; - background-color: var(--surface-secondary); - border-bottom: 1px solid var(--border-base); -} - -.connection-status-info { - justify-self: start; -} - -.connection-status-shortcut { - justify-self: center; - text-align: center; -} - -.connection-status-meta { - justify-self: end; -} - -.connection-status-text { - color: var(--text-muted); -} - -:root { - --session-status-working-fg: #b45309; - --session-status-working-bg: rgba(245, 158, 11, 0.16); - --session-status-compacting-fg: #6d28d9; - --session-status-compacting-bg: rgba(109, 40, 217, 0.18); - --session-status-idle-fg: #15803d; - --session-status-idle-bg: rgba(22, 163, 74, 0.16); - --list-item-highlight-bg: rgba(0, 102, 255, 0.1); - --list-item-highlight-border: rgba(0, 102, 255, 0.25); -} - -[data-theme="dark"] { - --session-status-working-fg: #facc15; - --session-status-working-bg: rgba(250, 204, 21, 0.25); - --session-status-compacting-fg: #c084fc; - --session-status-compacting-bg: rgba(192, 132, 252, 0.28); - --session-status-idle-fg: #4ade80; - --session-status-idle-bg: rgba(74, 222, 128, 0.22); - --list-item-highlight-bg: rgba(0, 128, 255, 0.2); - --list-item-highlight-border: rgba(0, 128, 255, 0.4); -} - -.status-indicator { - @apply flex items-center gap-1.5 text-xs; - color: var(--text-muted); -} - -.status-dot { - @apply w-2 h-2 rounded-full; -} - -.status-indicator.connected .status-dot { - background-color: var(--status-success); -} - -.status-indicator.connecting .status-dot { - background-color: var(--status-warning); - animation: pulse 1.5s ease-in-out infinite; -} - -.status-indicator.disconnected .status-dot { - background-color: var(--status-error); -} - -.status-indicator.session-status { - --session-status-dot: var(--text-muted); -} - -.status-indicator.session-status.session-working, -.status-indicator.session-status.session-compacting, -.status-indicator.session-status.session-idle { - font-weight: var(--font-weight-medium); -} - -.status-indicator.session-status.session-working { - color: var(--session-status-working-fg); - --session-status-dot: var(--session-status-working-fg); -} - -.status-indicator.session-status.session-compacting { - color: var(--session-status-compacting-fg); - --session-status-dot: var(--session-status-compacting-fg); -} - -.status-indicator.session-status.session-idle { - color: var(--session-status-idle-fg); - --session-status-dot: var(--session-status-idle-fg); -} - -.status-indicator.session-status .status-dot { - background-color: var(--session-status-dot); -} - -.status-indicator.session-status.session-working .status-dot, -.status-indicator.session-status.session-compacting .status-dot { - animation: pulse 1.5s ease-in-out infinite; -} - -.status-indicator.session-status.session-working.session-status-list { - background-color: var(--session-status-working-bg); -} - -.status-indicator.session-status.session-compacting.session-status-list { - background-color: var(--session-status-compacting-bg); -} - -.status-indicator.session-status.session-idle.session-status-list { - background-color: var(--session-status-idle-bg); -} - -.status-indicator.session-status-list { - font-size: 0.65rem; - text-transform: uppercase; - letter-spacing: 0.05em; - font-weight: var(--font-weight-medium); - color: inherit; - display: inline-flex; - align-items: center; - gap: 0.25rem; - padding: 0.125rem 0.5rem; - border-radius: 9999px; - border: 1px solid transparent; -} - - -.message-stream { - @apply flex-1 min-h-0 overflow-y-auto flex flex-col gap-1; - background-color: var(--surface-base); - color: inherit; -} - - -.message-scroll-button-wrapper { - position: absolute; - right: 1rem; - bottom: 1rem; - display: flex; - flex-direction: column; - gap: 0.5rem; - align-items: flex-end; -} - -.message-scroll-button { - @apply inline-flex items-center justify-center; - width: 2.75rem; - height: 2.75rem; - border-radius: 9999px; - border: 1px solid var(--border-base); - background-color: transparent; - color: var(--text-primary); - box-shadow: 0 10px 25px rgba(0, 0, 0, 0.08); - transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease; -} - -.message-scroll-button:hover { - background-color: var(--surface-hover); - transform: translateY(-1px); -} - -.message-scroll-button:focus-visible { - outline: none; - box-shadow: 0 0 0 2px var(--surface-base), 0 0 0 4px var(--accent-primary); -} - -.message-scroll-icon { - font-size: var(--font-size-lg); - color: var(--accent-primary); -} - -/* Tool call message wrapper */ -.tool-call-message { - @apply flex flex-col gap-2 p-3 w-full; - background-color: var(--message-tool-bg); - border-left: 4px solid var(--message-tool-border); - color: inherit; -} - - -.tool-call-header-label { - @apply flex items-center justify-between gap-2 font-semibold text-sm; - color: var(--message-tool-border); - margin-bottom: 1px; -} - -.tool-call-header-meta { - @apply flex items-center gap-2; -} - -.tool-call-header-button { - background-color: transparent; - border: 1px solid var(--border-base); - color: var(--message-tool-border); - padding: 0.15rem 0.75rem; - border-radius: 0.375rem; - font-size: 0.75rem; - font-weight: var(--font-weight-semibold); - line-height: 1; - display: inline-flex; - align-items: center; - justify-content: center; - height: 1.5rem; - transition: all 0.2s ease; -} - -.tool-call-header-button:hover:not(:disabled) { - background-color: var(--surface-hover); - border-color: var(--accent-primary); - color: var(--accent-primary); -} - -.tool-call-header-button:active:not(:disabled) { - transform: scale(0.95); -} - -.tool-call-header-button:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.tool-call-header-label .tool-call-icon { - @apply text-base; -} - -.tool-call-header-label .tool-name { - font-family: var(--font-family-mono); - color: inherit; - background-color: var(--surface-secondary); - border: 1px solid var(--border-base); - padding: 2px 6px; - border-radius: 3px; - font-size: 13px; -} - -/* Message text styling */ -.message-text { - font-size: var(--font-size-base); - line-height: var(--line-height-normal); - word-wrap: break-word; - overflow-wrap: break-word; - color: inherit; -} - -.message-text-assistant { - white-space: normal; -} - -.message-text pre { - overflow-x: auto; - padding: 8px; - background-color: var(--surface-code); - border-radius: 4px; -} - -/* Message error part */ -.message-error-part { - color: var(--status-error); - font-size: var(--font-size-base); - padding: 8px; - background-color: rgba(244, 67, 54, 0.1); - border-radius: 4px; -} - -[data-theme="dark"] .message-error-part { - background-color: rgba(244, 67, 54, 0.15); -} - -/* Message reasoning */ -.message-reasoning { - @apply my-2 border rounded; - border-color: var(--border-base); - background-color: var(--surface-secondary); - color: inherit; -} - -.reasoning-container { - @apply p-2; -} - -.reasoning-header { - @apply flex items-center gap-1.5 text-xs cursor-pointer select-none; - color: var(--text-muted); -} - -.reasoning-header:hover { - color: var(--accent-primary); -} - -.reasoning-icon { - @apply text-xs; - transition: transform 150ms ease; -} - -.reasoning-label { - font-weight: var(--font-weight-medium); -} - -/* Tool call component */ -.tool-call { - @apply border overflow-hidden; - border-color: var(--border-base); - color: inherit; - --tool-call-line-unit: 1.4em; - --tool-call-lines-compact: 24; - --tool-call-lines-large: 48; - --tool-call-max-height-compact: calc(var(--tool-call-lines-compact) * var(--tool-call-line-unit)); - --tool-call-max-height-large: calc(var(--tool-call-lines-large) * var(--tool-call-line-unit)); -} - - -.tool-call-message .tool-call { - border: none; - border-radius: 0; - margin: 0; -} - -.tool-call-header { - @apply flex items-center gap-2 p-2 w-full bg-transparent border-none cursor-pointer text-left; - font-family: var(--font-family-mono); - font-size: 13px; - border-radius: 0; -} - -.tool-call-header:hover { - background-color: var(--surface-hover); -} - -.tool-call-icon { - @apply text-xs; -} - -.tool-call-summary { - @apply flex-1 text-left; -} - -.tool-call-status { - @apply text-sm; -} - -.tool-call-status-success { - border-left: 3px solid var(--status-success); -} - -.tool-call-status-error { - border-left: 3px solid var(--status-error); -} - -.tool-call-status-running { - border-left: 3px solid var(--status-warning); -} - -.tool-call-status-running .tool-call-status { - animation: pulse 1.5s ease-in-out infinite; -} - -.tool-call-status-pending { - border-left: 3px solid var(--accent-primary); -} - -.tool-call-status-pending .tool-call-summary { - animation: shimmer 2s ease-in-out infinite; -} - -@keyframes shimmer { - 0%, 100% { opacity: 0.6; } - 50% { opacity: 1; } -} - -.tool-call-preview { - @apply p-2 flex flex-col gap-1.5; - background-color: var(--surface-code); - border-top: 1px solid var(--border-base); -} - -.tool-call-preview-label { - @apply text-xs font-semibold uppercase tracking-wide; - color: var(--text-muted); - letter-spacing: 0.5px; -} - -.tool-call-preview-text { - font-family: var(--font-family-mono); - font-size: var(--font-size-xs); - line-height: var(--line-height-tight); - color: var(--text-muted); - white-space: pre-wrap; - word-wrap: break-word; - overflow-wrap: break-word; - max-height: var(--tool-call-max-height-compact, calc(25 * 1.4em)); - overflow-y: scroll; -} - -.tool-call-details { - - @apply flex flex-col; - background-color: var(--surface-code); - font-size: var(--font-size-xs); -} - -.tool-call-markdown { - background-color: var(--surface-code); - border: none; - border-radius: 0; - padding: 0; - font-size: var(--font-size-xs); - line-height: var(--line-height-tight); - max-height: var(--tool-call-max-height-compact, calc(25 * 1.4em)); - overflow-y: scroll; - scrollbar-width: thin; - scrollbar-color: var(--border-base) transparent; - scrollbar-gutter: stable both-edges; - position: relative; -} - -.tool-call-markdown-large { - max-height: var(--tool-call-max-height-large, calc(48 * 1.4em)); -} - -.tool-call-diff-shell { - padding: 0; -} - -.tool-call-diff-viewer { - max-height: var(--tool-call-max-height-large, calc(48 * 1.4em)); - overflow: auto; - background-color: var(--surface-code); -} - -.tool-call-diff-toolbar { - @apply flex items-center justify-between gap-3 px-3 py-2; - background-color: var(--surface-secondary); - border-bottom: 1px solid var(--border-base); -} - -.tool-call-diff-toolbar-label { - font-size: 11px; - color: var(--text-muted); - text-transform: uppercase; - letter-spacing: 0.08em; -} - -.tool-call-diff-toggle { - @apply inline-flex items-center gap-1; -} - -.tool-call-diff-mode-button { - @apply border text-xs font-semibold px-3 py-1 rounded transition-all duration-150; - border-color: var(--border-base); - background-color: transparent; - color: var(--text-muted); -} - -.tool-call-diff-mode-button:hover { - background-color: var(--surface-hover); - color: var(--text-primary); -} - -.tool-call-diff-mode-button.active { - background-color: var(--accent-primary); - border-color: var(--accent-primary); - color: var(--text-inverted); -} - -.tool-call-diff-viewer .diff-tailwindcss-wrapper { - background-color: transparent; - color: inherit; -} - -.tool-call-diff-viewer .diff-view-wrapper { - font-family: var(--font-family-mono); -} - -.tool-call-diff-fallback { - margin: 0; - padding: 0.75rem; - background-color: var(--surface-code); - font-family: var(--font-family-mono); - font-size: var(--font-size-xs); - line-height: var(--line-height-tight); -} - -.tool-call-diff-viewer .diff-line-old-num, -.tool-call-diff-viewer .diff-line-new-num, -.tool-call-diff-viewer .diff-line-num { - width: auto !important; - min-width: 4ch; - padding-left: 0.5rem; - padding-right: 0.5rem; - white-space: nowrap; -} - -.tool-call-markdown .markdown-code-block { - - margin: 0; - border: none; - background-color: transparent; -} - -.tool-call-markdown .code-block-header { - position: sticky; - top: 0; - z-index: auto; - box-shadow: 0 1px 0 var(--border-base); -} - -.tool-call-markdown .markdown-code-block pre { - margin: 0 !important; - min-height: auto; - max-height: none; - overflow-y: visible; -} - -.tool-call-markdown::-webkit-scrollbar { - width: 8px; -} - -.tool-call-markdown::-webkit-scrollbar-track { - background: transparent; -} - -.tool-call-markdown::-webkit-scrollbar-thumb { - background-color: var(--border-base); - border-radius: 4px; - border: 2px solid transparent; - background-clip: padding-box; -} - -.tool-call-section h4 { - font-size: var(--font-size-xs); - font-weight: var(--font-weight-semibold); - margin-bottom: 4px; - color: var(--text-muted); -} - -.tool-call-section pre { - margin: 0; - padding: 8px; - background-color: var(--surface-base); - border-radius: 0px; - overflow-x: auto; - max-height: var(--tool-call-max-height-compact, calc(25 * 1.4em)); - overflow-y: scroll; -} - -.tool-call-section code { - - font-family: var(--font-family-mono); - font-size: var(--font-size-xs); - line-height: var(--line-height-tight); -} - -.tool-call-section pre::-webkit-scrollbar { - width: 8px; - height: 8px; -} - -.tool-call-section pre::-webkit-scrollbar-track { - background: var(--surface-secondary); - border-radius: 0px; -} - -.tool-call-section pre::-webkit-scrollbar-thumb { - background: var(--border-base); - border-radius: 0px; -} - -.tool-call-section pre::-webkit-scrollbar-thumb:hover { - background: var(--text-muted); -} - -.tool-call-pending-message { - @apply flex items-center gap-2 p-3 text-xs italic; - color: var(--text-muted); -} - -.tool-call-emoji { - @apply text-base mr-1; -} - - -.tool-call-action-button { - @apply border text-xs font-semibold px-3 py-1 rounded transition-colors h-8 flex items-center; - border-color: var(--border-base); - color: var(--text-muted); - background-color: transparent; -} - -.tool-call-action-button:hover:not(:disabled) { - background-color: var(--surface-hover); - color: var(--text-primary); -} - -.tool-call-action-button:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.tool-call-bash, -.tool-call-diff { - @apply my-2; -} - -.tool-call-content { - background-color: var(--surface-secondary); - border: 1px solid var(--border-base); - border-radius: 0; - padding: 8px 12px; - font-family: var(--font-family-mono); - font-size: var(--font-size-xs); - line-height: var(--line-height-tight); - overflow-x: auto; - margin: 0; -} - -.tool-call-content code { - font-family: inherit; - background: none; - padding: 0; - font-size: inherit; -} - -.tool-call-todos { - @apply my-2 flex flex-col gap-2; - list-style: none; - padding: 4px 0; -} - -.tool-call-todo-item { - @apply flex items-start gap-3; - border: 1px solid var(--border-base); - border-radius: 8px; - padding: 10px 12px; - background-color: var(--surface-secondary); -} - -.tool-call-todo-item-completed { - background-color: var(--surface-code); -} - -.tool-call-todo-item-active { - border-color: var(--accent-primary); - background-color: var(--surface-hover); -} - -.tool-call-todo-item-cancelled { - opacity: 0.75; -} - -.tool-call-todo-checkbox { - width: 1.1rem; - height: 1.1rem; - border-radius: 9999px; - border: 2px solid var(--border-base); - display: inline-flex; - align-items: center; - justify-content: center; - font-size: 0.75rem; - font-weight: var(--font-weight-semibold); - color: var(--text-muted); - background-color: transparent; -} - -.tool-call-todo-checkbox::after { - content: ""; - line-height: 1; -} - -.tool-call-todo-checkbox[data-status="completed"] { - background-color: var(--accent-primary); - border-color: var(--accent-primary); - color: var(--text-inverted); -} - -.tool-call-todo-checkbox[data-status="completed"]::after { - content: "✓"; -} - -.tool-call-todo-checkbox[data-status="in_progress"]::after { - content: "…"; - color: var(--accent-primary); -} - -.tool-call-todo-checkbox[data-status="cancelled"]::after { - content: "×"; - color: var(--status-error); -} - -.tool-call-todo-body { - flex: 1; - display: flex; - flex-direction: column; - gap: 4px; -} - -.tool-call-todo-text { - font-size: var(--font-size-sm); - line-height: var(--line-height-tight); - color: var(--text-primary); -} - -.tool-call-todo-item-cancelled .tool-call-todo-text { - text-decoration: line-through; - color: var(--text-muted); -} - -.tool-call-todo-tag { - font-size: 10px; - text-transform: uppercase; - letter-spacing: 0.08em; - border-radius: 9999px; - padding: 2px 8px; - background-color: var(--surface-hover); - color: var(--text-muted); -} - -.tool-call-todo-item-active .tool-call-todo-tag { - background-color: var(--accent-primary); - color: var(--text-inverted); -} - -.tool-call-task-container { - padding: 12px; -} - -.tool-call-task-summary { - @apply my-2 flex flex-col gap-1.5; -} - -.tool-call-task-item { - font-size: var(--font-size-xs); - line-height: var(--line-height-normal); - padding-left: 8px; - border-left: 2px solid var(--border-base); -} - -.tool-call-task-item::before { - content: "∟ "; - color: var(--text-muted); -} - -.tool-call-error-content { - background-color: rgba(244, 67, 54, 0.1); - border-left: 3px solid var(--status-error); - padding: 12px; - margin: 8px 0; - border-radius: 4px; - color: var(--status-error); - font-size: var(--font-size-xs); -} - -[data-theme="dark"] .tool-call-error-content { - background-color: rgba(244, 67, 54, 0.2); -} - -.tool-call-error-content strong { - font-weight: var(--font-weight-semibold); -} - -/* Empty state */ -.empty-state { - @apply flex-1 flex items-center justify-center p-12; -} - -.empty-state-content { - @apply text-center max-w-sm; -} - -.empty-state-content h3 { - font-size: var(--font-size-xl); - margin-bottom: 12px; -} - -.empty-state-content p { - font-size: var(--font-size-base); - color: var(--text-muted); - margin-bottom: 16px; -} - -.empty-state-content ul { - list-style: none; - padding: 0; - @apply flex flex-col gap-2; -} - -.empty-state-content li { - font-size: var(--font-size-base); - color: var(--text-muted); -} - -.empty-state-content code { - background-color: var(--surface-code); - padding: 2px 6px; - border-radius: 3px; - font-family: var(--font-family-mono); - font-size: 13px; -} - -/* Loading state */ -.loading-state { - @apply flex-1 flex flex-col items-center justify-center gap-4 p-12; -} - -.spinner { - @apply w-8 h-8 border-2 border-t-transparent rounded-full; - border-color: var(--border-base); - border-top-color: var(--accent-primary); - animation: spin 1s linear infinite; -} - -.folder-loading-overlay { - position: absolute; - inset: 0; - background-color: rgba(0, 0, 0, 0.35); - display: flex; - align-items: center; - justify-content: center; - z-index: 50; - backdrop-filter: blur(2px); -} - -.folder-loading-indicator { - @apply flex flex-col items-center gap-3 text-center; - padding: 24px 32px; - border-radius: 16px; - background-color: var(--surface-base); - border: 1px solid var(--border-base); - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2); - min-width: 260px; -} - -.folder-loading-text { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-semibold); - color: var(--text-primary); -} - -.folder-loading-subtext { - font-size: var(--font-size-sm); - color: var(--text-secondary); -} - -@keyframes spin { - to { transform: rotate(360deg); } -} - -@keyframes pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.5; } -} - -/* Dropdown utilities */ -.dropdown-surface { - @apply absolute w-full rounded-md shadow-lg z-50; - background-color: var(--surface-base); - border: 1px solid var(--border-base); -} - -.dropdown-header { - @apply px-3 py-2 border-b; - border-color: var(--border-base); - background-color: var(--surface-secondary); -} - -.dropdown-header-title { - @apply text-xs font-medium; - color: var(--text-muted); -} - -.dropdown-section-header { - @apply px-3 py-1.5 text-xs font-semibold; - color: var(--text-muted); - background-color: var(--surface-secondary); -} - -.dropdown-content { - @apply overflow-y-auto; -} - -.dropdown-item { - @apply cursor-pointer px-3 py-2 transition-colors; - color: var(--text-primary); -} - -.dropdown-item:hover { - background-color: var(--surface-hover); -} - -.dropdown-item-highlight { - background-color: var(--accent-primary); - color: var(--text-inverted); -} - -[data-theme="dark"] .dropdown-item-highlight { - background-color: rgba(0, 128, 255, 0.2); - color: var(--text-primary); -} - -.dropdown-empty { - @apply px-3 py-4 text-center text-sm; - color: var(--text-muted); -} - -.dropdown-loading { - @apply p-4 text-center text-sm; - color: var(--text-muted); -} - -.dropdown-footer { - @apply border-t px-3 py-2 text-xs; - border-color: var(--border-base); - color: var(--text-muted); -} - -.dropdown-badge { - @apply rounded px-1.5 py-0.5 text-xs font-normal; - background-color: var(--accent-primary); - color: var(--text-inverted); -} - -[data-theme="dark"] .dropdown-badge { - background-color: rgba(0, 128, 255, 0.2); - color: var(--text-primary); -} - -.dropdown-diff-added { - @apply text-xs; - color: var(--status-success); -} - -.dropdown-diff-removed { - @apply text-xs; - color: var(--status-error); -} - -.dropdown-icon { - @apply flex-shrink-0; - color: var(--text-muted); -} - -.dropdown-icon-accent { - color: var(--accent-primary); -} - -[data-theme="dark"] .dropdown-icon-accent { - color: var(--accent-primary); -} - -/* Selector component utilities */ -.selector-trigger { - @apply inline-flex items-center justify-between gap-2 px-2 py-1 border rounded outline-none transition-colors text-xs min-w-[180px]; - background-color: var(--surface-base); - border-color: var(--border-base); - color: var(--text-primary); -} - -.selector-trigger:hover { - background-color: var(--surface-hover); -} - -.selector-trigger:focus { - @apply ring-2; - ring-color: var(--accent-primary); -} - -.selector-trigger-disabled { - @apply opacity-50 cursor-not-allowed; -} - -.selector-trigger-label { - @apply flex flex-col min-w-0; -} - -.selector-trigger-label--stacked { - @apply items-start; -} - -.selector-trigger-primary { - @apply text-sm font-medium truncate; - color: var(--text-primary); -} - -.selector-trigger-primary--align-left { - @apply text-left w-full; -} - -.selector-trigger-secondary { - @apply text-xs text-left truncate; - color: var(--text-muted); -} - -.selector-trigger-icon { - @apply flex-shrink-0; - color: var(--text-muted); -} - -.selector-popover { - @apply rounded-md shadow-lg overflow-hidden z-50 min-w-[300px]; - background-color: var(--surface-base); - border: 1px solid var(--border-base); -} - -.selector-search-container { - @apply p-2 border-b; - border-color: var(--border-base); -} - -.selector-search-input { - @apply w-full px-3 py-1.5 text-xs border rounded outline-none transition-colors; - background-color: var(--surface-base); - border-color: var(--border-base); - color: var(--text-primary); -} - -.selector-search-input:focus { - @apply ring-2; - ring-color: var(--accent-primary); -} - -.selector-search-input::placeholder { - color: var(--text-muted); -} - -.selector-listbox { - @apply max-h-64 overflow-auto p-1; - background-color: var(--surface-base); -} - -.selector-option { - @apply px-3 py-2 cursor-pointer rounded outline-none transition-colors flex items-start gap-2 w-full; - color: var(--text-primary); -} - -.selector-option:hover { - background-color: var(--surface-hover); -} - -.selector-option[data-highlighted], -.selector-option[data-focused] { - background-color: rgba(0, 102, 255, 0.1); -} - -[data-theme="dark"] .selector-option[data-highlighted], -[data-theme="dark"] .selector-option[data-focused] { - background-color: rgba(0, 128, 255, 0.2); -} - -.selector-option[data-selected] { - background-color: rgba(0, 102, 255, 0.15); -} - -.selector-option-selected { - background-color: rgba(0, 102, 255, 0.15); -} - -[data-theme="dark"] .selector-option[data-selected] { - background-color: rgba(0, 128, 255, 0.25); -} - -[data-theme="dark"] .selector-option-selected { - background-color: rgba(0, 128, 255, 0.25); -} - -.selector-option-content { - @apply flex flex-col flex-1 min-w-0; -} - -.selector-option-label { - @apply font-medium text-sm; - color: var(--text-primary); -} - -.selector-option-description { - @apply text-xs; - color: var(--text-muted); -} - -.selector-option .remove-binary-button { - opacity: 0; -} - -.selector-option:hover .remove-binary-button { - opacity: 1; -} - -.remove-binary-button { - @apply p-1 rounded transition-all; - color: var(--text-muted); -} - -.remove-binary-button:hover { - background-color: rgba(239, 68, 68, 0.1); - color: var(--status-error); -} - -[data-theme="dark"] .remove-binary-button:hover { - background-color: rgba(239, 68, 68, 0.2); -} - -.selector-option-indicator { - @apply flex-shrink-0 mt-0.5; - color: var(--accent-primary); -} - -.selector-section { - @apply px-3 py-2 border-b; - border-color: var(--border-base); - background-color: var(--surface-secondary); -} - -.selector-section-title { - @apply text-xs font-medium; - color: var(--text-muted); -} - -.selector-badge { - @apply rounded px-1.5 py-0.5 text-xs font-normal; - background-color: var(--accent-primary); - color: var(--text-inverted); -} - -[data-theme="dark"] .selector-badge { - background-color: rgba(0, 128, 255, 0.2); - color: var(--text-primary); -} - -.selector-badge-version { - @apply text-xs; - color: var(--text-muted); -} - -.selector-badge-time { - @apply text-xs; - color: var(--text-muted); -} - -.selector-validation-error { - @apply p-2 rounded border; - background-color: rgba(244, 67, 54, 0.1); - border-color: var(--status-error); - color: var(--status-error); -} - -[data-theme="dark"] .selector-validation-error { - background-color: rgba(244, 67, 54, 0.2); -} - -.selector-validation-error-content { - @apply flex items-start gap-2; -} - -.selector-validation-error-icon { - @apply w-4 h-4 mt-0.5 flex-shrink-0; - color: var(--status-error); -} - -.selector-validation-error-text { - @apply text-xs; -} - -.selector-input-group { - @apply flex gap-2; -} - -.selector-input { - @apply flex-1 px-2 py-1.5 text-sm border rounded outline-none transition-colors; - background-color: var(--surface-base); - border-color: var(--border-base); - color: var(--text-primary); -} - -.selector-input:focus { - @apply ring-1; - ring-color: var(--accent-primary); -} - -.selector-input::placeholder { - color: var(--text-muted); -} - -.selector-button { - @apply px-3 py-1.5 text-sm rounded transition-colors cursor-pointer w-full inline-flex items-center justify-center font-medium; - background-color: var(--surface-secondary); - color: var(--text-primary); - border: 1px solid var(--border-base); -} - -.selector-button-primary { - background-color: var(--accent-primary) !important; - color: var(--text-inverted) !important; - border: 1px solid var(--accent-primary) !important; -} - -.selector-button-primary:hover:not(:disabled) { - background-color: var(--accent-hover); -} - -.selector-button-primary:disabled { - @apply opacity-50 cursor-not-allowed; - background-color: var(--surface-muted); -} - -[data-theme="dark"] .selector-button-primary:disabled { - background-color: var(--surface-secondary); -} - -.selector-button-secondary { - background-color: var(--surface-secondary); - color: var(--text-primary); -} - -.selector-button-secondary:hover:not(:disabled) { - background-color: var(--surface-hover); -} - -.selector-button-secondary:disabled { - @apply opacity-50 cursor-not-allowed; -} - -.focus-ring-accent:focus { - outline: none; - border-color: transparent; - box-shadow: 0 0 0 2px var(--accent-primary); -} - -.selector-empty-state { - @apply p-4 text-center text-sm; - color: var(--text-muted); -} - -.selector-loading { - @apply flex items-center gap-2; - color: var(--text-muted); -} - -.selector-loading-spinner { - @apply w-4 h-4 animate-spin; - color: var(--accent-primary); -} - -/* Modal utilities */ -.modal-overlay { - @apply fixed inset-0 z-50; - background-color: rgba(0, 0, 0, 0.5); -} - -.modal-surface { - @apply rounded-lg shadow-2xl flex flex-col; - background-color: var(--surface-base); - color: var(--text-primary); -} - -.modal-search-container { - @apply p-4 border-b; - border-color: var(--border-base); -} - -.modal-search-input { - @apply flex-1 bg-transparent outline-none; - color: var(--text-primary); -} - -.modal-search-input::placeholder { - color: var(--text-muted); -} - -.modal-search-icon { - color: var(--text-muted); -} - -.modal-list-container { - @apply flex-1 overflow-y-auto; -} - -.modal-section-header { - @apply px-4 py-2 text-xs font-semibold uppercase tracking-wide; - color: var(--text-muted); -} - -.modal-item { - @apply w-full px-4 py-3 flex items-start gap-3 transition-colors cursor-pointer border-none text-left; - color: var(--text-primary); -} - -.modal-list-container[data-pointer-mode="pointer"] .modal-item:hover { - background-color: var(--surface-hover); -} - -.modal-list-container[data-pointer-mode="keyboard"] .modal-item:hover:not(.modal-item-highlight) { - background-color: inherit; -} - -.modal-item-highlight { - background-color: rgba(0, 102, 255, 0.1); -} - -[data-theme="dark"] .modal-item-highlight { - background-color: rgba(0, 128, 255, 0.2); -} - -.modal-item-label { - @apply font-medium; - color: var(--text-primary); -} - -.modal-item-description { - @apply text-sm mt-0.5; - color: var(--text-secondary); -} - -.modal-empty-state { - @apply p-8 text-center; - color: var(--text-muted); -} - -/* Keyboard utilities */ -.kbd { - @apply inline-flex items-center gap-0.5 font-mono text-xs px-1.5 py-0.5 rounded; - background-color: var(--surface-secondary); - border: 1px solid var(--border-base); - color: var(--text-primary); -} - -.kbd-separator { - @apply opacity-50; -} - -/* Panel component utilities */ -.panel { - @apply rounded-lg shadow-sm border overflow-hidden; - background-color: var(--surface-base); - border-color: var(--border-base); - color: var(--text-primary); -} - -.panel-header { - @apply px-4 py-3 border-b; - border-color: var(--border-base); - background-color: var(--surface-secondary); -} - -.panel-title { - @apply text-base font-semibold; - color: var(--text-primary); -} - -.panel-subtitle { - @apply text-xs mt-0.5; - color: var(--text-muted); -} - -.panel-body { - @apply p-4; - background-color: var(--surface-base); -} - -.panel-section { - @apply border-t; - border-color: var(--border-base); -} - -.panel-section-header { - @apply w-full px-4 py-3 flex items-center justify-center transition-colors cursor-pointer gap-2; - background-color: var(--surface-secondary); -} - -.panel-section-header:hover { - background-color: var(--surface-hover); -} - -.panel-section-content { - @apply px-4 py-3 border-t overflow-visible space-y-4 w-full; - border-color: var(--border-base); - background-color: var(--surface-secondary); -} - -.panel-list { - @apply max-h-[400px] overflow-y-auto; -} - -.panel-list--fill { - max-height: none; - height: 100%; -} - -.panel-list-item { - @apply border-b last:border-b-0 transition-colors w-full; - border-color: var(--border-base); -} - -.panel-list-item:hover { - background-color: var(--surface-hover); -} - -.panel-list-item-highlight { - background-color: var(--list-item-highlight-bg) !important; - box-shadow: inset 0 0 0 1px var(--list-item-highlight-border); -} - -.panel-list-item-content { - @apply flex-1 text-left px-4 py-3 flex items-center justify-between gap-3 outline-none transition-colors w-full; -} - -.panel-list-item-content:hover { - background-color: transparent; -} - -.panel-list-item-content:disabled { - opacity: 0.6; -} - -.panel-list-item button:disabled { - cursor: not-allowed; -} - -.panel-list-item-disabled { - opacity: 0.6; -} - -.panel-empty-state { - @apply p-6 text-center; -} - -.panel-empty-state-icon { - @apply text-gray-400 dark:text-gray-600 mb-2; - color: var(--text-muted); -} - -.panel-empty-state-title { - @apply font-medium text-sm mb-1; - color: var(--text-secondary); -} - -.panel-empty-state-description { - @apply text-xs; - color: var(--text-muted); -} - -.panel-footer { - @apply px-4 py-3 border-t; - border-color: var(--border-base); - background-color: var(--surface-secondary); -} - -.panel-footer-hints { - @apply flex items-center justify-center flex-wrap gap-3 text-xs; - color: var(--text-muted); -} - -/* Log view specific utilities */ -.log-container { - @apply flex flex-col h-full; - background-color: var(--surface-base); -} - -.log-header { - @apply flex items-center justify-between px-4 py-3 border-b; - border-color: var(--border-base); - background-color: var(--surface-secondary); -} - -.log-content { - @apply flex-1 overflow-y-auto p-4 font-mono text-xs leading-relaxed; - background-color: var(--surface-secondary); - color: var(--text-primary); -} - -.log-entry { - @apply flex gap-3 py-0.5 px-2 -mx-2 rounded transition-colors; -} - -.log-entry:hover { - background-color: var(--surface-hover); -} - -.log-timestamp { - @apply select-none shrink-0; - color: var(--text-muted); -} - -.log-message { - @apply break-all; -} - -.log-level-error { - color: var(--status-error); -} - -.log-level-warn { - color: var(--status-warning); -} - -.log-level-debug { - color: var(--text-muted); -} - -.log-level-default { - color: var(--text-primary); -} - -.log-empty-state { - @apply text-center py-8; - color: var(--text-muted); -} - -.log-paused-state { - @apply flex flex-col items-center justify-center gap-3 text-center py-10 px-6; - border: 1px dashed var(--border-base); - border-radius: 12px; - background-color: var(--surface-base); -} - -.log-paused-title { - font-size: var(--font-size-base); - font-weight: var(--font-weight-semibold); - color: var(--text-primary); -} - -.log-paused-description { - font-size: var(--font-size-sm); - color: var(--text-secondary); - max-width: 320px; -} - -/* Environment variables display */ -.env-vars-container { - @apply px-4 py-3 border-b; - background-color: rgba(0, 102, 255, 0.1); - border-color: rgba(0, 102, 255, 0.2); -} - -[data-theme="dark"] .env-vars-container { - background-color: rgba(0, 128, 255, 0.2); - border-color: rgba(0, 128, 255, 0.3); -} - -.env-vars-title { - @apply text-xs font-medium mb-2; - color: #0066ff; -} - -[data-theme="dark"] .env-vars-title { - color: #0080ff; -} - -.env-var-item { - @apply flex items-center gap-2 text-xs; -} - -.env-var-key { - @apply font-mono font-medium min-w-0 flex-1; - color: #0066ff; -} - -[data-theme="dark"] .env-var-key { - color: #0080ff; -} - -.env-var-separator { - color: #0066ff; -} - -[data-theme="dark"] .env-var-separator { - color: #0080ff; -} - -.env-var-value { - @apply font-mono min-w-0 flex-1; - color: #0066ff; -} - -[data-theme="dark"] .env-var-value { - color: #0080ff; -} - -/* Session view utility */ -.session-view { - @apply flex flex-1 min-h-0 flex-col; - background-color: var(--surface-base); - color: inherit; -} - -/* Session list component */ -.session-list-container { - @apply flex flex-col flex-1 min-h-0 relative; - background-color: var(--surface-secondary); - min-width: 200px; - max-width: 500px; -} - -.session-sidebar { - @apply flex flex-col min-h-0; - background-color: var(--surface-secondary); -} - -.session-sidebar-header { - @apply flex flex-col gap-2 w-full; -} - -.session-sidebar-title { - color: var(--text-primary); -} - -.session-sidebar-shortcuts { - @apply flex flex-col gap-1; -} - -.session-sidebar-new { - @apply w-full; -} - -.session-sidebar-controls { - @apply flex flex-col gap-3; - background-color: var(--surface-secondary); -} - -.session-sidebar-controls > * { - @apply w-full; -} - -.session-sidebar-controls .selector-trigger, -.session-sidebar-controls [data-model-selector-control], -.session-sidebar-controls .selector-trigger-label, -.session-sidebar-controls .selector-trigger-primary { - @apply w-full; -} - -.sidebar-selector { - @apply flex flex-col gap-1 w-full; -} - -.sidebar-selector-hint { - @apply flex justify-center text-xs w-full; - color: var(--text-muted); -} - -.session-sidebar-separator { - background-color: var(--border-base); - height: 1px; - width: 100%; -} - -.session-resize-handle { - @apply absolute top-0 right-0 w-1 h-full cursor-col-resize bg-transparent transition-colors; - z-index: 10; -} - -.session-resize-handle:hover { - background-color: var(--accent-primary); -} - -.session-resize-handle::before { - content: ""; - @apply absolute top-0 left-0 w-2 h-full -translate-x-1/2; -} - -.session-list-header { - @apply border-b relative; - border-color: var(--border-base); -} - -.session-list-header h3 { - color: var(--text-primary); - font-size: var(--font-size-sm); - font-weight: var(--font-weight-semibold); -} - -.session-header-hints { - @apply flex-shrink-0; -} - -.session-list { - @apply flex-1; -} - -.session-list-item { - @apply border-b last:border-b-0; - border-color: var(--border-base); -} - -.session-item-base { - @apply w-full flex flex-col gap-1 px-3 py-2.5 text-left transition-colors outline-none; - font-family: var(--font-family-sans); - font-size: var(--font-size-sm); -} - -.session-item-base:focus-visible { - @apply ring-2 ring-offset-1; - ring-color: var(--accent-primary); - ring-offset-color: var(--surface-secondary); -} - -.session-item-row { - @apply flex items-center gap-2 w-full; -} - -.session-item-header { - @apply justify-between; -} - -.session-item-title-row { - @apply flex items-center gap-2 min-w-0 flex-1; -} - -.session-item-meta { - @apply justify-between items-center; - font-size: var(--font-size-xs); - color: var(--text-secondary); - margin-top: 0.125rem; -} - -.session-item-active .session-item-meta { - color: var(--text-secondary); - opacity: 1; -} - -.session-item-actions { - @apply flex items-center gap-1; -} - -.session-item-active { - background-color: var(--list-item-highlight-bg); - color: var(--text-primary); - font-weight: var(--font-weight-medium); - box-shadow: inset 0 0 0 1px var(--list-item-highlight-border); -} - -.session-item-inactive { - color: var(--text-secondary); -} - -.session-item-inactive:hover { - background-color: var(--surface-hover); - color: var(--text-primary); -} - -.session-item-active .session-item-close:hover { - background-color: var(--surface-hover); - color: var(--text-primary); -} - -.session-item-title { - @apply flex-1 min-w-0; - font-weight: inherit; -} - -.session-item-close { - @apply flex-shrink-0 p-0.5 rounded transition-all; -} - -.session-item-close:focus-visible { - @apply ring-2 ring-offset-1; - ring-color: var(--accent-primary); - ring-offset-color: inherit; -} - -.session-list-footer { - @apply border-t; - border-color: var(--border-base); -} - -.session-new-button { - background-color: var(--surface-base); - color: var(--text-primary); - border: 1px solid var(--border-base); -} - -.session-new-button:hover { - background-color: var(--surface-hover); -} - -.session-new-button:focus-visible { - @apply ring-2 ring-offset-1; - ring-color: var(--accent-primary); - ring-offset-color: var(--surface-secondary); -} - -[data-theme="dark"] .session-new-button { - background-color: var(--surface-base); - color: var(--text-primary); -} - -[data-theme="dark"] .session-new-button:hover { - background-color: var(--surface-hover); -} - -/* Responsive behavior for session list */ -@media (max-width: 768px) { - .session-list-container { - min-width: 200px; - } - - .session-item-base { - @apply px-2 py-2; - } -} \ No newline at end of file diff --git a/src/styles/controls.css b/src/styles/controls.css new file mode 100644 index 00000000..fd74f0ac --- /dev/null +++ b/src/styles/controls.css @@ -0,0 +1,497 @@ +@import "./tokens.css"; +@import "./utilities.css"; + +.button-primary, +button.button-primary { + @apply px-6 py-3 text-base rounded-lg; + background-color: var(--button-primary-bg); + color: var(--button-primary-text); + border-color: var(--button-primary-bg); +} + +.button-primary:hover:not(:disabled), +button.button-primary:hover:not(:disabled) { + background-color: var(--button-primary-hover-bg); + border-color: var(--button-primary-hover-bg); +} + +.button-primary:focus-visible, +button.button-primary:focus-visible { + box-shadow: 0 0 0 2px var(--focus-ring-offset), 0 0 0 4px var(--focus-ring-color); +} + +.button-secondary, +button.button-secondary { + @apply px-6 py-3 text-base rounded-lg; + background-color: var(--surface-secondary); + color: var(--text-primary); + border-color: var(--border-base); +} + +.button-secondary:hover:not(:disabled), +button.button-secondary:hover:not(:disabled) { + background-color: var(--surface-hover); +} + +.button-secondary:focus-visible, +button.button-secondary:focus-visible { + box-shadow: 0 0 0 2px var(--focus-ring-offset), 0 0 0 4px var(--focus-ring-color); +} + +.button-tertiary, +button.button-tertiary { + @apply px-4 py-2 text-sm rounded-lg; + background-color: transparent; + color: var(--text-secondary); + border-color: var(--border-base); +} + +.button-tertiary:hover:not(:disabled), +button.button-tertiary:hover:not(:disabled) { + color: var(--text-primary); + background-color: var(--surface-hover); +} + +.button-tertiary:focus-visible, +button.button-tertiary:focus-visible { + box-shadow: 0 0 0 2px var(--focus-ring-offset), 0 0 0 4px var(--focus-ring-color); +} + +/* Neutral badge utilities */ +.neutral-badge { + @apply inline-flex items-center rounded px-1.5 py-0.5 text-xs font-normal; + background-color: var(--badge-neutral-bg); + color: var(--badge-neutral-text); +} + +/* Status badge utilities */ +.status-badge { + @apply inline-flex items-center gap-1.5 rounded px-2 py-1 text-xs font-medium; +} + +.status-badge.ready { + background-color: var(--status-ready-bg); + color: var(--status-ready-fg); +} + +.status-badge.starting { + background-color: var(--status-starting-bg); + color: var(--status-starting-fg); +} + +.status-badge.error { + background-color: var(--status-error-bg); + color: var(--status-error-fg); +} + +.status-badge.stopped { + background-color: var(--status-stopped-bg); + color: var(--status-stopped-fg); +} + +.status-dot.ready { + background-color: var(--status-ready-fg); +} + +.status-dot.starting { + background-color: var(--status-starting-fg); +} + +.status-dot.error { + background-color: var(--status-error-fg); +} + +.status-dot.stopped { + background-color: var(--status-stopped-fg); +} + +.folder-loading-overlay { + position: absolute; + inset: 0; + background-color: var(--folder-overlay-bg); + display: flex; + align-items: center; + justify-content: center; + z-index: 50; + backdrop-filter: blur(2px); +} + +.folder-loading-indicator { + @apply flex flex-col items-center gap-3 text-center; + padding: 24px 32px; + border-radius: var(--folder-card-radius); + background-color: var(--surface-base); + border: 1px solid var(--border-base); + box-shadow: var(--folder-card-shadow); + min-width: 260px; +} + +.folder-loading-text { + font-size: var(--font-size-lg); + font-weight: var(--font-weight-semibold); + color: var(--text-primary); +} + +.folder-loading-subtext { + font-size: var(--font-size-sm); + color: var(--text-secondary); +} + +/* Dropdown utilities */ +.dropdown-surface { + @apply absolute w-full rounded-md shadow-lg z-50; + background-color: var(--surface-base); + border: 1px solid var(--border-base); +} + +.dropdown-header { + @apply px-3 py-2 border-b; + border-color: var(--border-base); + background-color: var(--surface-secondary); +} + +.dropdown-header-title { + @apply text-xs font-medium; + color: var(--text-muted); +} + +.dropdown-section-header { + @apply px-3 py-1.5 text-xs font-semibold; + color: var(--text-muted); + background-color: var(--surface-secondary); +} + +.dropdown-content { + @apply overflow-y-auto; +} + +.dropdown-item { + @apply cursor-pointer px-3 py-2 transition-colors; + color: var(--text-primary); +} + +.dropdown-item:hover { + background-color: var(--surface-hover); +} + +.dropdown-item-highlight { + background-color: var(--dropdown-highlight-bg); + color: var(--dropdown-highlight-text); +} + + +.dropdown-empty { + @apply px-3 py-4 text-center text-sm; + color: var(--text-muted); +} + +.dropdown-loading { + @apply p-4 text-center text-sm; + color: var(--text-muted); +} + +.dropdown-footer { + @apply border-t px-3 py-2 text-xs; + border-color: var(--border-base); + color: var(--text-muted); +} + +.dropdown-badge { + @apply rounded px-1.5 py-0.5 text-xs font-normal; + background-color: var(--accent-primary); + color: var(--text-inverted); +} + +.dropdown-icon { + @apply flex-shrink-0; + color: var(--text-muted); +} + +.dropdown-icon-accent { + color: var(--accent-primary); +} + +/* Selector component utilities */ + +.selector-trigger { + @apply inline-flex items-center justify-between gap-2 px-2 py-1 border rounded outline-none transition-colors text-xs min-w-[180px]; + background-color: var(--surface-base); + border-color: var(--border-base); + color: var(--text-primary); +} + +.selector-trigger:hover { + background-color: var(--surface-hover); +} + +.selector-trigger:focus { + @apply ring-2; + ring-color: var(--accent-primary); +} + +.selector-trigger-disabled { + @apply opacity-50 cursor-not-allowed; +} + +.selector-trigger-label { + @apply flex flex-col min-w-0; +} + +.selector-trigger-label--stacked { + @apply items-start; +} + +.selector-trigger-primary { + @apply text-sm font-medium truncate; + color: var(--text-primary); +} + +.selector-trigger-primary--align-left { + @apply text-left w-full; +} + +.selector-trigger-secondary { + @apply text-xs text-left truncate; + color: var(--text-muted); +} + +.selector-trigger-icon { + @apply flex-shrink-0; + color: var(--text-muted); +} + +.selector-popover { + @apply rounded-md shadow-lg overflow-hidden z-50 min-w-[300px]; + background-color: var(--surface-base); + border: 1px solid var(--border-base); +} + +.selector-search-container { + @apply p-2 border-b; + border-color: var(--border-base); +} + +.selector-search-input { + @apply w-full px-3 py-1.5 text-xs border rounded outline-none transition-colors; + background-color: var(--surface-base); + border-color: var(--border-base); + color: var(--text-primary); +} + +.selector-search-input:focus { + @apply ring-2; + ring-color: var(--accent-primary); +} + +.selector-search-input::placeholder { + color: var(--text-muted); +} + +.selector-listbox { + @apply max-h-64 overflow-auto p-1; + background-color: var(--surface-base); +} + +.selector-option { + @apply px-3 py-2 cursor-pointer rounded outline-none transition-colors flex items-start gap-2 w-full; + color: var(--text-primary); +} + +.selector-option:hover { + background-color: var(--surface-hover); +} + +.selector-option[data-highlighted], +.selector-option[data-focused] { + background-color: var(--selection-highlight-bg); +} + +.selector-option[data-selected], +.selector-option-selected { + background-color: var(--selection-highlight-strong-bg); +} + +.selector-option-content { + @apply flex flex-col flex-1 min-w-0; +} + +.selector-option-label { + @apply font-medium text-sm; + color: var(--text-primary); +} + +.selector-option-description { + @apply text-xs; + color: var(--text-muted); +} + +.selector-option .remove-binary-button { + opacity: 0; +} + +.selector-option:hover .remove-binary-button { + opacity: 1; +} + +.remove-binary-button { + @apply p-1 rounded transition-all; + color: var(--text-muted); +} + +.remove-binary-button:hover { + background-color: var(--danger-soft-bg); + color: var(--status-error); +} + +.selector-option-indicator { + @apply flex-shrink-0 mt-0.5; + color: var(--accent-primary); +} + +.selector-section { + @apply px-3 py-2 border-b; + border-color: var(--border-base); + background-color: var(--surface-secondary); +} + +.selector-section-title { + @apply text-xs font-medium; + color: var(--text-muted); +} + +.selector-badge { + @apply rounded px-1.5 py-0.5 text-xs font-normal; + background-color: var(--accent-primary); + color: var(--text-inverted); +} + +.selector-badge-version { + @apply text-xs; + color: var(--text-muted); +} + +.selector-badge-time { + @apply text-xs; + color: var(--text-muted); +} + +.selector-validation-error { + @apply p-2 rounded border; + background-color: var(--message-error-bg); + border-color: var(--status-error); + color: var(--status-error); +} + +.selector-validation-error-content { + @apply flex items-start gap-2; +} + +.selector-validation-error-icon { + @apply w-4 h-4 mt-0.5 flex-shrink-0; + color: var(--status-error); +} + +.selector-validation-error-text { + @apply text-xs; +} + +.selector-input-group { + @apply flex gap-2; +} + +.selector-input { + @apply flex-1 px-2 py-1.5 text-sm border rounded outline-none transition-colors; + background-color: var(--surface-base); + border-color: var(--border-base); + color: var(--text-primary); +} + +.selector-input:focus { + @apply ring-1; + ring-color: var(--accent-primary); +} + +.selector-input::placeholder { + color: var(--text-muted); +} + +.selector-button { + @apply px-3 py-1.5 text-sm rounded transition-colors cursor-pointer w-full inline-flex items-center justify-center font-medium; + background-color: var(--surface-secondary); + color: var(--text-primary); + border: 1px solid var(--border-base); +} + +.selector-button-primary { + background-color: var(--accent-primary) !important; + color: var(--text-inverted) !important; + border: 1px solid var(--accent-primary) !important; +} + +.selector-button-primary:hover:not(:disabled) { + background-color: var(--accent-hover); +} + +.selector-button-primary:disabled { + @apply opacity-50 cursor-not-allowed; + background-color: var(--surface-muted); +} + +.selector-button-secondary { + background-color: var(--surface-secondary); + color: var(--text-primary); +} + +.selector-button-secondary:hover:not(:disabled) { + background-color: var(--surface-hover); +} + +.selector-button-secondary:disabled { + @apply opacity-50 cursor-not-allowed; +} + +.selector-empty-state { + @apply p-4 text-center text-sm; + color: var(--text-muted); +} + +.selector-loading { + @apply flex items-center gap-2; + color: var(--text-muted); +} + +.selector-loading-spinner { + @apply w-4 h-4 animate-spin; + color: var(--accent-primary); +} + +/* Environment variables display */ +.env-vars-container { + @apply px-4 py-3 border-b; + background-color: var(--env-vars-bg); + border-color: var(--env-vars-border); +} + +.env-vars-title { + @apply text-xs font-medium mb-2; + color: var(--env-vars-text); +} + +.env-var-item { + @apply flex items-center gap-2 text-xs; +} + +.env-var-key { + @apply font-mono font-medium min-w-0 flex-1; + color: var(--env-vars-text); +} + +.env-var-separator { + color: var(--env-vars-text); +} + +.env-var-value { + @apply font-mono min-w-0 flex-1; + color: var(--env-vars-text); +} + diff --git a/src/styles/messaging.css b/src/styles/messaging.css new file mode 100644 index 00000000..66553001 --- /dev/null +++ b/src/styles/messaging.css @@ -0,0 +1,847 @@ +@import "./tokens.css"; +@import "./utilities.css"; + +/* Message item base styles */ + +.message-item-base { + @apply flex flex-col gap-2 p-3 w-full; +} + +.assistant-message { + /* gap: 0.25rem; */ + padding: 0.6rem 0.65rem; +} + +/* Message state badges */ +.message-queued-badge { + @apply inline-block font-bold px-3 py-1 rounded mb-3 text-xs tracking-wide; + background-color: var(--accent-primary); + color: var(--text-inverted); +} + +/* Message error block */ +.message-error-block { + @apply text-sm p-3 rounded border-l-[3px] my-2; + color: var(--status-error); + background-color: var(--message-error-bg); + border-color: var(--status-error); +} + +/* Message state indicators */ +.message-generating { + @apply text-sm italic py-2; + color: var(--text-muted); +} + +.message-sending { + @apply text-xs italic mt-1; + color: var(--text-muted); +} + +.message-error { + @apply text-xs mt-1; + color: var(--status-error); +} + +.generating-spinner { + @apply inline-block; + animation: pulse 1.5s ease-in-out infinite; +} + +/* Prompt input component utilities */ +.prompt-input-container { + @apply flex flex-col border-t; + border-color: var(--border-base); + background-color: var(--surface-base); +} + +.prompt-input-wrapper { + @apply flex items-end gap-2 p-3; +} + +.prompt-input { + @apply flex-1 min-h-[96px] max-h-[200px] p-2.5 border rounded-md text-sm resize-none outline-none transition-colors; + font-family: inherit; + background-color: var(--surface-base); + color: inherit; + border-color: var(--border-base); + line-height: var(--line-height-normal); +} + +.prompt-input:focus { + border-color: var(--accent-primary); +} + +.prompt-input:disabled { + @apply opacity-60 cursor-not-allowed; +} + +.prompt-input::placeholder { + color: var(--text-muted); +} + +.send-button { + @apply w-10 h-10 rounded-md border-none cursor-pointer flex items-center justify-center transition-all flex-shrink-0; + background-color: var(--accent-primary); + color: var(--text-inverted); +} + +.send-button:hover:not(:disabled) { + @apply opacity-90 scale-105; +} + +.send-button:active:not(:disabled) { + @apply scale-95; +} + +.send-button:disabled { + @apply opacity-40 cursor-not-allowed; +} + +.send-icon { + @apply text-base; +} + +.prompt-input-hints { + @apply px-4 pb-2 flex justify-between items-center; +} + +.hint { + @apply text-xs; + color: var(--text-muted); +} + +.hint kbd { + @apply inline-block px-1.5 py-0.5 text-xs font-mono rounded mx-0.5; + background-color: var(--surface-secondary); + border: 1px solid var(--border-base); + border-radius: 3px; +} + +/* Attachment chip utilities */ +.attachment-chip { + @apply px-2.5 py-1 text-xs font-medium ring-1 ring-inset; + background-color: var(--attachment-chip-bg); + color: var(--attachment-chip-text); + ring-color: var(--attachment-chip-ring); +} + +.attachment-remove { + @apply ml-0.5 flex h-4 w-4 items-center justify-center rounded transition-colors; +} + +.attachment-remove:hover { + background-color: var(--attachment-chip-ring); +} + +/* Message stream component utilities */ +.message-stream-container { + @apply relative flex-1 min-h-0 flex flex-col overflow-hidden; +} + +.connection-status { + @apply grid items-center px-4 py-2 gap-4; + grid-template-columns: 1fr auto 1fr; + background-color: var(--surface-secondary); + border-bottom: 1px solid var(--border-base); +} + +.message-stream { + @apply flex-1 min-h-0 overflow-y-auto flex flex-col gap-1; + background-color: var(--surface-base); + color: inherit; +} + +.message-scroll-button-wrapper { + position: absolute; + right: 1rem; + bottom: 1rem; + display: flex; + flex-direction: column; + gap: 0.5rem; + align-items: flex-end; +} + +.message-scroll-button { + @apply inline-flex items-center justify-center; + width: 2.75rem; + height: 2.75rem; + border-radius: 9999px; + border: 1px solid var(--border-base); + background-color: transparent; + color: var(--text-primary); + box-shadow: var(--scroll-elevation-shadow); + transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease; +} + +.message-scroll-button:hover { + background-color: var(--surface-hover); + transform: translateY(-1px); +} + +.message-scroll-button:focus-visible { + outline: none; + box-shadow: 0 0 0 2px var(--surface-base), 0 0 0 4px var(--accent-primary); +} + +.message-scroll-icon { + font-size: var(--font-size-lg); + color: var(--accent-primary); +} + +/* Tool call message wrapper */ +.tool-call-message { + @apply flex flex-col gap-2 p-3 w-full; + background-color: var(--message-tool-bg); + border-left: 4px solid var(--message-tool-border); + color: inherit; +} + +.tool-call-header-label { + @apply flex items-center justify-between gap-2 font-semibold text-sm; + color: var(--message-tool-border); + margin-bottom: 1px; +} + +.tool-call-header-meta { + @apply flex items-center gap-2; +} + +.tool-call-header-button { + background-color: transparent; + border: 1px solid var(--border-base); + color: var(--message-tool-border); + padding: 0.15rem 0.75rem; + border-radius: 0.375rem; + font-size: 0.75rem; + font-weight: var(--font-weight-semibold); + line-height: 1; + display: inline-flex; + align-items: center; + justify-content: center; + height: 1.5rem; + transition: all 0.2s ease; +} + +.tool-call-header-button:hover:not(:disabled) { + background-color: var(--surface-hover); + border-color: var(--accent-primary); + color: var(--accent-primary); +} + +.tool-call-header-button:active:not(:disabled) { + transform: scale(0.95); +} + +.tool-call-header-button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.tool-call-header-label .tool-call-icon { + @apply text-base; +} + +.tool-call-header-label .tool-name { + font-family: var(--font-family-mono); + color: inherit; + background-color: var(--surface-secondary); + border: 1px solid var(--border-base); + padding: 2px 6px; + border-radius: 3px; + font-size: 13px; +} + +.message-text { + font-size: var(--font-size-base); + line-height: var(--line-height-normal); + word-wrap: break-word; + overflow-wrap: break-word; + color: inherit; +} + +.message-text-assistant { + white-space: normal; +} + +.message-text pre { + overflow-x: auto; + padding: 8px; + background-color: var(--surface-code); + border-radius: 4px; +} + +/* Message error part */ +.message-error-part { + color: var(--status-error); + font-size: var(--font-size-base); + padding: 8px; + background-color: var(--message-error-bg); + border-radius: 4px; +} + +/* Message reasoning */ +.message-reasoning { + @apply my-2 border rounded; + border-color: var(--border-base); + background-color: var(--surface-secondary); + color: inherit; +} + +.reasoning-container { + @apply p-2; +} + +.reasoning-header { + @apply flex items-center gap-1.5 text-xs cursor-pointer select-none; + color: var(--text-muted); +} + +.reasoning-header:hover { + color: var(--accent-primary); +} + +.reasoning-icon { + @apply text-xs; + transition: transform 150ms ease; +} + +.reasoning-label { + font-weight: var(--font-weight-medium); +} + +/* Tool call component */ +.tool-call { + @apply border overflow-hidden; + border-color: var(--border-base); + color: inherit; + --tool-call-line-unit: 1.4em; + --tool-call-lines-compact: 24; + --tool-call-lines-large: 48; + --tool-call-max-height-compact: calc(var(--tool-call-lines-compact) * var(--tool-call-line-unit)); + --tool-call-max-height-large: calc(var(--tool-call-lines-large) * var(--tool-call-line-unit)); +} + +.tool-call-message .tool-call { + border: none; + border-radius: 0; + margin: 0; +} + +.tool-call-header { + @apply flex items-center gap-2 p-2 w-full bg-transparent border-none cursor-pointer text-left; + font-family: var(--font-family-mono); + font-size: 13px; + border-radius: 0; +} + +.tool-call-header:hover { + background-color: var(--surface-hover); +} + +.tool-call-icon { + @apply text-xs; +} + +.tool-call-summary { + @apply flex-1 text-left; +} + +.tool-call-status { + @apply text-sm; +} + +.tool-call-status-success { + border-left: 3px solid var(--status-success); +} + +.tool-call-status-error { + border-left: 3px solid var(--status-error); +} + +.tool-call-status-running { + border-left: 3px solid var(--status-warning); +} + +.tool-call-status-running .tool-call-status { + animation: pulse 1.5s ease-in-out infinite; +} + +.tool-call-status-pending { + border-left: 3px solid var(--accent-primary); +} + +.tool-call-status-pending .tool-call-summary { + animation: shimmer 2s ease-in-out infinite; +} + +.tool-call-preview { + @apply p-2 flex flex-col gap-1.5; + background-color: var(--surface-code); + border-top: 1px solid var(--border-base); +} + +.tool-call-preview-label { + @apply text-xs font-semibold uppercase tracking-wide; + color: var(--text-muted); + letter-spacing: 0.5px; +} + +.tool-call-preview-text { + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + line-height: var(--line-height-tight); + color: var(--text-muted); + white-space: pre-wrap; + word-wrap: break-word; + overflow-wrap: break-word; + max-height: var(--tool-call-max-height-compact, calc(25 * 1.4em)); + overflow-y: scroll; +} + +.tool-call-details { + + @apply flex flex-col; + background-color: var(--surface-code); + font-size: var(--font-size-xs); +} + +.tool-call-markdown { + background-color: var(--surface-code); + border: none; + border-radius: 0; + padding: 0; + font-size: var(--font-size-xs); + line-height: var(--line-height-tight); + max-height: var(--tool-call-max-height-compact, calc(25 * 1.4em)); + overflow-y: scroll; + scrollbar-width: thin; + scrollbar-color: var(--border-base) transparent; + scrollbar-gutter: stable both-edges; + position: relative; +} + +.tool-call-markdown-large { + max-height: var(--tool-call-max-height-large, calc(48 * 1.4em)); +} + +.tool-call-diff-shell { + padding: 0; +} + +.tool-call-diff-viewer { + max-height: var(--tool-call-max-height-large, calc(48 * 1.4em)); + overflow: auto; + background-color: var(--surface-code); +} + +.tool-call-diff-toolbar { + @apply flex items-center justify-between gap-3 px-3 py-2; + background-color: var(--surface-secondary); + border-bottom: 1px solid var(--border-base); +} + +.tool-call-diff-toolbar-label { + font-size: 11px; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 0.08em; +} + +.tool-call-diff-toggle { + @apply inline-flex items-center gap-1; +} + +.tool-call-diff-mode-button { + @apply border text-xs font-semibold px-3 py-1 rounded transition-all duration-150; + border-color: var(--border-base); + background-color: transparent; + color: var(--text-muted); +} + +.tool-call-diff-mode-button:hover { + background-color: var(--surface-hover); + color: var(--text-primary); +} + +.tool-call-diff-mode-button.active { + background-color: var(--accent-primary); + border-color: var(--accent-primary); + color: var(--text-inverted); +} + +.tool-call-diff-viewer .diff-tailwindcss-wrapper { + background-color: transparent; + color: inherit; +} + +.tool-call-diff-viewer .diff-view-wrapper { + font-family: var(--font-family-mono); +} + +.tool-call-diff-fallback { + margin: 0; + padding: 0.75rem; + background-color: var(--surface-code); + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + line-height: var(--line-height-tight); +} + +.tool-call-diff-viewer .diff-line-old-num, +.tool-call-diff-viewer .diff-line-new-num, +.tool-call-diff-viewer .diff-line-num { + width: auto !important; + min-width: 4ch; + padding-left: 0.5rem; + padding-right: 0.5rem; + white-space: nowrap; +} + +.tool-call-markdown .markdown-code-block { + + margin: 0; + border: none; + background-color: transparent; +} + +.tool-call-markdown .code-block-header { + position: sticky; + top: 0; + z-index: auto; + box-shadow: 0 1px 0 var(--border-base); +} + +.tool-call-markdown .markdown-code-block pre { + margin: 0 !important; + min-height: auto; + max-height: none; + overflow-y: visible; +} + +.tool-call-markdown::-webkit-scrollbar { + width: 8px; +} + +.tool-call-markdown::-webkit-scrollbar-track { + background: transparent; +} + +.tool-call-markdown::-webkit-scrollbar-thumb { + background-color: var(--border-base); + border-radius: 4px; + border: 2px solid transparent; + background-clip: padding-box; +} + +.tool-call-section h4 { + font-size: var(--font-size-xs); + font-weight: var(--font-weight-semibold); + margin-bottom: 4px; + color: var(--text-muted); +} + +.tool-call-section pre { + margin: 0; + padding: 8px; + background-color: var(--surface-base); + border-radius: 0px; + overflow-x: auto; + max-height: var(--tool-call-max-height-compact, calc(25 * 1.4em)); + overflow-y: scroll; +} + +.tool-call-section code { + + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + line-height: var(--line-height-tight); +} + +.tool-call-section pre::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +.tool-call-section pre::-webkit-scrollbar-track { + background: var(--surface-secondary); + border-radius: 0px; +} + +.tool-call-section pre::-webkit-scrollbar-thumb { + background: var(--border-base); + border-radius: 0px; +} + +.tool-call-section pre::-webkit-scrollbar-thumb:hover { + background: var(--text-muted); +} + +.tool-call-pending-message { + @apply flex items-center gap-2 p-3 text-xs italic; + color: var(--text-muted); +} + +.tool-call-emoji { + @apply text-base mr-1; +} + +.tool-call-action-button { + @apply border text-xs font-semibold px-3 py-1 rounded transition-colors h-8 flex items-center; + border-color: var(--border-base); + color: var(--text-muted); + background-color: transparent; +} + +.tool-call-action-button:hover:not(:disabled) { + background-color: var(--surface-hover); + color: var(--text-primary); +} + +.tool-call-action-button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.tool-call-bash, +.tool-call-diff { + @apply my-2; +} + +.tool-call-content { + background-color: var(--surface-secondary); + border: 1px solid var(--border-base); + border-radius: 0; + padding: 8px 12px; + font-family: var(--font-family-mono); + font-size: var(--font-size-xs); + line-height: var(--line-height-tight); + overflow-x: auto; + margin: 0; +} + +.tool-call-content code { + font-family: inherit; + background: none; + padding: 0; + font-size: inherit; +} + +.tool-call-todos { + @apply my-2 flex flex-col gap-2; + list-style: none; + padding: 4px 0; +} + +.tool-call-todo-item { + @apply flex items-start gap-3; + border: 1px solid var(--border-base); + border-radius: 8px; + padding: 10px 12px; + background-color: var(--surface-secondary); +} + +.tool-call-todo-item-completed { + background-color: var(--surface-code); +} + +.tool-call-todo-item-active { + border-color: var(--accent-primary); + background-color: var(--surface-hover); +} + +.tool-call-todo-item-cancelled { + opacity: 0.75; +} + +.tool-call-todo-checkbox { + width: 1.1rem; + height: 1.1rem; + border-radius: 9999px; + border: 2px solid var(--border-base); + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 0.75rem; + font-weight: var(--font-weight-semibold); + color: var(--text-muted); + background-color: transparent; +} + +.tool-call-todo-checkbox::after { + content: ""; + line-height: 1; +} + +.tool-call-todo-checkbox[data-status="completed"] { + background-color: var(--accent-primary); + border-color: var(--accent-primary); + color: var(--text-inverted); +} + +.tool-call-todo-checkbox[data-status="completed"]::after { + content: "✓"; +} + +.tool-call-todo-checkbox[data-status="in_progress"]::after { + content: "…"; + color: var(--accent-primary); +} + +.tool-call-todo-checkbox[data-status="cancelled"]::after { + content: "×"; + color: var(--status-error); +} + +.tool-call-todo-body { + flex: 1; + display: flex; + flex-direction: column; + gap: 4px; +} + +.tool-call-todo-text { + font-size: var(--font-size-sm); + line-height: var(--line-height-tight); + color: var(--text-primary); +} + +.tool-call-todo-item-cancelled .tool-call-todo-text { + text-decoration: line-through; + color: var(--text-muted); +} + +.tool-call-todo-tag { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.08em; + border-radius: 9999px; + padding: 2px 8px; + background-color: var(--surface-hover); + color: var(--text-muted); +} + +.tool-call-todo-item-active .tool-call-todo-tag { + background-color: var(--accent-primary); + color: var(--text-inverted); +} + +.tool-call-task-container { + padding: 12px; +} + +.tool-call-task-summary { + @apply my-2 flex flex-col gap-1.5; +} + +.tool-call-task-item { + font-size: var(--font-size-xs); + line-height: var(--line-height-normal); + padding-left: 8px; + border-left: 2px solid var(--border-base); +} + +.tool-call-task-item::before { + content: "∟ "; + color: var(--text-muted); +} + +.tool-call-error-content { + background-color: var(--message-error-bg); + border-left: 3px solid var(--status-error); + padding: 12px; + margin: 8px 0; + border-radius: 4px; + color: var(--status-error); + font-size: var(--font-size-xs); +} + +.tool-call-error-content strong { + font-weight: var(--font-weight-semibold); +} + +.dropdown-diff-added { + @apply text-xs; + color: var(--status-success); +} + +.dropdown-diff-removed { + @apply text-xs; + color: var(--status-error); +} + +/* Log view specific utilities */ +.log-container { + @apply flex flex-col h-full; + background-color: var(--surface-base); +} + +.log-header { + @apply flex items-center justify-between px-4 py-3 border-b; + border-color: var(--border-base); + background-color: var(--surface-secondary); +} + +.log-content { + @apply flex-1 overflow-y-auto p-4 font-mono text-xs leading-relaxed; + background-color: var(--surface-secondary); + color: var(--text-primary); +} + +.log-entry { + @apply flex gap-3 py-0.5 px-2 -mx-2 rounded transition-colors; +} + +.log-entry:hover { + background-color: var(--surface-hover); +} + +.log-timestamp { + @apply select-none shrink-0; + color: var(--text-muted); +} + +.log-message { + @apply break-all; +} + +.log-level-error { + color: var(--log-level-error); +} + +.log-level-warn { + color: var(--log-level-warn); +} + +.log-level-debug { + color: var(--log-level-debug); +} + +.log-level-default { + color: var(--log-level-default); +} + +.log-empty-state { + @apply text-center py-8; + color: var(--text-muted); +} + +.log-paused-state { + @apply flex flex-col items-center justify-center gap-3 text-center py-10 px-6; + border: 1px dashed var(--border-base); + border-radius: 12px; + background-color: var(--surface-base); +} + +.log-paused-title { + font-size: var(--font-size-base); + font-weight: var(--font-weight-semibold); + color: var(--text-primary); +} + +.log-paused-description { + font-size: var(--font-size-sm); + color: var(--text-secondary); + max-width: 320px; +} + diff --git a/src/styles/panels.css b/src/styles/panels.css new file mode 100644 index 00000000..81cf7f5f --- /dev/null +++ b/src/styles/panels.css @@ -0,0 +1,669 @@ +@import "./tokens.css"; +@import "./utilities.css"; + +/* Tab component utilities */ +.tab-bar { + @apply border-b; + border-color: var(--border-base); +} + +.tab-bar-instance { + background-color: var(--surface-secondary); +} + +.tab-bar-session { + background-color: var(--surface-base); +} + +.tab-container { + @apply flex items-center justify-between gap-1 px-2 py-1 overflow-x-auto; +} + +.tab-base { + @apply inline-flex items-center gap-2 px-3 py-2 rounded-t-md max-w-[200px] transition-colors text-sm font-medium; + font-family: var(--font-family-sans); + outline: none; +} + +.tab-base:focus-visible { + @apply ring-2 ring-offset-1; + ring-color: var(--accent-primary); + ring-offset-color: var(--surface-base); +} + +.tab-active { + background-color: var(--tab-active-bg); + color: var(--tab-active-text); +} + +.tab-inactive { + background-color: var(--tab-inactive-bg); + color: var(--tab-inactive-text); +} + +.tab-inactive:hover { + background-color: var(--tab-inactive-hover-bg); +} + +.tab-active:hover { + background-color: var(--tab-active-hover-bg); +} + +.tab-label { + @apply truncate; +} + +.tab-close { + @apply opacity-0 group-hover:opacity-100 hover:bg-red-500 hover:text-white rounded p-0.5 transition-all cursor-pointer; +} + +.tab-close:focus-visible { + @apply ring-2 ring-offset-1; + ring-color: var(--accent-primary); + ring-offset-color: inherit; +} + +.new-tab-button { + @apply inline-flex items-center justify-center w-8 h-8 rounded-md transition-colors; + background-color: var(--new-tab-bg); + color: var(--new-tab-text); +} + +.new-tab-button:hover { + background-color: var(--new-tab-hover-bg); +} + +.new-tab-button:focus-visible { + @apply ring-2 ring-offset-1; + ring-color: var(--accent-primary); + ring-offset-color: var(--surface-base); +} + +/* Session tab specific styles */ +.session-tab-base { + @apply inline-flex items-center gap-2 px-3 py-1.5 rounded-t-md max-w-[150px] transition-colors text-sm; + font-family: var(--font-family-sans); + outline: none; + border-bottom: 2px solid transparent; +} + +.session-tab-base:focus-visible { + @apply ring-2 ring-offset-1; + ring-color: var(--accent-primary); + ring-offset-color: var(--surface-base); +} + +.session-tab-active { + background-color: var(--session-tab-active-bg); + border-bottom-color: var(--accent-primary); + color: var(--session-tab-active-text); + font-weight: var(--font-weight-medium); +} + +.session-tab-inactive { + color: var(--session-tab-inactive-text); +} + +.session-tab-inactive:hover { + background-color: var(--session-tab-hover-bg); +} + +.session-tab-special { + color: var(--session-tab-inactive-text); +} + +.connection-status-info { + justify-self: start; +} + +.connection-status-shortcut { + justify-self: center; + text-align: center; +} + +.connection-status-meta { + justify-self: end; +} + +.connection-status-text { + color: var(--text-muted); +} + +.sidebar-selector-hint { + @apply flex justify-center text-xs w-full; + color: var(--text-muted); +} + +.session-header-hints { + @apply flex-shrink-0; +} + +.session-sidebar-controls .selector-trigger, +.session-sidebar-controls [data-model-selector-control], +.session-sidebar-controls .selector-trigger-label, +.session-sidebar-controls .selector-trigger-primary { + @apply w-full; +} + +.sidebar-selector { + @apply flex flex-col gap-1 w-full; +} + +.status-indicator { + @apply flex items-center gap-1.5 text-xs; + color: var(--text-muted); +} + +.status-indicator .status-dot { + @apply w-2 h-2 rounded-full; +} + +.status-indicator.connected .status-dot { + background-color: var(--status-success); +} + +.status-indicator.connecting .status-dot { + background-color: var(--status-warning); + animation: pulse 1.5s ease-in-out infinite; +} + +.status-indicator.disconnected .status-dot { + background-color: var(--status-error); +} + +.status-indicator.session-status { + --session-status-dot: var(--text-muted); +} + +.status-indicator.session-status.session-working, +.status-indicator.session-status.session-compacting, +.status-indicator.session-status.session-idle { + font-weight: var(--font-weight-medium); +} + +.status-indicator.session-status.session-working { + color: var(--session-status-working-fg); + --session-status-dot: var(--session-status-working-fg); +} + +.status-indicator.session-status.session-compacting { + color: var(--session-status-compacting-fg); + --session-status-dot: var(--session-status-compacting-fg); +} + +.status-indicator.session-status.session-idle { + color: var(--session-status-idle-fg); + --session-status-dot: var(--session-status-idle-fg); +} + +.status-indicator.session-status .status-dot { + background-color: var(--session-status-dot); +} + +.status-indicator.session-status.session-working .status-dot, +.status-indicator.session-status.session-compacting .status-dot { + animation: pulse 1.5s ease-in-out infinite; +} + +.status-indicator.session-status.session-working.session-status-list { + background-color: var(--session-status-working-bg); +} + +.status-indicator.session-status.session-compacting.session-status-list { + background-color: var(--session-status-compacting-bg); +} + +.status-indicator.session-status.session-idle.session-status-list { + background-color: var(--session-status-idle-bg); +} + +.status-indicator.session-status-list { + font-size: 0.65rem; + text-transform: uppercase; + letter-spacing: 0.05em; + font-weight: var(--font-weight-medium); + color: inherit; + display: inline-flex; + align-items: center; + gap: 0.25rem; + padding: 0.125rem 0.5rem; + border-radius: 9999px; + border: 1px solid transparent; +} + +/* Empty state */ +.empty-state { + @apply flex-1 flex items-center justify-center p-12; +} + +.empty-state-content { + @apply text-center max-w-sm; +} + +.empty-state-content h3 { + font-size: var(--font-size-xl); + margin-bottom: 12px; +} + +.empty-state-content p { + font-size: var(--font-size-base); + color: var(--text-muted); + margin-bottom: 16px; +} + +.empty-state-content ul { + list-style: none; + padding: 0; + @apply flex flex-col gap-2; +} + +.empty-state-content li { + font-size: var(--font-size-base); + color: var(--text-muted); +} + +.empty-state-content code { + background-color: var(--surface-code); + padding: 2px 6px; + border-radius: 3px; + font-family: var(--font-family-mono); + font-size: 13px; +} + +/* Loading state */ +.loading-state { + @apply flex-1 flex flex-col items-center justify-center gap-4 p-12; +} + +.spinner { + @apply w-8 h-8 border-2 border-t-transparent rounded-full; + border-color: var(--border-base); + border-top-color: var(--accent-primary); + animation: spin 1s linear infinite; +} + +/* Modal utilities */ +.modal-overlay { + @apply fixed inset-0 z-50; + background-color: var(--overlay-scrim); +} + +.modal-surface { + @apply rounded-lg shadow-2xl flex flex-col; + background-color: var(--surface-base); + color: var(--text-primary); +} + +.modal-search-container { + @apply p-4 border-b; + border-color: var(--border-base); +} + +.modal-search-input { + @apply flex-1 bg-transparent outline-none; + color: var(--text-primary); +} + +.modal-search-input::placeholder { + color: var(--text-muted); +} + +.modal-search-icon { + color: var(--text-muted); +} + +.modal-list-container { + @apply flex-1 overflow-y-auto; +} + +.modal-section-header { + @apply px-4 py-2 text-xs font-semibold uppercase tracking-wide; + color: var(--text-muted); +} + +.modal-item { + @apply w-full px-4 py-3 flex items-start gap-3 transition-colors cursor-pointer border-none text-left; + color: var(--text-primary); +} + +.modal-list-container[data-pointer-mode="pointer"] .modal-item:hover { + background-color: var(--surface-hover); +} + +.modal-list-container[data-pointer-mode="keyboard"] .modal-item:hover:not(.modal-item-highlight) { + background-color: inherit; +} + +.modal-item-highlight { + background-color: var(--selection-highlight-bg); +} + +.modal-item-label { + @apply font-medium; + color: var(--text-primary); +} + +.modal-item-description { + @apply text-sm mt-0.5; + color: var(--text-secondary); +} + +.modal-empty-state { + @apply p-8 text-center; + color: var(--text-muted); +} + +/* Panel component utilities */ +.panel { + @apply rounded-lg shadow-sm border overflow-hidden; + background-color: var(--surface-base); + border-color: var(--border-base); + color: var(--text-primary); +} + +.panel-footer-hints { + @apply flex items-center justify-center flex-wrap gap-3 text-xs; + color: var(--text-muted); +} + +.panel-header { + @apply px-4 py-3 border-b; + border-color: var(--border-base); + background-color: var(--surface-secondary); +} + +.panel-title { + @apply text-base font-semibold; + color: var(--text-primary); +} + +.panel-subtitle { + @apply text-xs mt-0.5; + color: var(--text-muted); +} + +.panel-body { + @apply p-4; + background-color: var(--surface-base); +} + +.panel-section { + @apply border-t; + border-color: var(--border-base); +} + +.panel-section-header { + @apply w-full px-4 py-3 flex items-center justify-center transition-colors cursor-pointer gap-2; + background-color: var(--surface-secondary); +} + +.panel-section-header:hover { + background-color: var(--surface-hover); +} + +.panel-section-content { + @apply px-4 py-3 border-t overflow-visible space-y-4 w-full; + border-color: var(--border-base); + background-color: var(--surface-secondary); +} + +.panel-list { + @apply max-h-[400px] overflow-y-auto; +} + +.panel-list--fill { + max-height: none; + height: 100%; +} + +.panel-list-item { + @apply border-b last:border-b-0 transition-colors w-full; + border-color: var(--border-base); +} + +.panel-list-item:hover { + background-color: var(--surface-hover); +} + +.panel-list-item-highlight { + background-color: var(--list-item-highlight-bg) !important; + box-shadow: inset 0 0 0 1px var(--list-item-highlight-border); +} + +.panel-list-item-content { + @apply flex-1 text-left px-4 py-3 flex items-center justify-between gap-3 outline-none transition-colors w-full; +} + +.panel-list-item-content:hover { + background-color: transparent; +} + +.panel-list-item-content:disabled { + opacity: 0.6; +} + +.panel-list-item button:disabled { + cursor: not-allowed; +} + +.panel-list-item-disabled { + opacity: 0.6; +} + +.panel-empty-state { + @apply p-6 text-center; +} + +.panel-empty-state-icon { + @apply text-gray-400 dark:text-gray-600 mb-2; + color: var(--text-muted); +} + +.panel-empty-state-title { + @apply font-medium text-sm mb-1; + color: var(--text-secondary); +} + +.panel-empty-state-description { + @apply text-xs; + color: var(--text-muted); +} + +.panel-footer { + @apply px-4 py-3 border-t; + border-color: var(--border-base); + background-color: var(--surface-secondary); +} + +/* Session view utility */ +.session-view { + @apply flex flex-1 min-h-0 flex-col; + background-color: var(--surface-base); + color: inherit; +} + +/* Session list component */ +.session-list-container { + @apply flex flex-col flex-1 min-h-0 relative; + background-color: var(--surface-secondary); + min-width: 200px; + max-width: 500px; +} + +.session-sidebar { + @apply flex flex-col min-h-0; + background-color: var(--surface-secondary); +} + +.session-sidebar-header { + @apply flex flex-col gap-2 w-full; +} + +.session-sidebar-title { + color: var(--text-primary); +} + +.session-sidebar-shortcuts { + @apply flex flex-col gap-1; +} + +.session-sidebar-new { + @apply w-full; +} + +.session-sidebar-controls { + @apply flex flex-col gap-3; + background-color: var(--surface-secondary); +} + +.session-sidebar-controls > * { + @apply w-full; +} + +.session-sidebar-separator { + background-color: var(--border-base); + height: 1px; + width: 100%; +} + +.session-resize-handle { + @apply absolute top-0 right-0 w-1 h-full cursor-col-resize bg-transparent transition-colors; + z-index: 10; +} + +.session-resize-handle:hover { + background-color: var(--accent-primary); +} + +.session-resize-handle::before { + content: ""; + @apply absolute top-0 left-0 w-2 h-full -translate-x-1/2; +} + +.session-list-header { + @apply border-b relative; + border-color: var(--border-base); +} + +.session-list-header h3 { + color: var(--text-primary); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); +} + +.session-list { + @apply flex-1; +} + +.session-list-item { + @apply border-b last:border-b-0; + border-color: var(--border-base); +} + +.session-item-base { + @apply w-full flex flex-col gap-1 px-3 py-2.5 text-left transition-colors outline-none; + font-family: var(--font-family-sans); + font-size: var(--font-size-sm); +} + +.session-item-base:focus-visible { + @apply ring-2 ring-offset-1; + ring-color: var(--accent-primary); + ring-offset-color: var(--surface-secondary); +} + +.session-item-row { + @apply flex items-center gap-2 w-full; +} + +.session-item-header { + @apply justify-between; +} + +.session-item-title-row { + @apply flex items-center gap-2 min-w-0 flex-1; +} + +.session-item-meta { + @apply justify-between items-center; + font-size: var(--font-size-xs); + color: var(--text-secondary); + margin-top: 0.125rem; +} + +.session-item-active .session-item-meta { + color: var(--text-secondary); + opacity: 1; +} + +.session-item-actions { + @apply flex items-center gap-1; +} + +.session-item-active { + background-color: var(--list-item-highlight-bg); + color: var(--text-primary); + font-weight: var(--font-weight-medium); + box-shadow: inset 0 0 0 1px var(--list-item-highlight-border); +} + +.session-item-inactive { + color: var(--text-secondary); +} + +.session-item-inactive:hover { + background-color: var(--surface-hover); + color: var(--text-primary); +} + +.session-item-active .session-item-close:hover { + background-color: var(--surface-hover); + color: var(--text-primary); +} + +.session-item-title { + @apply flex-1 min-w-0; + font-weight: inherit; +} + +.session-item-close { + @apply flex-shrink-0 p-0.5 rounded transition-all; +} + +.session-item-close:focus-visible { + @apply ring-2 ring-offset-1; + ring-color: var(--accent-primary); + ring-offset-color: inherit; +} + +.session-list-footer { + @apply border-t; + border-color: var(--border-base); +} + +.session-new-button { + background-color: var(--surface-base); + color: var(--text-primary); + border: 1px solid var(--border-base); +} + +.session-new-button:hover { + background-color: var(--surface-hover); +} + +.session-new-button:focus-visible { + @apply ring-2 ring-offset-1; + ring-color: var(--accent-primary); + ring-offset-color: var(--surface-secondary); +} + +/* Responsive behavior for session list */ +@media (max-width: 768px) { + .session-list-container { + min-width: 200px; + } + + .session-item-base { + @apply px-2 py-2; + } +} diff --git a/src/styles/tokens.css b/src/styles/tokens.css index e9b14ded..2d1ff818 100644 --- a/src/styles/tokens.css +++ b/src/styles/tokens.css @@ -34,6 +34,90 @@ --message-tool-bg: #f8f9fa; --message-tool-border: #6c757d; + + /* Semantic component colors */ + --session-status-working-fg: #b45309; + --session-status-working-bg: rgba(245, 158, 11, 0.16); + --session-status-compacting-fg: #6d28d9; + --session-status-compacting-bg: rgba(109, 40, 217, 0.18); + --session-status-idle-fg: #15803d; + --session-status-idle-bg: rgba(22, 163, 74, 0.16); + --list-item-highlight-bg: rgba(0, 102, 255, 0.1); + --list-item-highlight-border: rgba(0, 102, 255, 0.25); + --attachment-chip-bg: rgba(0, 102, 255, 0.1); + --attachment-chip-text: #0066ff; + --attachment-chip-ring: rgba(0, 102, 255, 0.1); + --badge-neutral-bg: rgba(0, 102, 255, 0.05); + --badge-neutral-text: #0066ff; + --status-ready-fg: #16a34a; + --status-ready-bg: rgba(34, 197, 94, 0.1); + --status-starting-fg: #ca8a04; + --status-starting-bg: rgba(250, 204, 21, 0.1); + --status-error-fg: #dc2626; + --status-error-bg: rgba(239, 68, 68, 0.1); + --status-stopped-fg: #6b7280; + --status-stopped-bg: rgba(107, 114, 128, 0.1); + --env-vars-bg: rgba(0, 102, 255, 0.1); + --env-vars-border: rgba(0, 102, 255, 0.2); + --env-vars-text: #0066ff; + --folder-overlay-bg: rgba(0, 0, 0, 0.35); + --folder-card-shadow: 0 20px 60px rgba(0, 0, 0, 0.2); + --folder-card-radius: 16px; + --dropdown-highlight-bg: rgba(0, 102, 255, 0.1); + --dropdown-highlight-text: var(--text-inverted); + --selection-highlight-bg: rgba(0, 102, 255, 0.12); + --selection-highlight-strong-bg: rgba(0, 102, 255, 0.18); + --overlay-scrim: rgba(0, 0, 0, 0.5); + --scroll-elevation-shadow: 0 10px 25px rgba(0, 0, 0, 0.08); + --message-error-bg: rgba(244, 67, 54, 0.1); + --message-error-bg-strong: rgba(244, 67, 54, 0.15); + --danger-soft-bg: rgba(239, 68, 68, 0.1); + --danger-soft-bg-strong: rgba(244, 67, 54, 0.15); + --log-level-error: var(--status-error); + --log-level-warn: var(--status-warning); + --log-level-debug: var(--text-muted); + --log-level-default: var(--text-primary); + --focus-ring-color: var(--accent-primary); + --focus-ring-offset: var(--surface-base); + --kbd-bg: var(--surface-secondary); + --kbd-border: var(--border-base); + --kbd-text: var(--text-primary); + --button-primary-bg: var(--accent-primary); + --button-primary-hover-bg: var(--accent-hover); + --button-primary-text: var(--text-inverted); + --tab-active-bg: var(--accent-primary); + --tab-active-hover-bg: var(--accent-hover); + --tab-active-text: var(--text-inverted); + --tab-inactive-bg: var(--surface-muted); + --tab-inactive-hover-bg: var(--surface-hover); + --tab-inactive-text: var(--text-secondary); + --new-tab-bg: var(--surface-secondary); + --new-tab-hover-bg: var(--surface-hover); + --new-tab-text: var(--text-muted); + --session-tab-active-bg: var(--surface-base); + --session-tab-active-text: var(--text-primary); + --session-tab-inactive-text: var(--text-muted); + --session-tab-hover-bg: var(--surface-hover); + + /* Layout & spacing tokens */ + --space-2xs: 2px; + --space-xs: 4px; + --space-sm: 8px; + --space-md: 12px; + --space-lg: 16px; + --space-xl: 24px; + --radius-xs: 3px; + --radius-sm: 4px; + --radius-md: 6px; + --radius-lg: 8px; + --radius-xl: 12px; + --radius-2xl: 16px; + --radius-full: 9999px; + --button-padding-y: 0.75rem; + --button-padding-x: 1.25rem; + --button-radius: 0.5rem; + --chip-radius: 0.375rem; + --pill-radius: 9999px; /* Typography tokens */ --font-family-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; @@ -96,17 +180,104 @@ --message-tool-bg: #212529; --message-tool-border: #adb5bd; + + /* Semantic component colors */ + --session-status-working-fg: #facc15; + --session-status-working-bg: rgba(250, 204, 21, 0.25); + --session-status-compacting-fg: #c084fc; + --session-status-compacting-bg: rgba(192, 132, 252, 0.28); + --session-status-idle-fg: #4ade80; + --session-status-idle-bg: rgba(74, 222, 128, 0.22); + --list-item-highlight-bg: rgba(0, 128, 255, 0.2); + --list-item-highlight-border: rgba(0, 128, 255, 0.4); + --attachment-chip-bg: rgba(0, 128, 255, 0.1); + --attachment-chip-text: #0080ff; + --attachment-chip-ring: rgba(0, 128, 255, 0.2); + --badge-neutral-bg: rgba(0, 128, 255, 0.15); + --badge-neutral-text: #0080ff; + --status-ready-fg: #22c55e; + --status-ready-bg: rgba(34, 197, 94, 0.2); + --status-starting-fg: #facc15; + --status-starting-bg: rgba(250, 204, 21, 0.2); + --status-error-fg: #ef4444; + --status-error-bg: rgba(239, 68, 68, 0.2); + --status-stopped-fg: #9ca3af; + --status-stopped-bg: rgba(107, 114, 128, 0.2); + --env-vars-bg: rgba(0, 128, 255, 0.2); + --env-vars-border: rgba(0, 128, 255, 0.3); + --env-vars-text: #0080ff; + --folder-overlay-bg: rgba(0, 0, 0, 0.45); + --folder-card-shadow: 0 20px 60px rgba(0, 0, 0, 0.35); + --folder-card-radius: 16px; + --dropdown-highlight-bg: rgba(0, 128, 255, 0.2); + --dropdown-highlight-text: var(--text-primary); + --kbd-bg: var(--surface-secondary); + --kbd-border: var(--border-base); + --kbd-text: var(--text-primary); + --button-primary-bg: #3f3f46; + --button-primary-hover-bg: #52525b; + --button-primary-text: #f5f6f8; + --tab-active-bg: #3f3f46; + --tab-active-hover-bg: #52525b; + --tab-active-text: #f5f6f8; + --tab-inactive-bg: #2a2a31; + --tab-inactive-hover-bg: #3f3f46; + --tab-inactive-text: #d4d4d8; + --new-tab-bg: #3f3f46; + --new-tab-hover-bg: #52525b; + --new-tab-text: #f5f6f8; + --session-tab-active-bg: var(--surface-muted); + --session-tab-active-text: var(--text-primary); + --session-tab-inactive-text: var(--text-muted); + --session-tab-hover-bg: #3f3f46; + + --button-primary-bg: #3f3f46; + --button-primary-hover-bg: #52525b; + --button-primary-text: #f5f6f8; + --tab-active-bg: #3f3f46; + --tab-active-hover-bg: #52525b; + --tab-active-text: #f5f6f8; + --tab-inactive-bg: #2f2f36; + --tab-inactive-hover-bg: #3d3d45; + --tab-inactive-text: #d4d4d8; + --new-tab-bg: #3f3f46; + --new-tab-hover-bg: #52525b; + --new-tab-text: #f5f6f8; + --session-tab-active-bg: var(--surface-muted); + --session-tab-active-text: var(--text-primary); + --session-tab-inactive-text: var(--text-muted); + --session-tab-hover-bg: #3f3f46; + + /* Layout & spacing tokens */ + --space-2xs: 2px; + --space-xs: 4px; + --space-sm: 8px; + --space-md: 12px; + --space-lg: 16px; + --space-xl: 24px; + --radius-xs: 3px; + --radius-sm: 4px; + --radius-md: 6px; + --radius-lg: 8px; + --radius-xl: 12px; + --radius-2xl: 16px; + --radius-full: 9999px; + --button-padding-y: 0.75rem; + --button-padding-x: 1.25rem; + --button-radius: 0.5rem; + --chip-radius: 0.375rem; + --pill-radius: 9999px; /* Typography tokens (same as light theme) */ --font-family-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; --font-family-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; - + /* Font weights */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; - + /* Font sizes */ --font-size-xs: 11px; --font-size-sm: 12px; @@ -119,6 +290,7 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; --line-height-relaxed: 1.6; + } } @@ -158,17 +330,85 @@ --message-tool-bg: #212529; --message-tool-border: #adb5bd; + + /* Semantic component colors */ + --session-status-working-fg: #facc15; + --session-status-working-bg: rgba(250, 204, 21, 0.25); + --session-status-compacting-fg: #c084fc; + --session-status-compacting-bg: rgba(192, 132, 252, 0.28); + --session-status-idle-fg: #4ade80; + --session-status-idle-bg: rgba(74, 222, 128, 0.22); + --list-item-highlight-bg: rgba(0, 128, 255, 0.2); + --list-item-highlight-border: rgba(0, 128, 255, 0.4); + --attachment-chip-bg: rgba(0, 128, 255, 0.1); + --attachment-chip-text: #0080ff; + --attachment-chip-ring: rgba(0, 128, 255, 0.2); + --badge-neutral-bg: rgba(0, 128, 255, 0.15); + --badge-neutral-text: #0080ff; + --status-ready-fg: #22c55e; + --status-ready-bg: rgba(34, 197, 94, 0.2); + --status-starting-fg: #facc15; + --status-starting-bg: rgba(250, 204, 21, 0.2); + --status-error-fg: #ef4444; + --status-error-bg: rgba(239, 68, 68, 0.2); + --status-stopped-fg: #9ca3af; + --status-stopped-bg: rgba(107, 114, 128, 0.2); + --env-vars-bg: rgba(0, 128, 255, 0.2); + --env-vars-border: rgba(0, 128, 255, 0.3); + --env-vars-text: #0080ff; + --folder-overlay-bg: rgba(0, 0, 0, 0.45); + --folder-card-shadow: 0 20px 60px rgba(0, 0, 0, 0.35); + --folder-card-radius: 16px; + --dropdown-highlight-bg: rgba(0, 128, 255, 0.2); + --dropdown-highlight-text: var(--text-primary); + --selection-highlight-bg: rgba(0, 128, 255, 0.18); + --selection-highlight-strong-bg: rgba(0, 128, 255, 0.28); + --overlay-scrim: rgba(0, 0, 0, 0.6); + --scroll-elevation-shadow: 0 10px 25px rgba(0, 0, 0, 0.35); + --message-error-bg: rgba(244, 67, 54, 0.12); + --message-error-bg-strong: rgba(244, 67, 54, 0.2); + --danger-soft-bg: rgba(244, 67, 54, 0.16); + --danger-soft-bg-strong: rgba(244, 67, 54, 0.28); + --log-level-error: var(--status-error); + --log-level-warn: var(--status-warning); + --log-level-debug: var(--text-secondary); + --log-level-default: var(--text-primary); + --focus-ring-color: var(--accent-primary); + --focus-ring-offset: var(--surface-base); + --kbd-bg: var(--surface-secondary); + --kbd-border: var(--border-base); + --kbd-text: var(--text-primary); + + /* Layout & spacing tokens */ + --space-2xs: 2px; + --space-xs: 4px; + --space-sm: 8px; + --space-md: 12px; + --space-lg: 16px; + --space-xl: 24px; + --radius-xs: 3px; + --radius-sm: 4px; + --radius-md: 6px; + --radius-lg: 8px; + --radius-xl: 12px; + --radius-2xl: 16px; + --radius-full: 9999px; + --button-padding-y: 0.75rem; + --button-padding-x: 1.25rem; + --button-radius: 0.5rem; + --chip-radius: 0.375rem; + --pill-radius: 9999px; /* Typography tokens (same as light theme) */ --font-family-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; --font-family-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; - + /* Font weights */ --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; - + /* Font sizes */ --font-size-xs: 11px; --font-size-sm: 12px; @@ -181,4 +421,5 @@ --line-height-tight: 1.25; --line-height-normal: 1.5; --line-height-relaxed: 1.6; + } diff --git a/src/styles/utilities.css b/src/styles/utilities.css new file mode 100644 index 00000000..8f3d6238 --- /dev/null +++ b/src/styles/utilities.css @@ -0,0 +1,135 @@ +@import "./tokens.css"; + +/* Reusable component utilities using tokens */ + +/* Base token utility helpers */ +.text-primary { + color: var(--text-primary); +} + +.text-secondary { + color: var(--text-secondary); +} + +.text-muted { + color: var(--text-muted); +} + +.text-inverted { + color: var(--text-inverted); +} + +.text-accent { + color: var(--accent-primary); +} + +.bg-surface-base { + background-color: var(--surface-base); +} + +.bg-surface-secondary { + background-color: var(--surface-secondary); +} + +.bg-surface-muted { + background-color: var(--surface-muted); +} + +.border-base { + border-color: var(--border-base); +} + +.icon-muted { + color: var(--text-muted); +} + +.icon-accent { + color: var(--accent-primary); +} + +.icon-danger-hover:hover { + color: var(--status-error); +} + +.icon-accent-hover:hover { + color: var(--accent-primary); +} + +.ring-accent-inset { + box-shadow: inset 0 0 0 2px var(--accent-primary); +} + +/* Shared button + chip helpers */ +:is(.button-primary, + button.button-primary, + .button-secondary, + button.button-secondary, + .button-tertiary, + button.button-tertiary) { + @apply inline-flex items-center justify-center gap-2 font-medium transition-colors rounded-md; + border: 1px solid transparent; +} + +:is(.button-primary, + button.button-primary, + .button-secondary, + button.button-secondary, + .button-tertiary, + button.button-tertiary):focus-visible { + outline: none; + box-shadow: 0 0 0 2px var(--focus-ring-offset), 0 0 0 4px var(--focus-ring-color); +} + +:is(.button-primary, + button.button-primary, + .button-secondary, + button.button-secondary, + .button-tertiary, + button.button-tertiary):disabled { + @apply cursor-not-allowed opacity-50; +} + +:is(.attachment-chip, + .neutral-badge, + .status-badge) { + @apply inline-flex items-center gap-1; + border-radius: var(--chip-radius); +} + +/* Focus helpers */ +.focus-ring-accent:focus { + outline: none; + border-color: transparent; + box-shadow: 0 0 0 2px var(--accent-primary); +} + +/* Shared animations */ +@keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.5; } +} + +@keyframes shimmer { + 0%, 100% { opacity: 0.6; } + 50% { opacity: 1; } +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +/* Shared layout helpers */ +.status-dot { + @apply w-1 h-1 rounded-full; +} + +.kbd { + @apply inline-flex items-center gap-0.5 font-mono text-xs px-1.5 py-0.5 rounded; + background-color: var(--surface-secondary); + border: 1px solid var(--border-base); + color: var(--text-primary); +} + +.kbd-separator { + @apply opacity-50; +}