Attachment
A hand-drawn file chip with an optional icon, metadata, and remove button.
Overview
Attachment is a compact chip representing a file or resource — an optional leading icon, a name
with optional metadata (like a size), and an optional remove button. Use it to show uploaded files,
email attachments, or any referenced resource that a user can review and optionally remove.
Anatomy
A hand-drawn box (@ghds/sketch-core) laying out, left to right: an optional Icon, a stacked
name + meta column, and — when onRemove is set — a remove <button> with a close icon. Every
colour, padding, radius, and sketch parameter comes from @ghds/tokens (comp.attachment.*).
Variants & States
No named variants — the chip is shaped by which optional parts you supply (icon, meta,
onRemove).
| State | Status | Notes |
|---|---|---|
| With icon | Implemented | A leading @ghds/icons glyph via the icon prop. |
| With meta | Implemented | A secondary line, e.g. a file size. |
| Removable | Implemented | onRemove renders a labelled remove button. |
| Disabled | Not implemented | — |
| Loading | Not implemented | — |
Usage
Do
- Show a human-readable size or type in meta so users can judge the file at a glance.
- Provide onRemove for attachments the user can detach, and keep the default Remove {name} label meaningful.
- Pick an icon that matches the file kind when one is available.
Don't
- Don't put a long file name in an unbounded row; let the layout wrap or truncate as your container needs.
- Don't use Attachment as a button for opening the file — it's a descriptive chip, with only the remove action interactive.
Accessibility
- The remove control is a real
<button>with an accessible label —removeLabel, or the defaultRemove {name}— so screen-reader users know exactly which attachment it detaches. - The leading icon is decorative; the name text carries the meaning.
- When you render a set of attachments, place them in a list structure so their count and grouping are conveyed.
- See the Accessibility Guide for shared conventions.
Content
Keep name the actual file name and meta a short, factual descriptor (size, type, or date). Avoid
duplicating the name inside meta.
Props API
React@ghds/react
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | — | File (or resource) name shown as the primary label. Required. |
meta | string | — | Secondary metadata, e.g. a human-readable size like "2.4 MB". |
icon | IconName | — | Optional leading icon (a @ghds/icons name). |
onRemove | () => void | — | When provided, renders a remove button that calls this handler. |
removeLabel | string | 'Remove {name}' | Accessible label for the remove button. |
...rest | HTMLAttributes<HTMLDivElement> | — | Native <div> attributes pass through. |
Web Components@ghds/web-components
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | — | File (or resource) name shown as the primary label. |
meta | string | — | Secondary metadata, e.g. a human-readable size. |
icon | string | — | Optional leading icon (a @ghds/icons name). |
removable | boolean | false | Reflected attribute; renders a remove button that emits gh-remove. |
gh-remove | CustomEvent | — | Fired when the remove button is pressed (no detail). |
React Native@ghds/react-native
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | — | File (or resource) name shown as the primary label. Required. |
meta | string | — | Secondary metadata, e.g. a human-readable size. |
icon | IconName | — | Optional leading icon (a @ghds/icons name). |
onRemove | () => void | — | When provided, renders a remove button that calls this handler. |
removeLabel | string | 'Remove {name}' | Accessible label for the remove button. |
testID | string | — | Test handle for queries. |
Code examples
// React — @ghds/react
import { Attachment } from '@ghds/react/attachment';
<Attachment name="newsletter.eml" meta="12 KB" icon="mail" />
<Attachment name="quarterly-report.pdf" meta="2.4 MB" onRemove={() => detach()} />;
<!-- Web Components — @ghds/web-components -->
<script type="module">
import '@ghds/web-components/attachment';
</script>
<gh-attachment name="newsletter.eml" meta="12 KB" icon="mail"></gh-attachment>
<gh-attachment name="quarterly-report.pdf" meta="2.4 MB" removable></gh-attachment>
// React Native — @ghds/react-native
import { Attachment } from '@ghds/react-native/attachment';
<Attachment name="quarterly-report.pdf" meta="2.4 MB" onRemove={() => detach()} />;
Live Demo
React and Web Components render live below, driven by the same tokens — toggle dark mode in the
header to see both respond identically. React Native can’t run in a browser without additional
react-native-web wiring (not set up in this site), so its usage is shown as a code sample instead.
Note the remove API differs: React/React Native take an onRemove callback, while Web Components
sets removable and emits a gh-remove event.