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

SearchTable mode

Documents mode (WIP)


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:

  1. .page → height: 100%; min-height: unset; overflow: hidden
  2. main → height: 100%; display: flex; flex-direction: column; overflow: hidden
  3. article.article → flex: 1 1 0; min-height: 0; overflow: hidden
  4. .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.