Skip to content

Replace Chakra/Formik with antd Form in user management#7843

Merged
gilluminate merged 11 commits intomainfrom
gill/ENG-3168/replace-chakra-formik-with-antd-user-management
Apr 7, 2026
Merged

Replace Chakra/Formik with antd Form in user management#7843
gilluminate merged 11 commits intomainfrom
gill/ENG-3168/replace-chakra-formik-with-antd-user-management

Conversation

@gilluminate
Copy link
Copy Markdown
Contributor

Ticket ENG-3168

Description Of Changes

Full migration of user management forms from Formik + Yup + Chakra UI to antd Form with inline validation rules. Replaces all Chakra layout/display components with antd equivalents and Tailwind CSS. Keeps existing form behavior and validation logic intact.

Key changes:

  • Formik → antd Form: Form.useForm(), Form.useWatch(), onFinish, Form.Item with rules arrays replace Formik's render props, Yup schemas, and CustomTextInput/CustomSwitch wrappers
  • Chakra layout → antd + Tailwind: Box/Flex/Stack/HStack/VStack → antd Flex, Card, Typography, and Tailwind layout classes
  • Chakra Table → antd Table: AssignSystemsTable uses columns/dataSource pattern with onRow for row test IDs
  • useChakraDisclosureuseState<boolean> for all modal open/close state
  • Shared passwordRules: extracted to common/form/validation.ts, consumed by UserForm, NewPasswordModal, and login.tsx (replaces 3 duplicate definitions)
  • New Cypress helper: cy.getAntFormError(fieldName) in ant-support.ts for querying antd Form.Item validation errors

Also fixes UserFormProps.onSubmit type signature to accept UserCreateExtended (the actual payload shape) instead of using an unsafe as cast.

Code Changes

  • UserForm.tsx — Formik/Yup/Chakra → antd Form with Form.useWatch for reactive password toggle, inline validation rules, Form.Item + Input/Switch
  • PermissionsForm.tsx — Formik → antd Form with useEffect for enableReinitialize, added missing loading state on Save button
  • RoleOption.tsxuseFormikContextform prop (FormInstance), Chakra Stack → antd Card/Flex
  • NewPasswordModal.tsx — Formik/Yup → antd Form with Input.Password and dependencies for confirmation matching
  • UpdatePasswordModal.tsx — Chakra Input/FormControl/Stack → antd Input.Password/Flex
  • DeleteUserModal.tsx — Formik/Yup/Chakra Alert → antd Form/Input/Alert with custom username validator
  • PasswordManagement.tsx — Chakra Box/HStack → antd Flex
  • RoleDescriptionDrawer.tsx — Chakra Box/VStack → antd Card/Flex/Typography
  • AssignSystemsModal.tsx — Chakra layout → antd Flex/Typography
  • AssignSystemsTable.tsx — Chakra Table → antd Table with columns/dataSource, restored row data-testid via onRow
  • EditUserForm.tsx / NewUserForm.tsx — Updated onSubmit type to UserCreateExtended
  • common/form/validation.ts — Added shared passwordRules antd rules array
  • pages/login.tsx — Uses shared passwordRules instead of inline duplicate
  • cypress/support/ant-support.ts — Added getAntFormError command
  • cypress/e2e/user-management.cy.ts — Updated error selector to use getAntFormError

Steps to Confirm

  1. Navigate to /user-management and verify the user table renders
  2. Click "Add new user" and verify all form fields render (username, email, first/last name)
  3. Submit with invalid email — verify validation error appears and Save is disabled
  4. Submit with weak password — verify password complexity errors appear
  5. Create a valid user — verify success toast and redirect
  6. Edit an existing user profile — verify fields populate and Save works
  7. Test password management: update own password, reset another user's password
  8. Test delete user modal: type mismatching username (error), type correct username (submit)
  9. Navigate to Permissions/Roles tab — verify role selection and system assignment work
  10. If Plus + SSO enabled: verify password login toggle shows/hides password field reactively

Pre-Merge Checklist

  • Issue requirements met
  • All CI pipelines succeeded
  • CHANGELOG.md updated
    • Updates unreleased work already in Changelog, no new entry necessary
  • UX feedback:
    • All UX related changes have been reviewed by a designer
  • Followup issues:
    • No followup issues
  • Database migrations:
    • No migrations
  • Documentation:
    • No documentation updates required

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fides-plus-nightly Ready Ready Preview, Comment Apr 7, 2026 5:02pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
fides-privacy-center Ignored Ignored Apr 7, 2026 5:02pm

Request Review

gilluminate added a commit that referenced this pull request Apr 6, 2026
@gilluminate gilluminate force-pushed the gill/ENG-3168/replace-chakra-formik-with-antd-user-management branch from e355ad4 to 4b99954 Compare April 6, 2026 20:47
@gilluminate gilluminate changed the title ENG-3168: Replace Chakra/Formik with antd Form in user management Replace Chakra/Formik with antd Form in user management Apr 6, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 6, 2026

Title Lines Statements Branches Functions
admin-ui Coverage: 7%
5.82% (2500/42929) 4.71% (1146/24310) 3.88% (495/12726)
fides-js Coverage: 78%
78.98% (1962/2484) 65.55% (1214/1852) 72.57% (336/463)
privacy-center Coverage: 86%
84.05% (290/345) 79.18% (156/197) 76.56% (49/64)

Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: antd migration for user management forms

This is a solid, well-scoped migration. The Formik/Chakra removal is consistent across all the targeted forms, the shared passwordRules constant eliminates the duplication that existed in login.tsx, and the loading-state fix in AssignSystemsModal (emptySystems now guards against the loading phase) is a genuine improvement that wasn't there before.

Issues to address

Medium

  • UserForm.tsxform.isFieldsTouched() (no argument) enables the Save button after touching any single field, while DeleteUserModal and NewPasswordModal both use isFieldsTouched(true). The getFieldsError() guard won't cover untouched required fields, so a user could see the Save button enabled while Email Address is still empty. Should align with the pattern used in the other modals.
  • PermissionsForm.tsxForm.useWatch("roles", form) returns undefined on the first render (before the Form.Item child registers the field), causing isEqual(undefined, []) to be false and the Save button to flash as enabled. Fix: const currentRoles = Form.useWatch("roles", form) ?? initialValues.roles.
  • UpdatePasswordModal.tsx — Not migrated to antd Form. It still uses raw useState/onChange and a boolean changePasswordValidation check, unlike every other modal in this PR. The old Formik version had password confirmation cross-field validation; this version lost it. Needs a comment explaining why it was left out, or should be brought in line with NewPasswordModal.

Low / Nice to have

  • PermissionsForm.tsx — The hidden <Input /> used to register the roles array field in the form store is unconventional. It works today, but a programmatic-only field storing an array through a string Input is fragile. Worth noting for follow-up or replacing with a cleaner approach.
  • RoleOption.tsxaria-selected="true" on a Card (<div>) has no semantic meaning for assistive technology. aria-pressed or aria-checked would be correct for a selection affordance, or the attribute can be dropped since data-testid="selected" already covers the test targeting.

What's done well

  • Shared passwordRules constant with proper reuse in UserForm, NewPasswordModal, and login.tsx
  • Consistent Form + Form.Item + dependencies pattern for password confirmation in NewPasswordModal
  • isLoading propagation to AssignSystemsTable and the emptySystems guard fix
  • Form.useWatch([], form) used to trigger re-renders for the disabled-button check — this is the correct antd v5 pattern
  • useChakraDisclosure replaced with plain useState booleans throughout — cleaner and removes the Chakra dependency

Comment thread clients/admin-ui/src/features/user-management/UserForm.tsx
Comment thread clients/admin-ui/src/features/user-management/PermissionsForm.tsx
Comment thread clients/admin-ui/src/features/user-management/PermissionsForm.tsx
Comment thread clients/admin-ui/src/features/user-management/RoleOption.tsx Outdated
@@ -216,7 +195,7 @@ const useLogin = () => {
handleSubmit,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good refactor — the local inline rules duplication has been eliminated by importing the shared passwordRules. The rename to loginPasswordRules cleanly avoids the naming conflict with the import. 👍

Migrate all user management forms from Formik + Yup + Chakra UI to
antd Form with inline validation rules. Replace all Chakra layout
components with antd equivalents and Tailwind CSS.

- UserForm: antd Form with Form.useWatch for reactive fields
- PermissionsForm + RoleOption: migrate coupled Formik context to
  antd Form instance passed as prop
- NewPasswordModal: antd Form with Input.Password and confirmation
  matching via dependencies
- UpdatePasswordModal: replace Chakra inputs with antd Input.Password
- DeleteUserModal: antd Form with Alert and custom username validator
- PasswordManagement, RoleDescriptionDrawer: Chakra layout to antd Flex
- AssignSystemsModal: Chakra layout to antd Flex + Typography
- AssignSystemsTable: Chakra Table to antd Table with columns/dataSource

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@lucanovera lucanovera left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User managements work as expected, code changes & ui look good. Approved!

gilluminate and others added 10 commits April 7, 2026 10:56
- Fix unsafe `as FormValues` cast: change onSubmit prop to accept
  UserCreateExtended, update callers in NewUserForm and EditUserForm
- Add validation error check to UserForm Save button (was only
  checking dirty state, not validity)
- Add missing loading state to PermissionsForm Save button
- Remove dead `xs:` Tailwind breakpoint class from UserForm
- Restore data-testid on table rows in AssignSystemsTable via onRow
- Use `color` prop for Carbon icon in RoleOption per conventions
- Restore JSDoc on PermissionsForm explaining legacy non-RBAC role
- Extract shared passwordRules to common/form/validation.ts, used by
  UserForm, NewPasswordModal, and login page

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restore data-testid values to match what Cypress selectors expect:
- input-email_address, input-first_name, input-last_name (underscores
  matching field names, not hyphens)
- input-password_login_enabled on Switch (was toggle-allow-password-login)
- input-usernameConfirmation on DeleteUserModal Input
- input-password and input-passwordConfirmation on NewPasswordModal inputs
- Update Cypress error selector to use antd's .ant-form-item-explain-error
  class (replaces Formik's FormErrorMessage data-testid)

The 7 remaining test failures (Permission assignment tests looking for
"Permissions" tab) are pre-existing on main -- the RBAC flag now defaults
enabled, rendering "Roles" instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a reusable command for querying antd Form.Item validation errors
by field name. Uses antd's generated #fieldName_help container.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Default useWatch("roles") to initialValues.roles to prevent Save button flash on first render
- Remove semantically incorrect aria-selected from RoleOption Card

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gilluminate gilluminate force-pushed the gill/ENG-3168/replace-chakra-formik-with-antd-user-management branch from 569b269 to 0b8e556 Compare April 7, 2026 16:57
@gilluminate gilluminate added this pull request to the merge queue Apr 7, 2026
Merged via the queue into main with commit 34b5506 Apr 7, 2026
50 of 51 checks passed
@gilluminate gilluminate deleted the gill/ENG-3168/replace-chakra-formik-with-antd-user-management branch April 7, 2026 17:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants