From 763d9ce8f0bfa4fc07627bc488066a0f1989087a Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 24 Jun 2025 04:32:36 +0200 Subject: [PATCH] Improve Arc-style sidebar UI for better space utilization - Put Browse Files and Kill buttons on the same line in sidebar header - Remove "running" text from session status, keep only the colored dot - Apply home directory path filtering (~/...) for better readability - Import and use formatPathForDisplay from path-utils These changes maximize usable space in the vertical tabs sidebar. --- .../menubar.imageset/menubar@2x.png | Bin 2291 -> 795 bytes .../Settings/DashboardSettingsView.swift | 40 +++++++++++ web/src/client/components/session-list.ts | 21 +++--- web/src/client/components/sidebar-header.ts | 62 +++++++++--------- 4 files changed, 79 insertions(+), 44 deletions(-) diff --git a/mac/VibeTunnel/Assets.xcassets/menubar.imageset/menubar@2x.png b/mac/VibeTunnel/Assets.xcassets/menubar.imageset/menubar@2x.png index 3682b057676af1098f424ee14c3a7a7bbf544fd5..cc84904f809cbf7d621af12d1385001270ee1b98 100644 GIT binary patch delta 786 zcmV+t1MU3t5t{}fiBL{Q4GJ0x0000DNk~Le0000W0000W2nGNE0CReJ^pP$Xe*(=( zL_t(oh2_^lh*wn<$MMfUozlP*B{6F(7Yd@Gg6D9#L`Hi3$$IbpBGeJ}33-n;)djxY-k9R81c&%M9zyZ794 z|F4y0nbEW-MpYeSi-%UL)h=!+e_qXhr(-G};0k(i3`fw{MEJjz&$3Kn8^&NYE+T8_ zM=+}iK$c}mfalON4B^-Zv1ud#^Ms{+81dNmR)qYc1cn9&5_cr@q^-ouksOIWgr_!##S5c}Eze{@E{y?D8S zaM>2&at*)(p?1^)tjPoW@IsA1vRdWViT)ahH7S7o!m`heCYyk@IGTeE3d?*AC-6RA ztbmv+?0XsDa0;LY>!L~C#r2vuiTyr46%sSH4=Z9%w_AahkaYVR2$%gw(H;v0=+9Ej z^%TJTyl?MAh!=iRIHrYde=GIhNddsBib?;$S$vIdd?H*pXYhAL{6`VMic(*H3SgX} z+1rQBLcyuCm#{N`vtry$Ov?MGlmJep0N#oMcjM`VaM_+0608`%HtM?%6-Ju`+tTimwdKsb}f{=J?ki7gSX@-spX-NpqR#G9gjRE2KqvHv>$7qzj@+BYlQ QkN^Mx07*qoM6N<$g4kegyZ`_I literal 2291 zcmVPx#32;bRa{vGf6951U69E94oEQKA2$)GkK~#9!?b&&7mDL%?@y`t*A%UbJ1%gN* zAYn6XS%gwi#J0AUvCtOW>QYhBDlUkMmO3gfbpdti0;150JE9;cD3T~58dN|;NJKzM zP+0^Fkgx>Of0#S(ymN0!s?M}CexLvDoO9mi{Onu-CeH1EE zBwsIiy6LEm49R{#eyY$ASG&tJ&v@Az-twmTUNFr=#yMACEqw1pG}T5ICpp(G9<$JD zTkUd4-C^5jt1rCgdE<>RNH1+P^*z$b*&a}Ane{4dv&&xl9gI3qYp-fMd}Y0IB_20I zE`W&dK&qn+a)sw?P*-pJ$}D4?sIxQ)z7ri??PbetQQZIs_S$Tn*{;`DyV+^F=^#sn6o~+cNRlekQ9A4640l^%Z(J3= zG~IAn5TAU{M*q)U)_c(yg%Z_=Gy{w?*G9WzI*f@HwCWZ-Nze#EgU0&eANNqUn12t99zsS?L;i zGSP5a$TP;rF%?+r26@uNB+F1!ZBeJ(1bF}&Nz+;f-Sm{NNMFY(QlOVSon*_DEKCm* zmBomKO4Iy7mYB42xi{4M+IU4W0VM0;bk}*v)8={867P7^>t>p2ypc|jB}}H{-0E{- z2ev78wVe0~=tGre8wg01t*4>Jnr@LVR0%G&&sNLLakq<{sGCfQf($fUP3T@Y_r4jf)Cthl1s=ClnXhbDZGY%=+v{6fY*1#d+x<#fXhUPY9SX*36&}%DO!7Qw zfl+!$Lc0F0G}~r%^{@jza=#(6r2fq4+ie03Gl)$E*Qe}VWFe(s}OeZ@5 zO`K-3Rch5W*fv?_Y>Vx7sfpoa zjX8cJStF3;_ok{89I-H-0}&C;<+{|8n6>_wKDAV_xn_CQ5^Gedi81mMx9Kkbg=${{RT_d z5OUq%O%;dx<0lN$8WbprIq0DTqct-Fp|NfiM=mJwd^r9H|_&;=A) z7PbjTade397bdp@b!Zphn#WtCv4=C_j zbk@7hkReG-vR&>f-9-Sc4ELZnthLcLyB!EQP<^;vn{Bjwi2zb{bB#|eRs{0Ri}qJf z>nkqlj#D5RWa{R8Pt+?T)+jMnf5H2per9+^kAMOPt@ok}wFVIp5g`&~NC%DdH_?YS zs;TEqNU8h$T2lb+UE*R#gCdL7+3E$uWJv-M2@*sEhychkz#YmPcnz_}{RT=A0jcuz z&ygksv8LYKI^_+~h_b2-Ds;rM8D0 zsPKwAoo|SN`YQ5sr@6=^s{|c5WSrh?v*EA2=1`~%S!9Zl z`fDLEF!m_Fb%zoaY6Yv~GL!sHww9WR5OSrd=JK6qvQ=Kxiy+N(HQLHhPydKv3bmFY zSwg^pWG%IKrk8AUFrY$>wdT9kU~Pm+)Xflgd)o%(!u^4xoZ+cJA5deXe;F)Id|J4` zi^46~J}XQ%(y52PCiK!rz7q{`t*KV3bI20chGU?UTPzDif2Dg3(pE%#8f#&=S5=2z z%5QD-iDed<>jg8-Rie~#v<9Bz6bX(@Yooj_{vdHhnrQ3KO5*epht#TdDAdT!F^I6Xx$f|WSIt*qy3zVeQ(xM< zPO;AedyQ`u78!*lC)B2nDJ&>sX}$Yfvw8T^N@=T&_;?MkaR`PcZWwj zZ=Mn*UN_q`6I|vL*?w>u`-!9F>aLf3g^CpDBTpCYw2<=S*Wdq1{tfvb6t2mZ@k0Or N002ovPDHLkV1oPcQOy7V diff --git a/mac/VibeTunnel/Presentation/Views/Settings/DashboardSettingsView.swift b/mac/VibeTunnel/Presentation/Views/Settings/DashboardSettingsView.swift index 38759028..1b9469d1 100644 --- a/mac/VibeTunnel/Presentation/Views/Settings/DashboardSettingsView.swift +++ b/mac/VibeTunnel/Presentation/Views/Settings/DashboardSettingsView.swift @@ -434,6 +434,45 @@ private struct ServerConfigurationSection: View { } header: { Text("Server Configuration") .font(.headline) + } footer: { + // Dashboard URL display + if accessMode == .localhost { + HStack(spacing: 5) { + Text("Dashboard available at") + .font(.caption) + .foregroundStyle(.secondary) + + if let url = URL(string: "http://127.0.0.1:\(serverPort)") { + Link(url.absoluteString, destination: url) + .font(.caption) + .foregroundStyle(.blue) + } + } + .frame(maxWidth: .infinity) + .multilineTextAlignment(.center) + } else if accessMode == .network { + if let ip = localIPAddress { + HStack(spacing: 5) { + Text("Dashboard available at") + .font(.caption) + .foregroundStyle(.secondary) + + if let url = URL(string: "http://\(ip):\(serverPort)") { + Link(url.absoluteString, destination: url) + .font(.caption) + .foregroundStyle(.blue) + } + } + .frame(maxWidth: .infinity) + .multilineTextAlignment(.center) + } else { + Text("Fetching local IP address...") + .font(.caption) + .foregroundStyle(.secondary) + .frame(maxWidth: .infinity) + .multilineTextAlignment(.center) + } + } } } } @@ -646,6 +685,7 @@ private struct NgrokIntegrationSection: View { } footer: { Text("ngrok creates secure tunnels to your dashboard from anywhere.") .font(.caption) + .frame(maxWidth: .infinity) .multilineTextAlignment(.center) } } diff --git a/web/src/client/components/session-list.ts b/web/src/client/components/session-list.ts index e82bf27c..10bd62c0 100644 --- a/web/src/client/components/session-list.ts +++ b/web/src/client/components/session-list.ts @@ -24,6 +24,7 @@ import type { AuthClient } from '../services/auth-client.js'; import './session-create-form.js'; import './session-card.js'; import { createLogger } from '../utils/logger.js'; +import { formatPathForDisplay } from '../utils/path-utils.js'; const logger = createLogger('session-list'); @@ -281,22 +282,16 @@ export class SessionList extends LitElement { ${session.name || session.command}
- ${session.workingDir} + ${formatPathForDisplay(session.workingDir)}
- -
- ${session.status} -
+
${session.status === 'running' || session.status === 'exited' ? html` + ${this.renderUtilityAndKillButtons(runningSessions)} ${this.renderExitedToggleButton(exitedSessions, true)} - ${this.renderActionButtons(exitedSessions, runningSessions, true)} + ${!this.hideExited && exitedSessions.length > 0 + ? html` + + ` + : ''}
@@ -113,30 +116,27 @@ export class SidebarHeader extends HeaderBase { `; } - private renderActionButtons( - exitedSessions: Session[], - runningSessions: Session[], - compact: boolean - ) { - const buttonClass = compact - ? 'btn-ghost font-mono text-xs px-3 py-1.5 w-full' - : 'btn-ghost font-mono text-xs px-4 py-2'; - + private renderUtilityAndKillButtons(runningSessions: Session[]) { return html` - ${!this.hideExited && exitedSessions.length > 0 - ? html` - - ` - : ''} - ${runningSessions.length > 0 && !this.killingAll - ? html` - - ` - : ''} +
+ + ${runningSessions.length > 0 && !this.killingAll + ? html` + + ` + : ''} +
`; } }