sdxc

[ @sdxc/u/state ]

open

Sugar over when("&[open], &:popover-open", input), matching both the <details>/<dialog> open attribute and the Popover API's :popover-open pseudo-class.

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

Quick reference

Every documented call, beside the CSS it emits.

CallCSS
u.open(u.opacity(100))css({ "&[open], &:popover-open": { opacity: 1 } })

Examples

Basic example

Wrap utilities in open() to style a <details>, <dialog> or popover while it is open. Click the summary:

Can I use it without Remix?Yes. The utilities return plain style objects any renderer can apply.
<details
	mix={[
		border({ color: "neutral.border", width: 1 }),
		open([bg("brand.tint"), border("brand")]),
		rounded("lg"),
		p(4),
		...,
	]}
>
	<summary mix={[cursor("pointer"), weight("semibold")]}>Can I use it without Remix?</summary>
	Yes. The utilities return plain style objects any renderer can apply.
</details>

Styling the contents

Nest where() inside open() to change a descendant, like turning a chevron. Click the summary:

▸Shipping and returnsOrders ship within two business days.
<details mix={[open(where("[data-chevron]", rotate(90))), ...]}>
	<summary
		mix={[
			hstack({ gap: 2, align: "center" }),
			listStyle("none"),
			cursor("pointer"),
			weight("semibold"),
		]}
	>
		<span data-chevron mix={[inlineBlock(), fg("brand"), transition("transform")]}>
			▸
		</span>
		Shipping and returns
	</summary>
	Orders ship within two business days.
</details>

Popovers

open() also matches a popover while it is shown; with when("@starting-style", …) it fades in. Click the button to toggle the popover:

You have no new notifications.
<div>
	<button
		type="button"
		popovertarget="open-popover"
		mix={[bg("brand.solid"), fg("brand.onSolid"), cursor("pointer"), ...]}
	>
		Notifications
	</button>
	<div
		id="open-popover"
		popover
		mix={[
			opacity(0),
			open([opacity(100), when("@starting-style", opacity(0))]),
			transition("opacity, display, overlay", { duration: 200 }),
			transitionBehavior("allow-discrete"),
			...,
		]}
	>
		You have no new notifications.
	</div>
</div>

Using a custom value

Every scale argument also takes a raw CSS value, which passes through untouched.

u.open(u.opacity("2.75rem"))

Responsive design

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

u.at("md", u.open(u.opacity(100)))

Signature

u.open(input: UtilityInput<Node>)

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