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.

plugin-view: the create/edit record Drawer is opened with direction right but DrawerContent is styled as a bottom sheet, so on desktop it renders as a half-width panel at the bottom left #11775

Closed

Description

@objectstack-fleet

Filing gate ① — product defect with a named location and a reproduction. reach: Studio → Data → Records → Add record on any object renders the create form as a 672×526 bottom sheet anchored at the bottom-left of a 1440×900 window.

Who acts on it: objectui triage → the Studio / app-shell owner. ⛔ Not a claim. Found in a manual browser QA pass of Studio on 2026-10-07; filed one card per finding on the maintainer's word: 「你发现的问题全部提交 issue」, and on the one-card-per-finding question 「覆盖规则,逐条立卡」.

What happens

The create-record form opens as a bottom sheet with a drag handle, clamped to the left half of the screen; the right half of the bottom area is an unshaded block. Measured geometry of the [role=dialog]: x=0, y=374, width=672, height=526, with data-vaul-drawer-direction="right".

Where it comes from (read in source)

renderDrawerForm in plugin-view/src/ObjectView.tsx opens <Drawer … direction="right"> and passes className="w-full sm:max-w-2xl" to DrawerContent. DrawerContent in components/src/ui/drawer.tsx hard-codes the bottom-sheet classes ("fixed inset-x-0 bottom-0 z-50 mt-24 … rounded-t-[10px]"), so the direction is ignored and sm:max-w-2xl pins it to the left.

Expected

A right-hand drawer: full height, anchored to the right edge.

Suggested direction (triage to rule)

Let DrawerContent choose its classes from the drawer direction (right → inset-y-0 right-0 h-full, no top rounding), or render the form in a Sheet/Dialog on desktop. Any other direction caller gets the same fix.

Environment

objectstack 879bd38c · examples/app-showcase booted with objectstack dev --ui --seed-admin on an isolated port and SQLite file · objectui 179f6fe9 (HEAD; the framework pin .objectui-sha is a58626c8) served by the console's Vite dev server, perf numbers from a vite build of the same commit · Chromium 141 at 1440×900 · signed in as the seeded platform admin admin@objectos.ai unless stated.

Duplicate check

Dedupe words: drawer direction right rendered bottom sheet · DrawerContent inset-x-0 bottom-0 · create record form half width

Filed by Claude Code (session session_01D76mrPJrSSdaKRxR2rvrMG) from that QA pass.


Generated by Claude Code

Activity

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

    @objectstack-fleet
    ContributorAuthor

    Path: ② the capabilities an end user meets in the app — creating and editing a record | 缺项 | P2

    Triage: first grade, bug · priority:p2 (re-graded from the filed p1) · domain:ui · area:records · pm:queue. Direction: DrawerContent takes its classes from the drawer direction

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-07T16:00Z. ⛔ Not a claim, ⛔ not a dispatch.

    Triage: lands in plugin-view's record Drawer and the shared DrawerContent styles ⇒ domain:ui; rationale: a Studio or console surface in objectui. Filed from the Studio browser QA pass of 2026-10-07 (objectstack 879bd38c, objectui 179f6fe9).

    • Why p2, not p1: the create and edit form renders as a left-pinned bottom sheet on desktop, but it is usable and saves correctly. It runs, but looks wrong.
    • Direction:
      • DrawerContent chooses its classes from the direction: right → inset-y-0 right-0 h-full, with no top rounding
      • or the form renders in a right-hand sheet primitive; the claimant picks the one that keeps mobile's bottom sheet
    • Pins: desktop renders a full-height right drawer; mobile keeps the bottom sheet (control).
    • Clause-②: no. Patch changeset in objectui.
  3. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3
    Session: session_01CGZy1BGCjdN5cXqL9cnvB8
    Account: os-support-ai
    Branch: claude/issue-11775-record-drawer-direction
    Worktree: objectui-issue-11775
    Domain: domain:ui
    Seat: domain:ui#3
    File surface: packages/plugin-view/src/ObjectView.tsx (renderDrawerForm at :2673, the <Drawer … direction="right"> at :2674, on 9990f9e); one of the two sanctioned routes for the primitive, chosen by the dev and named in the PR body: a wrapper under packages/components/src/custom/ (with its index.ts export), or an entry in scripts/shadcn-local-patches.mjs plus the file that script regenerates; the tests beside them; .changeset/11775-*.md. ⛔ No hand edit to packages/components/src/ui/drawer.tsx (objectui AGENTS.md #7, No-Touch zones). Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus (dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate; default tier)
    Clause-②: no
    Responsibility: objectui plugin-view + components: renderDrawerForm opens a right-direction Drawer, but DrawerContent hard-codes bottom-sheet classes, so on desktop the form is a 672×526 sheet pinned bottom-left | the platform path: vaul honours direction and stamps data-vaul-drawer-direction; only the styling ignores it | every user who creates or edits a record through a drawer-layout object view, including Studio → Data → Records → Add record
    Thread-read: 6041701641
    Serial constraints cleared: none blocking. No other area:records card is in flight. objectui#11777 (pm:queue, area:records, the form's group headings) touches the form renderer, not ObjectView.tsx or the drawer, so the surfaces are disjoint and nothing is folded. No open objectui PR touches the files above (read 2026-10-07T16:26Z; open: #11600, #11069). ObjectView.tsx:2674 is the only <Drawer direction=…> caller in packages/ and apps/ at 9990f9e.

    Why Clause-②: no: a styling fix. A new exported wrapper component would widen @object-ui/components' public surface. If the dev takes that route, it is reported before the PR opens, and the seat amends this line.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 11775,
    "status": "blocked",
    "branch": "claude/issue-11775-record-drawer-direction",
    "pr": null,
    "session": "session_01CGZy1BGCjdN5cXqL9cnvB8",
    "premise_still_valid": true,
    "summary": "Implemented and pushed (branch head fa16463): renderDrawerForm in plugin-view ObjectView now opens the record form in the right-hand Sheet (side="right", w-full sm:max-w-2xl) on a desktop and in vaul's bottom sheet, in vaul's default bottom direction and with no width cap, on a phone (useIsMobile, 768px). This is triage direction 2: no wrapper, no local patch, no file under packages/components changes, so ui/drawer.tsx is untouched and Clause-② stays no. Measured in Chromium: desktop 1440x900 went from x=0 y=600 672x300 (vaul right, base markup) to x=768 y=0 672x900 (Sheet). BLOCKED on one PM-only step: the draft PR was never created. The fleet-write dispatch (request fw-20261007T165414Z-0f301c, HTTP 204) returned UNCONFIRMED (exit 6), and its run, most likely objectstack Actions run 37655514198, has sat queued with 0 jobs for more than 30 minutes alongside three other runs from the same three-minute window, while every relay run dispatched since then has completed. Per the rest-channel rule I did not retry. The PM needs to cancel or confirm that run, then open the PR from the prepared actions file (11775-actions-pr.json in the issue-11775 scratchpad directory; body in 11775-pr-body.md beside it), then set the PR assignee to os-support-ai.",
    "tests": "All on fa16463 (git rev-parse --short HEAD), run from the worktree root under os-verify-lock. (1) pnpm exec vitest run --maxWorkers=2 packages/plugin-view/ → exit 0, "Test Files 67 passed (67)", "Tests 623 passed (623)". (2) New pin ObjectView.drawerDirection-11775.test.tsx, verbose → 7 passed: THE FIX desktop create, edit and view (dialog not vaul; has inset-y-0 right-0 h-full; none of inset-x-0 bottom-0 rounded-t-[10px]; w-full sm:max-w-2xl, not sm:max-w-sm); CONTROL phone create, edit and view (vaul, data-vaul-drawer-direction=bottom, bottom classes, no sm:max-w-2xl); CONTROL stock DrawerContent still the bottom sheet. (3) Ablation, fix committed first: node objectstack/scripts/ablation-replace.mjs swapped renderDrawerForm back to the base markup (anchor 1 → 0, blob 46fbd4ed441f → b4542c644a0b) and ran the 3 files → "Tests 6 failed | 21 passed (27)". The 6 were 3x "the desktop form is still on vaul's drawer, whose content is styled as a bottom sheet" and 3x "expected 'right' to be 'bottom'". Restored: blob == HEAD 46fbd4ed441f, git diff HEAD empty. With the fix the same 3 files gave "Tests 27 passed (27)". (4) Real browser, Chromium /opt/pw-browsers/chromium, through a throwaway console Vite entry mounting ObjectView with layout drawer (uncommitted, removed; my dev server on :5196 started and stopped by PID). Base markup was read through the same ablation tool and restored. Base → fix: 1440x900 x0 y600 672x300 vaul right → x768 y0 672x900 Sheet; 390x844 x0 y496 390x348 vaul right → same box, vaul bottom; 700x900 x0 y600 672x300 vaul right → x0 y600 700x300 vaul bottom. (5) pnpm --filter @object-ui/plugin-view type-check → exit 0 (script echoed as type-check: "tsc --noEmit && tsc -p tsconfig.test.json"), after turbo run build --filter=@object-ui/plugin-view^... --concurrency=2 → exit 0, 15 tasks, 13 from cache. tsc --listFiles on tsconfig.test.json lists all 3 touched test files.",
    "mcp_calls": "0",
    "api_writes": "2 — (1) the relay dispatch POST /repos/objectstack-ai/objectstack/dispatches carrying one pr_create for objectstack-ai/objectui (executor target POST /repos/objectstack-ai/objectui/pulls). UNCONFIRMED: its run never started and no PR exists. (2) This os-dev-report comment, POST /repos//issues/11775/comments through the relay. git push is not counted. No label-write: there is no PR number to assign.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: 承接者:无 · noted in the PR body's Acceptance notes, not filed. The bar for filing is not met (class would be b): the reading was in-process only, through the real SchemaRenderer and registry in the dom project via an uncommitted probe, and no producer in the tree authors direction or side on a drawer node (examples/schema-catalog basic-drawer.json authors neither). Evidence: the SDUI drawer node with direction right stamps data-vaul-drawer-direction=right but keeps the classes fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background. With no direction it stamps bottom, while the DrawerSchema.direction JSDoc says @default right. With side right, the member content/docs/components/overlay/drawer.mdx shows and DrawerSchema does not declare, it stamps bottom. Seam: types:DrawerSchema.direction (objectui authoring face; the renderer notes the installed spec has no drawer row) → renderer:packages/components/src/renderers/overlay/drawer.tsx prop spread onto vaul Root → ui:DrawerContent. Dedupe words: drawer node direction ignored bottom sheet · DrawerSchema direction default right · drawer docs side member",
    "carrier: 承接者:无 · noted, not filed. Read-only inference, not measured: ObjectView formWidthClass builds a max-w-[N...] class at runtime. Tailwind generates only classes it finds in source, so an authored navigation.width on the drawer or modal probably draws nothing. The desktop behaviour is the same before and after this PR. NavigationOverlay carries its width through a CSS custom property instead. Dedupe words: navigation width dynamic tailwind class ignored",
    "carrier: 承接者:无 · noted, not filed. Not measured: the phone bottom sheet keeps upstream h-auto with no max height, and a form taller than the viewport was not read. This PR does not change it."
    ],
    "gates": [
    {
    "command": "pnpm exec vitest run --maxWorkers=2 packages/plugin-view/",
    "exit": 0,
    "verdict": "Test Files 67 passed (67) · Tests 623 passed (623)"
    },
    {
    "command": "pnpm --filter @object-ui/plugin-view type-check",
    "exit": 0,
    "verdict": "tsc --noEmit && tsc -p tsconfig.test.json printed nothing; lock VERDICT command-exit 0"
    },
    {
    "command": "pnpm exec eslint (4 touched ts/tsx files) --format json",
    "exit": 0,
    "verdict": "4 files, 0 errors; warnings identical to base per file (61, 2, 0; new file 0)"
    },
    {
    "command": "pnpm check:control-bytes",
    "exit": 0,
    "verdict": "check-control-bytes: OK (scanned 7780 tracked text file(s); skipped 85 binary)"
    },
    {
    "command": "pnpm check:test-path-roots",
    "exit": 0,
    "verdict": "check-test-path-roots: OK"
    },
    {
    "command": "pnpm check:changeset-claims",
    "exit": 0,
    "verdict": "No pending changeset names a file this change touches."
    },
    {
    "command": "pnpm check:pending-changeset-literals",
    "exit": 0,
    "verdict": "No test source names a pending changeset."
    },
    {
    "command": "pnpm check:new-line-citations",
    "exit": 0,
    "verdict": "VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0"
    },
    {
    "command": "node scripts/check-changeset-presence.mjs",
    "exit": 0,
    "verdict": "4 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)"
    },
    {
    "command": "node scripts/check-changeset-no-major.mjs",
    "exit": 0,
    "verdict": "No changeset declares a major bump."
    },
    {
    "command": "i18n gates, check:readme-exports",
    "exit": null,
    "verdict": "not owed: no locale pack and no package export changed (the diff adds or removes no export line; positive control: 8 export lines in ObjectView.tsx)"
    }
    ],
    "deviations": [
    "Route: triage direction 2, the right-hand Sheet, chosen over a direction-aware DrawerContent; reasons on the four axes are in the PR body. The claim lists one primitive route (a custom/ wrapper or a local-patch entry); neither was used, and packages/components has no diff.",
    "The phone half changed too, deliberately: vaul direction right became vaul default bottom, so the slide and the drag now match the drawn sheet. The phone bottom sheet also takes no width classes (sm:max-w-2xl and the navigation.width class), because between 640 and 767px they pinned it left (measured at 700px: 672 → 700 wide).",
    "Two existing pins were edited, the drawer-locating helper only, within the tests-beside-them surface: ObjectView.pageSurfaceFallback-11015.test.tsx and ObjectView.splitPopoverCreate-10975.test.tsx. Both stay green under the ablation, as expected for surface-choice pins.",
    "PR not opened: the fleet-write dispatch is UNCONFIRMED and was not retried (rest-channel: UNCONFIRMED 6, read only, never retry). GitHub refuses a second open PR for the same head and base with a 422 (known platform behaviour, not measured here), so a PM re-dispatch cannot produce two PRs.",
    "Commit trailers follow objectui AGENTS.md: the model-free pair Claude-Session plus Co-authored-by: Claude. The harness offered a model-named Co-Authored-By line, which AGENTS.md says yields.",
    "Throwaway artefacts, all uncommitted and removed, with git status clean after removal: a components probe test (zz-probe-11775), a console Vite entry (zz-11775-drawer), and a Playwright driver under node_modules. Screenshots are in /tmp/issue-11775-*.png.",
    "Upstream registry bytes were read into the scratchpad only: shadcn-ui/ui apps/v4/public/r/styles/default/drawer.json and the new-york-v4 drawer.tsx via raw.githubusercontent.com. ui.shadcn.com answered a proxy 403."
    ],
    "files_changed": [
    "packages/plugin-view/src/ObjectView.tsx",
    "packages/plugin-view/src/tests/ObjectView.drawerDirection-11775.test.tsx",
    "packages/plugin-view/src/tests/ObjectView.pageSurfaceFallback-11015.test.tsx",
    "packages/plugin-view/src/tests/ObjectView.splitPopoverCreate-10975.test.tsx",
    ".changeset/11775-record-drawer-direction.md"
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — domain:ui seat 3, session_01CGZy1BGCjdN5cXqL9cnvB8, 2026-10-07T18:13Z. PR objectui#11821, head 6f6daa6.

    • PR shape: draft against main (9990f9e). First line Fixes #11775, no other closing keyword. Clause-②: no at line start.

    • The PR was opened by the seat. The dev's own pr_create relay dispatch (fw-20261007T165414Z-0f301c) came back UNCONFIRMED: its run, 37655514198, sat queued with 0 jobs. The dev did not retry. The seat read that no PR existed for the head, re-dispatched the dev's prepared action unchanged, and it read back as objectui#11821. GitHub refuses a second open PR for the same head and base, so a late run of the stuck dispatch cannot open a duplicate.

    • Scope: 5 files, +271/−18, all in @object-ui/plugin-view plus the changeset:

      • ObjectView.tsx;
      • a new pin file ObjectView.drawerDirection-11775.test.tsx;
      • a locator-helper change in two existing pins (…pageSurfaceFallback-11015…, …splitPopoverCreate-10975…), whose assertions are unchanged;
      • the changeset.

      Nothing under packages/components changes, and ui/drawer.tsx is untouched (objectui AGENTS.md 构建一个 **Live Playground (实时演练场)** (用于展示引擎能力) #7). No new export, prop, type member or key. No governed path.

    • Route: triage's second direction, the right-hand Sheet. The claim listed two routes for changing the primitive (a custom/ wrapper or a local patch). This PR needs neither, because it changes no primitive, so its surface is narrower than the claim's.

    • Diff read (the seat's own): renderDrawerForm branches on the existing isMobile (useIsMobile, ObjectView.tsx:1580 on main).

      • Desktop: Sheet side="right" keeps w-full sm:max-w-2xl plus formWidthClass. The header has pr-12, so the title clears the Sheet's close button.
      • Phone: vaul's Drawer in its default bottom direction, with no width classes.

      The phone change is deliberate and named in the PR body: the slide and drag now match the sheet as drawn, and 640–767px is no longer pinned left.

    • Ruling honoured (triage 6041701641): desktop renders a full-height right panel, and mobile keeps the bottom sheet (control).

    • One seat fix round (prose): the first head's changeset said the drawer opens right "again", which no reading supports. 6f6daa6 drops it. The dev also corrected a second sentence it could not support. The Sheet is now "the panel the console's record drawer (NavigationOverlay in drawer mode) already opens a record in", which the seat confirmed: NavigationOverlay renders drawer mode as a SheetContent. The diff fa16463..6f6daa6 is that changeset file only.

    • Changeset sentences checked against the head:

      • "opens as a right-hand panel on a desktop, and stays a bottom sheet on a phone";
      • the vaul direction paragraph (direction="right" on every viewport at main);
      • "keeps the width it had";
      • "DrawerContent itself is unchanged".

      patch on @object-ui/plugin-view.

    • Reverse verification (dev report 6043168067):

      • Ablation through ablation-replace.mjs, restored with the blob equal to HEAD: 6 red, the three desktop THE FIX rows and the three phone direction controls. With the fix: 27/27. packages/plugin-view full run: 623 passed.
      • Real-browser reading in Chromium at 1440×900: x=0 y=600 672×300 (vaul right) became x=768 y=0 672×900 (Sheet). 390×844 and 700×900 were read too.
    • Gates: CI on 6f6daa6 (head_sha equals the PR head): 43 runs, 40 success, 3 skipped (Test (coverage), its shard template, dependabot), 0 failure. Lint and Type Check are success. Mergeable state clean.

    • Contract review: not required (Clause-②: no; the diff adds and removes no export line).

    Findings:

    • The SDUI drawer node meets the same primitive. An authored direction: 'right' stamps data-vaul-drawer-direction="right" but draws a bottom sheet, and DrawerSchema.direction's @default 'right' disagrees with the stamped bottom. This was measured in-process only, and no producer in the tree authors direction or side on a drawer node, so the filing gate's reach is not met → Acceptance notes
    • navigation.width on this drawer probably draws nothing, because the class is built at runtime and Tailwind never sees it. Not measured, and unchanged by this PR → Acceptance notes
    • Tall forms in the phone bottom sheet: not measured, and unchanged → Acceptance notes

    Landing: ready + auto-merge through the queue, now.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed — domain:ui seat 3, session_01CGZy1BGCjdN5cXqL9cnvB8, 2026-10-07T19:20Z. PR objectui#11821 merged through the queue as 282f252 at 2026-10-07T18:31Z.

    • The merge:
      • One parent, e06365c (objectui#11777's landing), an ancestor of origin/main.
      • The landed tree equals git merge-tree of that parent and the accepted head 6f6daa6 (tree 80c2303e on both).
      • 5 files, +271/−18.
    • Content check, 9990f9e → 282f252, in plugin-view/src/ObjectView.tsx:
      • SheetContent: 0 → 3.
      • The only remaining direction="right" is the docblock line :2682 that explains the old behaviour. The drawer at :2700 opens with no direction.
      • Control: renderDrawerForm is 3 on both sides, so the record surfaces that route to it are unchanged.
      • The changeset's corrected first sentence is on main.
    • Closures: the PR's only closing keyword was Fixes #11775. Since 18:25Z, the issues closed are objectui#11777 (seat 1's own PR), objectui#11775 and objectui#11772. None of them was closed by a stray keyword. 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: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