feat: constrain Chat/Knowledge width + persistent expandable graph panel

Layout:
- Chat and Knowledge views now max out at 1600px and center on wide
  screens, consistent with the rest of the app; app-content overflow
  is set to hidden for both so they manage their own scroll

Graph panel (Knowledge):
- Open/closed state persisted to localStorage (fa_knowledge_graph_open)
  — stays open across navigation and page refreshes
- Expanded state persisted (fa_knowledge_graph_expanded): chevron button
  in the panel header toggles between 420px (normal) and 700px (expanded)
- Minichat right offset follows the panel width with a matching transition

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-01 16:01:18 -04:00
parent d96895c276
commit 0d12d01115
3 changed files with 44 additions and 6 deletions
+3 -1
View File
@@ -318,7 +318,9 @@ onUnmounted(() => {
min-height: 0;
overflow-y: auto;
}
.app-content:has(.workspace-root) {
.app-content:has(.workspace-root),
.app-content:has(.chat-page),
.app-content:has(.knowledge-root) {
overflow: hidden;
}
+3
View File
@@ -1034,6 +1034,9 @@ onUnmounted(() => {
display: flex;
height: 100%;
overflow: hidden;
max-width: 1600px;
width: 100%;
margin: 0 auto;
}
.chat-sidebar {
+38 -5
View File
@@ -123,10 +123,20 @@ const formatEventDate = fmtCompact
// ─── Graph panel ──────────────────────────────────────────────────────────────
const graphOpen = ref(false);
const _GRAPH_OPEN_KEY = 'fa_knowledge_graph_open'
const _GRAPH_EXP_KEY = 'fa_knowledge_graph_expanded'
const graphOpen = ref(localStorage.getItem(_GRAPH_OPEN_KEY) === 'true')
const graphExpanded = ref(localStorage.getItem(_GRAPH_EXP_KEY) === 'true')
function toggleGraph() {
graphOpen.value = !graphOpen.value;
graphOpen.value = !graphOpen.value
localStorage.setItem(_GRAPH_OPEN_KEY, String(graphOpen.value))
}
function toggleGraphExpand() {
graphExpanded.value = !graphExpanded.value
localStorage.setItem(_GRAPH_EXP_KEY, String(graphExpanded.value))
}
// ─── Mini-chat widget ─────────────────────────────────────────────────────────
@@ -262,7 +272,7 @@ onUnmounted(() => {
</script>
<template>
<div class="knowledge-root" :class="{ 'graph-open': graphOpen }">
<div class="knowledge-root" :class="{ 'graph-open': graphOpen, 'graph-expanded': graphExpanded && graphOpen }">
<!-- Today bar -->
<div class="today-bar">
@@ -421,10 +431,22 @@ onUnmounted(() => {
</div>
<!-- Graph panel -->
<aside v-if="graphOpen" class="graph-panel">
<aside v-if="graphOpen" class="graph-panel" :class="{ expanded: graphExpanded }">
<div class="graph-panel-header">
<span>Graph</span>
<button class="btn-icon-sm" @click="toggleGraph"></button>
<div style="display:flex;gap:4px;align-items:center">
<button
class="btn-icon-sm"
@click="toggleGraphExpand"
:title="graphExpanded ? 'Narrow panel' : 'Expand panel'"
>
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline v-if="graphExpanded" points="15 18 9 12 15 6"/>
<polyline v-else points="9 18 15 12 9 6"/>
</svg>
</button>
<button class="btn-icon-sm" @click="toggleGraph" title="Close graph"></button>
</div>
</div>
<div class="graph-embed">
<GraphView :embedded="true" />
@@ -523,6 +545,9 @@ onUnmounted(() => {
flex-direction: column;
height: calc(100vh - var(--header-height, 56px));
overflow: hidden;
max-width: 1600px;
width: 100%;
margin: 0 auto;
}
/* ── Today bar ───────────────────────────────────────────── */
@@ -871,6 +896,10 @@ onUnmounted(() => {
display: flex;
flex-direction: column;
background: var(--color-bg-secondary);
transition: width 0.2s ease;
}
.graph-panel.expanded {
width: 700px;
}
.graph-panel-header {
display: flex;
@@ -919,6 +948,10 @@ onUnmounted(() => {
}
.knowledge-root.graph-open .minichat {
right: 420px;
transition: right 0.2s ease;
}
.knowledge-root.graph-open.graph-expanded .minichat {
right: 700px;
}
.minichat-messages {
max-height: 360px;