Saltar al contenido principal
NachUI

Attachments

Archivos colgando de un mensaje o de un composer, como grilla, fila de chips o lista.

design-system.pdf243 KB
registry.ts12 KB
notes.md3.0 KB
1'use client';
2
3import { useState } from 'react';
4import { Attachments, type AttachmentData } from '@/components/ui/attachments';
5
6const INITIAL: AttachmentData[] = [
7 { id: '1', filename: 'design-system.pdf', mediaType: 'application/pdf', size: 248320 },
8 { id: '2', filename: 'registry.ts', mediaType: 'text/typescript', size: 12480 },
9 { id: '3', filename: 'notes.md', mediaType: 'text/markdown', size: 3120 },
10];
11
12export function Default() {
13 const [files, setFiles] = useState(INITIAL);
14
15 if (files.length === 0) {
16 return (
17 <div className="w-full max-w-md">
18 <Attachments>
19 <Attachments.Empty>Everything removed, reload the demo to start over</Attachments.Empty>
20 </Attachments>
21 </div>
22 );
23 }
24
25 return (
26 <div className="w-full max-w-md">
27 <Attachments>
28 {files.map((file) => (
29 <Attachments.Item
30 key={file.id}
31 data={file}
32 onRemove={() => setFiles((current) => current.filter((item) => item.id !== file.id))}
33 >
34 <Attachments.Preview />
35 <Attachments.Info />
36 <Attachments.Remove />
37 </Attachments.Item>
38 ))}
39 </Attachments>
40 </div>
41 );
42}

Instalación

pnpm dlx nachui add attachments

Anatomía

1import { Attachments } from '@/components/ui/attachments';
1<Attachments variant="grid">
2 {archivos.map((archivo) => (
3 <Attachments.Item key={archivo.id} data={archivo} onRemove={() => quitar(archivo.id)}>
4 <Attachments.Preview />
5 <Attachments.Info />
6 <Attachments.Remove />
7 </Attachments.Item>
8 ))}
9</Attachments>
Item pone el archivo en contexto, así Preview, Info y Remove lo leen solos en vez de recibir el mismo objeto tres veces. Una imagen con url se previsualiza en línea; cualquier otra cosa cae en un icono que podés cambiar.
Este es el lado de lectura. Para el selector y la zona de drop mirá Prompt Input, y para una fila de un solo archivo con progreso de subida mirá Attachment.

Composición

Usa la siguiente composición para construir un Attachments:
Attachments
├── Attachments.Item
│ ├── Attachments.Preview
│ ├── Attachments.Info
│ └── Attachments.Remove
└── Attachments.Empty

Variantes

grid acomoda tarjetas y esconde el botón de quitar hasta el hover, inline es una fila de píldoras que entra arriba del composer, y list es una fila de ancho completo por archivo con el botón de quitar al final.
grid
hero.png180 KB
spec.pdf61 KB
inline
hero.png180 KB
spec.pdf61 KB
list
hero.pngimage/png · 180 KB
spec.pdfapplication/pdf · 61 KB
1'use client';
2
3import { Attachments, type AttachmentData } from '@/components/ui/attachments';
4
5const FILES: AttachmentData[] = [
6 { id: '1', filename: 'hero.png', mediaType: 'image/png', size: 184320 },
7 { id: '2', filename: 'spec.pdf', mediaType: 'application/pdf', size: 62400 },
8];
9
10export function Variants() {
11 return (
12 <div className="flex w-full max-w-md flex-col gap-6">
13 {(['grid', 'inline', 'list'] as const).map((variant) => (
14 <div key={variant} className="flex flex-col gap-2">
15 <span className="text-muted-foreground font-mono text-[11px]">{variant}</span>
16 <Attachments variant={variant}>
17 {FILES.map((file) => (
18 <Attachments.Item key={file.id} data={file}>
19 <Attachments.Preview />
20 <Attachments.Info showMediaType={variant === 'list'} />
21 <Attachments.Remove />
22 </Attachments.Item>
23 ))}
24 </Attachments>
25 </div>
26 ))}
27 </div>
28 );
29}

Datos

data es un objeto plano, no un tipo de un SDK:
1interface AttachmentData {
2 id: string;
3 filename?: string;
4 mediaType?: string;
5 url?: string;
6 size?: number;
7}
formatSize y attachmentLabel se exportan junto al componente, así el mismo texto aparece en cualquier lugar donde listes archivos.

Referencia de API

Attachments

PropTypeDefaultDescription
variant'grid' | 'inline' | 'list''grid'Disposición de los ítems
classNamestring-Clases CSS adicionales

Attachments.Item

PropTypeDefaultDescription
dataAttachmentData-El archivo que describe este ítem
onRemove() => void-Lo llama Attachments.Remove
classNamestring-Clases CSS adicionales

Attachments.Preview

PropTypeDefaultDescription
fallbackIconReactNodeicono de archivoSe muestra cuando no hay previsualización
classNamestring-Clases CSS adicionales

Attachments.Info

PropTypeDefaultDescription
showMediaTypebooleanfalseAgrega el tipo a la línea de detalle
classNamestring-Clases CSS adicionales

Attachments.Remove

PropTypeDefaultDescription
labelstring'Remove'Prefijo del nombre accesible
classNamestring-Clases CSS adicionales

Attachments.Empty

PropTypeDefaultDescription
classNamestring-Clases CSS adicionales
¿Encontraste algo que mejorar?

¿Notaste un error, tipografía o detalle faltante en esta página? Ayúdanos a mejorar la documentación abriendo un issue en GitHub.

Crear un Issue