mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
fix(intelligence): make page content scrollable inside Brain card (#4332)
This commit is contained in:
@@ -328,3 +328,9 @@ Quick reference for anyone starting with Claude on this project. Updated by the
|
||||
- **Queue self-heal retries transient failures only** — `memory_queue/scheduler.rs` calls `store::requeue_transient_failed` every 3h (excludes `failure_class = 'unrecoverable'` so bad keys/budget don't retry-loop). Full reset stays manual via `memory_tree_retry_failed` RPC.
|
||||
- **`openhuman.memory_sources_reconcile` RPC** — Reports per-scope raw coverage `{total_raw_files, covered, pending}`; `execute: true` spawns background incremental rebuild. Same reconcile auto-runs after every sync via `check_and_rebuild_tree`.
|
||||
- **L0 seal gate is token-only by design** — `should_seal` has NO sibling-count fallback at L0 (docs used to lie about this); small buffers seal via the 3-hourly `flush_stale` path. L≥1 gates on `SUMMARY_FANOUT` (10) — an L1 buffer holding <10 summaries is healthy, not stuck.
|
||||
|
||||
## Intelligence page scroll ownership (#4267)
|
||||
|
||||
- **`app/src/pages/Intelligence.tsx` is rendered ONLY by `Brain.tsx`** (`/settings/intelligence` redirects to `/brain?tab=intelligence`), inside a card with `h-full overflow-hidden` (`Brain.tsx` ~line 255). A code comment there asserts the embedded panels "own their own scroll directly" — true for the sibling `PanelPage`/`PanelScaffold` panels (MemoryDataPanel etc.), but Intelligence previously returned a bare `<div className="z-10 relative">` with NO height/scroll, so its content overflowed the card and was clipped with no scrollbar.
|
||||
- **Fix pattern (matches `PanelPage`)**: root `flex h-full min-h-0 flex-col` → pinned `SettingsHeader` wrapper (`flex-shrink-0`) → body `min-h-0 flex-1 overflow-y-auto` wrapping ChipTabs + the content card. `ToastContainer`/`ConfirmationModal` stay as siblings OUTSIDE the scroll region. The scroll body carries `data-testid="intelligence-scroll"` for the regression test.
|
||||
- **Gotcha for any panel embedded in Brain's Knowledge/Memory card**: it must own its own vertical scroll (the card is `overflow-hidden`). Don't rely on a parent scroll — there isn't one.
|
||||
|
||||
@@ -201,15 +201,24 @@ export default function Intelligence({ tabParamKey = 'tab' }: IntelligenceProps
|
||||
const activeTabDef = tabs.find(tab => tab.id === activeTab);
|
||||
|
||||
return (
|
||||
<div className="z-10 relative">
|
||||
<SettingsHeader
|
||||
title={t('settings.developerMenu.intelligence.title')}
|
||||
showBackButton={true}
|
||||
onBack={navigateBack}
|
||||
breadcrumbs={breadcrumbs}
|
||||
/>
|
||||
// Rendered inside Brain's `h-full overflow-hidden` card, so this panel must
|
||||
// own its own scroll (like the sibling PanelPage panels) — otherwise its
|
||||
// content overflows the card and is clipped with no scrollbar (#4267). A
|
||||
// flex column pins the header (`flex-shrink-0`) and gives the body the one
|
||||
// vertical scroll (`min-h-0 flex-1 overflow-y-auto`).
|
||||
<div className="z-10 relative flex h-full min-h-0 flex-col">
|
||||
<div className="flex-shrink-0">
|
||||
<SettingsHeader
|
||||
title={t('settings.developerMenu.intelligence.title')}
|
||||
showBackButton={true}
|
||||
onBack={navigateBack}
|
||||
breadcrumbs={breadcrumbs}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="p-4 space-y-4">
|
||||
<div
|
||||
className="min-h-0 flex-1 overflow-y-auto p-4 space-y-4"
|
||||
data-testid="intelligence-scroll">
|
||||
<ChipTabs<IntelligenceTab>
|
||||
items={tabs.map(tab => ({
|
||||
id: tab.id,
|
||||
|
||||
@@ -97,4 +97,14 @@ describe('Intelligence URL-backed tab', () => {
|
||||
expect(screen.getByTestId('tab-council')).toBeInTheDocument();
|
||||
expect(screen.getByText('selected:council')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// Regression for #4267: rendered inside Brain's `overflow-hidden` card, the
|
||||
// panel must own a vertical scroll region that wraps the tab content, or the
|
||||
// content is clipped with no scrollbar.
|
||||
it('wraps the tab content in an overflow-y-auto scroll container', () => {
|
||||
renderAt('/intelligence');
|
||||
const scroll = screen.getByTestId('intelligence-scroll');
|
||||
expect(scroll).toHaveClass('overflow-y-auto');
|
||||
expect(scroll).toContainElement(screen.getByTestId('tab-tasks'));
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user