Skip to content

refactor(forms): adopt FieldLabel and FieldError for hand-rolled labels - #8117

Draft
talissoncosta wants to merge 7 commits into
mainfrom
refactor/fieldlabel-component-sites
Draft

refactor(forms): adopt FieldLabel and FieldError for hand-rolled labels#8117
talissoncosta wants to merge 7 commits into
mainfrom
refactor/fieldlabel-component-sites

Conversation

@talissoncosta

@talissoncosta talissoncosta commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Thanks for submitting a PR! Please check the boxes below:

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Contributes to #8120 (epic #8119)

First adoption pass of the field components over hand-rolled form labels and unwired errors, and it introduces Field: the shared field skeleton (wrapper + FieldLabel + control + FieldError, wiring via an explicit htmlFor). Each migrated site is a single element; with Field there is no need to ever build PasswordField/DateField/SwitchField wrappers.

  • 15 sites that hand-rolled labels around custom controls (via InputGroup's component slot, which wires nothing) now render Field: metadata editors, date picker, colour picker, value editor, switch, copy field, checkbox group, search rows, user/group chips. Title-less sites just unwrap. Follow-up: InputGroup/SelectField compose Field internally so the app has one field skeleton.
  • CopyField owns its label: optional title, wired internally (callers cannot reach the inner input's id for htmlFor).
  • DateSelect forwards an id, so its two call sites' labels (change request schedule, API key expiry) actually resolve, plus the raw <label>Expiry</label> in AdminAPIKeys is now wired.
  • Chip close icons in touched files swap IonIcon for the custom Icon (18px, matching the chip-icon box); ad-hoc inline font sizes go with it.

Not in scope here: the wider raw-<label> population (~87 occurrences across 42 files) continues in batches under #8120, and nothing about InputGroup's component prop changes in this PR.

How did you test this code?

  • tsc: 0 new errors vs main.
  • eslint: clean on all changed files.
  • Storybook: CopyField WithTitle story added.

Smoke test (light + dark):

  • Change request modal: Schedule Change label + tooltip, Clear button beside the picker, assignee chips (new close icon), label focuses the date input
  • Change request detail page: assigned users/groups chips
  • Edit permissions (org level): Assign roles label + role chips
  • Create feature: Tags label/tooltip, Value label/tooltip (variations on = no tooltip icon)
  • Create segment: Users tab environment label + last-synced note; metadata tab
  • Create environment: clone metadata custom fields label; admin chips
  • Environment settings: custom fields tab label/tooltip
  • Create org page: hosting option label + checkbox group
  • SAML modal: IdP-initiated switch label/tooltip
  • SCIM token modal: labelled copy field (label focuses the input)
  • Admin API keys: expiry label focuses the picker; role chips
  • Release manager: search label focuses the input
  • Feature value tooltip, tag colour picker, MV variation value label

@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
flagsmith-frontend-preview Ready Ready Preview Jul 30, 2026 11:30am
flagsmith-frontend-staging Ready Ready Preview Jul 30, 2026 11:30am
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview Jul 30, 2026 11:30am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 611d572a-2721-46c9-afd1-7383eac6cc6d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

talissoncosta and others added 6 commits July 29, 2026 10:53
Wrapper + FieldLabel + control + FieldError as one layout-only
component: unlike the InputGroup component slot it never pretends to
wire a control it cannot reach, wiring is the explicit htmlFor. With
Field, PasswordField/DateField/SwitchField wrappers never need to
exist.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The component slot renders custom controls with no label or error
wiring. The 15 non-Select sites now render FieldLabel (plus a
form-group wrapper) directly; title-less sites just unwrap. The
remaining component= sites are Selects, which move to SelectField in
a follow-up, after which the prop is deleted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The label must live inside CopyField: htmlFor needs the inner
read-only input's id, which callers cannot reach. The SCIM modal's
hand-rolled label collapses into the title prop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DateSelect never exposed an id, so neither of its two call sites could
associate its label with the input. react-datepicker forwards id to
the input, so both labels now resolve.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Chip close icons standardise on Icon name='close' width 18 (the
chip-icon box size); the two ad-hoc 13px inline styles go with it.
CreateSAML's download icon stays on IonIcon until the icon set gains
a download SVG.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Each hand-rolled wrapper + FieldLabel pair becomes a single Field
element (net -61 lines at the sites). Also annotates two CreateGroup
mutation callbacks whose inference flips when anything in the service
import cycle changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@talissoncosta talissoncosta reopened this Jul 29, 2026
@talissoncosta
talissoncosta force-pushed the refactor/fieldlabel-component-sites branch from 7983e5f to 99dc7a2 Compare July 29, 2026 13:56
Field provides {controlId, errorId, hasError} when htmlFor is set;
Input adopts them as defaults (explicit props win), so the id is
declared once on Field and aria-invalid/aria-describedby wire
themselves. Context only exists for an explicit htmlFor, keeping
wiring a visible call-site decision. Pattern follows Primer
FormControl / React Aria field context.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

front-end Issue related to the React Front End Dashboard refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant