Skip to content

Commit 7046d73

Browse files
committed
fix(form): improve validation trigger to work reliably on WebKit
The previous implementation relied solely on onBlur to show validation errors, which is unreliable on WebKit/Safari browsers. The new approach: - Tracks 'interacted' state (set on focus or change) - Tracks 'focused' state (set on focus, cleared on blur) - Shows errors when: interacted && !focused && errorMessage This makes validation work consistently across all browsers without needing to skip the E2E test on WebKit. Closes: rb-webkit-validation
1 parent d15d2dc commit 7046d73

2 files changed

Lines changed: 12 additions & 9 deletions

File tree

app/components/form-elements.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,16 @@ export const Field = React.forwardRef<
141141
const instructionId = `${inputId}-instruction`
142142

143143
const [value, setValue] = React.useState(defaultValue ?? '')
144-
const [touched, setTouched] = React.useState(false)
144+
const [interacted, setInteracted] = React.useState(false)
145+
const [focused, setFocused] = React.useState(false)
145146

146147
const errorMessage =
147148
validator?.(label, value) ??
148149
(required ? validateRequired(label, value) : undefined) ??
149150
error
150151

151-
const status = (touched && errorMessage) || error ? 'error' : 'default'
152+
const showError = interacted && !focused && !!errorMessage
153+
const status = showError || !!error ? 'error' : 'default'
152154

153155
return (
154156
<div className={className}>
@@ -182,10 +184,15 @@ export const Field = React.forwardRef<
182184
readOnly={readOnly}
183185
disabled={readOnly}
184186
value={value}
185-
onChange={(event: React.BaseSyntheticEvent) =>
187+
onFocus={() => {
188+
setFocused(true)
189+
setInteracted(true)
190+
}}
191+
onChange={(event: React.BaseSyntheticEvent) => {
186192
setValue(event.currentTarget.value)
187-
}
188-
onBlur={() => setTouched(true)}
193+
setInteracted(true)
194+
}}
195+
onBlur={() => setFocused(false)}
189196
status={status}
190197
aria-describedby={
191198
errorMessage

e2e/profile.spec.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@ test('Validate phone number when updating data', async ({
1515
page,
1616
noscript,
1717
screen,
18-
browserName,
1918
}) => {
20-
// Skip on WebKit - validation error messages don't appear reliably after blur()
21-
// See: rb-webkit-validation
22-
test.skip(browserName === 'webkit', 'WebKit blur validation is unreliable')
2319
await page.goto('/dashboard/profile/edit')
2420

2521
// Query phoneNumber - using Locator-based screen queries

0 commit comments

Comments
 (0)