Skip to content

feat(frontend): top-label form fields via FormField/FormGroup - #12425

Open
Healsi wants to merge 13 commits into
mainfrom
ds-inputs
Open

feat(frontend): top-label form fields via FormField/FormGroup#12425
Healsi wants to merge 13 commits into
mainfrom
ds-inputs

Conversation

@Healsi

@Healsi Healsi commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

About the changes

Moves our text inputs and selects away from MUI's floating label to a top label convention, and introduces the shared building blocks to make that consistent across the app.

New shared components

  • FormField — wraps a control with a static label above it (plus optional description), and wires htmlFor / id / aria-describedby so labels and help text are correctly associated. Non-labelable controls (Select / radio / switch) point their aria-labelledby at the field label id via formFieldLabelId.
  • FormGroup — groups related fields and normalises the spacing between them.
  • SteadyWidthText — reserves width for text that changes weight (e.g. active/selected states) to avoid layout shift.

Shared sizing layer (themes/controls.ts)

  • Inputs and selects now size on the v2 control scale (small / medium / large) with shared heights, horizontal padding and font sizes, applied through MuiOutlinedInput / MuiTextField / MuiInputLabel / MuiAutocomplete / MuiFormHelperText overrides (re-applied in the dark theme).
  • GeneralSelect / SelectMenu derive their aria-labelledby from the FormField label, gain placeholder support, and old MUI small maps to the new large so unsized fields keep today's visual weight.

Forms migrated to top labels

  • Configure + project/product settings: all input fields (project general settings, enterprise/naming-pattern settings, environments, segments, context, tags, integrations, banners, groups, license, impact metrics, API tokens, auth — login / forgotten password / SSO).
  • Add strategy / edit strategy on a flag: the floating-label inputs that were in use (flexible & general strategy parameters, stickiness, strategy parameter lists, strategy title).
  • Release templates: create/edit template form (replaced the bespoke borderless h1/h2 floating-label inputs).

Fixes made along the way

  • Whole select field is clickable again (not just the text).
  • Hidden the leftover floating label on the projects sort select.
  • Aligned strategy parameter fields with the delete button; consistent spacing in the project general settings form.
  • Restored the accessible (and clickable) label on the "Impression data" switch after its migration.

Important files

  • frontend/src/component/common/FormField/FormField.tsx (+ FormField.test.tsx)
  • frontend/src/component/common/FormGroup/FormGroup.tsx
  • frontend/src/component/common/SteadyWidthText/SteadyWidthText.tsx
  • frontend/src/themes/controls.ts — the sizing layer / theme overrides
  • frontend/src/component/common/GeneralSelect/GeneralSelect.tsx, frontend/src/component/common/select.tsx, frontend/src/component/common/Input/Input.tsx

Screenshots

TODO: add before/after screenshots — at minimum project settings, an add/edit strategy dialog, and the release template form.

Notes for reviewers

  • Large but mechanical: ~110 files, mostly the same float-label → FormField transformation. The substance is in the shared components and controls.ts.
  • This is a visual change to most forms; worth a click-through of the migrated areas above.
  • Not exhaustive: some floating-label inputs (e.g. nested fields outside the migrated forms) are intentionally left for follow-up.

🤖 Generated with Claude Code

Before/after examples

Playground:
image
image

Configure / Context fields / new:
image
image

Configure / Strategy types / edit:
image
image

Configure / environments / create
image
image

Configure / release templates / create
image
image

Configure / tag types / create
image
image

Configure / integrations / configure
image
image

Configure / integrations / edit
image
image
image
image


Project settings /
image
image

Project settings / use access / edit
image
image

Project settings / API / new
image
image

Project settings / Context fields / create
image
image

Project settings / actions / new
image
image


Add strategy
image
image

Healsi and others added 12 commits June 23, 2026 15:01
Add the design-system v2 input layer on top of the already-merged button
foundation: `outlinedInputSizing` plus MuiOutlinedInput/MuiTextField/
MuiAutocomplete/MuiFormHelperText/MuiInputLabel overrides in controls.ts
(wired into both light and dark themes), the `size="large"` type
augmentations, and the new FormField/FormGroup components that render a
static label above the control instead of MUI's floating label.

Inputs now share the same 24/30/36 control-height scale as buttons.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update the shared select/input primitives to the v2 sizing and FormField
label wiring: GeneralSelect, select, Input, ProjectSelect, RoleSelect,
MultipleRoleSelect, AutocompleteBox, DateTimePicker, PasswordField,
Dialogue, InputListField, SteadyWidthText.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Migrate forms across admin, auth, projects, strategies, segments,
integrations, playground, impact metrics, change requests and user
account to FormField/FormGroup with static labels on the shared control
scale.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The v2 input layer set a fixed height on the input root and zeroed the
input's vertical padding. For selects that left `.MuiSelect-select` —
the element MUI attaches the open-on-click handler and `cursor: pointer`
to — shorter than the field and vertically centered, so only the value
text and the dropdown icon were clickable and the rest of the field had
no pointer cursor. Make `.MuiSelect-select` fill the field height so the
whole control is the click target again.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "Sort by" dropdown in the projects list header showed a floating
label that read as cluttered. Hide it visually via `visuallyHideLabel`
(kept for screen readers); the selected sort value carries the meaning.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…op labels

Give the standard email/password login and the forgotten-password form
the same static top-label treatment as the rest of the app: wrap the
email/password fields in FormField, drop the floating label, and keep
them full width. Column gap owns the spacing (FormField's own margin is
zeroed in the form container).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mGroup

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lay out the parameter name/type/description fields and the delete button
in a CSS grid (1fr auto) so all inputs share the same right edge and the
delete button sits in an auto-sized gutter beside the name field, aligned
to its baseline. Replaces the flex row whose :first-of-type rule also
matched the delete <button> and stretched it to full width.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Give the feature-limit row the standard FormField bottom margin so the
Save button is no longer squeezed against it, and drop the legacy bottom
margin that StickinessSelect (and the collaboration Select) ship, since
the wrapping FormField owns the spacing. Evens out the field rhythm.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
FormField is a new shared component the form migrations depend on, but
had no test. Cover the accessibility-critical behaviour: the static
label names the control (htmlFor → injected id), the description is
wired via aria-describedby, an existing aria-describedby on the control
is preserved, and data-testid forwards to the field container.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wrap the impression-data Switch in a MUI FormControlLabel (inside the
FormField) so the control keeps an accessible name and a clickable label,
matching the switch-in-FormField pattern used in EnvironmentCloneModal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the bespoke borderless h1/h2 floating-label inputs with standard
FormField + Input (name) and FormField + multiline Input (description), so
the create/edit release template form uses top labels like the rest.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@gastonfournier gastonfournier moved this from New to In Progress in Issues and PRs Jun 29, 2026
The multiline OutlinedInput emotion class hash changed with the shared
control sizing in controls.ts; the committed snapshot was stale.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Healsi
Healsi marked this pull request as ready for review June 29, 2026 13:09

@dharmadeveloper108 dharmadeveloper108 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you for this!!! 🙌
I haven't finished testing around, but thought I'd leave a comment about an issue with the Context form in the meantime. Let me know if you need a hand fixing it!!
Also (probably out of scope for this PR, can be done in a follow up one) these inputs need updating too, just a heads up:

  • the profile settings
Screenshot 2026-06-29 at 16 52 59 - the "Create project" form has different inputs (they're not floating label inputs so maybe it was intentional to leave them unchanged?) Screenshot 2026-06-29 at 16 53 55

</StyledInputDescription>
<Input
sx={styledInput}
<FormField

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Something happened with this form, sadly it's broken now 😩 focus is stuck on the first input. also (as a consequence of that probably) the validation error is now gone

Screen.Recording.2026-06-29.at.16.44.13.mov

current actual sandbox:

Screen.Recording.2026-06-29.at.16.44.49.mov

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Legal values are also broken:

Screen.Recording.2026-06-29.at.16.45.48.mov

in sandbox:

Screen.Recording.2026-06-29.at.16.46.28.mov

@dharmadeveloper108

Copy link
Copy Markdown
Contributor

Also it seems that all inputs are by default way narrower (small by default?), maybe it's intentional though

(this branch vs sandbox)
Screenshot 2026-06-30 at 10 00 05
Screenshot 2026-06-30 at 10 03 09

=======

Screenshot 2026-06-30 at 10 02 43 Screenshot 2026-06-30 at 10 04 23

pull Bot pushed a commit to anaktampan/unleash that referenced this pull request Jul 31, 2026
Inputs and selects previously had effectively one size. This PR adds the
design-system v2 **control scale** to them (from [the original
PR](Unleash#12425) by UX, Claude
generated), so inputs/selects/autocompletes can be sized `small` (24px),
`medium` (30px), or `large` (36px) and line up with buttons and
icon-buttons.

- This updates the wrappers (`Input`, `GeneralSelect`, `SelectField`,
`PasswordField`, `DateTimePicker`) to default to `large`.
- Updates the ~94 existing input/select call-sites that were explicitly
`size='small'`, and moves to `size='large'` (the bulk of the 69
component files) so they keep their current height. `medium` and `small`
are now opt-in sizes.

From the look around I had, controls look pretty similar to production
(except they are a tiny bit smaller, but barely).

## Screenshots 

Flag on this branch vs sandbox
<img width="611" height="593" alt="Screenshot 2026-07-27 at 18 11 08"
src="https://github.com/user-attachments/assets/1223ba9b-456b-49bf-bb1f-8cb67c3cdcc1"
/>

<img width="611" height="593" alt="Screenshot 2026-07-27 at 18 11 13"
src="https://github.com/user-attachments/assets/626dda31-e1f2-4b3e-a73f-b2480030cf8a"
/>


Flag off this branch vs hosted 

<img width="611" height="593" alt="Screenshot 2026-07-27 at 18 16 26"
src="https://github.com/user-attachments/assets/e38921d5-4ffe-4f52-b2c7-621b2059a481"
/>
<img width="611" height="593" alt="Screenshot 2026-07-27 at 18 16 31"
src="https://github.com/user-attachments/assets/3d41f77b-870f-46ad-a67d-30bc69b627b9"
/>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

3 participants