Repository navigation
fix(console): a refused form submit marks the fields it names; markdown placeholder in sans - #27443
Merged
Merged
Conversation
A refused submit on the console form page (public /f/:slug and the internal /forms/:name) now marks each field it names: aria-invalid on the control and the reason under it, for the client required check, a faulted visibleWhen (pointed at the banner that names it) and the server's field-level refusals, read with extractFieldErrors from @object-ui/react. The banner and the toast are unchanged. Claude-Session: https://claude.ai/code/session_01JQwxbX1Zhx8ST6DDF1AGvD Co-authored-by: Claude <noreply@anthropic.com>
…d=false default Claude-Session: https://claude.ai/code/session_01JQwxbX1Zhx8ST6DDF1AGvD Co-authored-by: Claude <noreply@anthropic.com>
…changeset Claude-Session: https://claude.ai/code/session_01JQwxbX1Zhx8ST6DDF1AGvD Co-authored-by: Claude <noreply@anthropic.com>
Contributor
Author
|
domain:ui#5 · os-warren · session_01JQwxbXGpVJHZTXXerMoY4C 席位核对ACCEPT · seat 席位意见:网页表单提交被拒时,以前只有一条横幅和一条提示,输入框上没有任何标记。现在每个被拒的字段都会标上
Generated by Claude Code |
This was referenced Oct 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Warren · project thread
Fixes #27417
Clause-②: no
Metadata-protocol: none
维护者速读
/f/:slug、/forms/:name、应用内表单)提交被拒时,逐个标出被拒字段(aria-invalid+ 控件下方原因);markdown/html/richtext 编辑器的占位文字改用无衬线字体,输入的源码仍是等宽。ui/apps/console/src/components/FormPage.tsx(refusedWriteError与 catch 里的extractFieldErrors)、ui/packages/fields/src/widgets/RichTextField.tsx、新测试FormPage.refusalMarks-27417.test.tsx。pnpm --dir ui exec vitest run apps/console/src/components/FormPage.refusalMarks-27417.test.tsx,预期 8 个测试全绿。What changes
@object-ui/console,FormPage.tsx). Every refusal on the form page used to end in one string on the banner and the outcome toast. Each refused row is now marked:aria-invalid="true"on its control and the reason under the control, which the control names inaria-describedby.validation.requiredmessage ("Name is required").visibleWhen: the row is marked and points at the banner, which already names the field and the rule, so no sentence is repeated under it.extractFieldErrorsfrom@object-ui/react, reads the refusal. No second parser was written.submitPublic/submitInternalused to throw a bareError(text), which lost the field paths. They now throwrefusedWriteError, which keeps the same message and attaches the parsed body the way@objectstack/clientattaches it (code, anddetails= wrappederror.details, else the flat body). That covers the flat400 VALIDATION_FAILEDwithfields[], the wrapped dispatcher envelope, and the flat409 UNIQUE_VIOLATIONnaming itsfield. Only the rows the form draws are marked.revealRefusedshared by the client and server paths (the client path's existing behaviour, moved, not changed). Editing a marked row clears its mark. The banner and the toast are unchanged.@object-ui/fields,RichTextField.tsx). The markdown / html / richtext textarea isfont-monoon every host, and its placeholder inherited that. It now carriesplaceholder:font-sans, so typed source stays mono and the placeholder reads as prose. This widened the claimed file surface; the seat approved it in its thread.@object-ui/consolepatch,@object-ui/fieldspatch.Why
HotCRM's browser pass on 18.2.0 (#27355 rows 9 and 10): a refused public-form submit showed a toast and a banner but marked no field, and the form's description placeholder was monospace.
Tests
ui/apps/console/src/components/FormPage.refusalMarks-27417.test.tsx, 8 tests. A server refusal naming A and B marks both and not the third row, on the public route (flat envelope) and the internal route (wrapped envelope). A 409 UNIQUE_VIOLATION marks its one field. An edit clears one mark and keeps the other. A 400 naming no field marks none. A field the form does not draw marks nothing. The client required refusal marks both empty required rows and writes nothing. A faultedvisibleWhenrow points at the banner.ui/packages/fields/src/widgets/__tests__/RichTextField.placeholderFont-27417.test.tsx, 3 tests (markdown, html, richtext): the control keepsfont-monoand carriesplaceholder:font-sans. jsdom computes no placeholder style, so the computed font is the Chromium reading below.scripts/ablation-replace.mjs, fix committed first): rowmarkforced toundefinedmakes 6 of 8 red. The 2 that stay green are the "marks none" pins, as predicted. Restored blob matchesHEAD.FormPage*.testplus the fields RichText, aria-invalid and dom-leak suites, 47 files and 739 tests, all passed.pnpm --filter @object-ui/console --filter @object-ui/fields run type-checkexit 0.Acceptance notes
FormPage.tsx, in itsFORM_SPEC_TYPEShunk only. That hunk is disjoint from these, and whichever lands second merges main./forms/:namerenders in the app-independent Home layout, and the anonymousGET /forms/:slugpayload isslug, object, label, form, objectSchema, with no app and no branding. The app metadata read is authenticated, so no server read was invented. It is reported to the seat as an open question with options.font-sansstack, which is a system sans stack. The console body sets its own system stack, which differs in its first families. Both are sans.Verification
Real Chromium (
/opt/pw-browsers/chromium) against the showcase backend (objectstack dev --fresh) and the console's Vite dev server. "Before" isFormPage.tsxat main and "after" is this branch./f/contact-us, empty submit: Name / Email / Messagearia-invalid/f/contact-us, server 400VALIDATION_FAILEDonemail(real server answer)--primary,/apps/showcase_app/forms/showcase_inquiry.contact#7C3AED--primary,/forms/...and/f/contact-usfont-familyThe server-refusal probe set
form.noValidatebefore submitting, because the browser's own email check would otherwise stop the submit before the server judged it. The server's answer is its real one.Derived gates at d32c6b1:
node scripts/pm/dispatch-gates.mjs --commandsderived 34 families. All 34 exit 0, includingnode scripts/check-sdui-manifest.mjsand the uiscripts/suite (169 files passed).--ranreconciliation: 34 run, 0 NOT-MEASURED.pnpm --dir ui run check:new-line-citations: 0 new citations.Generated by Claude Code