sdxc

[ @sdxc/u/state ]

has

Sugar over when("&:has({selector})", input).

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

Quick reference

Every documented call, beside the CSS it emits.

CallCSS
u.has("input:user-invalid", u.border("danger"))css({ "&:has(input:user-invalid)": { borderColor: "..." } })
u.has("img", u.p(4))css({ "&:has(img)": { padding: "..." } })

Examples

Basic example

Pass a selector to has() to style an element by what it contains, like a card holding a checked radio. Pick a plan:

<div mix={[...]}>
	<label
		mix={[
			hstack({ gap: 2, align: "center" }),
			p(3, 4),
			rounded("lg"),
			border({ color: "neutral.border", width: 2 }),
			has("input:checked", [border("brand"), bg("brand.tint")]),
			cursor("pointer"),
		]}
	>
		<input type="radio" name="has-plan" checked mix={[accent()]} />
		<span mix={[text("sm"), weight("semibold")]}>Starter</span>
	</label>
	<label
		mix={[
			hstack({ gap: 2, align: "center" }),
			p(3, 4),
			rounded("lg"),
			border({ color: "neutral.border", width: 2 }),
			has("input:checked", [border("brand"), bg("brand.tint")]),
			cursor("pointer"),
		]}
	>
		<input type="radio" name="has-plan" mix={[accent()]} />
		<span mix={[text("sm"), weight("semibold")]}>Team</span>
	</label>
</div>

Styling by a child's state

Any selector works, like input:user-invalid to color a label from its field. Type a word that is not a URL, then click outside:

<label
	mix={[
		vstack({ gap: 1 }),
		text("sm"),
		weight("medium"),
		fg(),
		has("input:user-invalid", fg("danger")),
	]}
>
	Website
	<input type="url" placeholder="https://" mix={[border("neutral.border"), ...]} />
</label>

Responsive design

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

u.at("md", u.has("input:user-invalid", u.border("danger")))

Signature

u.has(selector: string, input: UtilityInput<Node>)

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