Attachment
Datei- und Bildkarten für Uploads, mit Fortschritt, Zuständen, Aktionen, einem Trigger über die ganze Karte und Namen, die ihre Dateiendung behalten.
pnpm dlx shadcn@latest add https://hextaui.com/r/attachment.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 @base-ui/react @tabler/icons-react class-variance-authority cnKopiere den folgenden Code und füge ihn in dein Projekt ein.
components/ui/attachment.tsx components/ui/aspect-ratio.tsx components/ui/skeleton.tsx components/ui/button.tsx components/ui/progress.tsx components/ui/scroll-area.tsx lib/motion.ts Passe die Importpfade an dein Projekt-Setup an.
Bild
variant="image" auf <AttachmentMedia /> zeigt ein quadratisches Vorschaubild, das beim Laden schimmert. Setze orientation="vertical" für eine Kachel mit der Vorschau oben.
Zustände
state deckt den gesamten Upload-Lebenszyklus ab. Inaktive Dateien erhalten einen gestrichelten Rahmen, Titel beim Hochladen und Verarbeiten schimmern, und bei Fehlern werden Media und Beschreibung rot.
Upload-Ablauf
Übergib progress, solange state="uploading" gilt, um einen dünnen Fortschrittsbalken am unteren Rand zu zeichnen. Bildvorschauen bleiben abgedunkelt, bis der Upload abgeschlossen ist.
Größen
size skaliert Padding, Media und Text gemeinsam und hält die inneren Ecken konzentrisch zur Karte.
Lange Namen
Lange Dateinamen werden vor der Endung gekürzt, sodass man weiterhin eine .pdf von einer .zip unterscheiden kann. Fahre über den Namen, um ihn vollständig zu lesen.
Gruppe
<AttachmentGroup /> ordnet Anhänge in einer Reihe an, die seitlich scrollt, mit ausblendenden Rändern und Elementen, die einrasten.
Trigger
<AttachmentTrigger /> macht die ganze Karte klickbar, zum Beispiel um eine Vorschau oder einen Link zu öffnen, während die Aktionen darauf unabhängig bleiben. Gib ihr ein aria-label.
Composer
Dateien, die nach dem Laden der Seite hinzukommen, poppen ein, und der Rest der Reihe rutscht sanft nach, wenn eine entfernt wird.
Defektes Bild
Wenn eine Bildvorschau nicht lädt, fällt sie auf ein Datei-Icon zurück.
Stresstest
Feindselige Namen in einer schmalen Spalte, alle 60 ms ein zufälliger Zustand und 200 Elemente in einer Gruppe. Nichts läuft über, und das Layout hält.
Rechts nach links
Media, Inhalt und Aktionen werden gespiegelt, und der Fortschrittsbalken füllt sich von der Startkante aus.
| Taste | Aktion |
|---|---|
| Tab | Setzt den Fokus auf jede Aktion und dann auf den Trigger. Verborgene Aktionen auf vertikalen Kacheln erscheinen, sobald der Fokus in die Karte wechselt. |
| EnterSpace | Aktiviert die fokussierte Aktion oder den fokussierten Trigger. |
- Während des Uploads hat der Fortschrittsbalken
role="progressbar"und wird nach dem Titel benannt. - String-Titel erhalten ein
title-Attribut mit dem vollständigen Namen, sodass gekürzte Namen weiterhin lesbar sind. - Reine Icon-Aktionen und der Trigger haben keinen Text, gib ihnen deshalb immer ein
aria-label, das die Datei benennt. - Bei reduzierter Bewegung erscheinen Anhänge ohne Einpoppen, der Fortschrittsbalken springt statt zu gleiten, und Gruppen ordnen sich sofort neu an.
Jeder Teil außer Group, Action und Trigger rendert ein einfaches Element und akzeptiert dessen Attribute. Die Kartenstile werden als attachmentVariants exportiert.
| Prop | Typ | Standard |
|---|---|---|
state | "idle" | "uploading" | "processing" | "error" | "done" | "done" |
progress0 bis 100. Wird nur während des Hochladens angezeigt und auf diesen Bereich begrenzt. | number | – |
size | "default" | "sm" | "xs" | "default" |
orientation | "horizontal" | "vertical" | "horizontal" |
| Attribut | Beschreibung |
|---|---|
data-slot="attachment" | Die Card in CSS ansprechen. |
data-state | Der aktuelle Zustand. |
data-size | Die aktuelle Größe. |
data-orientation | Die aktuelle Orientierung. |
data-slot="attachment-progress" | Der Fortschrittsbalken, vorhanden während des Uploads. |
--attachment-radius | Der Eckenradius der Karte. Die inneren Ecken werden davon abgeleitet. |
| Prop | Typ | Standard |
|---|---|---|
variantimage umschließt sein Kind mit einem quadratischen AspectRatio und einem Datei-Icon als Fallback. | "icon" | "image" | "icon" |
| Attribut | Beschreibung |
|---|---|
data-slot="attachment-media" | Das Media in CSS ansprechen. |
data-variant | Die aktuelle Variante. |
Eine <div>, die Titel und Beschreibung enthält und die verbleibende Breite einnimmt.
| Attribut | Beschreibung |
|---|---|
data-slot="attachment-content" | Den Inhalt in CSS ansprechen. |
| Prop | Typ | Standard |
|---|---|---|
childrenEin String wird so aufgeteilt, dass seine Dateiendung nie gekürzt wird. | ReactNode | – |
titleWird beim Hovern angezeigt. Standardmäßig der vollständige Name. | string | children |
idWird erzeugt, wenn nicht angegeben. Der Fortschrittsbalken wird danach benannt. | string | – |
| Attribut | Beschreibung |
|---|---|
data-slot="attachment-title" | Den Titel in CSS ansprechen. |
Eine einzeilige <span> für Größe, Typ oder Status. Sie wird gekürzt, wenn der Platz ausgeht.
| Attribut | Beschreibung |
|---|---|
data-slot="attachment-description" | Die Beschreibung in CSS ansprechen. |
Eine <div> für die Aktions-Buttons. Bei vertikalen Kacheln schwebt sie über der Vorschau und erscheint auf Geräten mit Maus beim Hovern oder Fokussieren.
| Attribut | Beschreibung |
|---|---|
data-slot="attachment-actions" | Die Aktionen in CSS ansprechen. |
Eine <Button />, die über dem Trigger sitzt. Sie akzeptiert alle Button-Props.
| Prop | Typ | Standard |
|---|---|---|
variant | ButtonVariant | "ghost" |
size | ButtonSize | "icon-xs" |
| Attribut | Beschreibung |
|---|---|
data-slot="attachment-action" | Actions in CSS ansprechen. |
Eine unsichtbare Ebene, die die ganze Karte abdeckt. Kombiniere sie mit einem Dialog-Trigger, einem Link oder einem beliebigen Button.
| Prop | Typ | Standard |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <button type="button"> |
| Attribut | Beschreibung |
|---|---|
data-slot="attachment-trigger" | Den Trigger in CSS ansprechen. |
Eine horizontale <ScrollArea />, die an jedem Anhang einrastet und die Reihe animiert, wenn Elemente hinzukommen oder entfernt werden. Sie akzeptiert alle ScrollArea-Props außer scrollbars.
| Attribut | Beschreibung |
|---|---|
data-slot="attachment-group" | Die Gruppe in CSS ansprechen. |
data-slot="attachment-group-list" | Die Reihe, die die Anhänge enthält. |
- Aspect ratioEine Box, die ihre Form behält, bevor Medien geladen sind, beim Laden schimmert, das Medium einblendet und bei einem Fehler auf einen Fallback zurückfällt.
- ButtonButtons in allen Varianten und Größen, mit eingebautem Lade-, Erfolgs- und Fehlerablauf, der den Spinner bei schnellen Anfragen überspringt.
- MotionDie Easing-Kurven, Dauern und der Reduced-Motion-Check, mit denen jede Komponente animiert, plus Hooks für Größen-Morphs und gleitende Hervorhebungen.
- ProgressEin Balken oder Ring, der zeigt, wie weit eine Aufgabe fortgeschritten ist, sanft zwischen Aktualisierungen wechselt und gleitet, solange die Gesamtmenge unbekannt ist.
- Scroll areaNatives Scrollen mit minimaler Scrollbar, Kanten, die nur dort ausblenden, wo es mehr zu sehen gibt, und einem optionalen Anschnitt, der das letzte Element halbiert.
- BubbleChat-Nachrichten-Bubbles mit Varianten, gruppierten Ecken, Reaktionen und Platz für interaktive Inhalte.
In Blocks verwendet
Blocks, die auf Attachment aufbauen.
- Prompt InputEin Chat-Composer, der als ruhige einzelne Zeile beginnt, beim Schreiben zu einer Karte wächst und nach unten wandert, sobald die Unterhaltung beginnt. Enter sendet, sicher bei japanischer und chinesischer Eingabe. Dateien per Einfügen, Ablegen oder Auswählen hinzufügen, mit Vorschau, Fortschritt und Wiederholen. @ fügt Dateien hinzu und / führt Befehle aus einem Menü an der Einfügemarke aus. Ein Modellwähler mit Zifferntasten, ein Effort-Slider, der bei Max lebendig wird, ein Kontextring, Diktat mit Live-Wellenform, Tool-Chips, eine Warteschlange für Nachrichten, die während einer streamenden Antwort getippt werden, und Entwürfe, die einen Reload überstehen.
- Chat ThreadDie ganze Unterhaltung rund um den Composer. Deine Frage bleibt oben angeheftet, während die Antwort streamt, Checkpoints an der Seite springen zwischen Nachrichten, und jede Antwort lässt sich kopieren, bearbeiten, wiederholen, bewerten und zwischen Versionen umschalten. Antworten rendern Markdown mit Codeblöcken, Tabellen und Zitaten, und Thinking, Tool-Aufrufe und Prompt Input lassen sich direkt einsetzen.