drizzle 0.2.0

A type-safe SQL query builder for Rust
Documentation
<script lang="ts">
	import { cn } from '#lib/utils.js';

	export interface SelectOption {
		value: string;
		label: string;
	}

	/**
	 * A native `<select>`, styled to match the rest of the controls.
	 *
	 * This replaced the shadcn/bits-ui Select, which renders a button plus a JS-driven listbox: with
	 * scripting off it had no options at all and the picker was simply inert. A native select is
	 * keyboard- and screen-reader-native everywhere, works in the enclosing GET form with no
	 * scripting, and gets the same instant navigation once hydrated.
	 */
	let {
		id,
		name,
		label,
		value,
		options,
		placeholder,
		class: className,
	}: {
		id: string;
		name: string;
		label: string;
		value: string;
		options: readonly SelectOption[];
		placeholder?: string;
		class?: string;
	} = $props();
</script>

<!--
	Stacked on a phone, inline from `sm`. A native select sizes itself to its widest option, and the
	set picker's options are long enough ("Turso · drivers to ORMs · 3247f5b · Jul 30 23:50") that
	side by side with its label they pushed past a 375px viewport.

	`flex-1` is `sm:` only, and that matters: the wrapper is a *column* flex container below `sm`,
	where `flex: 1 1 0%` applies to the vertical axis and collapsed the select's `h-10` to its
	content height of 20px. It only means "take the remaining width" once the row direction is back.
-->
<div class={cn('flex min-w-0 flex-col gap-1 sm:flex-row sm:items-center sm:gap-2', className)}>
	<label for={id} class="text-label text-muted-foreground shrink-0 font-mono uppercase">
		{label}
	</label>
	<select
		{id}
		{name}
		{value}
		onchange={(event) => event.currentTarget.form?.requestSubmit()}
		class="border-input bg-input/20 text-meta focus-visible:border-ring focus-visible:ring-ring/30 h-10 w-full min-w-0 rounded-md border px-2 font-mono transition-colors focus-visible:ring-2 sm:h-8 sm:max-w-md sm:flex-1"
	>
		{#if placeholder}
			<option value="">{placeholder}</option>
		{/if}
		{#each options as option (option.value)}
			<option value={option.value}>{option.label}</option>
		{/each}
	</select>
</div>