Gebaut auf Vercels UI SDK 0.1.0-beta.2. Die API kann sich ändern.
File input
Ein Datei-Input auf Vercels UI SDK mit Drop-Zone, Einfügen, Typ- und Größenprüfung, abgelehnten Dateien mit Gründen, Bildvorschauen und Formularunterstützung.
- Formularkomponenten
- 14 Teilen
- 12 Beispielen
@tabler/icons-react@ui-sdk/core@ui-sdk/reactclass-variance-authority
Drop files here
Images or PDFs, up to 5 files of 5 MB each. You can paste them too.
pnpm dlx shadcn@latest add https://hextaui.com/r/ui-sdk-file-input.jsonFügt die Komponente, die HextaUI-Theme-Tokens und alle HextaUI-Komponenten hinzu, von denen sie abhängt.
Füge die Theme-Tokens zu deinem globalen CSS hinzu, falls du das noch nicht getan hast.
Installiere die Abhängigkeiten.
pnpm add @ui-sdk/react@0.1.0-beta.2 @ui-sdk/core@0.1.0-beta.2 @tabler/icons-react class-variance-authority cnKopiere den folgenden Code und füge ihn in dein Projekt ein.
components/ui/ui-sdk-file-input.tsx components/ui/button.tsx Passe die Importpfade an dein Projekt-Setup an.
UI SDK bringt etwas eigenes CSS in einem Cascade Layer namens ui-sdk mit. Deklariere diesen Layer ganz oben im globalen Stylesheet, über dem Tailwind-Import, damit deine Klassen gewinnen.
Der Datei-Input hält die Dateien, die Leute auswählen, ablegen oder einfügen, und sendet sie mit einem Formular. Das Hochladen übernimmt deine App. FileInputItem ohne Kinder rendert eine fertige Zeile mit Vorschau, Name, Größe und Entfernen-Button, einmal pro Datei in der Liste.
Die Prüfungen für accept, Größen, Anzahl und validate laufen nur im Browser, damit Leute früh erfahren, warum eine Datei fehlt. Jeder kann sie umgehen, prüfe also jeden Upload erneut auf deinem Server.
accept nimmt MIME-Typen, Platzhalter und Endungen. maxFiles, minSize und maxSize setzen die Grenzen, und validate ergänzt eigene Prüfungen. FileInputRejections listet jede ausgelassene Datei mit allen Gründen, bis zur nächsten angenommenen Datei.
FileInputItemPreview zeigt ein Bild aus einer Object-URL, die es freigibt, wenn die Datei verschwindet, und für andere Typen ein Icon. Mit layout="grid" ist jede Datei eine quadratische Kachel.
Ein Auslöser allein öffnet die Dateiauswahl des Systems. Ohne multiple ersetzt eine neue Datei die aktuelle, und die Kinder der Wurzel können eine Funktion ihres Zustands sein.
Mit variant="composer" ist die Drop-Zone die Karte um ein Nachrichtenfeld, und layout="chips" listet Dateien als kompakte Chips. pasteTarget nimmt eingefügte Screenshots aus dem Textfeld, eingefügter Text bleibt Text.
Mit target="document" und variant="overlay" bedeckt die Zone die Seite, solange Dateien über das Fenster gezogen werden, und nimmt überall abgelegte Dateien. Was auf einer anderen Zone landet, bleibt dort.
directory wählt einen ganzen Ordner und schaltet multiple ein. Eintragsnamen zeigen den Pfad im Ordner.
Übergib value und onValueChange. Ein Controller aus createFileInputController() öffnet die Auswahl von jedem Button aus und leert oder ergänzt Dateien.
Mit einem name werden die Dateien über einen nativen Datei-Input gesendet, sogar bevor die Seite hydriert. Abgelehnte Dateien werden nie gesendet, und ein Formular-Reset leert die Liste.
invalid markiert Drop-Zone und Auslöser, und der Auslöser meldet es Screenreadern. Richte aria-describedby des Auslösers auf deine Meldung.
Ein deaktivierter Datei-Input ignoriert Auswahl, Ablegen und Einfügen und sendet nichts.
Zeilen und Drop-Zone werden gespiegelt, Dateinamen behalten ihre eigene Richtung, und Größen werden im übergebenen Locale formatiert.
| Taste | Aktion |
|---|---|
| Tab | Springt zum Auslöser, dann in die Liste, auf die zuletzt fokussierte oder die erste Datei. |
| EnterSpace | Öffnet die Dateiauswahl vom Auslöser aus. |
| ↑↓←→ | Wechselt zwischen den Dateien der Liste. |
| HomeEnd | Springt zur ersten oder letzten Datei. |
| DeleteBackspace | Entfernt die fokussierte Datei und fokussiert die nächste. |
| ⌘V | Fügt Dateien ein, solange der Fokus in der Drop-Zone oder ihrem Einfügeziel liegt. |
Die Drop-Zone ist kein Bedienelement, also gehört immer ein Auslöser daneben, für Leute mit Tastatur oder Screenreader. Die Liste ist ein Tab-Stopp, jeder Entfernen-Button ist nach seiner Datei benannt, etwa „Remove photo.png“, und bleibt außerhalb der Tab-Reihenfolge, weil Entf auf dem Eintrag dasselbe tut.
Angenommene, entfernte und abgelehnte Dateien werden über eine höfliche Live-Region auf Englisch angesagt. Übergib announcement, um es in deiner Sprache zu sagen, und getReasonLabel an FileInputRejections für die Gründe. Das Drop-Zonen-Icon hebt sich nur, wenn Bewegung erlaubt ist, und nur dann blenden neue Zeilen ein.
Jeder Teil umhüllt den gleichnamigen UI-SDK-Teil und nimmt alle seine Props an, auch render und einen className, der eine Funktion des Zustands sein kann.
| Prop | Typ | Standard |
|---|---|---|
value | File[] | – |
defaultValue | File[] | [] |
onValueChangedetails enthält den Grund und die hinzugefügten, entfernten und abgelehnten Dateien. | (value: File[], details) => void | – |
onRejectLäuft, wenn Dateien die Prüfungen nicht bestehen, auch wenn keine angenommen wurde. | (rejected: FileRejection[], details) => void | – |
accept | string | string[] | – |
multiple | boolean | false |
maxFiles | number | – |
maxSizeIn Bytes. | number | – |
minSizeIn Bytes. | number | – |
validateGib einen Grund zurück, um die Datei abzulehnen, nach den eingebauten Prüfungen. | (file: File) => string | null | – |
directory | boolean | false |
captureÖffnet auf Smartphones die Kamera. | "user" | "environment" | boolean | – |
invalid | boolean | false |
disabled | boolean | false |
required | boolean | false |
name | string | – |
form | string | – |
announcementWas Screenreader nach einer Änderung hören. | (change) => string | null | – |
controllerAus createFileInputController(). | FileInputController | – |
children | ReactNode | (state) => ReactNode | – |
| Attribut | Beschreibung |
|---|---|
data-slot="file-input" | Spricht den Datei-Input in CSS an. |
data-dragging | Vorhanden, solange Dateien über eine seiner Drop-Zonen gezogen werden. |
data-invalid | Vorhanden, wenn ungültig. |
data-required | Vorhanden, wenn eine Datei Pflicht ist. |
data-disabled | Vorhanden, wenn deaktiviert. |
| Prop | Typ | Standard |
|---|---|---|
variantEine gestrichelte Zone, eine Karte um einen Nachrichten-Editor oder ein ganzseitiges Overlay, das beim Ziehen erscheint. | "default" | "composer" | "overlay" | "default" |
target | "element" | "document" | "element" |
pasteTargetEin weiterer Ort, von dem eingefügte Dateien kommen. | "document" | string | Element | () => Element | – |
render | ReactElement | (props, state) => ReactElement | – |
| Attribut | Beschreibung |
|---|---|
data-slot="file-input-dropzone" | Spricht die Drop-Zone in CSS an. |
data-variant | Die Variante: default, composer oder overlay. |
data-dragging | Vorhanden, solange Dateien darüber gezogen werden. |
data-drag-accept | Vorhanden, solange die gezogenen Dateien nach Typ und Anzahl annehmbar aussehen. |
data-drag-reject | Vorhanden, solange eine gezogene Datei einen nicht angenommenen Typ hat oder es zu viele sind. |
data-disabled | Vorhanden, wenn deaktiviert. |
| Prop | Typ | Standard |
|---|---|---|
variant | Button variant | "outline" |
size | Button size | "sm" |
controllerVerbindet einen Auslöser außerhalb des Datei-Inputs, etwa einen in einer Toolbar. | FileInputController | – |
render | ReactElement | (props, state) => ReactElement | – |
| Prop | Typ | Standard |
|---|---|---|
layoutZeilen, quadratische Bildkacheln oder kompakte Chips. Einträge übernehmen ihr Aussehen daraus. | "list" | "grid" | "chips" | "list" |
render | ReactElement | (props, state) => ReactElement | – |
| Attribut | Beschreibung |
|---|---|
data-slot="file-input-list" | Spricht die Liste in CSS an. |
data-layout | Das Layout: list, grid oder chips. Einträge tragen es ebenfalls. |
| Prop | Typ | Standard |
|---|---|---|
childrenStandardmäßig Vorschau, Name, Größe und Entfernen-Button. Der Zustand enthält die Datei und ihren Index. | ReactNode | (state) => ReactNode | – |
render | ReactElement | (props, state) => ReactElement | – |
| Attribut | Beschreibung |
|---|---|
data-slot="file-input-item" | Spricht die Zeile einer Datei in CSS an. |
data-disabled | Vorhanden, wenn deaktiviert. |
| Attribut | Beschreibung |
|---|---|
data-slot="file-input-item-preview" | Spricht die Vorschau in CSS an. |
data-kind | image für eine Bildvorschau, icon für ein Icon nach Dateityp. |
| Prop | Typ | Standard |
|---|---|---|
localeFormatiert die Größe, etwa 2.4 kB, in diesem Locale. Standard ist das des Browsers. | string | – |
| Prop | Typ | Standard |
|---|---|---|
childrenStandardmäßig ein X-Icon. | ReactNode | – |
render | ReactElement | (props, state) => ReactElement | – |
| Prop | Typ | Standard |
|---|---|---|
getReasonLabelBenennt jeden Grund. Standardmäßig auf Englisch, etwa „Larger than 5 MB“. | (reason, rules, rejection) => string | – |
| Attribut | Beschreibung |
|---|---|
data-slot="file-input-rejections" | Spricht die Liste abgelehnter Dateien in CSS an. |
- ButtonButtons in allen Varianten und Größen, mit eingebautem Lade-, Erfolgs- und Fehlerablauf, der den Spinner bei schnellen Anfragen überspringt.
- CalendarEin Datumsraster für Einzel-, Bereichs- und Mehrfachauswahl, mit gleitenden Monaten, Bereichsvorschau und Tagen in Touch-Größe.
- CheckboxEine Checkbox, deren Häkchen sich einzeichnet, mit unbestimmten übergeordneten Elementen, Gruppen und Labels, die ihren Hover teilen.
- ComboboxEin filterbares Select mit Chips, Gruppen und asynchronen Ergebnissen, in einem Popup, das sich beim Tippen anpasst.
- Date pickerEin Button, der einen Kalender in einem Popover öffnet, auf Smartphones als Bottom Sheet, für einzelne Daten und Zeiträume.
- FieldLabels, Beschreibungen und Fehler, mit ihrem Steuerelement verbunden, mit Validierungszuständen und Layouts für Formulare.