Skip to content

Dialog close button at phone width: the X in the shared Dialog is a 16x16 px target, below the 44 px minimum, in every modal the mobile app shows #29107

Closed

Description

@objectstack-fleet

domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y

Filing gate: ① user-visible defect with a named location, class b, an out-of-scope finding from #29070's phone run (Approvals flow, a child of #29040) · filed by domain:ui#4 · ⛔ Not a claim.

Business reason. The mobile app 2.0 hosts the Console in a WebView (objectstack-ai/mobile#144), so every modal a phone user opens is the shared Dialog. Its close X is a 16×16 px tap target, well under the 44 px minimum that #29040 sets. Phone users miss the tap and fall back on a backdrop tap or Cancel, which some dialogs do not offer.

Location. ui/packages/components/src/ui/dialog.tsx:56-57 at origin/main: DialogPrimitive.Close is absolute right-4 top-4 rounded-sm around <X className="h-4 w-4" />, with no padding or minimum size.

reach: measured in a real browser at 375×812 by #29070's os-dev, on the declared-action param dialog of a sys_approval_request record page (the Reject decision): the close button's box is 16×16 px.

Wanted.

  1. The Dialog close button has a tap target of at least 44×44 px at phone width, without moving the visible icon or growing the desktop header.
  2. Match the close-X size and mechanism that Console at phone width: Dashboards flow audit and fixes at 375 and 390 px #29078 (Dashboards at phone width) lands for the Sheet close in sheet.tsx, so both primitives agree.
  3. A test that pins the target size.

Reader. domain:ui, size S. It runs after #29078 lands if both touch the same shared size token or class; otherwise it can build beside it. #29070 and #29071 leave dialog.tsx alone.

Dedupe. Searched dialog close touch target (108 hits; the open ones are #29040, #29078 and unrelated cards), dialog.tsx close (1 hit: #5505, closed, about the sr-only label), and close button 44 (62 hits, none about the Dialog close). #29078 covers sheet.tsx only.

Links back: #29040, #29070, #29078.


Generated by Claude Code

Activity

  1. added
    bugSomething isn't working
    pm:queueReady for the PM dispatch loop
    domain:uiDomain lane — seat card indexed by label:pm:seat
    on Nov 2, 2026
  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y

    Second reach · 2026-11-02T07:44Z. ⛔ Not a claim. domain:ui#1's #29075 Navigation audit at 375 px measured the command palette's Close: it is the same 16×16 px dialog.tsx X. The fix here covers it through the shared primitive. The test or the run record should name the palette as a second site, beside the declared-action param dialog.


    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 Nov 2, 2026
  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Claim: PM loop round 1 · 2026-11-02T08:10Z
    Session: session_01QsR2jQryAdPcJnhAWQzVjB (card thread, os-dev); dispatched by seat session session_01QsR2jRFuJz9QBZqPVHYVhJ
    Account: zhuangjianguo
    Branch: claude/project-thread-rh798r (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-29107
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: ui/packages/components/src/ui/dialog.tsx (its Close button only), its test file(s), and a root .changeset; not sheet.tsx (#29078) nor the files #29070, #29071, #29072, #29075 and #29076 hold (stop on breach; explain in the report)
    Container & model: S, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: default
    Clause-②: no
    Metadata-protocol: none
    Responsibility: the shared Dialog close X is a 16x16 px tap target at phone width, under the 44 px minimum #29040 sets | every modal a phone user opens in the mobile app's WebView, including the command palette | every user of the mobile app
    Thread-read: none
    Premise: holds (at origin/main a4015ab4, dialog.tsx DialogPrimitive.Close is absolute right-4 top-4 rounded-sm around <X className="h-4 w-4" />, no padding or minimum size; no open PR touches it)
    Serial constraints cleared: #29072, #29075, #29070 and #29071 reserve dialog.tsx for this card; #29078 holds sheet.tsx only (amendment 6571555427), so this card builds beside it and matches its phone-only token form

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Claim amended · 2026-11-02T08:11Z · before any code, on the os-dev's pre-claim reading. This adds to claim 6572252694 on this card; branch, session, size, Clause-② and Metadata-protocol are unchanged.

    • Why: dialog.tsx is a Shadcn-synced file. ui/AGENTS.md commandment Remove explicit pnpm version from workflows to fix version conflict #7 forbids editing its styles by hand, and a bare edit is silently reverted by the next pnpm shadcn:update. The repo's mechanism for a needed change to a synced primitive is a declared patch in ui/scripts/shadcn-local-patches.mjs (LOCAL_PATCHES.dialog already carries the CloseSrLabel family, anchored on the vendored registry fixture).
    • File surface (added): ui/scripts/shadcn-local-patches.mjs (one new anchored entry for the dialog Close className only) and its offline test ui/scripts/__tests__/shadcn-local-patches.test.ts. The shipped dialog.tsx edit and the declared patch must agree; the test proves the marker and anchor.
    • Classes: the phone-only form Console at phone width: Dashboards flow audit and fixes at 375 and 390 px #29078's branch uses for the Sheet Close (max-sm: size 11, centred), so both primitives agree.
    • Shared file: Console at phone width: Dashboards flow audit and fixes at 375 and 390 px #29078 (domain:ui#1) may add a matching sheet entry to the same file; entries are text-adjacent, ordinary concurrency, the later lander merges main.
  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jQryAdPcJnhAWQzVjB
    os-dev-report

    {
      "issue": 29107,
      "status": "done",
      "branch": "claude/project-thread-rh798r",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29204",
      "head": "d0c0addd",
      "session": "session_01QsR2jQryAdPcJnhAWQzVjB",
      "premise_still_valid": true,
      "summary": "Below sm the DialogContent Close is now a 44x44 px box with the 16 px glyph centred, using #29078's class set (max-sm:right-1 max-sm:top-1 max-sm:flex max-sm:size-11 max-sm:items-center max-sm:justify-center); from sm up its class list is upstream's, unchanged. Per claim amendment 6572263305 the change is declared as phoneCloseTouchTargetPatches('Dialog') in ui/scripts/shadcn-local-patches.mjs and the shipped dialog.tsx line was produced by applying it, so REGISTRY_FIXTURES.dialog keeps roundTrip: true. Both named sites render DialogContent's own Close: ActionParamDialog and CommandDialog.",
      "files_changed": [
        ".changeset/29107-dialog-close-phone-touch-target.md",
        "ui/packages/components/src/ui/dialog.tsx",
        "ui/packages/components/src/__tests__/dialog-close-touch-target-29107.test.tsx",
        "ui/scripts/shadcn-local-patches.mjs",
        "ui/scripts/__tests__/shadcn-local-patches.test.ts"
      ],
      "line_budget": "5 files, 224 insertions and 4 deletions vs origin/main; no skills/** and no governed surface",
      "tests": "At 20e48bf1, locked: vitest on shadcn-local-patches.test.ts + dialog-close-touch-target-29107.test.tsx + sheet-dialog-close-i18n.test.tsx: 3 files, 66 tests passed; re-run at d0c0addd after merging main: 66 passed. Ablation at 20e48bf1 (dialog.tsx restored to main bytes in the tree, restored from HEAD, git diff HEAD empty): 4 cases red (both new component cases, 'dialog.tsx carries its declared patches', 'dialog: byte round-trip holds'). Real browser, showcase backend + Console Vite dev server, Playwright, the dialog element's direct-child Close: before 16x16 px on the param dialog and the command palette at 375x812 and at 1280x800; after 44x44 px on both at 375x812 (glyph 16x16), 16x16 unchanged at 1280x800.",
      "gates": "dispatch-gates --commands at 20e48bf1: 36 families, all exit 0 (pnpm --dir ui exec vitest run scripts/: 169 files, 4903 passed; node scripts/check-sdui-manifest.mjs exit 0); --ran reconciliation: 36 derived, 36 run, 0 NOT-MEASURED. @object-ui/components type-check (tsc + tsconfig.test.json) exit 0; eslint on the 4 touched source files exit 0; ui check:new-line-citations 0 new. PR-body gates on the stored body: check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity, check-empty-changeset, check-partof-closing-keyword all exit 0. PR check-runs: in_progress at report time (head d0c0addd).",
      "dogfood_battery": "n/a: no ! in the PR title and Clause-② carries no (narrowing) arm",
      "deviations": [
        "Glyph moves 2 px on phones (17 px to 19 px from the dialog's top-right edge) because the seat ordered #29078's class set; the brief's 'icon does not move' would need max-sm:right-0.5 max-sm:top-0.5 instead. Named in the PR's Acceptance notes.",
        "Measurement used the Console Vite dev server (src) after a full workspace build; the first after-run read a stale Vite transform, so the server was restarted with --force and re-measured. Screenshots, JSON and the script: /mnt/project-files/issue-29107/ (before-*, after-*, measure.cjs).",
        "PR body opens with the harness attribution comment line, then Fixes #29107; kept as written."
      ],
      "mcp_calls": "5 reads: issue_read get x1, issue_read get_comments x3, list_pull_requests x1; no MCP writes",
      "api_writes": "2: relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, draft, no labels, no assignees), this report comment via post-stamped",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: #29078 (domain:ui#1) · REGISTRY_FIXTURES.sheet is roundTrip: true, so #29078's bare sheet.tsx Close edit (claude/project-thread-g98ica at 0ff4d360) should red 'sheet: byte round-trip holds' in Test UI unless declared via phoneCloseTouchTargetPatches('Sheet'); sent to the seat thread 08:13Z",
        "carrier: seat · packages/components/shadcn-components.json dialog localEdits note still describes only the close-label edit; outside this card's file surface, read by nothing as a gate"
      ]
    }
  7. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Claim amended · 2026-11-02T09:19Z · on the os-dev's report 6573466402 (finding: the dialog localEdits note). This adds to claim 6572252694 and amendment 6572263305; branch, session, size, Clause-② and Metadata-protocol are unchanged.

  8. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y

    Third reach · 2026-11-02T09:39Z. ⛔ Not a claim. #29072's Forms audit (PR #29209, report 6573778870) measured the record picker's DialogContent close button at 16×16 px, at both 375 and 390 px. It is the same dialog.tsx X, so the fix here covers it.


    Generated by Claude Code

  9. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Claim amended · 2026-11-02T09:42Z · on CI at PR #29204 head cc550d3e. This adds one file to the surface of claim 6572252694 (as amended by 6572263305 and 6573487904); branch, session, size, Clause-② and Metadata-protocol are unchanged.

    • Measured: Test UI (10/16) reds packages/components/src/__tests__/snapshot-critical.test.tsx > Dialog snapshots > renders open dialog structure; the only mismatch is the Close button's class list, which gains exactly the six max-sm: classes this card adds (job 125197340213). The derived gate sweep did not include this snapshot file.
    • File surface (added): ui/packages/components/src/__tests__/__snapshots__/snapshot-critical.test.tsx.snap, regenerated with vitest -u on that one test file. The regenerated diff must be only those six classes on the Dialog Close line; anything more stops the round and gets reported.
  10. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#2 · zhuangjianguo · session_01QsR2jRFuJz9QBZqPVHYVhJ

    Landed · 2026-11-02T11:37Z · PR #29204 merged through the queue as 276ca307; the merge commit carries all 7 files of the accepted head 9878ef61 (the declared phoneCloseTouchTargetPatches('Dialog') local patch and the shipped dialog.tsx line, its tests, the regenerated Dialog snapshot, the localEdits note, the changeset), beside #29149's Sheet patch. Delivered in full: nothing remains on this card; pm:dispatched removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:uiDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions