Group toolbar items into visual pill containers
Four groups: connection, quad view, themes, panel config. Each group shares one background pill. Bigger icons (w-6 h-6), 36px hit area with minimal padding. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f8ef8141f5
commit
4abbe86963
@ -1,93 +1,69 @@
|
||||
<template>
|
||||
<div v-if="isLoggedIn" class="app-toolbar">
|
||||
<!-- Connection pill -->
|
||||
<button class="toolbar-pill" :class="{ active: connActive }" @click="toggleDropdown('conn')" :title="connLabel || 'Connection'">
|
||||
<WifiIcon class="w-4 h-4" />
|
||||
<span v-if="connLabel" class="toolbar-pill-label">{{ connLabel }}</span>
|
||||
|
||||
<!-- Group: Connection + Takeover -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-btn" :class="{ active: connActive }" @click="toggleDropdown('conn')" :title="connLabel || 'Connection'">
|
||||
<WifiIcon class="w-6 h-6" />
|
||||
<span v-if="connLabel" class="toolbar-btn-label">{{ connLabel }}</span>
|
||||
</button>
|
||||
<button v-if="takeoverToken" class="toolbar-btn" :class="{ active: captureActive }" @click="toggleDropdown('takeover')" title="Takeover">
|
||||
<SignalIcon class="w-6 h-6" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-spacer" />
|
||||
|
||||
<!-- Pane toggles -->
|
||||
<button
|
||||
class="toolbar-pill toolbar-pill-icon"
|
||||
:class="{ active: isPaneOpen('chat') }"
|
||||
@click="togglePane('chat')"
|
||||
title="Chat"
|
||||
>
|
||||
<ChatBubbleLeftIcon class="w-4 h-4" />
|
||||
<!-- Group: Quad view (pane toggles) -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-btn" :class="{ active: isPaneOpen('chat') }" @click="togglePane('chat')" title="Chat">
|
||||
<ChatBubbleLeftIcon class="w-6 h-6" />
|
||||
</button>
|
||||
<button
|
||||
class="toolbar-pill toolbar-pill-icon"
|
||||
:class="{ active: isPaneOpen('dashboard') }"
|
||||
@click="togglePane('dashboard')"
|
||||
title="Display"
|
||||
>
|
||||
<RectangleGroupIcon class="w-4 h-4" />
|
||||
<button class="toolbar-btn" :class="{ active: isPaneOpen('dashboard') }" @click="togglePane('dashboard')" title="Display">
|
||||
<RectangleGroupIcon class="w-6 h-6" />
|
||||
</button>
|
||||
<button
|
||||
class="toolbar-pill toolbar-pill-icon"
|
||||
:class="{ active: isPaneOpen('files') }"
|
||||
@click="togglePane('files')"
|
||||
title="Files"
|
||||
>
|
||||
<FolderIcon class="w-4 h-4" />
|
||||
<button class="toolbar-btn" :class="{ active: isPaneOpen('files') }" @click="togglePane('files')" title="Files">
|
||||
<FolderIcon class="w-6 h-6" />
|
||||
</button>
|
||||
<button
|
||||
class="toolbar-pill toolbar-pill-icon"
|
||||
:class="{ active: isPaneOpen('artifacts') }"
|
||||
@click="togglePane('artifacts')"
|
||||
title="Konsole"
|
||||
>
|
||||
<SparklesIcon class="w-4 h-4" />
|
||||
<button class="toolbar-btn" :class="{ active: isPaneOpen('artifacts') }" @click="togglePane('artifacts')" title="Konsole">
|
||||
<SparklesIcon class="w-6 h-6" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-divider" />
|
||||
|
||||
<!-- Theme pills (icon only) -->
|
||||
<!-- Group: Themes -->
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
v-for="t in THEMES"
|
||||
:key="t"
|
||||
class="toolbar-pill toolbar-pill-icon"
|
||||
class="toolbar-btn"
|
||||
:class="{ active: theme === t }"
|
||||
@click="setTheme(t)"
|
||||
:title="THEME_NAMES[t]"
|
||||
>
|
||||
<component :is="THEME_ICONS[t]" class="w-4 h-4" />
|
||||
<component :is="THEME_ICONS[t]" class="w-6 h-6" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Panel toggles (dev/operator tools) -->
|
||||
<!-- Group: Panel config + version -->
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
v-for="panel in availablePanels"
|
||||
:key="panel.id"
|
||||
class="toolbar-pill toolbar-pill-icon"
|
||||
class="toolbar-btn"
|
||||
:class="{ active: isPanelOpen(panel.id) }"
|
||||
@click="togglePanelBtn(panel.id)"
|
||||
:title="panel.label"
|
||||
>
|
||||
<component :is="panelIcon(panel.id)" class="w-4 h-4" />
|
||||
<component :is="panelIcon(panel.id)" class="w-6 h-6" />
|
||||
</button>
|
||||
|
||||
<!-- Takeover / Capture -->
|
||||
<button
|
||||
v-if="takeoverToken"
|
||||
class="toolbar-pill"
|
||||
:class="{ active: captureActive }"
|
||||
@click="toggleDropdown('takeover')"
|
||||
title="Takeover"
|
||||
>
|
||||
<SignalIcon class="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
<!-- Version pill -->
|
||||
<button class="toolbar-pill toolbar-pill-dim" @click="copyVersionDetails" :title="versionFull">
|
||||
<button class="toolbar-btn toolbar-btn-dim" @click="copyVersionDetails" :title="versionFull">
|
||||
<span class="toolbar-version-text">{{ versionShort }}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Panels (dropdown from toolbar) -->
|
||||
<!-- Dropdowns -->
|
||||
<div v-if="openDropdown" class="toolbar-panel-backdrop" @click="openDropdown = null" />
|
||||
|
||||
<!-- Connection panel -->
|
||||
<div v-if="openDropdown === 'conn'" class="toolbar-panel" style="right: auto; left: 0;">
|
||||
<div class="toolbar-panel-header">Connection</div>
|
||||
<div class="toolbar-panel-row"><span>HTTP</span><span>{{ chatStore.connectionState }}</span></div>
|
||||
@ -96,7 +72,6 @@
|
||||
<div class="toolbar-panel-row"><span>Mode</span><span>{{ selectedMode }}</span></div>
|
||||
</div>
|
||||
|
||||
<!-- Takeover panel -->
|
||||
<div v-if="openDropdown === 'takeover'" class="toolbar-panel" style="right: 0;">
|
||||
<div class="toolbar-panel-header">Takeover</div>
|
||||
<div class="toolbar-panel-token" @click="copyToken" :title="tokenCopied ? 'Copied!' : 'Click to copy'">
|
||||
@ -107,11 +82,10 @@
|
||||
<span>Capture</span>
|
||||
<span :style="{ color: captureActive ? 'var(--success, #22c55e)' : 'var(--text-dim)' }">{{ captureActive ? 'ON' : 'OFF' }}</span>
|
||||
</div>
|
||||
<button class="toolbar-panel-action" @click="toggleCapture">
|
||||
{{ captureActive ? 'Disable Capture' : 'Enable Capture' }}
|
||||
</button>
|
||||
<button class="toolbar-panel-action" @click="toggleCapture">{{ captureActive ? 'Disable Capture' : 'Enable Capture' }}</button>
|
||||
<button class="toolbar-panel-action" @click="revokeAndClose">Revoke</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -218,51 +192,57 @@ function toggleDropdown(panel: 'conn' | 'takeover') {
|
||||
|
||||
.toolbar-spacer { flex: 1; }
|
||||
|
||||
.toolbar-divider {
|
||||
width: 1px;
|
||||
height: 18px;
|
||||
background: var(--border);
|
||||
opacity: 0.5;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.toolbar-pill {
|
||||
/* Group: shared pill container */
|
||||
.toolbar-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
background: var(--panel-bg);
|
||||
border-radius: var(--radius-panel, 12px);
|
||||
box-shadow: var(--panel-shadow);
|
||||
padding: 0 12px;
|
||||
height: 34px;
|
||||
font-size: 0.85rem;
|
||||
padding: 2px;
|
||||
gap: 1px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Button inside a group */
|
||||
.toolbar-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: calc(var(--radius-panel, 12px) - 3px);
|
||||
color: var(--text-dim);
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.12s, background 0.12s;
|
||||
font-size: 0.85rem;
|
||||
white-space: nowrap;
|
||||
transition: color 0.12s, background 0.12s;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.toolbar-pill:hover { color: var(--text); }
|
||||
.toolbar-pill.active { color: var(--accent); }
|
||||
.toolbar-btn:hover { color: var(--text); background: color-mix(in srgb, var(--text) 6%, transparent); }
|
||||
.toolbar-btn.active { color: var(--accent); }
|
||||
|
||||
.toolbar-pill-icon {
|
||||
width: 34px;
|
||||
padding: 0;
|
||||
justify-content: center;
|
||||
/* Connection button widens when it has a label */
|
||||
.toolbar-btn:has(.toolbar-btn-label) {
|
||||
width: auto;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.toolbar-pill-dim {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.toolbar-pill-dim:hover { opacity: 0.8; }
|
||||
|
||||
.toolbar-pill-label {
|
||||
.toolbar-btn-label {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.toolbar-version-text {
|
||||
font-size: 0.65rem;
|
||||
.toolbar-btn-dim { opacity: 0.45; }
|
||||
.toolbar-btn-dim:hover { opacity: 0.8; }
|
||||
|
||||
.toolbar-version-text { font-size: 0.65rem; }
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.toolbar-btn-label { display: none; }
|
||||
.toolbar-btn:has(.toolbar-btn-label) { width: 32px; padding: 0; }
|
||||
}
|
||||
|
||||
/* Panel dropdown */
|
||||
@ -334,9 +314,7 @@ function toggleDropdown(panel: 'conn' | 'takeover') {
|
||||
}
|
||||
.toolbar-panel-action:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); color: var(--accent); }
|
||||
|
||||
/* Mobile: hide labels, shrink pills */
|
||||
@media (max-width: 480px) {
|
||||
.toolbar-pill-label { display: none; }
|
||||
.toolbar-panel { width: min(220px, calc(100vw - 16px)); }
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user