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.

Studio New object dialog: "Object name" and "Identifier" labels are not bound to their inputs (screen readers hear two unlabeled fields) #13128

Closed

Description

@objectstack-fleet

Filing gate: ① a user-visible UX defect with a named landing point and a reproduction (pm:queue class).
Reader: the objectui lane owning packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx — the fix PR there.
Dedupe (open AND closed, semantic search on objectstack-ai/objectui): "Studio new object dialog label not associated with input htmlFor accessibility" → 16 hits (top: #12680, #12510, #12718, #12691, #11847 — all closed; #12510 covered other unnamed Studio controls, not this dialog); none covers this item.

reach: measured in the console UX walkthrough — stock showcase with --seed-admin, framework objectstack-ai/objectstack@54159fd742e5, console pin objectui@12dc7b47c340 (dist stamp equal to the pin), Chromium at 1440x900; re-checked against objectui main source at df943a2 when found and ed28057 when split (the cited files are unchanged between the two).
type: Bug

Split out of #13115 (item 7), which folded fifteen independent defects into one card under the per-fire filing quota, which the maintainer has since ruled does not bind a concentrated test run such as a walkthrough. Split by the 18.0 QA wave dispatch session session_01CfRDy7SuTfUqaTu2AEH2Hi, on the maintainer's instruction there, verbatim: 「#13115 你可以拆」.

Where

Studio → New object.

Actual

"Object name" and "Identifier" are label elements with no htmlFor, and the inputs carry no id or aria-label, so a screen reader announces two unlabeled edit fields (Playwright getByLabel('Object name') finds nothing).

Expected

Each label bound to its input.

Source

packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx — the create-object dialog (next to the create-object-owd select).


Generated by Claude Code

Activity

  1. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    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
  2. 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-13128-new-object-labels
    Worktree: objectui-issue-13128
    Domain: domain:ui
    Seat: domain:ui#2
    File surface:

    • packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx, the create-object dialog (beside create-object-owd): "Object name" and "Identifier" labels are bound to their inputs (htmlFor + id, ids unique per mount), and the dialog's other unlabelled controls likewise if any.
    • Tests beside it.
    • One .changeset/13128-new-object-labels.md (@object-ui/app-shell patch).

    ⛔ No new package export, no copy change. 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 (markup inside an internal Studio dialog; no export, prop or key moves)
    Responsibility: the create-object dialog's labels carry no htmlFor and its inputs no id | the Studio's other dialogs already bind labels (objectui#12510) | every screen-reader user creating an object in Studio (two unlabeled edit fields)
    Thread-read: none
    Serial constraints cleared: no in-flight objectui card or open PR touches StudioDesignSurface.tsx (read at 06:35Z).
    Claimed at: 2026-10-20T06:34Z


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 13128,
    "status": "blocked",
    "branch": "claude/issue-13128-new-object-labels",
    "pr": null,
    "session": "session_01XVp19E1MYUTFM3dnkwz8gB",
    "premise_still_valid": true,
    "summary": "Defect confirmed on objectui origin/main d05f33b, but its landing point is NOT the claimed file. The New object dialog is the shared component packages/app-shell/src/views/studio-design/CreateItemDialog.tsx (StudioDesignSurface.tsx line 6815 only renders it and passes labelFieldLabel/idFieldLabel strings); the two unbound Label + Input pairs are at CreateItemDialog.tsx (Label with no htmlFor, Input with no id; the components Label is a bare Radix label root, so nothing associates them). Any fix must edit CreateItemDialog.tsx, which is outside the claim's file surface (StudioDesignSurface.tsx + tests beside it + one changeset), and the order says 'Anything else: stop and report' - so I stopped before the first edit. Second consequence for the ruling: CreateItemDialog is shared by five call sites in StudioDesignSurface.tsx (lines 2234, 4993, 6815, 8203, 8833: package / app / object / flow / permission create dialogs), so the htmlFor+id fix binds the labels in all five, not only New object. Ready-to-land shape once the surface is amended: two React.useId() ids in CreateItemDialog, Label htmlFor + Input id for both pairs, no visual or copy change, no new export; pin in a new CreateItemDialog.labels-13128.test.tsx (getByLabelText for 'Object name' and 'Identifier' through the real StudioDesignSurface New object path), ablation by dropping one htmlFor; changeset @object-ui/app-shell patch. The New object dialog's OWD picker is already named by its wrapping label element (no change needed there). Branch pushed empty at d05f33b as the write-route probe; worktree removed, no uncommitted work.",
    "tests": "NOT MEASURED: no edit made (stopped on file-surface breach before the first edit). Premise evidence is source reading at origin/main d05f33b: CreateItemDialog.tsx renders Label {labelFieldLabel} and Label {idFieldLabel} with no htmlFor and both Input elements with no id/aria-label; packages/components/src/ui/label.tsx is a plain LabelPrimitive.Root forwarder.",
    "mcp_calls": "0",
    "api_writes": "1 - POST issues/13128/comments (this os-dev-report, via post-stamped relay); plus 1 git push of the empty branch (not REST)",
    "open_questions": [
    {
    "question": "Amend the claim's file surface to packages/app-shell/src/views/studio-design/CreateItemDialog.tsx (plus a test beside it), accepting that the fix also binds labels in the other four Studio create dialogs that share the component?",
    "options": [
    "A - amend the surface to CreateItemDialog.tsx + test + changeset; the fix lands in the shared component and covers all five create dialogs (one owner of the markup, no per-caller ids)",
    "B - keep StudioDesignSurface.tsx only: impossible without also editing CreateItemDialog.tsx (the Input elements are not reachable from the caller), so B is not a real option",
    "C - add id props to CreateItemDialog threaded from each caller: still edits CreateItemDialog.tsx and widens its props for no gain"
    ],
    "recommendation": "A, because the markup lives in one shared component, useId per mount satisfies the ruling's uniqueness, there is no visual/copy/export change, and the four sibling dialogs carry the same defect today; re-dispatch with Resume-from: claude/issue-13128-new-object-labels@d05f33b2ef"
    }
    ],
    "out_of_scope_findings": []
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat ruling on the dev's open question (os-dev report 6284996245) · domain:ui seat 2 (session_01XVp19E1MYUTFM3dnkwz8gB)

    A. Claim amended. The defect lives in the shared packages/app-shell/src/views/studio-design/CreateItemDialog.tsx. StudioDesignSurface.tsx only renders it and passes in the labels. The file surface becomes:

    • CreateItemDialog.tsx: two React.useId() ids, with htmlFor and id on both label/input pairs. No visual, copy or export change.
    • A test beside it.
    • One @object-ui/app-shell patch changeset.

    StudioDesignSurface.tsx comes off the surface unless the test needs it.

    The fix binds the labels in all five Studio create dialogs that share the component (package, app, object, flow, permission set). They have the same defect today, and the changeset names them. The OWD picker is already named by its wrapping label and stays as it is.

    Pin: getByLabelText for "Object name" and "Identifier" through the real New object path, plus one sibling dialog, to show the shared fix. Ablation: drop one htmlFor.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 13128,
    "status": "done",
    "branch": "claude/issue-13128-new-object-labels",
    "pr": "#13176",
    "session": "session_01XVp19E1MYUTFM3dnkwz8gB",
    "premise_still_valid": true,
    "summary": "Following the seat ruling A (comment 6285011413), I resumed from claude/issue-13128-new-object-labels@d05f33b2ef. CreateItemDialog.tsx now has two React.useId() ids, with Label htmlFor and Input id on both the display-name pair and the identifier pair; nothing changes visually, in copy or in exports. The new pin, CreateItemDialog.labels-13128.test.tsx, uses getByLabelText through the real New object path (the DataPillar empty state) and through the sibling Create app dialog (the StudioDesignSurface toolbar). The changeset is an @object-ui/app-shell patch. It names the five dialogs correctly: Create app, the Interfaces create dialog (report, page or dashboard), New object, New automation and New permission set. My first report said package and flow instead; that was wrong, and the ruling repeated it. No package dialog uses CreateItemDialog, and the automation dialog is titled New automation. I corrected this in commit af6b19e. Draft PR #13176 has assignee baozhoutao, Fixes #13128 on line 1 and Clause-②: no on line 2.",
    "tests": "All at HEAD af6b19e (code identical to 1efc5df; af6b only edits the changeset). (1) Closure build: pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build, under the lock, VERDICT command-exit 0. (2) pnpm --filter @object-ui/app-shell type-check: VERDICT command-exit 0. It runs tsc -p tsconfig.test.json, which includes src/**/*.test.tsx, so the new test is type-checked. (3) Targeted vitest with --maxWorkers=1 over the new pin plus the six files that render CreateItemDialog (oneLabel-11787, storedName-11792, createAppAccessibleName, createObjectOwd, flowPresets-11861, newFlowTrigger-11788): 'Test Files 7 passed (7) / Tests 34 passed (34)', VERDICT command-exit 0. The full packages/app-shell/ directory is declared to CI and was not run, per the order's lock clause. (4) Lint narrowed to the 2 changed .tsx files: eslint --no-inline-config --format json counted 2 files, 0 errors and 6 warnings. Five are no-explicit-any in the test's mocks, the same shape as its sibling suites. One is react-hooks/set-state-in-effect, which origin/main's copy of the file also reports. Both files resolve in the root eslint.config.js, and no parserOptions.project or projectService is set, so lint is not type-aware and the diff cannot change any untouched file's verdict. (5) Battery: 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 and control-bytes each exited 0. check-hand-rolled-comment-mask.mjs, check-changeset-fixed.mjs and check-changeset-presence.mjs also exited 0. check:spec-floors exited 1 with 'no-artifact: Build the workspace before running this gate', so it is NOT MEASURED: its prerequisite was not met and the gate body never ran. The control-byte self-scan of the 3 changed files had zero hits. (6) Ablation at 1efc5df with objectstack scripts/ablation-replace.mjs: the 'Label htmlFor={labelInputId}' anchor was replaced by a bare 'Label'. The anchor count went from 1 to 0 and the blob from 8e7320e102f7 to a9b1abd818f1. The pin then showed 'Tests 2 failed (2)'; both legs went red because both dialogs share the component ('Found a label with the text of: Object name, however no form control was found associated to that label'). After restore, the blob was 8e7320e102f7755e87fa8797cfb98bb39266d267, equal to the HEAD blob, git hash-object agrees and git status is clean. No build or dist was involved, because the test imports source relatively.",
    "mcp_calls": "0",
    "api_writes": "3 - through the fleet-write relay: POST issues/13128/comments (first os-dev-report, blocked, comment 6284996245); pr_create objectui#13176 (draft, assignee baozhoutao; read-back of 3973 bytes identical); POST issues/13128/comments (this os-dev-report). Plus git pushes of the branch, which are not REST. Labels: zero writes, because objectui is under the no-named-labels rule.",
    "open_questions": [],
    "out_of_scope_findings": []
    }


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #13176 @ af6b19e93535d3552452c2ed182c61eaa8b676f6 · domain:ui seat 2 (session_01XVp19E1MYUTFM3dnkwz8gB)

    • Clause-②: no. This is markup in an internal Studio dialog; no export, prop or key moves. No contract review is owed, and the seat read the report.
    • Scope under ruling 6285011413 (surface amended to the shared CreateItemDialog.tsx):
      • two React.useId() ids, with htmlFor and id on the display-name pair and the identifier pair;
      • no visual, copy or export change;
      • the fix binds the labels in the five Studio create dialogs that share the component: Create app, the Interfaces create dialog, New object, New automation and New permission set. The dev corrected the seat's ruling, which had named "package" and "flow"; the changeset names the right five.
    • Pins: getByLabelText through the real New object path and through the sibling Create app dialog. The ablation (one htmlFor dropped) turned both legs red, because the component is shared, and the restore was proven by blob. The six existing dialog suites are green.
    • 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, 147 changed lines. Seat landing.
    • Findings: none.

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


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB

    • Merged: PR fix(app-shell): bind Studio create-dialog labels to their inputs (objectui#13128) #13176 through the merge queue as main 157694c7b1.
    • Verified by content: each of the 3 files the PR changes has the same blob at 157694c7b1 as at the accepted head af6b19e935. The merge message carries no model identifier.
    • Landed: the shared CreateItemDialog binds its name and identifier labels to their inputs. That fixes the five Studio create dialogs that use it (Create app, the Interfaces create dialog, New object, New automation, New permission set), so a screen reader names both fields.

    pm:dispatched is removed.


    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:studioChanging a running app without code — authoring, publish, docs and the portalbugSomething 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