From c5c0eea0f55991cb846207bc2f80f0752e17c4bc Mon Sep 17 00:00:00 2001 From: dimakis Date: Fri, 22 May 2026 14:01:19 +0100 Subject: [PATCH 1/2] fix(ui): boot context pill markdown rendering, modal z-index, persistence - Replace
 with ReactMarkdown in SectionRow and full markdown modal
- Portal modal to document.body to escape sticky stacking context
- Add proper markdown styles for headings, tables, code, lists
- Preserve bootContext across switchSession() state resets

Co-Authored-By: Claude Opus 4.6 
---
 frontend/src/components/BootContextPill.tsx |  52 ++++---
 frontend/src/styles/global.css              | 145 +++++++++++++++++++-
 packages/client/src/store.ts                |   2 +-
 3 files changed, 172 insertions(+), 27 deletions(-)

diff --git a/frontend/src/components/BootContextPill.tsx b/frontend/src/components/BootContextPill.tsx
index c09989c5..cd92a044 100644
--- a/frontend/src/components/BootContextPill.tsx
+++ b/frontend/src/components/BootContextPill.tsx
@@ -1,4 +1,7 @@
 import { useState, useEffect } from 'react';
+import { createPortal } from 'react-dom';
+import ReactMarkdown from 'react-markdown';
+import remarkGfm from 'remark-gfm';
 import type { BootContextMeta, SectionMeta } from '@mitzo/client';
 
 interface Props {
@@ -31,7 +34,9 @@ function SectionRow({ section, dimmed }: { section: SectionMeta; dimmed?: boolea
         {section.tokens}t
       
       {open && section.content && (
-        
{section.content}
+
+ {section.content} +
)} ); @@ -133,29 +138,34 @@ export function BootContextPill({ context }: Props) { )} - {showModal && context.fullMarkdown && ( -
setShowModal(false)} - onTouchStart={(e) => e.stopPropagation()} - > + {showModal && + context.fullMarkdown && + createPortal(
e.stopPropagation()} - role="dialog" - aria-modal="true" - aria-label="Boot context full markdown" + className="boot-context-modal-overlay" + onClick={() => setShowModal(false)} + onTouchStart={(e) => e.stopPropagation()} > -
-

Boot Context (Full Markdown)

- +
e.stopPropagation()} + role="dialog" + aria-modal="true" + aria-label="Boot context full markdown" + > +
+

Boot Context (Full Markdown)

+ +
+
+ {context.fullMarkdown} +
-
{context.fullMarkdown}
-
-
- )} +
, + document.body, + )} ); } diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index 0a1941c2..0983e1de 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -2638,17 +2638,68 @@ textarea:focus { background: rgba(255, 255, 255, 0.03); border-left: 2px solid rgba(255, 255, 255, 0.1); border-radius: 0 4px 4px 0; - font-family: var(--code-font); font-size: 0.65rem; - line-height: 1.4; + line-height: 1.5; color: var(--text-dim); - white-space: pre-wrap; word-break: break-word; max-height: 200px; overflow-y: auto; -webkit-overflow-scrolling: touch; } +.boot-context-pill-section-content h1, +.boot-context-pill-section-content h2, +.boot-context-pill-section-content h3 { + font-size: 0.7rem; + margin: 0.4rem 0 0.2rem; + color: var(--text-secondary); +} + +.boot-context-pill-section-content p { + margin: 0.2rem 0; +} + +.boot-context-pill-section-content ul, +.boot-context-pill-section-content ol { + margin: 0.2rem 0; + padding-left: 1.2rem; +} + +.boot-context-pill-section-content code { + font-family: var(--code-font); + font-size: 0.6rem; + background: rgba(255, 255, 255, 0.06); + padding: 0.1rem 0.25rem; + border-radius: 3px; +} + +.boot-context-pill-section-content pre { + font-family: var(--code-font); + font-size: 0.6rem; + background: rgba(255, 255, 255, 0.04); + padding: 0.3rem 0.4rem; + border-radius: 4px; + overflow-x: auto; + margin: 0.2rem 0; +} + +.boot-context-pill-section-content pre code { + background: none; + padding: 0; +} + +.boot-context-pill-section-content table { + font-size: 0.6rem; + border-collapse: collapse; + width: 100%; +} + +.boot-context-pill-section-content th, +.boot-context-pill-section-content td { + border: 1px solid rgba(255, 255, 255, 0.1); + padding: 0.2rem 0.3rem; +} + .boot-context-pill-trimmed-toggle { display: flex; align-items: center; @@ -2752,15 +2803,99 @@ textarea:focus { overflow-y: auto; padding: 1.5rem; margin: 0; - font-family: var(--code-font); font-size: var(--text-xs); line-height: 1.6; color: var(--text-secondary); - white-space: pre-wrap; word-break: break-word; -webkit-overflow-scrolling: touch; } +.boot-context-modal-content h1 { + font-size: var(--text-lg); + margin: 1rem 0 0.5rem; + color: var(--text-primary); + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + padding-bottom: 0.3rem; +} + +.boot-context-modal-content h2 { + font-size: var(--text-base); + margin: 0.8rem 0 0.4rem; + color: var(--text-primary); +} + +.boot-context-modal-content h3 { + font-size: var(--text-sm); + margin: 0.6rem 0 0.3rem; + color: var(--text-secondary); +} + +.boot-context-modal-content p { + margin: 0.4rem 0; +} + +.boot-context-modal-content ul, +.boot-context-modal-content ol { + margin: 0.4rem 0; + padding-left: 1.5rem; +} + +.boot-context-modal-content li { + margin: 0.15rem 0; +} + +.boot-context-modal-content code { + font-family: var(--code-font); + font-size: 0.85em; + background: rgba(255, 255, 255, 0.06); + padding: 0.1rem 0.3rem; + border-radius: 3px; +} + +.boot-context-modal-content pre { + font-family: var(--code-font); + font-size: var(--text-xxs); + background: rgba(255, 255, 255, 0.04); + padding: 0.6rem 0.8rem; + border-radius: 6px; + overflow-x: auto; + margin: 0.5rem 0; +} + +.boot-context-modal-content pre code { + background: none; + padding: 0; +} + +.boot-context-modal-content table { + border-collapse: collapse; + width: 100%; + margin: 0.5rem 0; + font-size: var(--text-xxs); +} + +.boot-context-modal-content th, +.boot-context-modal-content td { + border: 1px solid rgba(255, 255, 255, 0.1); + padding: 0.3rem 0.5rem; + text-align: left; +} + +.boot-context-modal-content th { + background: rgba(255, 255, 255, 0.04); + font-weight: 500; +} + +.boot-context-modal-content strong { + color: var(--text-primary); +} + +.boot-context-modal-content hr { + border: none; + border-top: 1px solid rgba(255, 255, 255, 0.1); + margin: 0.8rem 0; +} + /* ===== Markdown Preview Card ===== */ .md-preview-card { diff --git a/packages/client/src/store.ts b/packages/client/src/store.ts index 02dc35a2..d114834b 100644 --- a/packages/client/src/store.ts +++ b/packages/client/src/store.ts @@ -251,7 +251,7 @@ export function createMitzoStore(options: MitzoStoreOptions): StoreApi ({ sessions: { ...s.sessions, active: id }, - messages: INITIAL_MESSAGES_STATE, + messages: { ...INITIAL_MESSAGES_STATE, bootContext: s.messages.bootContext }, permissions: INITIAL_PERMISSIONS_STATE, tokens: INITIAL_TOKENS_STATE, progress: INITIAL_PROGRESS_STATE, From b719e618ded7a2edbed49b4f3cf0cc1cf3baefa0 Mon Sep 17 00:00:00 2001 From: dimakis Date: Fri, 22 May 2026 18:18:47 +0100 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20address=20Centaur=20review=20?= =?UTF-8?q?=E2=80=94=20revert=20stale=20bootContext,=20extract=20shared=20?= =?UTF-8?q?CSS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Revert switchSession() bootContext preservation (stale data risk) - Extract shared .boot-context-md class for markdown element styles - Keep container-specific size overrides (compact vs modal) Co-Authored-By: Claude Opus 4.6 --- frontend/src/components/BootContextPill.tsx | 4 +- frontend/src/styles/global.css | 140 +++++++------------- packages/client/src/store.ts | 2 +- 3 files changed, 54 insertions(+), 92 deletions(-) diff --git a/frontend/src/components/BootContextPill.tsx b/frontend/src/components/BootContextPill.tsx index cd92a044..57af42ac 100644 --- a/frontend/src/components/BootContextPill.tsx +++ b/frontend/src/components/BootContextPill.tsx @@ -34,7 +34,7 @@ function SectionRow({ section, dimmed }: { section: SectionMeta; dimmed?: boolea {section.tokens}t {open && section.content && ( -
+
{section.content}
)} @@ -159,7 +159,7 @@ export function BootContextPill({ context }: Props) { ✕
-
+
{context.fullMarkdown}
diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index 0983e1de..f5731e4b 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -2647,57 +2647,85 @@ textarea:focus { -webkit-overflow-scrolling: touch; } -.boot-context-pill-section-content h1, -.boot-context-pill-section-content h2, -.boot-context-pill-section-content h3 { - font-size: 0.7rem; +/* Shared markdown styles for boot context (section + modal) */ + +.boot-context-md h1, +.boot-context-md h2, +.boot-context-md h3 { margin: 0.4rem 0 0.2rem; color: var(--text-secondary); } -.boot-context-pill-section-content p { - margin: 0.2rem 0; +.boot-context-md p { + margin: 0.3rem 0; } -.boot-context-pill-section-content ul, -.boot-context-pill-section-content ol { - margin: 0.2rem 0; - padding-left: 1.2rem; +.boot-context-md ul, +.boot-context-md ol { + margin: 0.3rem 0; + padding-left: 1.3rem; } -.boot-context-pill-section-content code { +.boot-context-md li { + margin: 0.15rem 0; +} + +.boot-context-md code { font-family: var(--code-font); - font-size: 0.6rem; + font-size: 0.85em; background: rgba(255, 255, 255, 0.06); padding: 0.1rem 0.25rem; border-radius: 3px; } -.boot-context-pill-section-content pre { +.boot-context-md pre { font-family: var(--code-font); - font-size: 0.6rem; + font-size: 0.85em; background: rgba(255, 255, 255, 0.04); - padding: 0.3rem 0.4rem; + padding: 0.4rem 0.6rem; border-radius: 4px; overflow-x: auto; - margin: 0.2rem 0; + margin: 0.3rem 0; } -.boot-context-pill-section-content pre code { +.boot-context-md pre code { background: none; padding: 0; } -.boot-context-pill-section-content table { - font-size: 0.6rem; +.boot-context-md table { border-collapse: collapse; width: 100%; + margin: 0.3rem 0; } -.boot-context-pill-section-content th, -.boot-context-pill-section-content td { +.boot-context-md th, +.boot-context-md td { border: 1px solid rgba(255, 255, 255, 0.1); - padding: 0.2rem 0.3rem; + padding: 0.2rem 0.4rem; + text-align: left; +} + +.boot-context-md th { + background: rgba(255, 255, 255, 0.04); + font-weight: 500; +} + +.boot-context-md strong { + color: var(--text-primary); +} + +.boot-context-md hr { + border: none; + border-top: 1px solid rgba(255, 255, 255, 0.1); + margin: 0.6rem 0; +} + +/* Section-specific size overrides (compact) */ +.boot-context-pill-section-content h1, +.boot-context-pill-section-content h2, +.boot-context-pill-section-content h3 { + font-size: 0.7rem; } .boot-context-pill-trimmed-toggle { @@ -2810,6 +2838,7 @@ textarea:focus { -webkit-overflow-scrolling: touch; } +/* Modal-specific size overrides (larger) */ .boot-context-modal-content h1 { font-size: var(--text-lg); margin: 1rem 0 0.5rem; @@ -2827,73 +2856,6 @@ textarea:focus { .boot-context-modal-content h3 { font-size: var(--text-sm); margin: 0.6rem 0 0.3rem; - color: var(--text-secondary); -} - -.boot-context-modal-content p { - margin: 0.4rem 0; -} - -.boot-context-modal-content ul, -.boot-context-modal-content ol { - margin: 0.4rem 0; - padding-left: 1.5rem; -} - -.boot-context-modal-content li { - margin: 0.15rem 0; -} - -.boot-context-modal-content code { - font-family: var(--code-font); - font-size: 0.85em; - background: rgba(255, 255, 255, 0.06); - padding: 0.1rem 0.3rem; - border-radius: 3px; -} - -.boot-context-modal-content pre { - font-family: var(--code-font); - font-size: var(--text-xxs); - background: rgba(255, 255, 255, 0.04); - padding: 0.6rem 0.8rem; - border-radius: 6px; - overflow-x: auto; - margin: 0.5rem 0; -} - -.boot-context-modal-content pre code { - background: none; - padding: 0; -} - -.boot-context-modal-content table { - border-collapse: collapse; - width: 100%; - margin: 0.5rem 0; - font-size: var(--text-xxs); -} - -.boot-context-modal-content th, -.boot-context-modal-content td { - border: 1px solid rgba(255, 255, 255, 0.1); - padding: 0.3rem 0.5rem; - text-align: left; -} - -.boot-context-modal-content th { - background: rgba(255, 255, 255, 0.04); - font-weight: 500; -} - -.boot-context-modal-content strong { - color: var(--text-primary); -} - -.boot-context-modal-content hr { - border: none; - border-top: 1px solid rgba(255, 255, 255, 0.1); - margin: 0.8rem 0; } /* ===== Markdown Preview Card ===== */ diff --git a/packages/client/src/store.ts b/packages/client/src/store.ts index d114834b..02dc35a2 100644 --- a/packages/client/src/store.ts +++ b/packages/client/src/store.ts @@ -251,7 +251,7 @@ export function createMitzoStore(options: MitzoStoreOptions): StoreApi ({ sessions: { ...s.sessions, active: id }, - messages: { ...INITIAL_MESSAGES_STATE, bootContext: s.messages.bootContext }, + messages: INITIAL_MESSAGES_STATE, permissions: INITIAL_PERMISSIONS_STATE, tokens: INITIAL_TOKENS_STATE, progress: INITIAL_PROGRESS_STATE,