Repository navigation
feat(ui): unify settings panels onto PanelPage + ChipTabs layout primitives - #3646
Conversation
…anels Extract the Settings → Account chip row into a shared ChipTabs component (layout/ChipTabs.tsx): a controlled pill/chip bar with tab (role=tablist) or nav (role=navigation/aria-current) semantics. Route SettingsSubNav through it and replace the duplicated underline-tab rows in Notifications, Usage, Personality and Integrations panels so every 'switch sibling views' surface reads identically.
Replace the bespoke pill tablist selecting which MCP client config to view with the shared ChipTabs bar so it matches the rest of the app's chip rows.
…ne panels Add layout/PanelScaffold.tsx: a reusable right-pane scaffold with a sticky header (optional title + description, plus leading/action/headerExtra slots) above a scrollable body with standardized spacing. The header stays pinned to the two-pane content pane while the body scrolls. Extract the route-aware back button into settings/components/SettingsBackButton so SettingsHeader and PanelScaffold-based panels share identical behavior, and migrate Account, Notifications, Usage, Personality, Integrations and MCP panels onto PanelScaffold (chip rows pinned via headerExtra).
…dies) Add the standard panel page composed from three layout primitives: - PanelHeader: the fixed header band (title/description/leading/action + extra) - PanelScaffold: PanelHeader + single scrollable body (the inner scaffold) - PanelPage: optional page title/description + optional chip row over one or more scaffold bodies; owns exactly one vertical scroll (the active body) Make PanelScaffold the only scroller (flex height chain) and pin the settings sub-nav chips, fixing the double-scroll. Drop redundant panel titles (sidebar / chips already name the view) in favor of descriptions sourced from existing menuDesc i18n keys. Migrate Account, Notifications, Usage, Personality, Integrations and MCP panels onto PanelPage.
Mechanically migrate the ~40 remaining top-level settings panels from SettingsHeader to the unified PanelPage: drop redundant titles in favour of descriptions (sourced from the route registry's existing descriptionKey i18n keys), route the back button through SettingsBackButton, and let each panel own a single scroll via PanelScaffold. Embedded tab-body panels and Connections/ Brain-hosted panels keep SettingsHeader (not part of the settings two-pane). Tests updated where they asserted the now-removed title heading.
…adding - Remove the title slot from PanelHeader/PanelScaffold/PanelPage — the sidebar, bottom bar and chips already name the view; lead with the description. - Add a hairline top border on the scrollable body (and under the chip row in tabbed pages) so the fixed header and scrolling content read as separate. - Align header padding to the body (px-4 pt-4) and drop the description's extra top margin so it lines up with the content instead of sitting more inset.
- TwoPanelLayout: add `seamless` mode — join both panes into one bordered card with a flush, draggable hairline seam instead of separate cards split by a gutter. Enable it on Settings, Brain and Connections. - PanelHeader: give the fixed header band a slightly off background (bg-stone-50 / dark neutral-800/40) so it reads as its own band. - PanelScaffold/PanelPage: even the body's top padding (p-4, was pt-2) so it lines up with the sides.
Migrate the Brain/Connections-hosted panels (MemoryData, MemoryDebug, AnalysisViews, AI, Embeddings, Voice, Search) from SettingsHeader to PanelPage (description, no title). Restructure the Brain page so bespoke tabs (graph, sources, sync, subconscious) render inside a PanelPage scaffold and the knowledge panels — now PanelPage themselves — fill the pane and own their scroll directly.
- Route Connections (Skills) tab content through PanelPage: intelligence tabs render their PanelPage panels directly; bespoke tabs share one scaffold. - Remove the redundant Composio 'Composio Integrations' inner title (now the scaffold description); anchor its tests on a data-testid instead. - Make the seamless single-card flush divider the permanent default for every TwoPanelLayout (Settings, Brain, Connections, Chat).
… 'API keys' - Connections sidebar: rename the Integrations 'Composio' tab to 'OAuth' (the OAuth connector grid), rename the 'Intelligence' group to 'API keys', and add a 'Composio' entry there that renders ComposioPanel (key + routing). - Migrate ComposioPanel to PanelPage (description, no title); recognise the new composio-key tab in the Connections tab resolver and give it a key icon. - Remove the Settings → Integrations → Composio sub-tab; redirect legacy /settings/composio[-routing] to /connections?tab=composio-key. - Add connections.tabs.oauth / composioKey + connections.groups.apiKeys across all 14 locales; update the affected tests.
SETTINGS_NAV_ICONS had no 'profiles' key, so the Agent profiles destination rendered without an icon. Add a user-in-circle glyph.
|
Warning Review limit reached
More reviews will be available in 14 minutes and 30 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (119)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a3779f67f2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const hashToTab = (hash: string): TabId => { | ||
| if (hash === '#composio') return 'composio'; | ||
| if (hash === '#webhooks') return 'webhooks'; | ||
| return 'task-sources'; |
There was a problem hiding this comment.
Preserve the old Composio tab hash
When a user opens an existing /settings/integrations#composio link/bookmark from the previous Composio tab, hashToTab now falls through to task-sources, so they are not taken to the relocated Composio API key panel. The new route redirects cover /settings/composio and /settings/composio-routing, but not this hash-backed tab; handle #composio by redirecting to /connections?tab=composio-key (or otherwise normalizing it) before the fallback.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in a0a060260: IntegrationsPanel now redirects the legacy #composio hash to /connections?tab=composio-key, and the onboarding custom-wizard oauth deep link points there directly. Added a unit test asserting the redirect.
The old Composio tab lived at /settings/integrations#composio. After moving Composio under Connections → API keys, that hash fell through to the task-sources tab, stranding existing bookmarks and the onboarding "oauth" deep link. Normalize #composio to /connections?tab=composio-key and point the custom-wizard oauth route at the new location.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fda367311c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| {activeTab === 'voice' && <VoicePanel />} | ||
| {activeTab === 'embeddings' && <EmbeddingsPanel />} | ||
| {activeTab === 'search' && <SearchPanel />} | ||
| {activeTab === 'composio-key' && <ComposioPanel />} |
There was a problem hiding this comment.
Refresh Composio key state after saving
In local sessions where the OAuth tab shows the no-key empty state, this in-page Composio API-key panel can save or clear the key without ever updating the parent hasComposioApiKey state, which is only loaded by the useEffect keyed on isLocalSession. Because the page no longer navigates away/remounts, returning to the OAuth tab keeps showing the no-key banner after a successful save (or keeps showing the catalog after clearing) until a full reload; refresh that state after ComposioPanel saves/clears or when switching back to the OAuth tab.
Useful? React with 👍 / 👎.
The PanelPage migration intentionally dropped panel-title headings, so
Playwright specs that asserted getByRole('heading', { name: 'Account' | 'Wallet
Balances' | 'Privacy & Security' | 'Appearance' | 'Embeddings' | 'Developer &
Diagnostics' | 'New agent' }) and the 'Composio Integrations' page heading no
longer match. Re-anchor those assertions on stable markers:
- panel test ids (account-panel, settings-privacy-panel, webhooks-debug-panel,
memory-debug-panel) and the composio-integrations-card container;
- existing in-panel controls/sub-nav where no panel test id exists.
Also fix two strict-mode violations where new PanelPage description copy now
contains the asserted text ("…temperature overrides", "App version and software
updates"): scope to the section heading / exact label.
The PanelPage migration changed the per-tab content branches in Brain and Skills (the Knowledge & Memory and API-keys groups now render relocated settings panels inside the two-pane shell). Drive each tab via the `?tab=` query param so those branches are exercised: - Brain: intelligence, memory-data, memory-debug, analysis-views, sources, sync, subconscious (stub the relocated panels + SettingsLayoutProvider). - Skills: llm, voice, embeddings, search, composio-key (stub AIPanel, VoicePanel, EmbeddingsPanel, SearchPanel, ComposioPanel). Raises changed-line coverage back above the 80% diff-cover gate.
There was a problem hiding this comment.
💡 Codex Review
openhuman/app/src/pages/Settings.tsx
Line 181 in 28e599c
The old Intelligence page used ?tab= for deep links to child tabs such as Workflows or Memory. This redirect always sends /settings/intelligence?... to /brain?tab=intelligence, dropping the existing query; for example, /settings/intelligence?tab=workflows now lands on the default child tab because the embedded page expects itab=workflows. Preserve the old tab value as itab when redirecting.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| {/* Distinct tab query key so the embedded Intelligence panel's | ||
| internal tab switches don't overwrite Brain's own | ||
| `?tab=intelligence` and unmount it. */} | ||
| {activeTab === 'intelligence' && <Intelligence tabParamKey="itab" />} |
There was a problem hiding this comment.
Restore scrolling for embedded Intelligence
When users open Brain → Intelligence, this renders the legacy Intelligence page directly inside TwoPanelLayout's content pane. That pane is overflow-hidden, and unlike the other knowledge tabs Intelligence still renders a plain page with its own SettingsHeader rather than a PanelPage, so long Tasks/Workflows content is clipped with no vertical scrollbar. Wrap this branch in a scroll container or migrate Intelligence to PanelPage before embedding it here.
Useful? React with 👍 / 👎.
CronJobsPanel's title heading was dropped in the PanelPage migration; the helper already asserts the cron-jobs-panel test id and the Scheduled Jobs section, so re-anchor on those instead of the gone heading.
…ai#3611/tinyhumansai#3632/tinyhumansai#3643/tinyhumansai#3646) Frontend IA refactors broke the WDIO/Appium E2E suite (baseline 83 failing specs). Test-only changes plus two one-line data-testid additions. Validated by running the full Linux E2E suite to green on a fork (see PR for RCAs).
…ai#3611/tinyhumansai#3632/tinyhumansai#3643/tinyhumansai#3646) Frontend IA refactors broke the WDIO/Appium E2E suite (baseline 83 failing specs). Test-only changes plus two one-line data-testid additions. Validated by running the full Linux E2E suite to green on a fork (see PR for RCAs).
…ai#3611/tinyhumansai#3632/tinyhumansai#3643/tinyhumansai#3646) Frontend IA refactors broke the WDIO/Appium E2E suite (baseline 83 failing specs). Test-only changes plus two one-line data-testid additions. Validated by running the full Linux E2E suite to green on a fork (see PR for RCAs).
Summary
PanelScaffold(fixed header + scrollable body),PanelPage(optional title/description/chips over the scaffold),PanelHeader, and a reusableChipTabsbar.PanelPagefor a consistent header band, seamless two-pane card, and even body padding.PanelPageon Brain and Connections pages and their hosted panels; adoptChipTabsfor the settings sub-nav and tabbed panels (MCP client selector, Notifications).settingsNavIconsand supporting i18n keys (with real translations across all 14 locales).Problem
Settings panels each rolled their own header/body scaffolding, producing inconsistent padding, divider treatment, and titling across the right pane. There was no shared primitive for the fixed-header/scrollable-body pattern or for the chip-style tab bar repeated across sub-navs.
Solution
PanelScaffoldand layer optional title/description/chips on top viaPanelPage, so every panel renders through one path.ChipTabsand adopt it wherever a segmented selector existed.AppearancePanelas the recipe reference, then the rest) keeping behavior identical — this is a presentation-layer refactor, not a behavior change.Submission Checklist
ChipTabs.test.tsx; updated panel/page unit tests to the new structure.ChipTabs/PanelPageprimitives.docs/TEST-COVERAGE-MATRIX.md.Impact
Related
AI Authored PR Metadata (required for Codex/Linear PRs)
Linear Issue
Commit & Branch
Validation Run
pnpm --filter openhuman-app format:checkpnpm typecheckChipTabs.test.tsxand migrated settings panel tests (Vitest)Validation Blocked
command:N/Aerror:N/Aimpact:N/ABehavior Changes
Parity Contract
Duplicate / Superseded PR Handling