Skip to content

feat(home-v2): allow multiple internal pages open as tabs - #350

Merged
QuickMythril merged 1 commit into
mainfrom
feat/home-v2-internal-tabs
Aug 24, 2026
Merged

feat(home-v2): allow multiple internal pages open as tabs#350
QuickMythril merged 1 commit into
mainfrom
feat/home-v2-internal-tabs

Conversation

@QuickMythril

Copy link
Copy Markdown
Member

Summary

Parity review P-3 — owner decision #17 (2026-08-24) reversed the recorded "single internal slot" decision: Dashboard and Settings (and any other Home pages) must be openable at the same time.

Design keeps the destination semantics everywhere (router, address bar, navigation guards untouched) and adds an ordered internalPages list to ProductState:

  • Each internal page opens at most once; a non-'tab' destination is always a member of the list. navigate appends-and-activates; re-navigating to an open page just activates it.
  • New close-internal action: closing the active page falls back to its neighbor page, then the first app tab; closing the very last surface reopens the Dashboard (never an empty window). Closing the last app tab now returns to the last open internal page instead of unconditionally to Dashboard.
  • TabStrip renders every open page as a closable tab (reusing the existing tabs.closeNamed i18n key — no new keys, so catalog parity is untouched). The home-v2-tab--dashboard class is kept on internal tabs so the existing desktop/Android smoke selectors keep working (dashboard remains the first internal tab).
  • Ctrl+W (menu close-tab) closes the active internal page when no app tab is active; internal-close is refused while a trusted overlay owns a tab, same as navigation.
  • Persistence: internalPages serializes with the shell state; restore validates/dedupes (cap 8), drops transient pages (releases/core-docs/welcome — they carry unpersisted side state, matching the existing destination downgrade), and migrates legacy states without the field to a single Dashboard tab.
  • Foundation contract tests cover append/dedupe on navigate, active/inactive close, the three close fallbacks, last-app-tab fallback, restore round-trip, legacy migration, and transient/unknown-page filtering.

Note for review: multiple simultaneous newtab pages are still one page (page-once model) — "+" activates the existing new-tab page; that matches the A2/A4 behavior. Internal tabs stay grouped before app tabs; mixed ordering comes with P-4 (tab drag) if wanted.

Testing

  • Both tsc projects clean; test:home-v2-foundation (extended), test:home-v2-browser-chrome, test:welcome-state pass; build:renderer succeeds.

🤖 Generated with Claude Code

Replaces the single internal slot (owner decision #17 reverses the A2
single-slot decision): ProductState gains an ordered internalPages list
(each page open at most once; a non-'tab' destination is always a
member). navigate appends-and-activates, a new close-internal action
closes with neighbor -> first app tab -> reopen-dashboard fallback, and
closing the last app tab returns to the last open internal page.
TabStrip renders every open page as a closable tab (existing
tabs.closeNamed key; no new i18n keys). Ctrl+W closes the active
internal page when no app tab is active. Persistence serializes
internalPages; restore validates, dedupes, drops transient pages
(releases/core-docs/welcome, matching the destination downgrade), and
migrates legacy states to a single dashboard tab. Contract tests cover
navigate/close/fallback/restore paths.

Parity review P-3 (projects/qortium-home-2.1/parity-review-2026-08-24).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@QuickMythril
QuickMythril merged commit 1554c5f into main Aug 24, 2026
6 checks passed
@QuickMythril
QuickMythril deleted the feat/home-v2-internal-tabs branch August 24, 2026 17:09
QuickMythril added a commit that referenced this pull request Aug 24, 2026
Replaces the grouped internalPages + tabs model (PR #350) with a single
ordered `entries` list holding both internal pages and app tabs, each
with its own id. `tabs` and `destination` are now DERIVED from it, so
the ~24 existing consumers of destination/tabs are untouched.

- Mixed ordering: one drag group, so an app tab can move ahead of a
  Home page and back.
- Duplicates: `open-internal` always appends another instance and is
  wired to "+" / Ctrl+T, while `navigate` still focuses an open page.
- Transient pages (welcome, releases, core-docs) render full-window via
  `transient` instead of taking a tab — they own unpersisted side state,
  so only one can exist and none may restore. Removes the stray Welcome
  tab.
- Close falls to the neighbour whatever its kind; the strip is never
  left empty.
- Internal tabs get per-page icons; Dashboard and Settings previously
  rendered the same Home mark and were distinguishable only by label.
- Persistence serializes `entries`; pre-unified states (separate
  internalPages + tabs) migrate on restore.

Smoke fix: the drag assertion released on the last tab's CENTRE, which
is exactly the midpoint where "insert after" is by design a no-op, so it
failed against correct behaviour. It now releases past that midpoint.

Parity review I1 + I6
(projects/qortium-home-2.1/parity-review-2026-08-24).

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant