sdxc

[ @sdxc/ui ]

Group

A visual and semantic wrapper binding a cluster of related controls into one unit.

Rotating the key revokes the previous one after an hour.

View code
let copied = false;

<Label htmlFor="apiKey">Secret key</Label>
<Group>
	<Input id="apiKey" name="apiKey" readOnly value="sk_live_51Nc8yR2eZvKYlo2C" />
	<Button
		variant="outline"
		color="neutral"
		commandfor="apiKey"
		command={COPY_COMMAND}
		mix={[
			copyToClipboard(),
			on<HTMLButtonElement, "ui:copy">("ui:copy", (event) => {
				copied = event.success;
				void handle.update();
			}),
		]}
	>
		{copied ? <CheckIcon /> : <ClipboardIcon />}
		<span mix={[visuallyHidden()]}>{copied ? "Copied" : "Copy"}</span>
	</Button>
</Group>
<Description>Rotating the key revokes the previous one after an hour.</Description>

<Label htmlFor="amount">Invoice total</Label>
<Group>
	<Select name="currency" aria-label="Currency">
		<Select.Option value="eur" selected>
			EUR
		</Select.Option>
		<Select.Option value="usd">USD</Select.Option>
		<Select.Option value="gbp">GBP</Select.Option>
	</Select>
	<Input id="amount" name="amount" type="number" min={0} step={0.01} defaultValue="1250.00" />
</Group>

Installation

An ordinary dependency: install it, import the theme once, and import the component where it is used.

npm add @sdxc/ui remix
import "@sdxc/ui/theme.css";

Usage

import { Group } from "@sdxc/ui";

Lays children out in a centered flex row with no border, background, or gap, joining their edges into one shape: only the cluster's outer corners stay round, and the seam two controls share is drawn once. Focus is shown by whichever control holds it.

Examples

Invalid

Enter a full address, like sergio@acme.com.
View code
<div mix={[vstack({ gap: 2, align: "stretch" })]}>
	<Group aria-invalid="true">
		<Input
			id="invite-email"
			name="email"
			type="email"
			defaultValue="sergio@acme"
			aria-label="Teammate's email"
			aria-invalid="true"
			aria-describedby="invite-email-error"
		/>
		<Button
			variant="outline"
			color="neutral"
			commandfor="invite-email"
			command={SEARCH_FIELD_CLEAR_COMMAND}
			aria-label="Clear the email"
			mix={[clearField()]}
		>
			<XIcon />
		</Button>
	</Group>
	<FieldError id="invite-email-error">Enter a full address, like sergio@acme.com.</FieldError>
</div>

Props

Read from the component's own types, so every prop, every default and every allowed value is listed.

Also accepts everything in TagProps<"div">.

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