From 1c1740aeabb22eda669c705e42c80acc45eb69db Mon Sep 17 00:00:00 2001 From: Federico Jaramillo Martinez Date: Thu, 28 May 2026 15:06:55 +0200 Subject: [PATCH] fix: keep navigation headings visible --- .../keep-navigation-headings-visible.md | 5 +++ src/client/src/components/ProjectList.ts | 42 ++++++++++--------- src/client/src/components/SessionList.ts | 14 ++++--- src/client/src/components/WorkspaceList.ts | 40 ++++++++++-------- src/client/src/components/shared.ts | 13 +++--- 5 files changed, 66 insertions(+), 48 deletions(-) create mode 100644 .changeset/keep-navigation-headings-visible.md diff --git a/.changeset/keep-navigation-headings-visible.md b/.changeset/keep-navigation-headings-visible.md new file mode 100644 index 0000000..3b59f9d --- /dev/null +++ b/.changeset/keep-navigation-headings-visible.md @@ -0,0 +1,5 @@ +--- +"@jmfederico/pi-web": patch +--- + +Keep left navigation section titles visible while project, workspace, and session lists scroll. diff --git a/src/client/src/components/ProjectList.ts b/src/client/src/components/ProjectList.ts index 2df8363..f857404 100644 --- a/src/client/src/components/ProjectList.ts +++ b/src/client/src/components/ProjectList.ts @@ -44,27 +44,31 @@ export class ProjectList extends LitElement { return html`

${this.renderHeading()}

- ${this.collapsed ? null : this.projects.map((project) => html` -
{ activateSelectableRow(event, () => this.onSelect?.(project)); }} - @keydown=${(event: KeyboardEvent) => { activateSelectableRowFromKeyboard(event, () => this.onSelect?.(project)); }} - > -
- ${project.name}${this.renderActivity(project)}${project.path} -
-
- - ${this.openMenuProjectId === project.id ? html` -
- + ${this.collapsed ? null : html` +
+ ${this.projects.map((project) => html` +
{ activateSelectableRow(event, () => this.onSelect?.(project)); }} + @keydown=${(event: KeyboardEvent) => { activateSelectableRowFromKeyboard(event, () => this.onSelect?.(project)); }} + > +
+ ${project.name}${this.renderActivity(project)}${project.path}
- ` : null} -
+
+ + ${this.openMenuProjectId === project.id ? html` +
+ +
+ ` : null} +
+
+ `)}
- `)} + `}
`; } diff --git a/src/client/src/components/SessionList.ts b/src/client/src/components/SessionList.ts index c60b0bb..0793781 100644 --- a/src/client/src/components/SessionList.ts +++ b/src/client/src/components/SessionList.ts @@ -76,11 +76,15 @@ export class SessionList extends LitElement { return html`
${this.renderHeading(activeRows.length + archivedRows.length)} - ${this.collapsed ? null : activeRows.map((row) => this.renderSession(row, descendantCounts.get(row.session.id) ?? 0))} - ${this.collapsed ? null : archivedRows.length > 0 ? html` -

- ${this.archivedExpanded ? archivedRows.map((row) => this.renderSession(row, descendantCounts.get(row.session.id) ?? 0)) : null} - ` : null} + ${this.collapsed ? null : html` +
+ ${activeRows.map((row) => this.renderSession(row, descendantCounts.get(row.session.id) ?? 0))} + ${archivedRows.length > 0 ? html` +

+ ${this.archivedExpanded ? archivedRows.map((row) => this.renderSession(row, descendantCounts.get(row.session.id) ?? 0)) : null} + ` : null} +
+ `}
`; } diff --git a/src/client/src/components/WorkspaceList.ts b/src/client/src/components/WorkspaceList.ts index 3874756..b130dbb 100644 --- a/src/client/src/components/WorkspaceList.ts +++ b/src/client/src/components/WorkspaceList.ts @@ -49,24 +49,28 @@ export class WorkspaceList extends LitElement { return html`

${this.renderHeading()}

- ${this.collapsed ? null : this.workspaces.map((workspace) => { - const label = workspacePrimaryLabel(workspace); - const items = this.workspaceLabelItems(workspace); - return html` -
{ activateSelectableRow(event, () => this.onSelect?.(workspace)); }} - @keydown=${(event: KeyboardEvent) => { this.handleWorkspaceKeydown(event, workspace); }} - > -
- ${this.renderWorkspaceMain(label, items, workspace)} -
- ${this.renderWorkspaceMenu(label, items, workspace)} -
- `; - })} + ${this.collapsed ? null : html` +
+ ${this.workspaces.map((workspace) => { + const label = workspacePrimaryLabel(workspace); + const items = this.workspaceLabelItems(workspace); + return html` +
{ activateSelectableRow(event, () => this.onSelect?.(workspace)); }} + @keydown=${(event: KeyboardEvent) => { this.handleWorkspaceKeydown(event, workspace); }} + > +
+ ${this.renderWorkspaceMain(label, items, workspace)} +
+ ${this.renderWorkspaceMenu(label, items, workspace)} +
+ `; + })} +
+ `}
`; } diff --git a/src/client/src/components/shared.ts b/src/client/src/components/shared.ts index 98eeeb1..a9e08f2 100644 --- a/src/client/src/components/shared.ts +++ b/src/client/src/components/shared.ts @@ -55,8 +55,8 @@ export const appStyles = css` aside { grid-column: 1; display: flex; flex-direction: column; min-height: 0; overflow: hidden; } header { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 12px; border-bottom: 1px solid var(--pi-border); } .header-actions { display: flex; align-items: center; gap: 8px; } - project-list, workspace-list { flex: 0 0 auto; max-height: 26%; overflow: auto; border-bottom: 1px solid var(--pi-border-muted); } - session-list { flex: 1 1 auto; min-height: 0; overflow: auto; } + project-list, workspace-list { flex: 0 0 auto; max-height: 26%; min-height: 0; overflow: hidden; border-bottom: 1px solid var(--pi-border-muted); } + session-list { flex: 1 1 auto; min-height: 0; overflow: hidden; } main { grid-column: 3; display: flex; flex-direction: column; min-width: 0; min-height: 0; } .context-bar { position: relative; flex: 0 0 auto; min-width: 0; display: none; align-items: center; gap: 0; padding: 6px 0; border-bottom: 1px solid var(--pi-border-muted); background: var(--pi-bg); } .context-bar::before, .context-bar::after { content: ""; position: absolute; top: 0; bottom: 0; z-index: 2; width: 20px; opacity: 0; pointer-events: none; transition: opacity .15s ease; } @@ -135,7 +135,7 @@ export const appStyles = css` main.navigation-view .mobile-navigation-panel { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden; } main.navigation-view .mobile-navigation-panel project-list, main.navigation-view .mobile-navigation-panel workspace-list, - main.navigation-view .mobile-navigation-panel session-list { flex: 1 1 auto; max-height: none; min-height: 0; overflow: auto; } + main.navigation-view .mobile-navigation-panel session-list { flex: 1 1 auto; max-height: none; min-height: 0; overflow: hidden; } main.navigation-view .mobile-navigation-panel project-list[collapsed], main.navigation-view .mobile-navigation-panel workspace-list[collapsed], main.navigation-view .mobile-navigation-panel session-list[collapsed] { flex: 0 0 auto; min-height: auto; overflow: hidden; } @@ -201,10 +201,11 @@ export const workspacePanelStyles = css` `; export const listStyles = css` - :host { display: block; color: var(--pi-text); font: 14px system-ui, sans-serif; } + :host { display: flex; flex-direction: column; min-height: 0; overflow: hidden; color: var(--pi-text); font: 14px system-ui, sans-serif; } :host([collapsed]) { flex: 0 0 auto; min-height: auto; overflow: hidden; } - section { padding: 10px; } - h2 { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin: 0 0 8px; color: var(--pi-muted); font-size: 12px; text-transform: uppercase; } + section { box-sizing: border-box; flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; padding: 10px; } + h2 { flex: 0 0 auto; display: flex; justify-content: space-between; align-items: center; gap: 8px; margin: 0 0 8px; color: var(--pi-muted); font-size: 12px; text-transform: uppercase; } + .list-body { flex: 1 1 auto; min-height: 0; overflow: auto; } button { border: 1px solid var(--pi-border); border-radius: 8px; background: var(--pi-surface); color: var(--pi-text); padding: 7px 9px; cursor: pointer; } section > button { display: block; width: 100%; text-align: left; margin: 6px 0; } .subheading { margin-top: 14px; }