sdxc

[ @sdxc/u/state ]

invalid

Waits for user interaction before flagging a field invalid, matching :user-invalid alongside the ARIA fallback so validation only surfaces once it is meaningful to the person filling in the field.

import { invalid } from "@sdxc/u/state";

Quick reference

Every documented call, beside the CSS it emits.

CallCSS
u.invalid(u.border("danger"))css({ '&:user-invalid, &[aria-invalid="true"]': { borderColor: "..." } })

Examples

Basic example

Wrap utilities in invalid() to style a field that fails validation after the user has edited it. Type "hello" in the field, then click outside it:

<label mix={[vstack({ gap: 1 }), text("sm"), weight("medium")]}>
	Email
	<input
		type="email"
		required
		placeholder="you@example.com"
		mix={[
			border("neutral.border"),
			invalid([border("danger.strong"), fg("danger"), outline({ color: "danger", width: 1 })]),
			...,
		]}
	/>
</label>

ARIA invalid

invalid() also matches aria-invalid="true", for a field the server rejected:

<label mix={[vstack({ gap: 1 }), text("sm"), weight("medium")]}>
	Username
	<input
		type="text"
		value="admin"
		aria-invalid="true"
		aria-describedby="username-error"
		mix={[
			border("neutral.border"),
			invalid([border("danger.strong"), fg("danger")]),
			...,
		]}
	/>
	<span id="username-error" mix={[fg("danger"), text("xs")]}>
		That username is taken.
	</span>
</label>

Responsive design

Wrap the call in a container query to scope it to one width.

u.at("md", u.invalid(u.border("danger")))

Signature

u.invalid(input: UtilityInput<Node>)

Written by Sergio Xalambrí. Follow @sergiodxa for new packages, or sponsor the work.