feat: make mobile breadcrumbs clickable

This commit is contained in:
Federico Jaramillo Martinez
2026-05-23 22:26:42 +02:00
parent df20563abb
commit f4aeb0675f
3 changed files with 30 additions and 10 deletions
@@ -0,0 +1,5 @@
---
"@jmfederico/pi-web": patch
---
Make the mobile location breadcrumbs clickable so they open project, workspace, or session selection directly.
+21 -9
View File
@@ -559,6 +559,12 @@ export class PiWebApp extends LitElement {
if (this.isMobileNavigationLayout) this.expandedMobileNavigationSection = section;
}
private openNavigationSection(section: NavigationSection): void {
if (!this.isMobileNavigationLayout) return;
this.expandNavigationSection(section);
this.selectMainView("navigation");
}
private visibleWorkspacePanels(): QualifiedWorkspacePanelContribution[] {
const workspace = this.state.selectedWorkspace;
if (workspace === undefined) return [];
@@ -845,17 +851,23 @@ export class PiWebApp extends LitElement {
<nav class=${this.contextBarClass()} aria-label="Current location">
<span class="context-bar-label">Location</span>
<ol class="context-items" @scroll=${this.onContextScroll}>
<li class=${project === undefined ? "context-chip empty" : "context-chip"} title=${projectContextTitle(project)} aria-label=${`Project: ${projectLabel}`}>
<span class="context-kind">Project</span>
<span class="context-value">${projectLabel}</span>
<li class="context-item">
<button type="button" class=${project === undefined ? "context-chip empty" : "context-chip"} title=${projectContextTitle(project)} aria-label=${`Project: ${projectLabel}. Open project selection.`} @click=${() => { this.openNavigationSection("projects"); }}>
<span class="context-kind">Project</span>
<span class="context-value">${projectLabel}</span>
</button>
</li>
<li class=${workspace === undefined ? "context-chip empty" : "context-chip"} title=${workspaceContextTitle(workspace)} aria-label=${`Workspace: ${workspaceLabel}`}>
<span class="context-kind">Workspace</span>
<span class="context-value">${workspaceLabel}</span>
<li class="context-item">
<button type="button" class=${workspace === undefined ? "context-chip empty" : "context-chip"} title=${workspaceContextTitle(workspace)} aria-label=${`Workspace: ${workspaceLabel}. Open workspace selection.`} @click=${() => { this.openNavigationSection("workspaces"); }}>
<span class="context-kind">Workspace</span>
<span class="context-value">${workspaceLabel}</span>
</button>
</li>
<li class=${session === undefined ? "context-chip empty" : "context-chip"} title=${sessionContextTitle(session)} aria-label=${`Session: ${sessionLabel}`}>
<span class="context-kind">Session</span>
<span class="context-value">${sessionLabel}</span>
<li class="context-item">
<button type="button" class=${session === undefined ? "context-chip empty" : "context-chip"} title=${sessionContextTitle(session)} aria-label=${`Session: ${sessionLabel}. Open session selection.`} @click=${() => { this.openNavigationSection("sessions"); }}>
<span class="context-kind">Session</span>
<span class="context-value">${sessionLabel}</span>
</button>
</li>
</ol>
<div class="context-actions">${this.renderAppRefresh()}</div>
+4 -1
View File
@@ -64,6 +64,7 @@ export const appStyles = css`
.context-bar.can-scroll-left::before, .context-bar.can-scroll-right::after { opacity: 1; }
.context-bar-label { display: none; }
.context-items { flex: 1 1 auto; min-width: 0; display: flex; align-items: stretch; gap: 5px; margin: 0; padding: 0 0 0 8px; list-style: none; overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; scroll-padding-inline: 8px; scrollbar-width: thin; }
.context-item { flex: 0 0 auto; min-width: 0; display: flex; }
.context-actions { position: absolute; top: 6px; right: 0; bottom: 6px; z-index: 3; display: flex; align-items: center; padding: 0 8px 0 0; background: var(--pi-bg); }
.app-refresh { position: relative; display: flex; align-items: center; -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.app-refresh, .app-refresh * { -webkit-user-select: none; user-select: none; }
@@ -73,7 +74,9 @@ export const appStyles = css`
.app-refresh-menu { position: fixed; z-index: 10000; box-sizing: border-box; min-width: min(170px, calc(100vw - 16px)); overflow: auto; padding: 4px; border: 1px solid var(--pi-border); border-radius: 8px; background: var(--pi-surface); box-shadow: 0 8px 24px var(--pi-shadow); overflow-wrap: anywhere; }
.app-refresh-menu button { display: block; width: 100%; border: 0; background: transparent; color: var(--pi-text); text-align: left; white-space: normal; overflow-wrap: anywhere; }
.app-refresh-menu button:hover, .app-refresh-menu button:focus { background: var(--pi-selection-bg); }
.context-chip { flex: 0 0 auto; min-width: 0; display: inline-flex; align-items: baseline; gap: 5px; border: 1px solid var(--pi-border-muted); border-radius: 999px; background: var(--pi-surface); color: var(--pi-text); padding: 4px 8px; }
.context-chip { flex: 0 0 auto; min-width: 0; display: inline-flex; align-items: baseline; gap: 5px; border: 1px solid var(--pi-border-muted); border-radius: 999px; background: var(--pi-surface); color: var(--pi-text); padding: 4px 8px; font: inherit; text-align: left; }
.context-chip:hover { background: var(--pi-surface-hover); }
.context-chip:focus-visible { outline: 2px solid var(--pi-accent); outline-offset: 2px; }
.context-chip.empty { border-style: dashed; color: var(--pi-muted); }
.context-kind { display: none; }
.context-value { min-width: 0; overflow: visible; text-overflow: clip; white-space: nowrap; }