Skip to content

Display menu: the layout row's five segments (表格 / 看板 / 日历 / 时间线 …) wrap their labels inside the 240 px popover; the row folds to icons with tooltips or the popover widens #26637

Closed

Description

@objectstack-fleet

Source

Walked on 2026-10-27 on the HotCRM opportunity list (/crm_opportunity, zh-CN, 1149 px): the Display popover's first row is now a segmented control 「布局 | 表格 | 看板 | 日历 | 时间线」 (the layouts the object offers). In the 240 px popover the five icon + label segments do not fit: 「表格」「看板」「日历」「时间线」 each break onto two lines and the row is twice its height; in en the labels are longer still.

Target

  1. The layout row shows icons only when the segments would wrap (a measured fold, not a count), each with a tooltip and an accessible name; the active segment keeps its label.
  2. Or the popover is 300 px wide on the list surfaces that offer four or more layouts; the card picks one and says why.
  3. A test with five layouts asserts no segment label wraps at the popover's width.

File surface

ui/packages/plugin-list/src/components/ViewSettingsPopover.tsx (the layout row), tests beside.

Acceptance

  1. Screenshots of the Display popover on an object with five layouts, zh-CN and en.
  2. pnpm --filter @object-ui/plugin-list test green.

Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff from the 2026-10-27 supplementary pass on objectstack main f9867020c6 (the source console at :5180 against HotCRM 18.2.0, the maintainer's browser pane at 1149 × 507, zh-CN and en, dark and light). The maintainer asked, verbatim: 「补测的前 3 项立卡到 objectstack,只立不派。」— the first of the three (the Data pillar's 高级 dropdown) turned out to be the 2026-10-15 ruling B as designed (it flattens from a 1000 px content column), so two cards are filed.

Activity

  1. added
    bugSomething isn't working
    pm:queueReady for the PM dispatch loop
    domain:uiDomain lane — seat card indexed by label:pm:seat
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    on Oct 27, 2026
  2. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: audit line · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-27T12:01Z

    ⛔ Not a claim, ⛔ not a dispatch.

    • Triage: lands in the Display popover's layout row (ui/); rationale: p3 · domain:ui · area:records. Fold the segments to icons with tooltips when they would wrap, measured and not tied to a breakpoint, in every locale.

    Generated by Claude Code

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Oct 27, 2026
  4. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01QsR2jTfvjNTaR29ehLk26T
    Account: zhuangjianguo
    Branch: claude/project-thread-vx54jd (platform-assigned card-thread branch; a card thread can push only its assigned branch, and the name carries no issue number, so this claim is the identity record)
    Worktree: objectstack-issue-26637
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: ui/packages/plugin-list/src/components/ViewSettingsPopover.tsx (the layout row), tests beside, one root changeset; ⛔ packages/spec/**, ⛔ widening the popover (stop on breach; explain in the report)
    Container & model: S, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate; reason: the maintainer's standing rule 「只认领不需要 fable 的卡」, 2026-10-27T10:39Z), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: the Display popover's layout row (plugin-list, this lane) wraps each segment label inside 240 px · the platform path that may cover it: none, the row is this component's own layout · reached by every list whose object offers four or more layouts (HotCRM opportunity, zh-CN and en)
    Thread-read: 6441384848
    Premise: holds (the card's walk on main f9867020c6; the layout row on origin/main 86ae47e1 has no measured fold, re-read at 2026-10-27T12:16Z)
    Serial constraints cleared: #26613 (this seat) edits ListViewBlock.tsx, ListView.tsx and ListViewCompact.tsx in plugin-list, not ViewSettingsPopover.tsx; no open PR touches it (scan 2026-10-27T12:13Z)

    Dispatched at 2026-10-27T12:16Z to the card thread on that branch; the order lives in the thread's opening message.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 26637,
    "status": "done",
    "branch": "claude/project-thread-vx54jd",
    "pr": "#26696",
    "session": "session_01QsR2jUfYgopbwA4FqJngRV",
    "premise_still_valid": true,
    "summary": "The Display popover's Layout row now wraps the host's layout control in a LayoutSlot (ViewSettingsPopover.tsx only) that measures the width the segments need with every label shown against the slot's own width, after every render and on resize. When they would not fit it sets data-layout-fold=icons and one class hides the words of every unselected role=tab; the selected segment keeps its label, and each tab keeps its existing aria-label and title as accessible name and tooltip (no locale key added). Measurement lifts the fold for one synchronous read so the row never oscillates; tabs no longer wrap, and the popover keeps w-80. Premise detail: the card says 240 px, main's popover is 320 px (w-80, measured in Chromium); the row still overflowed at 320 (slot 258 px zh-CN, 244 px en).",
    "tests": "ecb5f58f: pnpm --filter @object-ui/plugin-list test --maxWorkers=2 under os-verify-lock: Test Files 164 passed (164), Tests 1650 passed (1650), VERDICT command-exit 0. New ViewSettingsPopover.layoutFold.test.tsx 5/5 (zh-CN walked row folds with names+titles kept and only the selected label shown; en folds; five layouts fold at popover width; same five do not fold in a 600 px slot and two layouts never fold; a row that fits again unfolds; zero width reads while folded). type-check: turbo run type-check --filter=@object-ui/plugin-list, tsc --noEmit plus tsc -p tsconfig.test.json (listFilesOnly names the new test), 49/49 tasks, exit 0. Ablations on dfbd4bf via scripts/ablation-replace.mjs (anchor 1 to 0, blob restored to HEAD, git diff HEAD empty): (1) layout rendered without LayoutSlot: 4 failed / 1 passed; (2) delete the fold-lift line before measuring: 4 failed with Maximum update depth exceeded. Chromium check (real components, console index.css compiled through @tailwindcss/postcss, which emits the fold rule): zh-CN, en, ja, de with four layouts fold to a 49 px row, selected label kept, every tab named and titled; en with Timeline picked keeps Timeline; zh-CN with two layouts keeps both labels; popover 320 px in every run. Screenshots in the project folder issue-26637/.",
    "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at ecb5f58: 34 commands, each run with exit captured before any pipe, all 34 exit 0; --ran reconciliation: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. Includes pnpm --dir ui exec vitest run scripts/ (178 files passed, 2 skipped), check-sdui-manifest, check-changeset-no-major, check-closing-keyword-parity with this PR body as GITHUB_EVENT_PATH. check:partof-closing-keyword on the body: green. check:closing-target-claim needs the PR number: CI's pr-body-guards. PR check-runs at report time: 19 on ecb5f58, 17 in_progress, 2 skipped, none failed; mergeable_state blocked (draft, checks pending).",
    "dogfood_battery": "n/a, no ! in the PR title and no (narrowing) arm",
    "mcp_calls": "0",
    "api_writes": "2 — relay stroke fw-20261027T130927Z-f1e4dd (run 40509588019): pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/26696/assignees [zhuangjianguo], read back identical 8851 bytes; then this os-dev-report comment via post-stamped. git push is not a REST write. Reviewer request on the PR not made: the platform asks for it via GitHub MCP and the order forbids MCP writes; the seat can add it.",
    "open_questions": [
    {
    "question": "The fold reads the switcher's DOM shape (role=tab, aria-selected, words in a child span) instead of a prop, because the order keeps the fold inside the popover and ListView.tsx is held by #26613. Make it explicit later?",
    "options": [
    "A keep as is: the contract is written on the layout prop's doc comment; one host draws the row",
    "B follow-up card: pass an icons-only flag through the layout render prop and let ViewSwitcherDropdown hide its own labels (touches ListView.tsx and ViewSwitcher.tsx)"
    ],
    "recommendation": "A, because only ViewSwitcherDropdown fills the row today and B adds a prop with no second consumer; revisit if another host draws the row"
    }
    ],
    "out_of_scope_findings": []
    }


    Generated by Claude Code

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:uiDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions