diff --git a/packages/frontend/src/app-shell.css.ts b/packages/frontend/src/app-shell.css.ts index 4e20229..cfc9198 100644 --- a/packages/frontend/src/app-shell.css.ts +++ b/packages/frontend/src/app-shell.css.ts @@ -117,8 +117,9 @@ export const appShellStyles = css` align-items: center; justify-content: space-between; gap: 10px; - padding: 0 14px; - border-bottom: 1px solid var(--toolbar-border); + padding: 0 16px; + border-bottom: none; + box-shadow: 0 1px 0 var(--border-color); background: var(--toolbar-bg); position: relative; } @@ -149,31 +150,30 @@ export const appShellStyles = css` } .pane-toolbar-leading-btn { - width: 26px; - min-width: 26px; - height: 26px; - border: 1px solid var(--control-border); - border-radius: 9px; - background: var(--control-bg); - color: var(--text-secondary); + width: var(--control-height); + min-width: var(--control-height); + height: var(--control-height); + border: none; + border-radius: 8px; + background: transparent; + color: var(--text-muted); display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; - transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast); + transition: background var(--transition-fast), color var(--transition-fast); } .pane-toolbar-leading-btn:hover { - background: var(--control-bg-hover); - border-color: var(--border-primary); + background: var(--bg-hover); color: var(--text-primary); } .pane-toolbar-leading-btn svg { - width: 13px; - height: 13px; + width: 18px; + height: 18px; stroke: currentColor; - stroke-width: 1.9; + stroke-width: 1.6; fill: none; flex-shrink: 0; } @@ -199,11 +199,11 @@ export const appShellStyles = css` .pane-toolbar-title { margin: 0; - font-size: 13.5px; + font-size: 14px; line-height: 1.2; - font-weight: 650; + font-weight: 600; color: var(--text-primary); - letter-spacing: -0.015em; + letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -244,25 +244,24 @@ export const appShellStyles = css` } .window-control-btn { - border: 1px solid var(--control-border); - border-radius: 999px; + border: 1px solid var(--border-color); + border-radius: 8px; min-height: var(--control-height); padding: 0 12px; - background: var(--control-bg); - color: var(--text-primary); + background: transparent; + color: var(--text-secondary); display: inline-flex; align-items: center; justify-content: center; gap: 6px; font-size: 11px; font-weight: 600; - transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast); + transition: background var(--transition-fast), color var(--transition-fast); white-space: nowrap; } .window-control-btn:hover { - background: var(--control-bg-hover); - border-color: var(--border-primary); + background: var(--bg-hover); color: var(--text-primary); } @@ -304,7 +303,7 @@ export const appShellStyles = css` width: var(--control-height); min-width: var(--control-height); padding: 0; - border-radius: 9px; + border-radius: 8px; } .stage-shell { @@ -327,7 +326,7 @@ export const appShellStyles = css` border-top: 1px solid var(--footer-border); background: var(--footer-bg); color: var(--text-secondary); - font-size: 11.5px; + font-size: 12px; line-height: 1; } diff --git a/packages/frontend/src/app-shell.ts b/packages/frontend/src/app-shell.ts index 8df15b9..5c7b1d5 100644 --- a/packages/frontend/src/app-shell.ts +++ b/packages/frontend/src/app-shell.ts @@ -7,6 +7,7 @@ import * as api from './services/rpc.js' import { WsClient } from './services/rpc.js' import { initWorkspaceSync } from './services/workspace-sync.js' import { appShellStyles } from './app-shell.css.js' +import { iconMinus, iconSquare, iconX, iconPanelLeft } from './utils/icons.js' import type { ClaudeSettings, HostOperatorRequest, SelectedModelProvider } from '@dune/shared' import type { CreateAgentDialog } from './components/agents/create-dialog.js' import type { CreateChannelDialog } from './components/channels/create-dialog.js' @@ -939,9 +940,7 @@ export class AppShell extends LitElement { aria-label="Minimize window" @click=${() => this.handleWindowControl('minimize')} > - + ${iconMinus()} ` } private renderSidebarToggleIcon() { - return html` - - ` + return iconPanelLeft() } private renderToolbarLeadingCluster() { diff --git a/packages/frontend/src/components/agents/chat-view.css.ts b/packages/frontend/src/components/agents/chat-view.css.ts index c2531a9..1ffe16f 100644 --- a/packages/frontend/src/components/agents/chat-view.css.ts +++ b/packages/frontend/src/components/agents/chat-view.css.ts @@ -15,7 +15,7 @@ export const chatViewStyles = css` .header { display: flex; align-items: center; - padding: 10px 16px 8px; + padding: 12px 18px 10px; background: transparent; min-height: 54px; gap: 14px; @@ -30,9 +30,9 @@ export const chatViewStyles = css` flex: 1; } .header-avatar { - width: 32px; - height: 32px; - border-radius: 10px; + width: 36px; + height: 36px; + border-radius: 100%; display: flex; align-items: center; justify-content: center; @@ -104,7 +104,7 @@ export const chatViewStyles = css` .conversation { flex: 1; overflow-y: auto; - padding: 4px 18px 6px; + padding: 6px 20px 8px; min-height: 0; } .conversation-lane { @@ -125,7 +125,7 @@ export const chatViewStyles = css` .empty-avatar { width: 44px; height: 44px; - border-radius: 12px; + border-radius: 100%; display: flex; align-items: center; justify-content: center; @@ -169,7 +169,7 @@ export const chatViewStyles = css` .entry-thinking { display: flex; gap: 12px; - padding: 7px 12px; + padding: 8px 14px; max-width: 820px; } .thinking-dots { @@ -196,13 +196,13 @@ export const chatViewStyles = css` .entry-text { display: flex; gap: 12px; - padding: 7px 12px; + padding: 8px 14px; max-width: 820px; } .entry-avatar { width: 28px; height: 28px; - border-radius: 6px; + border-radius: 100%; display: flex; align-items: center; justify-content: center; @@ -435,7 +435,7 @@ export const chatViewStyles = css` .entry-user { display: flex; gap: 12px; - padding: 7px 12px; + padding: 8px 14px; max-width: 820px; } .user-avatar { diff --git a/packages/frontend/src/components/agents/chat-view.ts b/packages/frontend/src/components/agents/chat-view.ts index 5523b35..19ef8a6 100644 --- a/packages/frontend/src/components/agents/chat-view.ts +++ b/packages/frontend/src/components/agents/chat-view.ts @@ -22,6 +22,7 @@ import './memory-editor.js' import './host-settings.js' import './stash-strip.js' import { chatViewStyles } from './chat-view.css.js' +import { iconWrench, iconXCircle, iconFileText, iconAlertTriangle } from '../../utils/icons.js' import type { AgentMemoryEditor, MemoryEditorSnapshot } from './memory-editor.js' import type { StashItem } from './stash-strip.js' @@ -554,10 +555,7 @@ export class AgentChatView extends LitElement {
this.toggleExpand(entry.id)}> - + ${iconWrench()} ${d.toolName || 'unknown'} Tool Call
@@ -574,19 +572,7 @@ export class AgentChatView extends LitElement {
this.toggleExpand(entry.id)}> - ${d.isError - ? html` - - ` - : html` - - `} + ${d.isError ? iconXCircle() : iconFileText()} ${d.isError ? 'Error Result' : 'Result'} ${d.isError ? 'Error' : 'Output'}
@@ -689,9 +675,7 @@ export class AgentChatView extends LitElement { return html`
- + ${iconAlertTriangle()} ${d.message || 'Unknown error'}
diff --git a/packages/frontend/src/components/agents/computer-tab.ts b/packages/frontend/src/components/agents/computer-tab.ts index ab81920..c0f74b5 100644 --- a/packages/frontend/src/components/agents/computer-tab.ts +++ b/packages/frontend/src/components/agents/computer-tab.ts @@ -1,6 +1,7 @@ import { LitElement, html, css } from 'lit' import { customElement, property, state as litState } from 'lit/decorators.js' import * as api from '../../services/rpc.js' +import { iconPlus, iconMenu, iconPlay, iconCamera } from '../../utils/icons.js' @customElement('agent-computer-tab') export class AgentComputerTab extends LitElement { @@ -204,9 +205,7 @@ export class AgentComputerTab extends LitElement {
- + ${iconPlus()} Desktop @@ -223,23 +222,16 @@ export class AgentComputerTab extends LitElement {
- + ${iconMenu()} Screenshot Mode
diff --git a/packages/frontend/src/components/agents/memory-editor.ts b/packages/frontend/src/components/agents/memory-editor.ts index 2f850d4..7a9d259 100644 --- a/packages/frontend/src/components/agents/memory-editor.ts +++ b/packages/frontend/src/components/agents/memory-editor.ts @@ -3,6 +3,7 @@ import { customElement, property, state as litState } from 'lit/decorators.js' import type { Agent, MemoryFile } from '@dune/shared' import * as api from '../../services/rpc.js' import { uiPreferences } from '../../state/ui-preferences.js' +import { iconX } from '../../utils/icons.js' type MemorySort = 'name' | 'updated' | 'size' type MemoryPane = 'files' | 'editor' @@ -1101,9 +1102,7 @@ export class AgentMemoryEditor extends LitElement { title=${`Delete ${this.getMemoryFileName(f.path)}`} @click=${(e: Event) => { e.stopPropagation(); this.memoryDeleteConfirm = f.path }} > - + ${iconX()}
${this.memoryDeleteConfirm === f.path ? html` diff --git a/packages/frontend/src/components/agents/profile-panel.css.ts b/packages/frontend/src/components/agents/profile-panel.css.ts index 3250147..b1ee748 100644 --- a/packages/frontend/src/components/agents/profile-panel.css.ts +++ b/packages/frontend/src/components/agents/profile-panel.css.ts @@ -71,7 +71,7 @@ export const profilePanelStyles = css` max-height: none; background: var(--sheet-bg); border: 1px solid var(--border-color); - border-radius: 30px 0 0 30px; + border-radius: 16px 0 0 16px; box-shadow: var(--shadow-lg); display: flex; flex-direction: column; @@ -86,7 +86,7 @@ export const profilePanelStyles = css` .modal.computer { height: 85vh; width: min(94vw, calc((85vh - 120px) * 4 / 3 + 52px)); - border-radius: 28px; + border-radius: 16px; margin: auto 12px auto auto; align-self: center; } @@ -103,7 +103,7 @@ export const profilePanelStyles = css` .modal.prompt-view { width: min(800px, 92vw); height: 85vh; - border-radius: 28px; + border-radius: 16px; margin: auto 12px auto auto; align-self: center; } @@ -112,7 +112,7 @@ export const profilePanelStyles = css` display: flex; align-items: center; gap: 16px; - padding: 18px 18px 12px; + padding: 20px 20px 14px; transition: padding 0.25s ease; } @@ -124,7 +124,7 @@ export const profilePanelStyles = css` .avatar { width: 64px; height: 64px; - border-radius: var(--radius); + border-radius: 100%; display: flex; align-items: center; justify-content: center; @@ -711,7 +711,7 @@ export const profilePanelStyles = css` width: min(620px, 92vw); height: auto; max-height: 88vh; - border-radius: 24px; + border-radius: 16px; } .modal-header { diff --git a/packages/frontend/src/components/agents/profile-panel.ts b/packages/frontend/src/components/agents/profile-panel.ts index 31dfda1..cb079f3 100644 --- a/packages/frontend/src/components/agents/profile-panel.ts +++ b/packages/frontend/src/components/agents/profile-panel.ts @@ -10,6 +10,7 @@ import './profile-tab.js' import './skills-tab.js' import './logs-tab.js' import './system-prompt-overlay.js' +import { iconMinimize, iconMaximize, iconX, iconPlay, iconPause, iconTrash } from '../../utils/icons.js' const STATUS_LABELS: Record = { idle: 'Active', @@ -405,46 +406,22 @@ export class AgentProfilePanel extends LitElement {
${this.activeTab === 'computer' ? html` ` : ''}
diff --git a/packages/frontend/src/components/agents/profile-tab.ts b/packages/frontend/src/components/agents/profile-tab.ts index da4e999..6e85f95 100644 --- a/packages/frontend/src/components/agents/profile-tab.ts +++ b/packages/frontend/src/components/agents/profile-tab.ts @@ -3,6 +3,7 @@ import { customElement, property, state } from 'lit/decorators.js' import type { Agent, Channel } from '@dune/shared' import * as api from '../../services/rpc.js' import { profilePanelStyles } from './profile-panel.css.js' +import { iconFileText } from '../../utils/icons.js' const AVATAR_COLORS = ['#0f9a90', '#0ea5e9', '#3b82f6', '#6d28d9', '#ef4444', '#f97316', '#10b981', '#64748b'] @@ -268,10 +269,7 @@ export class AgentProfileTab extends LitElement {
diff --git a/packages/frontend/src/components/agents/system-prompt-overlay.ts b/packages/frontend/src/components/agents/system-prompt-overlay.ts index 84c790a..1c6a647 100644 --- a/packages/frontend/src/components/agents/system-prompt-overlay.ts +++ b/packages/frontend/src/components/agents/system-prompt-overlay.ts @@ -2,6 +2,7 @@ import { LitElement, html } from 'lit' import { customElement, property, state } from 'lit/decorators.js' import * as api from '../../services/rpc.js' import { profilePanelStyles } from './profile-panel.css.js' +import { iconX } from '../../utils/icons.js' @customElement('agent-system-prompt-overlay') export class AgentSystemPromptOverlay extends LitElement { @@ -42,9 +43,7 @@ export class AgentSystemPromptOverlay extends LitElement {
System Prompt
diff --git a/packages/frontend/src/components/channels/details-panel.ts b/packages/frontend/src/components/channels/details-panel.ts index cb5a6d4..87e9f47 100644 --- a/packages/frontend/src/components/channels/details-panel.ts +++ b/packages/frontend/src/components/channels/details-panel.ts @@ -3,6 +3,7 @@ import { customElement, property, state as litState } from 'lit/decorators.js' import type { Channel, Agent } from '@dune/shared' import * as api from '../../services/rpc.js' import { uiPreferences } from '../../state/ui-preferences.js' +import { iconX } from '../../utils/icons.js' const DEFAULT_INSPECTOR_WIDTH_PX = 520 const INSPECTOR_MIN_WIDTH_PX = 360 @@ -109,7 +110,7 @@ export class ChannelDetailsPanel extends LitElement { max-height: none; background: var(--sheet-bg); border: 1px solid var(--border-color); - border-radius: 30px 0 0 30px; + border-radius: 16px 0 0 16px; box-shadow: var(--shadow-lg); display: flex; flex-direction: column; @@ -358,7 +359,7 @@ export class ChannelDetailsPanel extends LitElement { width: min(560px, 92vw); height: auto; max-height: 88vh; - border-radius: 24px; + border-radius: 16px; } .modal-header { @@ -629,9 +630,7 @@ export class ChannelDetailsPanel extends LitElement { }
diff --git a/packages/frontend/src/components/messages/codex-composer.ts b/packages/frontend/src/components/messages/codex-composer.ts index 2ad623b..04d6e9c 100644 --- a/packages/frontend/src/components/messages/codex-composer.ts +++ b/packages/frontend/src/components/messages/codex-composer.ts @@ -1,5 +1,6 @@ import { LitElement, html, css } from 'lit' import { customElement, property, query, state as litState } from 'lit/decorators.js' +import { iconPlus, iconStop, iconArrowRight } from '../../utils/icons.js' export type CodexComposerInputDetail = { value: string @@ -60,15 +61,15 @@ export class CodexComposer extends LitElement { gap: 6px; min-height: var(--composer-min-height); border-radius: var(--composer-radius); - background: var(--composer-shell); + background: transparent; box-shadow: var(--composer-shadow); - padding: 12px 14px 12px; + padding: 14px 16px 14px; transition: box-shadow var(--transition-fast), background var(--transition-fast); - border: 1px solid color-mix(in srgb, var(--composer-seam) 88%, transparent); + border: none; } .shell:focus-within { - box-shadow: var(--composer-shadow), 0 0 0 2px var(--focus-ring); + box-shadow: var(--shadow-sm); } .composer-input { @@ -124,10 +125,10 @@ export class CodexComposer extends LitElement { .add-btn { width: var(--composer-submit-size); height: var(--composer-submit-size); - border: 1px solid var(--control-border); - border-radius: 10px; - background: var(--control-bg); - color: var(--text-secondary); + border: 1px solid var(--border-color); + border-radius: 8px; + background: transparent; + color: var(--text-muted); display: inline-flex; align-items: center; justify-content: center; @@ -145,9 +146,8 @@ export class CodexComposer extends LitElement { .add-btn:hover:enabled, .add-btn.open:enabled { - background: var(--control-bg-hover); + background: var(--bg-hover); color: var(--text-primary); - border-color: var(--border-primary); } .add-btn:disabled { @@ -161,11 +161,11 @@ export class CodexComposer extends LitElement { left: 0; bottom: calc(100% + 10px); min-width: 220px; - border-radius: 12px; + border-radius: 16px; background: var(--sheet-bg); border: 1px solid var(--border-color); box-shadow: var(--shadow-md); - padding: 8px; + padding: 10px; display: flex; flex-direction: column; gap: 4px; @@ -177,7 +177,7 @@ export class CodexComposer extends LitElement { background: transparent; color: var(--text-primary); text-align: left; - border-radius: 10px; + border-radius: 8px; padding: 9px 10px; font-size: 13px; font-weight: 500; @@ -450,9 +450,7 @@ export class CodexComposer extends LitElement { aria-label="Open actions" aria-expanded=${this.addMenuOpen ? 'true' : 'false'} > - + ${iconPlus()} ${this.addMenuOpen ? html` @@ -487,17 +485,7 @@ export class CodexComposer extends LitElement { @click=${this.handleSubmitClick} aria-label=${isInterruptMode ? 'Interrupt workflow' : 'Send'} > - ${isInterruptMode - ? html` - - ` - : html` - - `} + ${isInterruptMode ? iconStop() : iconArrowRight()}
diff --git a/packages/frontend/src/components/messages/message-area.ts b/packages/frontend/src/components/messages/message-area.ts index 7f8ec10..06ff027 100644 --- a/packages/frontend/src/components/messages/message-area.ts +++ b/packages/frontend/src/components/messages/message-area.ts @@ -1,6 +1,7 @@ import { LitElement, html, css } from 'lit' import { customElement, property, query, state } from 'lit/decorators.js' import type { Message, Agent, Channel, SelectedModelProvider } from '@dune/shared' +import { iconUsers } from '../../utils/icons.js' import type { MentionPopup } from './mention-popup.js' import './codex-composer.js' import type { @@ -197,9 +198,9 @@ export class MessageArea extends LitElement { margin-left: auto; max-width: min(62%, 520px); padding: 10px 16px; - border-radius: 18px; - background: color-mix(in srgb, var(--bg-surface) 96%, transparent); - border: 1px solid var(--glass-border); + border-radius: 12px; + background: var(--bg-surface); + border: 1px solid var(--border-color); color: var(--text-primary); font-size: 14px; line-height: 1.45; @@ -515,9 +516,7 @@ export class MessageArea extends LitElement {
diff --git a/packages/frontend/src/components/messages/message-item.ts b/packages/frontend/src/components/messages/message-item.ts index a5f8509..dc3b613 100644 --- a/packages/frontend/src/components/messages/message-item.ts +++ b/packages/frontend/src/components/messages/message-item.ts @@ -10,6 +10,7 @@ import { highlightCodeBlocks } from '../../utils/shiki-highlighter.js' import { renderMathBlocks } from '../../utils/katex-renderer.js' import { renderMermaidBlocks } from '../../utils/mermaid-renderer.js' import type { Message } from '@dune/shared' +import { iconInfo } from '../../utils/icons.js' @customElement('message-item') export class MessageItem extends LitElement { @@ -21,24 +22,24 @@ export class MessageItem extends LitElement { :host { display: flex; gap: 12px; - padding: 12px 14px 14px; - border-radius: 18px; - border: 1px solid var(--glass-border); - background: color-mix(in srgb, var(--bg-surface) 96%, transparent); + padding: 14px 16px 16px; + border-radius: 12px; + border: 1px solid var(--border-color); + background: var(--bg-primary); transition: background var(--transition-fast), border-color var(--transition-fast); position: relative; isolation: isolate; } :host(:hover) { - background: color-mix(in srgb, var(--bg-hover) 34%, var(--glass-bg)); + background: var(--bg-surface); border-color: var(--border-primary); } .avatar { width: 30px; height: 30px; - border-radius: 9px; + border-radius: 100%; display: inline-flex; align-items: center; justify-content: center; @@ -77,7 +78,7 @@ export class MessageItem extends LitElement { } .name { - font-size: 13px; + font-size: 14px; font-weight: 600; color: var(--text-primary); line-height: 1.2; @@ -97,9 +98,9 @@ export class MessageItem extends LitElement { } .content { - font-size: 13px; + font-size: 14px; color: var(--text-secondary); - line-height: 1.58; + line-height: 1.6; word-break: break-word; } @@ -305,9 +306,7 @@ export class MessageItem extends LitElement { if (isSystem) { return html` ` } diff --git a/packages/frontend/src/components/sandboxes/view.css.ts b/packages/frontend/src/components/sandboxes/view.css.ts index 80becd1..10b406a 100644 --- a/packages/frontend/src/components/sandboxes/view.css.ts +++ b/packages/frontend/src/components/sandboxes/view.css.ts @@ -3,9 +3,9 @@ import { css } from 'lit' /* ─── shared tokens used by child components ─── */ export const panelStyles = css` .panel { - border: 1px solid color-mix(in srgb, var(--text-muted) 15%, transparent); + border: 1px solid var(--border-color); border-radius: 12px; - background: color-mix(in srgb, var(--bg-primary) 96%, transparent); + background: var(--bg-primary); padding: 11px; display: flex; flex-direction: column; @@ -51,8 +51,8 @@ export const panelStyles = css` .textarea, .select { width: 100%; - border: 1px solid color-mix(in srgb, var(--text-muted) 22%, transparent); - border-radius: 10px; + border: 1px solid var(--border-primary); + border-radius: 8px; background: var(--bg-primary); color: var(--text-primary); font-size: 13px; @@ -64,7 +64,7 @@ export const panelStyles = css` .input:focus, .textarea:focus, .select:focus { - border-color: color-mix(in srgb, var(--accent) 45%, transparent); + border-color: var(--accent); background: var(--bg-surface); } diff --git a/packages/frontend/src/components/sandboxes/view.ts b/packages/frontend/src/components/sandboxes/view.ts index 9b47387..1d802cf 100644 --- a/packages/frontend/src/components/sandboxes/view.ts +++ b/packages/frontend/src/components/sandboxes/view.ts @@ -3,6 +3,7 @@ import { customElement, property, state as litState } from 'lit/decorators.js' import type { Agent, BoxResource } from '@dune/shared' import * as api from '../../services/rpc.js' import { parentStyles } from './view.css.js' +import { iconBox, iconPlus, iconRefresh, iconSearch } from '../../utils/icons.js' import './overview-tab.js' import './execs-tab.js' import './files-tab.js' @@ -189,10 +190,7 @@ export class SandboxesView extends LitElement { }} >
${title}
@@ -208,9 +206,7 @@ export class SandboxesView extends LitElement { e.stopPropagation() this.selectBox(box.boxId) }}> - + ${iconPlus()} ` @@ -225,21 +221,15 @@ export class SandboxesView extends LitElement {
diff --git a/packages/frontend/src/components/settings/view.css.ts b/packages/frontend/src/components/settings/view.css.ts index 3271bf6..61c86b2 100644 --- a/packages/frontend/src/components/settings/view.css.ts +++ b/packages/frontend/src/components/settings/view.css.ts @@ -17,24 +17,22 @@ export const settingsViewStyles = css` } .nav { - background: var(--glass-bg); + background: var(--bg-elevated); border: 1px solid var(--border-color); - border-radius: 24px; + border-radius: 16px; padding: 14px 10px 12px; display: flex; flex-direction: column; min-height: 0; gap: 12px; box-shadow: var(--shadow-sm); - backdrop-filter: blur(18px) saturate(150%); - -webkit-backdrop-filter: blur(18px) saturate(150%); } .back-btn { width: 100%; min-height: var(--control-height); border: 1px solid transparent; - border-radius: 14px; + border-radius: 8px; background: transparent; color: var(--text-secondary); font-size: var(--text-secondary-size); @@ -73,7 +71,7 @@ export const settingsViewStyles = css` width: 100%; min-height: var(--sidebar-row-height); border: 1px solid transparent; - border-radius: 16px; + border-radius: 8px; background: transparent; color: var(--text-secondary); font-size: var(--text-body-size); @@ -97,13 +95,11 @@ export const settingsViewStyles = css` .content { min-height: 0; overflow-y: auto; - padding: 22px 24px 28px; - background: var(--glass-bg); + padding: 24px 28px 32px; + background: var(--bg-elevated); border: 1px solid var(--border-color); - border-radius: 26px; + border-radius: 16px; box-shadow: var(--shadow-sm); - backdrop-filter: blur(18px) saturate(150%); - -webkit-backdrop-filter: blur(18px) saturate(150%); } .top { @@ -136,20 +132,20 @@ export const settingsViewStyles = css` } .card { - border-radius: 20px; - background: color-mix(in srgb, var(--bg-surface) 82%, transparent); + border-radius: 12px; + background: var(--bg-surface); overflow: visible; - padding: 4px; - border: 1px solid var(--border-light); + padding: 8px; + border: 1px solid var(--border-color); } .settings-card { - border-radius: 20px; - background: color-mix(in srgb, var(--bg-surface) 86%, transparent); - padding: 14px; + border-radius: 12px; + background: var(--bg-surface); + padding: 16px; display: grid; gap: 14px; - border: 1px solid var(--border-light); + border: 1px solid var(--border-color); } .row { @@ -157,10 +153,10 @@ export const settingsViewStyles = css` grid-template-columns: minmax(0, 1fr) auto; gap: 12px; align-items: center; - padding: 14px 16px; - border-radius: 18px; - background: color-mix(in srgb, var(--bg-surface) 78%, transparent); - border: 1px solid var(--border-light); + padding: 16px 18px; + border-radius: 12px; + background: var(--bg-surface); + border: 1px solid var(--border-color); } .row-copy { @@ -223,12 +219,12 @@ export const settingsViewStyles = css` } .field { - padding: 14px; - border-radius: 18px; - background: color-mix(in srgb, var(--bg-hover) 72%, transparent); + padding: 16px; + border-radius: 12px; + background: var(--bg-subtle); display: grid; gap: 8px; - border: 1px solid var(--border-light); + border: 1px solid var(--border-color); } .field-top { @@ -279,7 +275,7 @@ export const settingsViewStyles = css` .btn { border: none; border-radius: var(--radius-sm); - min-height: 32px; + min-height: 36px; padding: 0 10px; background: var(--bg-hover); color: var(--text-primary); diff --git a/packages/frontend/src/components/settings/view.ts b/packages/frontend/src/components/settings/view.ts index f2415d6..1f48da7 100644 --- a/packages/frontend/src/components/settings/view.ts +++ b/packages/frontend/src/components/settings/view.ts @@ -3,6 +3,7 @@ import { customElement, property, state } from 'lit/decorators.js' import type { ClaudeSettings } from '@dune/shared' import type { ThemeMode } from '../../state/ui-preferences.js' import { settingsViewStyles } from './view.css.js' +import { iconChevronLeft, iconMenu, iconBox, iconLink } from '../../utils/icons.js' import './model-section.js' import './slack-section.js' @@ -91,9 +92,7 @@ export class SettingsView extends LitElement {
diff --git a/packages/frontend/src/components/sidebar/panel.ts b/packages/frontend/src/components/sidebar/panel.ts index 85738e9..4257c43 100644 --- a/packages/frontend/src/components/sidebar/panel.ts +++ b/packages/frontend/src/components/sidebar/panel.ts @@ -2,6 +2,7 @@ import { LitElement, css, html } from 'lit' import { customElement, property, state as litState } from 'lit/decorators.js' import { ifDefined } from 'lit/directives/if-defined.js' import type { Agent, Channel } from '@dune/shared' +import { iconPanelLeft, iconBox, iconLayoutGrid, iconPlus, iconSettings, iconInfo, iconTrash } from '../../utils/icons.js' export type NavRow = { kind: 'channel' | 'agent' @@ -44,6 +45,9 @@ export class SidebarPanel extends LitElement { .workspace { padding: 10px 12px 8px; min-height: var(--header-height); + -webkit-app-region: drag; + user-select: none; + -webkit-user-select: none; } .workspace.native-traffic-lights { @@ -72,6 +76,7 @@ export class SidebarPanel extends LitElement { background: transparent; color: var(--sidebar-text-active); transition: color var(--transition-fast), opacity var(--transition-fast); + -webkit-app-region: no-drag; } .workspace-brand-mark { @@ -102,36 +107,6 @@ export class SidebarPanel extends LitElement { opacity: 0.9; } - .workspace-brand.style-signature { - gap: 11px; - } - - .workspace-brand.style-signature .workspace-brand-mark { - height: 17px; - opacity: 0.82; - background: linear-gradient( - to bottom, - color-mix(in srgb, var(--warning) 36%, var(--accent)) 0%, - color-mix(in srgb, var(--accent) 76%, var(--sidebar-text-active)) 100% - ); - } - - .workspace-brand.style-signature .workspace-brand-text { - font-weight: 635; - letter-spacing: 0.014em; - text-shadow: 0 1px 0 color-mix(in srgb, var(--bg-primary) 72%, transparent); - } - - .workspace-brand.style-signature .workspace-brand-text::after { - content: ''; - position: absolute; - left: 0; - right: 0; - bottom: -2px; - height: 1px; - background: color-mix(in srgb, var(--accent) 24%, transparent); - } - .workspace-brand.style-minimal .workspace-brand-mark { width: 1.5px; height: 14px; @@ -140,83 +115,31 @@ export class SidebarPanel extends LitElement { } .workspace-brand.style-minimal .workspace-brand-text { - font-weight: 615; - letter-spacing: 0.012em; - } - - .workspace-brand.style-technical { - gap: 8px; - } - - .workspace-brand.style-technical .workspace-brand-mark { - width: 1px; - height: 16px; - opacity: 0.88; - background: color-mix(in srgb, var(--accent) 72%, var(--sidebar-text-active)); - } - - .workspace-brand.style-technical .workspace-brand-text { - font-family: var(--font-mono); - font-size: var(--text-secondary-size); - letter-spacing: 0.015em; - font-weight: 620; - } - - .workspace-head.style-signature .sidebar-toggle { - border-color: color-mix(in srgb, var(--accent) 22%, transparent); - background: color-mix(in srgb, var(--accent-soft) 24%, var(--sidebar-hover)); - color: var(--sidebar-text-active); - } - - .workspace-head.style-signature .sidebar-toggle:hover { - border-color: color-mix(in srgb, var(--accent) 30%, transparent); - background: color-mix(in srgb, var(--accent-soft) 36%, var(--sidebar-hover)); - } - - .workspace-head.style-minimal .sidebar-toggle { - border-color: color-mix(in srgb, var(--text-muted) 22%, transparent); - background: color-mix(in srgb, var(--sidebar-hover) 50%, transparent); - } - - .workspace-head.style-minimal .sidebar-toggle:hover { - border-color: color-mix(in srgb, var(--text-muted) 32%, transparent); - background: color-mix(in srgb, var(--sidebar-hover) 72%, transparent); - } - - .workspace-head.style-technical .sidebar-toggle { - border-radius: var(--radius-xs); - border-color: color-mix(in srgb, var(--accent) 24%, transparent); - background: color-mix(in srgb, var(--accent-soft) 18%, var(--sidebar-hover)); - color: var(--sidebar-text-active); - } - - .workspace-head.style-technical .sidebar-toggle:hover { - border-color: color-mix(in srgb, var(--accent) 32%, transparent); - background: color-mix(in srgb, var(--accent-soft) 30%, var(--sidebar-hover)); + font-weight: 600; + letter-spacing: 0.01em; } .sidebar-toggle { width: var(--control-height); height: var(--control-height); - border: 1px solid color-mix(in srgb, var(--text-muted) 18%, transparent); - border-radius: var(--radius-sm); - background: color-mix(in srgb, var(--sidebar-hover) 52%, transparent); + border: none; + border-radius: 8px; + background: transparent; color: var(--sidebar-text); display: none; align-items: center; justify-content: center; flex-shrink: 0; - transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast); + transition: background var(--transition-fast), color var(--transition-fast); + -webkit-app-region: no-drag; } .sidebar-toggle:hover { - background: color-mix(in srgb, var(--sidebar-hover) 72%, transparent); - border-color: color-mix(in srgb, var(--text-muted) 30%, transparent); + background: var(--sidebar-hover); color: var(--sidebar-text-active); } .sidebar-toggle:focus-visible { - border-color: color-mix(in srgb, var(--accent) 46%, transparent); box-shadow: 0 0 0 2px var(--focus-ring); color: var(--sidebar-text-active); } @@ -290,7 +213,7 @@ export class SidebarPanel extends LitElement { display: flex; align-items: center; justify-content: space-between; - margin: 0 4px 5px; + margin: 0 6px 6px; gap: 8px; } @@ -357,7 +280,7 @@ export class SidebarPanel extends LitElement { grid-template-columns: 16px minmax(0, 1fr); gap: 9px; align-items: center; - padding: 6px 10px; + padding: 7px 12px; cursor: pointer; text-align: left; transition: background var(--transition-fast), color var(--transition-fast); @@ -373,6 +296,7 @@ export class SidebarPanel extends LitElement { .row.selected { background: var(--sidebar-selected); color: var(--sidebar-text-active); + border-left: 2px solid var(--accent); } .row-icon { @@ -666,28 +590,14 @@ export class SidebarPanel extends LitElement { data-testid="sidebar-toggle" @click=${this.toggleSidebar} > - + ${iconPanelLeft()}
- ${this.renderUtilityButton('Sandboxes', html` - - `, () => this.dispatchEvent(new CustomEvent('open-sandboxes', { bubbles: true, composed: true })), this.activeSurface === 'sandboxes', 'nav-sandboxes')} - ${this.renderUtilityButton('Apps', html` - - `, () => this.dispatchEvent(new CustomEvent('open-apps', { bubbles: true, composed: true })), this.activeSurface === 'apps', 'nav-apps')} + ${this.renderUtilityButton('Sandboxes', iconBox(), () => this.dispatchEvent(new CustomEvent('open-sandboxes', { bubbles: true, composed: true })), this.activeSurface === 'sandboxes', 'nav-sandboxes')} + ${this.renderUtilityButton('Apps', iconLayoutGrid(), () => this.dispatchEvent(new CustomEvent('open-apps', { bubbles: true, composed: true })), this.activeSurface === 'apps', 'nav-apps')}
@@ -701,9 +611,7 @@ export class SidebarPanel extends LitElement { title="Create channel" @click=${() => this.dispatchEvent(new CustomEvent('create-channel', { bubbles: true, composed: true }))} > - + ${iconPlus()}
@@ -724,9 +632,7 @@ export class SidebarPanel extends LitElement { title="Create agent" @click=${() => this.dispatchEvent(new CustomEvent('create-agent', { bubbles: true, composed: true }))} > - + ${iconPlus()} @@ -739,27 +645,18 @@ export class SidebarPanel extends LitElement { ${this.contextMenu ? html`
diff --git a/packages/frontend/src/styles/theme.css b/packages/frontend/src/styles/theme.css index a8ebccf..3a701ef 100644 --- a/packages/frontend/src/styles/theme.css +++ b/packages/frontend/src/styles/theme.css @@ -1,10 +1,8 @@ -@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&display=swap'); - :root { color-scheme: light dark; - --font: 'SF Pro Display', 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', sans-serif; - --font-mono: 'IBM Plex Mono', 'SFMono-Regular', 'Consolas', monospace; + --font: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; --text-meta-size: 12px; --text-secondary-size: 13px; @@ -13,11 +11,11 @@ --text-display-size: 24px; --text-hero-size: clamp(28px, 2.8vw, 38px); - --radius-xs: 5px; + --radius-xs: 6px; --radius-sm: 8px; --radius: 10px; - --radius-lg: 14px; - --radius-xl: 20px; + --radius-lg: 16px; + --radius-xl: 16px; --space-2xs: 4px; --space-xs: 6px; @@ -45,9 +43,9 @@ --composer-pad-x: 8px; --composer-gap: 4px; --composer-input-top-inset: 4px; - --control-height: 28px; - --sidebar-row-height: 32px; - --sidebar-utility-height: 30px; + --control-height: 32px; + --sidebar-row-height: 36px; + --sidebar-utility-height: 36px; --toolbar-glass-blur: 2px; --footer-height: 34px; @@ -58,155 +56,169 @@ :root, :root[data-theme='light'] { - --app-canvas: #faf9f6; + --app-canvas: #f8f8f7; --app-canvas-top: rgba(255, 255, 255, 0.88); - --bg-primary: #fcfbf8; - --bg-elevated: rgba(255, 255, 255, 0.94); - --bg-surface: rgba(249, 248, 244, 0.98); - --bg-subtle: rgba(244, 243, 238, 0.96); - --bg-hover: rgba(231, 229, 223, 0.92); - --bg-code: #efeee8; - - --text-primary: #191b1f; - --text-secondary: #61656d; - --text-muted: #8b8e95; - --text-disabled: #b2b8c1; - --text-blue: #0077ed; + --bg-primary: #ffffff; + --bg-elevated: #ffffff; + --bg-surface: #fafafa; + --bg-subtle: #37352f0a; + --bg-hover: #37352f0f; + --bg-code: #f0f0ef; + + --text-primary: #34322d; + --text-secondary: #5e5e5b; + --text-muted: #858481; + --text-disabled: #b9b9b7; + --text-blue: #0081f2; --accent: #ff5f73; --accent-hover: #f2475e; --accent-soft: rgba(255, 95, 115, 0.14); - --success: #2fa76d; - --warning: #d78a2d; - --error: #de4f4f; + --success: #25ba3b; + --warning: #efa201; + --error: #f25a5a; + --success-soft: #25ba3b14; + --warning-soft: #efa2011f; + --error-soft: #f25a5a14; + + --fill-subtle: #37352f0f; + --tab-fill: rgba(0, 0, 0, 0.04); + --tab-active: #1a1a19; - --toolbar-bg: rgba(252, 251, 248, 0.97); - --toolbar-border: rgba(24, 28, 34, 0.07); + --toolbar-bg: rgba(255, 255, 255, 0.97); + --toolbar-border: #0000000f; --toolbar-shadow: none; - --toolbar-text-muted: #80848c; - --shell-stage-bg: rgba(250, 249, 246, 0.995); + --toolbar-text-muted: #858481; + --shell-stage-bg: #fafafa; --shell-stage-border: transparent; --shell-stage-shadow: none; - --glass-bg: rgba(248, 247, 244, 0.985); - --glass-border: rgba(24, 28, 34, 0.07); - --dock-bg: rgba(248, 247, 244, 0.99); - --dock-border: rgba(24, 28, 34, 0.07); - --footer-bg: rgba(248, 247, 244, 0.99); - --footer-border: rgba(24, 28, 34, 0.07); - --sheet-bg: rgba(252, 251, 248, 0.99); - --sheet-scrim: rgba(36, 42, 51, 0.18); - - --sidebar-bg: rgba(242, 240, 235, 0.995); - --sidebar-text: #64676f; - --sidebar-text-active: #171a1f; - --sidebar-hover: rgba(232, 230, 224, 0.82); - --sidebar-selected: rgba(255, 255, 255, 0.96); - --sidebar-border: rgba(24, 28, 34, 0.07); - --row-selected-border: rgba(24, 28, 34, 0.08); - --pane-divider: rgba(24, 28, 34, 0.07); + --glass-bg: rgba(255, 255, 255, 0.98); + --glass-border: #0000000f; + --dock-bg: rgba(255, 255, 255, 0.99); + --dock-border: #0000000f; + --footer-bg: rgba(255, 255, 255, 0.99); + --footer-border: #0000000f; + --sheet-bg: #ffffff; + --sheet-scrim: rgba(0, 0, 0, 0.18); + + --sidebar-bg: #f8f8f7; + --sidebar-text: #5e5e5b; + --sidebar-text-active: #34322d; + --sidebar-hover: #37352f0f; + --sidebar-selected: #37352f0a; + --sidebar-border: #0000000f; + --row-selected-border: #0000000f; + --pane-divider: #0000000f; --control-bg: rgba(255, 255, 255, 0.84); --control-bg-hover: rgba(255, 255, 255, 0.97); - --control-border: rgba(24, 28, 34, 0.09); + --control-border: #0000001f; - --border-color: rgba(24, 28, 34, 0.08); - --border-primary: rgba(24, 28, 34, 0.11); - --border-input: rgba(24, 28, 34, 0.11); - --border-light: rgba(255, 255, 255, 0.64); - --border-dark: rgba(24, 28, 34, 0.12); + --border-color: #0000000f; + --border-primary: #0000001f; + --border-input: #0000001f; + --border-light: #0000000a; + --border-dark: #0000001f; --focus-ring: rgba(255, 95, 115, 0.24); - --composer-shell: rgba(255, 255, 255, 0.995); - --composer-seam: rgba(24, 28, 34, 0.08); - --composer-submit-bg: #1b1c1f; + --composer-shell: #ffffff; + --composer-seam: #0000000f; + --composer-submit-bg: #1a1a19; --composer-submit-hover: var(--accent); - --composer-submit-disabled: #b8bec7; + --composer-submit-disabled: #b9b9b7; --composer-shadow: none; - --button-primary-bg: #1a1917; + --button-primary-bg: #1a1a19; --button-primary-text: #ffffff; --button-brand-bg: #ff5f73; --button-brand-text: #ffffff; - --shadow-sm: 0 8px 18px rgba(35, 39, 46, 0.08); - --shadow-md: 0 18px 34px rgba(35, 39, 46, 0.1); - --shadow-lg: 0 28px 58px rgba(35, 39, 46, 0.14); + --shadow-sm: 0 2px 8px #00000014; + --shadow-md: 0 8px 24px #0000001f; + --shadow-lg: 0 16px 48px #0000003d; } :root[data-theme='dark'] { color-scheme: dark; - --app-canvas: #1d1e21; + --app-canvas: #272728; --app-canvas-top: transparent; - --bg-primary: #18191b; - --bg-elevated: rgba(30, 31, 34, 0.985); - --bg-surface: rgba(34, 35, 39, 0.99); - --bg-subtle: rgba(27, 28, 31, 0.99); - --bg-hover: rgba(74, 77, 84, 0.72); - --bg-code: #141517; - - --text-primary: #eef1f5; - --text-secondary: #b8bfca; - --text-muted: #8b93a0; - --text-disabled: #5d6470; - --text-blue: #7cb8ff; + --bg-primary: #161618; + --bg-elevated: #383739; + --bg-surface: #383739; + --bg-subtle: #ffffff0a; + --bg-hover: #ffffff0f; + --bg-code: #2f2f30; + + --text-primary: #dadada; + --text-secondary: #acacac; + --text-muted: #7f7f7f; + --text-disabled: #5f5f5f; + --text-blue: #1a93fe; --accent: #ff667a; --accent-hover: #ff7d8d; --accent-soft: rgba(255, 102, 122, 0.16); - --success: #57c485; - --warning: #f0b55a; - --error: #ff7474; + --success: #5eb92d; + --warning: #ffbf36; + --error: #eb4d4d; + --success-soft: #25ba3b1f; + --warning-soft: #ffbf361f; + --error-soft: #eb4d4d14; + + --fill-subtle: #ffffff0f; + --tab-fill: rgba(255, 255, 255, 0.06); + --tab-active: #ffffff; - --toolbar-bg: rgba(30, 31, 34, 0.99); - --toolbar-border: rgba(255, 255, 255, 0.09); + --toolbar-bg: rgba(39, 39, 40, 0.99); + --toolbar-border: #ffffff14; --toolbar-shadow: none; - --toolbar-text-muted: #949aa4; - --shell-stage-bg: rgba(29, 30, 33, 0.995); + --toolbar-text-muted: #7f7f7f; + --shell-stage-bg: #272728; --shell-stage-border: transparent; --shell-stage-shadow: none; - --glass-bg: rgba(35, 36, 40, 0.99); - --glass-border: rgba(255, 255, 255, 0.09); - --dock-bg: rgba(28, 29, 32, 0.995); - --dock-border: rgba(255, 255, 255, 0.1); - --footer-bg: rgba(26, 27, 30, 0.995); - --footer-border: rgba(255, 255, 255, 0.08); - --sheet-bg: rgba(25, 26, 29, 0.99); + --glass-bg: rgba(56, 55, 57, 0.99); + --glass-border: #ffffff14; + --dock-bg: rgba(33, 33, 34, 0.99); + --dock-border: #ffffff14; + --footer-bg: rgba(33, 33, 34, 0.99); + --footer-border: #ffffff14; + --sheet-bg: #383739; --sheet-scrim: rgba(0, 0, 0, 0.32); - --sidebar-bg: rgba(35, 36, 40, 0.995); - --sidebar-text: #c8cdd5; - --sidebar-text-active: #f5f7fa; - --sidebar-hover: rgba(255, 255, 255, 0.06); - --sidebar-selected: rgba(255, 255, 255, 0.08); - --sidebar-border: rgba(255, 255, 255, 0.08); - --row-selected-border: rgba(255, 255, 255, 0.06); - --pane-divider: rgba(255, 255, 255, 0.08); - --control-bg: rgba(43, 45, 49, 0.96); - --control-bg-hover: rgba(55, 58, 63, 0.98); - --control-border: rgba(255, 255, 255, 0.1); - - --border-color: rgba(255, 255, 255, 0.1); - --border-primary: rgba(255, 255, 255, 0.14); - --border-input: rgba(255, 255, 255, 0.14); - --border-light: rgba(255, 255, 255, 0.07); - --border-dark: rgba(255, 255, 255, 0.16); + --sidebar-bg: #212122; + --sidebar-text: #acacac; + --sidebar-text-active: #dadada; + --sidebar-hover: #ffffff0f; + --sidebar-selected: #ffffff0a; + --sidebar-border: #ffffff14; + --row-selected-border: #ffffff0f; + --pane-divider: #ffffff14; + --control-bg: rgba(62, 61, 62, 0.96); + --control-bg-hover: rgba(68, 67, 69, 0.98); + --control-border: #ffffff1a; + + --border-color: #ffffff14; + --border-primary: #ffffff1a; + --border-input: #ffffff1a; + --border-light: #ffffff0f; + --border-dark: #ffffff29; --focus-ring: rgba(255, 102, 122, 0.28); - --composer-shell: rgba(31, 32, 36, 0.995); - --composer-seam: rgba(255, 255, 255, 0.1); - --composer-submit-bg: #ebeff4; + --composer-shell: #363537; + --composer-seam: #ffffff14; + --composer-submit-bg: #ffffff; --composer-submit-hover: var(--accent); - --composer-submit-disabled: #525a66; + --composer-submit-disabled: #5f5f5f; --composer-shadow: none; - --button-primary-bg: #edf1f6; + --button-primary-bg: #ffffff; --button-primary-text: #14161a; --button-brand-bg: #ff667a; --button-brand-text: #14161a; - --shadow-sm: 0 8px 16px rgba(0, 0, 0, 0.16); - --shadow-md: 0 16px 28px rgba(0, 0, 0, 0.22); - --shadow-lg: 0 28px 52px rgba(0, 0, 0, 0.3); + --shadow-sm: 0 2px 8px #0000001f; + --shadow-md: 0 8px 24px #0000003d; + --shadow-lg: 0 16px 48px #00000066; } *, @@ -253,8 +265,8 @@ button { } ::-webkit-scrollbar { - width: 10px; - height: 10px; + width: 6px; + height: 6px; } ::-webkit-scrollbar-track { @@ -262,14 +274,14 @@ button { } ::-webkit-scrollbar-thumb { - background: color-mix(in srgb, var(--text-muted) 45%, transparent); + background: color-mix(in srgb, var(--text-muted) 18%, transparent); border-radius: 999px; - border: 2px solid transparent; + border: 1px solid transparent; background-clip: padding-box; } ::-webkit-scrollbar-thumb:hover { - background: color-mix(in srgb, var(--text-muted) 58%, transparent); + background: color-mix(in srgb, var(--text-muted) 36%, transparent); } @media (prefers-reduced-motion: reduce) { diff --git a/packages/frontend/src/utils/icons.ts b/packages/frontend/src/utils/icons.ts index 52d1718..1c14b43 100644 --- a/packages/frontend/src/utils/icons.ts +++ b/packages/frontend/src/utils/icons.ts @@ -34,7 +34,7 @@ function attrsToString(attrs: Record): string { function renderIcon( node: IconNode, - { size = 16, strokeWidth = 1.8 }: IconOptions = {}, + { size = 18, strokeWidth = 1.6 }: IconOptions = {}, ): SVGTemplateResult { const inner = node .map(([tag, attrs]) => `<${tag} ${attrsToString(attrs)}/>`)