@thebase/ui
Version:
CDN-installable Owl and Bootstrap 5 UI component library.
239 lines (213 loc) • 9.86 kB
Markdown
# Attachment
Use `b-ui="attachment"` for a CDN-ready attachment card with media, metadata, upload state, and actions.
## CDN install requirements
Load the pinned BaseUI CSS and JavaScript files; no extra dependency is required for this component.
## Pure Owl component
```js
import {
Attachment,
AttachmentAction,
AttachmentActions,
AttachmentContent,
AttachmentDescription,
AttachmentDropzone,
AttachmentGroup,
AttachmentMedia,
AttachmentTitle,
AttachmentTrigger,
} from "@thebase/ui";
```
```base-ui
<div class="d-grid gap-3" style="max-width: 28rem; width: 100%">
<AttachmentGroup className="'d-flex gap-3 overflow-auto pb-2'">
<Attachment state="'done'" size="'sm'" orientation="'vertical'">
<AttachmentMedia variant="'image'">
<img src="https://images.unsplash.com/photo-1497366754035-f200968a6e72?auto=format&fit=crop&w=240&q=80" alt="Workspace" class="w-100 h-100 object-fit-cover"/>
</AttachmentMedia>
<AttachmentContent>
<AttachmentTitle>workspace.png</AttachmentTitle>
<AttachmentDescription>PNG · 820 KB</AttachmentDescription>
</AttachmentContent>
</Attachment>
<Attachment state="'done'" size="'sm'" orientation="'vertical'">
<AttachmentMedia variant="'image'">
<img src="https://images.unsplash.com/photo-1497366811353-6870744d04b2?auto=format&fit=crop&w=240&q=80" alt="Desk" class="w-100 h-100 object-fit-cover"/>
</AttachmentMedia>
<AttachmentContent>
<AttachmentTitle>desk-reference.jpg</AttachmentTitle>
<AttachmentDescription>JPG · 1.1 MB</AttachmentDescription>
</AttachmentContent>
</Attachment>
<Attachment state="'done'" size="'sm'" orientation="'vertical'">
<AttachmentMedia variant="'image'">
<img src="https://images.unsplash.com/photo-1497366216548-37526070297c?auto=format&fit=crop&w=240&q=80" alt="Office" class="w-100 h-100 object-fit-cover"/>
</AttachmentMedia>
<AttachmentContent>
<AttachmentTitle>office-reference.jpg</AttachmentTitle>
<AttachmentDescription>JPG · 940 KB</AttachmentDescription>
</AttachmentContent>
</Attachment>
</AttachmentGroup>
<div class="d-grid gap-3">
<Attachment state="'uploading'" className="'w-100'">
<AttachmentMedia>
<Icon name="'refresh-cw'"/>
</AttachmentMedia>
<AttachmentContent>
<AttachmentTitle>sales-dashboard.pdf</AttachmentTitle>
<AttachmentDescription>Uploading · 64%</AttachmentDescription>
</AttachmentContent>
<AttachmentActions>
<AttachmentAction aria-label="'Remove sales-dashboard.pdf'">
<Icon name="'x'"/>
</AttachmentAction>
</AttachmentActions>
</Attachment>
<Attachment state="'done'" className="'w-100'">
<AttachmentMedia>
<Icon name="'file-code'"/>
</AttachmentMedia>
<AttachmentContent>
<AttachmentTitle>message-renderer.tsx</AttachmentTitle>
<AttachmentDescription>TypeScript · 12 KB</AttachmentDescription>
</AttachmentContent>
<AttachmentActions>
<AttachmentAction aria-label="'Remove message-renderer.tsx'">
<Icon name="'x'"/>
</AttachmentAction>
</AttachmentActions>
<AttachmentTrigger aria-label="'Open message-renderer.tsx'"/>
</Attachment>
</div>
</div>
```
```base-ui
<AttachmentGroup>
<Attachment state="'done'" size="'sm'">
<AttachmentMedia>PDF</AttachmentMedia>
<AttachmentContent>
<AttachmentTitle>sales-dashboard.pdf</AttachmentTitle>
<AttachmentDescription>PDF · 2.4 MB</AttachmentDescription>
</AttachmentContent>
<AttachmentActions>
<AttachmentAction aria-label="'Remove sales-dashboard.pdf'">×</AttachmentAction>
</AttachmentActions>
<AttachmentTrigger aria-label="'Open sales-dashboard.pdf'"/>
</Attachment>
</AttachmentGroup>
```
| Component | Prop | Type | Notes |
| --- | --- | --- | --- |
| `Attachment` | `state` | `String` | `idle`, `uploading`, `processing`, `error`, `done` |
| `Attachment` | `size` | `String` | `default`, `sm`, `xs` |
| `Attachment` | `orientation` | `String` | `horizontal` or `vertical` |
| `Attachment` | `multiple` | `Boolean` | file picker fallback only |
| `Attachment` | `onChange` | `Function` | receives selected file array |
| `AttachmentMedia` | `variant` | `String` | `icon` or `image` |
| `AttachmentTrigger` | `href` | `String` | renders a link when provided |
| `AttachmentTrigger` | `aria-label` | `String` | label for the full-card target |
| `AttachmentAction` | `variant` | `String` | `default`, `secondary`, `destructive`, `outline`, `ghost`, `link`; defaults to `ghost` |
| `AttachmentAction` | `size` | `String` | button size such as `icon-xs`, `icon-sm`, `icon`; defaults to `icon-xs` |
| `AttachmentAction` | `aria-label` | `String` | label for icon-only actions |
| `AttachmentDropzone` | `multiple` | `Boolean` | allow multi-file selection |
| `AttachmentDropzone` | `disabled` | `Boolean` | disables click/drag/drop |
| `AttachmentDropzone` | `onFilesSelected` | `Function` | receives the picked/dropped `File[]` |
See [Pure Owl Components](/examples/blocks.html#/docs/guide/owl-components) for how to load `@base/owl` and `dist/baseui.templates.xml`.
## Static component
```base-ui
<div class="d-grid justify-content-center gap-3" style="min-height: 18rem">
<div b-ui="attachment-group" aria-label="Image attachments">
<div b-ui="attachment" b-att-orientation="vertical">
<div b-attachment-media b-att-variant="image">
<img src="https://images.unsplash.com/photo-1497366754035-f200968a6e72?auto=format&fit=crop&w=240&q=80" alt="Workspace">
</div>
<div b-attachment-content>
<div b-attachment-title>workspace.png</div>
<div b-attachment-description>PNG · 820 KB</div>
</div>
</div>
<div b-ui="attachment" b-att-orientation="vertical">
<div b-attachment-media b-att-variant="image">
<img src="https://images.unsplash.com/photo-1497366811353-6870744d04b2?auto=format&fit=crop&w=240&q=80" alt="Desk">
</div>
<div b-attachment-content>
<div b-attachment-title>desk-reference.jpg</div>
<div b-attachment-description>JPG · 1.1 MB</div>
</div>
</div>
<div b-ui="attachment" b-att-orientation="vertical">
<div b-attachment-media b-att-variant="image">
<img src="https://images.unsplash.com/photo-1497366216548-37526070297c?auto=format&fit=crop&w=240&q=80" alt="Office">
</div>
<div b-attachment-content>
<div b-attachment-title>office-reference.jpg</div>
<div b-attachment-description>JPG · 940 KB</div>
</div>
</div>
</div>
<div class="d-grid gap-3" style="width: min(24rem, 100%)">
<div b-ui="attachment" b-att-state="uploading" class="w-100">
<div b-attachment-media>
<span b-icon="refresh-cw"></span>
</div>
<div b-attachment-content>
<div b-attachment-title>sales-dashboard.pdf</div>
<div b-attachment-description>Uploading · 64%</div>
</div>
<div b-attachment-actions>
<button b-attachment-action type="button" aria-label="Remove sales-dashboard.pdf">
<span b-icon="x"></span>
</button>
</div>
</div>
<div b-ui="attachment" class="w-100">
<div b-attachment-media>
<span b-icon="file-code"></span>
</div>
<div b-attachment-content>
<div b-attachment-title>message-renderer.tsx</div>
<div b-attachment-description>TypeScript · 12 KB</div>
</div>
<div b-attachment-actions>
<button b-attachment-action type="button" aria-label="Remove message-renderer.tsx">
<span b-icon="x"></span>
</button>
</div>
</div>
</div>
</div>
```
For file picker behavior, keep an input inside the root:
```base-ui
<div b-ui="attachment">
<input type="file" multiple>
<ul b-attachment-list></ul>
</div>
```
Use `b-ui="attachment-group"` to lay out multiple attachments in a horizontally scrollable, snapping row.
## Dropzone
Use `b-ui="attachment-dropzone"` for a drag-and-drop upload target with a hidden file input, for building an upload flow (e.g. paired with `attachment`/`attachment-group` to render the resulting list). It only reports the picked/dropped files — the host page owns the actual upload request.
```base-ui
<div b-ui="attachment-dropzone">
<input type="file" multiple hidden>
<p>Drag and drop a file here, or click to browse.</p>
</div>
```
| Attribute | Notes |
| --- | --- |
| `multiple` | on the inner `input[type=file]`; allows multi-file selection. |
| `disabled` | on the inner `input[type=file]`; visually and functionally disables the zone. |
The dropzone emits `baseui:change` with `{ files }` on drop, on file-input change, or on click-to-browse selection.
## Options and attributes
| Attribute | Values | Notes |
| --- | --- | --- |
| `b-att-state` | `idle`, `uploading`, `processing`, `error`, `done` | Adds upload-state styling; defaults to `done`. |
| `b-att-size` | `default`, `sm`, `xs` | Controls density. |
| `b-att-orientation` | `horizontal`, `vertical` | Vertical stacks media above content. |
| `b-att-variant` | `icon`, `image` | Use on `[b-attachment-media]`. |
| `b-attachment-trigger` | marker | Full-card button or link overlay. |
| `b-attachment-action` | marker | Compact ghost `icon-xs` action button; provide an `aria-label` when icon-only. |
## Events
The file picker fallback emits `baseui:change` with `{ files }` from the root element.
## Accessibility behavior
Use real buttons or links for actions and triggers. Icon-only action buttons need a target-specific `aria-label`, and error attachments should include the failure reason in the description.