Controlled input flashing error border style
- Dominant language
- TypeScript
- Stars
- 45
- Forks
- 9
- Avg merge
- 1d 9h
- Merged PRs (30d)
- 17
Description
## Background
When an html `` is typed into, the browser recalculates the internal validation state on every keypress. In Source we apply the error border using the :invalid CSS selector which — for emails — is applied as soon as a person begins typing.. this is because the field validity state is invalid until the user has completed the email.
As a result, the border state flickers between valid / invalid as the user types and the browser-level validity state is changed.
This was likely missed originally because most `` users have type=text set, which generally never reaches an invalid state.. however when type=email is set, there are way more cases where it can go from valid -> invalid while you're typing, surfacing the issue.
To further complicate matters, the `` component has some custom logic that looks at the value attribute so an invalid red border is not displayed when it is empty and invalid.
This adds a difference in behaviour for when the input is controlled vs uncontrolled.. because when it is uncontrolled, the value prop is not updated dynamically. That means that the issue hasn't shown up for uncontrolled uses (like on the Gateway email field) because the value attribute is never updated, so it's as if the input is still empty.
### tl;dr
**We’ve surfaced an issue where a collection of factors have combined to produce a flickering border behaviour on our text inputs where it cycles between default / invalid border states as the user types (an email in this case):**
- There is a controlled use of the `TextInput` component; meaning that the `value` attribute is updated as the user types.
- Border styles are applied using the CSS `:invalid` selector only when the `value` attribute is non empty (so empty input boxes do not have the invalid border applied)
- Code reference for these CSS rules: https://github.com/guardian/source/blob/main/packages/%40guardian/source-react-components/src/text-input/styles.ts#L52.
- This can only happen when the input is controlled, because an uncontrolled input would not update this attribute dynamically, meaning that the error border is never applied under the CSS rule linked above.
- Input validation is based on the email input in this specific instance ( `` ) so there is a high chance that the email is invalid whilst the user is typing their email, causing the invalid border to be applied as they type.
- This issue will also affect any other input type that can reach an `:invalid` state.
## Next steps
1. Investigate how we can allow end users of the Source `` (and other input types) to manually override the invalid border style when using it as a controlled component so our default implementation doesn't kick in, causing the flickering border issue.
2. We need to work out a way to do this without causing regressions (or as few as possible) for existing users of these components.
3. Issue to be updated once we have discussed our options and come up with some candidate solutions
Contributor guide
Research direction
Start with the CSS rules in packages/@guardian/source-react-components/src/text-input/styles.ts and trace how the TextInput component handles controlled values and invalid states. Determine a supported way to override the invalid border for controlled inputs, then verify that the approach avoids flickering without regressing existing TextInput behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- css, typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100