Session Page Layout Architecture
Overview
The Session page (/session/{SessionId}) is the primary interaction interface for thalabus.
It supports three rendering modes, switchable via the three-icon selector:
| Mode | Class on .main-session-div |
Content component |
|---|---|---|
| Chatbot | chatbot-mode |
Chat |
| SearchTable | search-table-mode |
SearchTable + SearchTableTopPanel |
| Documents | documents-mode |
SessionDocuments (WIP) |
Full DOM / Component Tree
<html> height: 100%
<body> height: 100%
<div.page> position: relative; min-height: 100%
<main.main> (no height constraint)
<div.top-row> global nav bar — height: 3.8rem; position: relative
</div.top-row>
<article.content.px-4.article> (no height constraint)
<!-- @Body → Session.razor -->
<div.main-session-div
[.search-table-mode|.documents-mode]>
min-height: calc(100vh - 79px)
<!-- ── FIXED OVERLAYS (position:fixed, outside normal flow) ── -->
<div.top-gradient /> fixed gradient under nav bar
<SessionRenderingChoice /> fixed, left: 12px, top: 80px — 3 icons (chat/table/docs)
<KeywordCategories /> fixed, left side — ontology categories panel
visibility: SearchTable mode only (when ontology loaded)
<DossierComponent /> fixed, centered top — dossier/reasoning document info
visibility: conditional on loaded dossier
<!-- ── MAIN LAYOUT COLUMN ── -->
<div.main-session-with-right-panel>
display: flex; flex-direction: row
height: 100%; overflow: hidden
<div.main-chat-container-div>
display: flex; flex-direction: column
height: 100%
<!-- TOP PANEL (SearchTable only) -->
<div.view-top-panel> flex-shrink: 0
<SearchTableTopPanel> 3 checkboxes + ChatPrompt input
</SearchTableTopPanel>
</div.view-top-panel>
<!-- SCROLLABLE CONTENT AREA -->
<div#chatScrollDiv
.main-chat-scroll-div>
flex-grow: 1; min-height: 0; overflow-y: auto
<!-- Chatbot mode -->
<Chat />
<!-- SearchTable mode -->
<SearchTable />
<!-- Documents mode -->
<SessionDocuments />
</div#chatScrollDiv>
<!-- BOTTOM PROMPT (Chatbot only) -->
<div.main-chat-prompt-div>
<ChatPrompt />
</div.main-chat-prompt-div>
</div.main-chat-container-div>
<!-- RIGHT PANEL (Chatbot only, conditional) -->
<ChatRightPanel /> resizable; visible when documents are loaded
contains tabbed content: "Loaded Documents"
</div.main-session-with-right-panel>
<!-- DEBUG OVERLAYS (Features.ENABLE_FOCUS only) -->
<div.float-top-right>
<CurrentFocus />
<CurrentPlan />
</div>
</div.main-session-div>
</article>
</main>
</div.page>
</body>
</html>
Component Reference
| Component | File | Positioning | Visible when |
|---|---|---|---|
SessionRenderingChoice |
RazorComponents/SessionAlternateRendering/SessionRenderingChoice.razor |
position: fixed; left: 12px; top: 80px |
Always (fades in/out on hover) |
KeywordCategories |
RazorComponents/Ontology/KeywordCategories.razor |
position: fixed; left side |
SearchTable + ontology loaded |
DossierComponent |
RazorComponents/DossierComponents/DossierComponent.razor |
position: fixed; centered top |
Dossier or reasoning doc loaded |
SearchTableTopPanel |
RazorComponents/SessionAlternateRendering/SearchTableTopPanel.razor |
Flex child (flex-shrink: 0) of .main-chat-container-div |
SearchTable mode |
Chat |
RazorComponents/ChatRazorComponents/Chat.razor |
Inside #chatScrollDiv |
Chatbot mode |
SearchTable |
RazorComponents/SessionAlternateRendering/SearchTable.razor |
Inside #chatScrollDiv |
SearchTable mode |
SessionDocuments |
RazorComponents/SessionAlternateRendering/SessionDocuments.razor |
Inside #chatScrollDiv |
Documents mode |
ChatPrompt (bottom) |
RazorComponents/ChatRazorComponents/ChatPrompt.razor |
.main-chat-prompt-div below scroll div |
Chatbot mode |
ChatRightPanel |
RazorComponents/ChatRazorComponents/ChatRightPanel.razor |
Flex-row sibling of .main-chat-container-div |
Chatbot mode + documents loaded |
CurrentFocus / CurrentPlan |
RazorComponents/DeepReasoningComponents/ |
position: fixed; top-right |
Features.ENABLE_FOCUS debug only |
Layout CSS Chain
| Element | Key CSS | File |
|---|---|---|
html, body |
height: 100% |
site.css |
.page |
position: relative; min-height: 100% |
MainLayout.razor.css |
main |
(no height) | — |
article.article |
z-index: 0 (no height) |
MainLayout.razor.css |
.main-session-div |
min-height: calc(100vh - 79px) |
Session.razor.css |
.main-session-with-right-panel |
display: flex; flex-direction: row; height: 100%; overflow: hidden |
Session.razor.css |
.main-chat-container-div |
display: flex; flex-direction: column; height: 100% |
site.css |
.view-top-panel |
flex-shrink: 0 |
site.css |
#chatScrollDiv |
flex-grow: 1; min-height: 0; overflow-y: auto |
site.css |
Rendering Mode Behaviour Summary
Chatbot mode
- Left:
SessionRenderingChoice(fixed) - Center top→bottom:
Chat(scrollable) →ChatPrompt(pinned bottom) - Right (optional):
ChatRightPanelwith loaded-documents tab
SearchTable mode
- Left:
SessionRenderingChoice(fixed) +KeywordCategories(fixed, if ontology active) - Center top→bottom:
SearchTableTopPanel(pinned top: 3 checkboxes + prompt) →SearchTable(scrollable) - No right panel
Documents mode (WIP)
- Left:
SessionRenderingChoice(fixed) - Center:
SessionDocuments(document cards from session history)
Known Issues and Planned Improvements
Issue 1 — SearchTable top prompt scrolls with content (resolved)
Problem: In SearchTable mode the SearchTableTopPanel (3 filter checkboxes + the user input
prompt) is supposed to stay pinned at the top of the content area while the results table scrolls
beneath it. In practice the entire page scrolls as a unit, so the panel disappears as soon as
the user scrolls down — forcing them to scroll back to the top for every new query.
Root cause — broken height chain: The CSS intent is:
html/body (height:100%) → .page → main → article → .main-session-div
→ .main-session-with-right-panel → .main-chat-container-div (flex column)
→ .view-top-panel (flex-shrink:0, stays put)
→ #chatScrollDiv (flex-grow:1, overflow-y:auto, scrolls)
For #chatScrollDiv to scroll internally its flex parent (.main-chat-container-div) must have
a definite, bounded height. That height propagates down via height: 100% from the chain above.
The chain breaks at three points:
| Element | Problem |
|---|---|
.page |
min-height: 100% — height is content-driven, not bounded |
main |
no height rule — inherits unconstrained content height |
article.article |
no height rule — inherits unconstrained content height |
.main-session-div |
min-height: calc(100vh - 79px) — also content-driven |
Because no ancestor has a definite height, height: 100% on .main-chat-container-div
resolves to the full content height, overflow-y: auto on #chatScrollDiv never activates,
and the browser scrolls the whole page instead.
Refactoring approach — :has() viewport-lock (implemented for both Chatbot and SearchTable modes):
Using the CSS :has(.search-table-mode) / :has(.chatbot-mode) selectors (well-supported in all
modern browsers), the chain is constrained exclusively when the corresponding mode is active,
leaving Documents mode and all other pages unaffected:
.page→height: 100%; min-height: unset; overflow: hiddenmain→height: 100%; display: flex; flex-direction: column; overflow: hiddenarticle.article→flex: 1 1 0; min-height: 0; overflow: hidden.main-session-div.search-table-mode→height: 100%; min-height: unset
With a definite height on every ancestor #chatScrollDiv is finally constrained to the remaining
viewport height, overflow-y: auto activates, and the top panel never moves.
These rules are implemented in site.css (global per-mode rules, steps 1–3, duplicated for
.chatbot-mode and .search-table-mode) and Session.razor.css (step 4, one rule per mode
class: .main-session-div.chatbot-mode and .main-session-div.search-table-mode).
Issue 2 — DossierComponent migration to right panel (planned)
DossierComponent and the reasoning-document info widget currently render as position: fixed
overlays at the top-centre of the viewport (above the content). They are planned to be migrated
into the ChatRightPanel tab system so the centre content area is not obscured.
Issue 3 — ChatRightPanel only available in Chatbot mode (planned)
The ChatRightPanel (loaded-documents tab) is rendered only in Chatbot mode. It should eventually
be available in all three modes.
Issue 4 — Documents mode is work in progress
SessionDocuments currently shows a "THIS PAGE IS WORK IN PROGRESS..." message.