# 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.

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

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.

## Quick reference

Every documented call, beside the CSS it emits.

| Call | CSS |
| --- | --- |
| `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:

```tsx
<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:

```tsx
<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.

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

## Signature

```ts
u.invalid(input: UtilityInput<Node>)
```
