fix(form): drop AntD Form/FormItem/useForm bridge, use native React state#7
Merged
Conversation
…nstead
User direction: project doesn't need AntD compat, doesn't need AntD
structural config. The <Form>/<FormItem>/useForm shim in
shared/components/ui/ui-components.tsx was fake AntD (neither real AntD
nor real RHF) and a source of confusion — Phase 2 dead-code cleanup
exposed it via broken jest-skipped ProjectEdit/ProjectDetail tests that
depended on this shim.
Removed from ui-components.tsx:
- <Form> component (97 lines, fake AntD onFinish bridge)
- <FormItem> component + FormWithItem compound pattern
- useForm re-export (was useRhfForm as useForm)
- FormValues type
- ValidationRule/FormProps/FormItemProps interfaces
- useRhfForm import
Replaced in 4 call sites with native React:
1. pages/project-edit/ProjectEditPage.tsx
- useForm() bridge → useState for 2 fields (name, description)
- setFieldsValue/validateFields/getFieldsValue/getFieldValue all gone
- form.handleSubmit gone, validation is one if (!name.trim()) check
- The page never rendered <Form> anyway — form lib was a value holder
2. features/script/components/ScriptGenerator.tsx
- 8 useState hooks (topic/keywords/style/tone/length/audience/language/requirements)
- buildFormValues() helper for handleGenerate payload
- <Form onFinish> → native <form onSubmit>
- 8 <FormItem> → direct <label> + controlled <Input>/<Select>/<RadioGroup>
- 2 form.handleSubmit callsites → void handleGenerate()
- Submit button onClick → htmlType=submit
3. shared/components/business/CompositionStudio/GlobalSettingsForm.tsx
- Was a dead shell (Slider/InputNumber/Select had no value/onChange)
- Now functional: 4 useState (frameDuration/effect/duration/easing) +
onSave wire-up
4. shared/components/business/CompositionStudio/FrameEditForm.tsx
- Same dead-shell pattern, now 12 useState + save/reset buttons
- CameraMotion null → undefined (Select doesn't accept null value)
5. shared/components/business/CompositionStudio/index.tsx
- 3 <FormItem label=> → plain <label> (no form state needed for skeleton)
Verification: lint 0 / tsc 0 / 1596 tests pass / build OK
react-vendor bundle dropped 311 KB → 287 KB (react-hook-form no longer
pulled into vendor chunk).
Agions
added a commit
that referenced
this pull request
Jun 4, 2026
Rename src/shared/components/ui/ui-components.tsx → src/shared/components/ui/antd-compat-deprecated.tsx to reflect that this file is the AntD-compatibility shim layer (not a generic UI module) and is deprecated for new code. The AntD Form bridge was already removed in PR #7 (commit 50b185e), leaving this file as a historical artifact. The new name makes the deprecation status visible in import statements, file listings, and editor pickers. Added a prominent @deprecated JSDoc block at the top with a full migration guide mapping every re-export to its canonical shadcn/ui path. Updated the backward-compat shim at src/components/ui/ui-components.tsx to follow the new file location. All 7 existing callers continue to work through the shim (zero-risk rename, no caller touched). Verification: tsc 0 / lint 0 / 1596 tests pass / build OK.
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.
🐱 fix(form): drop AntD Form/FormItem/useForm bridge, use native React state
Why
User direction: project doesn't need AntD compat, doesn't need AntD structural config.
The
<Form>/<FormItem>/useFormshim inshared/components/ui/ui-components.tsxwas fake AntD — neither real AntD nor real RHF, just a 97-line wrapper that bridgeduseRhfFormto AntD'ssetFieldsValue/validateFields/getFieldValueAPI. The Phase 2 dead-code cleanup (#6) exposed it via brokenjest-skippedProjectEdit/ProjectDetailtests that depended on this shim.The shim had 4 call sites, and 3 of them never used the validation/form-library features at all — they only used
formas a value holder for 2-12 primitive fields with no cross-field validation. NativeuseStateis the simplest correct form library for these cases.What changed
src/shared/components/ui/ui-components.tsx(-97 lines):<Form>component (97 lines, fake AntD onFinish bridge)<FormItem>component +FormWithItemcompound patternuseFormre-export (wasuseRhfForm as useForm)FormValuestypeValidationRule/FormProps/FormItemPropsinterfacesuseRhfFormimportuseStatefor simple forms, orimport { useForm } from 'react-hook-form'directly for complex ones4 call sites converted to native React:
pages/project-edit/ProjectEditPage.tsxuseForm()→useStateforname/description;form.setFieldsValue→setName();form.validateFields()→if (!name.trim());form.getFieldValue('name')→name;form.getFieldsValue()→ inline literal. Page never rendered<Form>anyway.features/script/components/ScriptGenerator.tsxuseStatehooks;<Form onFinish={handleGenerate}>→ native<form onSubmit>; 8<FormItem>→<label>+ controlled<Input>/<Select>/<RadioGroup>;form.handleSubmit(handleGenerate)()(2 sites) →void handleGenerate(); submitonClick→htmlType="submit"shared/components/business/CompositionStudio/GlobalSettingsForm.tsxuseState+onSavewire-up. Also addsonSavesubmit button.shared/components/business/CompositionStudio/FrameEditForm.tsxuseState+ save/reset buttons.CameraMotion | null→CameraMotion | undefined(Select doesn't acceptnullvalue).shared/components/business/CompositionStudio/index.tsx<FormItem label=>→ plain<label>(skeleton-only, no state needed)Verification
npm run lint --quietnpx tsc --noEmitnpm test --runInBand(90 suites)npm run buildBundle impact
react-vendorchunk: 311 KB → 287 KB (~24 KB smaller —react-hook-formno longer pulled into vendor chunk since no UI shim re-exports it)ui-vendorchunk: unchanged (118 KB)Diff
Out of scope (intentionally NOT touched)
__tests__/pages/project-{edit,detail}.test.tsxjest-skip entries stay in place. Now that the form refactor is done, the underlyinguseStateis honest, but the ProjectEditPage still needs an<Input>UI element to be user-editable. That's a separate feature (real project metadata form), not a refactor. Tests can be re-enabled when that UI lands.Modal/Spin/Space/Empty/Button/Card/Inputre-exports stay — they're AntD-style names but shadcn/RHF implementations, not part of the Form/FormItem bridge.FormWithItem as Formexport for non-Form usage is gone too (was unused in the codebase).Lesson learned (for future agent runs)
The fake-AntD shim is a textbook example of "in-progress refactor" residue: someone started bridging RHF to AntD-style API, shipped 97 lines of bridging code, then 4 call sites used it inconsistently and never finished the migration. Both Phase 1 (back-compat shims) and this form refactor cleanup the same kind of dead scaffolding. If you find yourself reaching for an
<Form>/<FormItem>API, ask first: does this need a form library, or isuseStateenough?