sdxc

Type to search, or start from one of these:

FileTrigger

A pressable surface that opens the platform's file picker, backed by a native <input type="file"> wrapped in a <label> so the platform itself handles the trigger-to-picker wiring.

Import contacts

The first row is read as the header. Columns named email and name are matched automatically; everything else is offered for mapping on the next step.

Nothing chosen yet.

View code
let chosen: File | null = null;

function readChoice(event: Event & { currentTarget: HTMLInputElement }) {
	chosen = event.currentTarget.files?.[0] ?? null;
	void handle.update();
}

<Header>Import contacts</Header>

<FileTrigger
	name="contacts"
	accept=".csv,text/csv"
	mix={[on<HTMLInputElement, "change">("change", readChoice)]}
>
	<UploadIcon aria-hidden="true" />
	Choose a CSV
</FileTrigger>

<FileTrigger
	name="vcards"
	acceptDirectory
	variant="outline"
	color="neutral"
	mix={[on<HTMLInputElement, "change">("change", readChoice)]}
>
	<FolderIcon aria-hidden="true" />
	Choose a vCard folder
</FileTrigger>

<Description>
	The first row is read as the header. Columns named email and name are matched
	automatically; everything else is offered for mapping on the next step.
</Description>

<Separator />

{chosen === null ? (
	<Description>Nothing chosen yet.</Description>
) : (
	<Item>
		<Item.Content>
			<Item.Title>{chosen.name}</Item.Title>
			<Item.Description>{formatFileSize(chosen.size)}</Item.Description>
		</Item.Content>
	</Item>
)}

<Button type="submit" disabled={chosen === null}>
	Import
</Button>

Installation

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

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

Usage

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

Renders a native <input type="file"> wrapped in a <label> styled through this library's shared data-color/data-variant/data-size contract; in dev mode, content lacking an accessible name logs a warning.

Examples

<FileTrigger name="attachments" multiple color="brand" variant="outline">
	{t("thread.attachFiles")}
</FileTrigger>
<FileTrigger name="folder" acceptDirectory aria-label={t("importer.chooseFolder")} />

Props

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

PropTypeDescription
color?"brand" | "neutral" | "success" | "warning" | "danger"Semantic color role. Defaults to DEFAULT_COLOR.
variant?"solid" | "outline" | "ghost"Visual weight. Defaults to DEFAULT_VARIANT.
size?"sm" | "md" | "lg"Size variant. Defaults to DEFAULT_SIZE.
acceptDirectory?booleanSwitches the picker from choosing individual files to choosing whole directories, carrying every file nested inside the chosen directory.
children?RemixNodeThe trigger's visible content, rendered inside the same <label> that wraps the host <input> — an icon, text, or both, kept decorative so the platform's label-to-control association reaches the input on click.
parts?PartsPropsPer-part styling for this component's internally composed elements.

Also accepts everything in Omit<TagProps<"input">, "type" | "role" | "size">.

Types

NameValuesWhat it decides
Color"brand" | "neutral" | "success" | "warning" | "danger"Semantic color role, each mapped to its matching --ui-* variables.
Variant"solid" | "outline" | "ghost"Visual weight the trigger renders with: a solid fill with an on-solid foreground, a transparent fill with a strong colored border, or a fully transparent fill with just a colored label.
Size"sm" | "md" | "lg"Size variant controlling the trigger's padding and font size.