General
Item
Usage#
import { WDS_ITEM } from '@wds/angular/item';Examples#
Default#
href the whole item is a link, while buttons in the actions slot work on their own.
import { Component } from '@angular/core';
import { WdsItemComponent } from '@wds/angular/item';
import { WdsButtonComponent } from '@wds/angular/button';
@Component({
selector: 'app-item-default-demo',
imports: [WdsItemComponent, WdsButtonComponent],
template: `
<div class="flex w-full max-w-md flex-col gap-4">
<wds-item variant="outline" heading="Basic Item" description="A simple item with title and description.">
<wds-button slot="actions" variant="outline" size="sm">Action</wds-button>
</wds-item>
<wds-item variant="outline" size="sm" href="#" heading="Your profile has been verified.">
<svg slot="media" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" /><path d="m9 12 2 2 4-4" /></svg>
<svg slot="actions" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 18 6-6-6-6" /></svg>
</wds-item>
</div>
`,
})
export class ItemDefaultDemo {}Variant#
import { Component } from '@angular/core';
import { WdsItemComponent } from '@wds/angular/item';
import { WdsButtonComponent } from '@wds/angular/button';
@Component({
selector: 'app-item-variant-demo',
imports: [WdsItemComponent, WdsButtonComponent],
template: `
<div class="flex w-full max-w-md flex-col gap-4">
<wds-item heading="Default Variant" description="Transparent background with no border.">
<wds-button slot="actions" variant="outline" size="sm">Open</wds-button>
</wds-item>
<wds-item variant="outline" heading="Outline Variant" description="Outlined style with a visible border.">
<wds-button slot="actions" variant="outline" size="sm">Open</wds-button>
</wds-item>
<wds-item variant="muted" heading="Muted Variant" description="Muted background for secondary content.">
<wds-button slot="actions" variant="outline" size="sm">Open</wds-button>
</wds-item>
</div>
`,
})
export class ItemVariantDemo {}Icon#
media="icon" shows the icon on a muted 32×32 background.
import { Component } from '@angular/core';
import { WdsItemComponent } from '@wds/angular/item';
import { WdsButtonComponent } from '@wds/angular/button';
@Component({
selector: 'app-item-icon-demo',
imports: [WdsItemComponent, WdsButtonComponent],
template: `
<div class="flex w-full max-w-md flex-col">
<wds-item variant="outline" media="icon" heading="Security Alert" description="New login detected from unknown device.">
<svg slot="media" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" /><path d="M12 8v4" /><path d="M12 16h.01" /></svg>
<wds-button slot="actions" size="sm">Review</wds-button>
</wds-item>
</div>
`,
})
export class ItemIconDemo {}Avatar#
import { Component } from '@angular/core';
import { WdsItemComponent } from '@wds/angular/item';
import { WdsAvatarComponent, WdsAvatarGroupComponent } from '@wds/angular/avatar';
import { WdsButtonComponent } from '@wds/angular/button';
@Component({
selector: 'app-item-avatar-demo',
imports: [WdsItemComponent, WdsAvatarComponent, WdsAvatarGroupComponent, WdsButtonComponent],
template: `
<div class="flex w-full max-w-md flex-col gap-4">
<wds-item variant="outline" heading="Evil Rabbit" description="Last seen 5 months ago">
<wds-avatar slot="media" size="lg" src="https://github.com/evilrabbit.png" aria-hidden="true">ER</wds-avatar>
<wds-button slot="actions" variant="outline" size="icon-sm" shape="circle" label="Invite">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</wds-button>
</wds-item>
<wds-item variant="outline" heading="No Team Members" description="Invite your team to collaborate on this project.">
<wds-avatar-group slot="media" class="grayscale" aria-hidden="true">
<wds-avatar src="https://github.com/octocat.png">OC</wds-avatar>
<wds-avatar src="https://github.com/maxleiter.png">LR</wds-avatar>
<wds-avatar src="https://github.com/evilrabbit.png">ER</wds-avatar>
</wds-avatar-group>
<wds-button slot="actions" size="sm">Invite</wds-button>
</wds-item>
</div>
`,
})
export class ItemAvatarDemo {}Image#
media="image" crops the image to 40×40.
import { Component } from '@angular/core';
import { WdsItemComponent } from '@wds/angular/item';
@Component({
selector: 'app-item-image-demo',
imports: [WdsItemComponent],
template: `
<div class="flex w-full max-w-md flex-col gap-4">
<wds-item variant="outline" media="image" href="#" heading="Midnight City Lights" description="Neon Dreams">
<img slot="media" alt="" src="data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2040%2040'%3E%3Crect%20width%3D'40'%20height%3D'40'%20fill%3D'%23c7d2fe'%2F%3E%3Ccircle%20cx%3D'20'%20cy%3D'16'%20r%3D'7'%20fill%3D'%234338ca'%2F%3E%3Cpath%20d%3D'M6%2038c2-8%208-11%2014-11s12%203%2014%2011z'%20fill%3D'%234338ca'%2F%3E%3C%2Fsvg%3E" />
<span slot="actions">3:45</span>
</wds-item>
<wds-item variant="outline" media="image" href="#" heading="Coffee Shop Conversations" description="Urban Stories">
<img slot="media" alt="" src="data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2040%2040'%3E%3Crect%20width%3D'40'%20height%3D'40'%20fill%3D'%23fecaca'%2F%3E%3Ccircle%20cx%3D'20'%20cy%3D'16'%20r%3D'7'%20fill%3D'%23b91c1c'%2F%3E%3Cpath%20d%3D'M6%2038c2-8%208-11%2014-11s12%203%2014%2011z'%20fill%3D'%23b91c1c'%2F%3E%3C%2Fsvg%3E" />
<span slot="actions">4:05</span>
</wds-item>
</div>
`,
})
export class ItemImageDemo {}Group#
wds-item-group is a list of items; wds-item-separator draws a line between them.
import { Component } from '@angular/core';
import { WdsItemComponent, WdsItemGroupComponent, WdsItemSeparatorComponent } from '@wds/angular/item';
import { WdsAvatarComponent } from '@wds/angular/avatar';
import { WdsButtonComponent } from '@wds/angular/button';
@Component({
selector: 'app-item-group-demo',
imports: [WdsItemGroupComponent, WdsItemComponent, WdsItemSeparatorComponent, WdsAvatarComponent, WdsButtonComponent],
template: `
<div class="flex w-full max-w-md flex-col">
<wds-item-group class="rounded-md border border-border">
<wds-item heading="Anna Smith" description="[email protected]">
<wds-avatar slot="media" size="lg" aria-hidden="true">AS</wds-avatar>
<wds-button slot="actions" variant="ghost" size="icon-sm" shape="circle" label="Message Anna Smith">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</wds-button>
</wds-item>
<wds-item-separator></wds-item-separator>
<wds-item heading="John Doe" description="[email protected]">
<wds-avatar slot="media" size="lg" aria-hidden="true">JD</wds-avatar>
<wds-button slot="actions" variant="ghost" size="icon-sm" shape="circle" label="Message John Doe">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</wds-button>
</wds-item>
<wds-item-separator></wds-item-separator>
<wds-item heading="Olivia Brown" description="[email protected]">
<wds-avatar slot="media" size="lg" aria-hidden="true">OB</wds-avatar>
<wds-button slot="actions" variant="ghost" size="icon-sm" shape="circle" label="Message Olivia Brown">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
</wds-button>
</wds-item>
</wds-item-group>
</div>
`,
})
export class ItemGroupDemo {}Header and footer#
header and footer slots add full-width rows above and below the item.
import { Component } from '@angular/core';
import { WdsItemComponent } from '@wds/angular/item';
import { WdsBadgeComponent } from '@wds/angular/badge';
import { WdsButtonComponent } from '@wds/angular/button';
@Component({
selector: 'app-item-header-footer-demo',
imports: [WdsItemComponent, WdsBadgeComponent, WdsButtonComponent],
template: `
<div class="flex w-full max-w-md flex-col">
<wds-item variant="outline" heading="Quarterly report" description="PDF, 2.4 MB. Generated automatically when the quarter closed.">
<wds-badge slot="header" variant="secondary">New</wds-badge>
<span slot="header">September 12</span>
<wds-button slot="footer" variant="outline" size="sm">Preview</wds-button>
<wds-button slot="footer" size="sm">Download</wds-button>
</wds-item>
</div>
`,
})
export class ItemHeaderFooterDemo {}Size#
import { Component } from '@angular/core';
import { WdsItemComponent } from '@wds/angular/item';
@Component({
selector: 'app-item-size-demo',
imports: [WdsItemComponent],
template: `
<div class="flex w-full max-w-md flex-col gap-4">
<wds-item variant="outline" heading="Default" description="16px padding."></wds-item>
<wds-item variant="outline" size="sm" heading="Small" description="Less vertical padding (12px)."></wds-item>
</div>
`,
})
export class ItemSizeDemo {}Tile#
layout="tile" makes a square with the media centered and the title below. It combines with variant and size.
import { Component } from '@angular/core';
import { WdsItemComponent } from '@wds/angular/item';
import { WdsIconComponent } from '@wds/angular/icon';
@Component({
selector: 'app-item-tile-demo',
imports: [WdsItemComponent, WdsIconComponent],
template: `
<div class="flex flex-wrap gap-3">
<wds-item variant="outline" layout="tile" href="#" heading="Analytics" class="w-28">
<wds-icon slot="media" name="analytics-dashboard" size="xl"></wds-icon>
</wds-item>
<wds-item variant="outline" layout="tile" href="#" heading="Campaigns" class="w-28">
<wds-icon slot="media" name="campaigns-dashboard" size="xl"></wds-icon>
</wds-item>
<wds-item variant="muted" layout="tile" href="#" heading="Settings" class="w-28">
<wds-icon slot="media" name="settings-dashboard" size="xl"></wds-icon>
</wds-item>
</div>
`,
})
export class ItemTileDemo {}Marker#
size="xs" makes a marker: one line of small, muted text with a 16px icon column and no padding, e.g. the steps of an agent or a build. Long text wraps inside the row.
import { Component } from '@angular/core';
import { WdsItemComponent } from '@wds/angular/item';
@Component({
selector: 'app-item-marker-demo',
imports: [WdsItemComponent],
template: `
<div class="flex w-full max-w-sm flex-col gap-2">
<wds-item size="xs" heading="Searched the codebase for “toast”">
<svg slot="media" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></svg>
</wds-item>
<wds-item size="xs" heading="Read src/components/toast/toaster.ts">
<svg slot="media" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" /><path d="M14 2v4a2 2 0 0 0 2 2h4" /></svg>
</wds-item>
<wds-item size="xs" heading="Ran pnpm build">
<svg slot="media" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m4 17 6-6-6-6" /><path d="M12 19h8" /></svg>
</wds-item>
</div>
`,
})
export class ItemMarkerDemo {}Marker with status#
media slot show the state of each step; a wds-spinner marks the running one. The actions slot holds the duration on the right.
import { Component } from '@angular/core';
import { WdsItemComponent } from '@wds/angular/item';
import { WdsSpinnerComponent } from '@wds/angular/spinner';
@Component({
selector: 'app-item-marker-status-demo',
imports: [WdsItemComponent, WdsSpinnerComponent],
template: `
<div class="flex w-full max-w-sm flex-col gap-2" aria-label="Deployment steps" role="list">
<wds-item size="xs" role="listitem" heading="Install dependencies">
<svg slot="media" class="text-emerald-600" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>
<span slot="actions" class="tabular-nums">12s</span>
</wds-item>
<wds-item size="xs" role="listitem" heading="Build">
<svg slot="media" class="text-emerald-600" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>
<span slot="actions" class="tabular-nums">48s</span>
</wds-item>
<wds-item size="xs" role="listitem" heading="Run tests" class="[--wds-muted-foreground:var(--wds-foreground)]">
<wds-spinner slot="media" size="sm" label="Running"></wds-spinner>
</wds-item>
<wds-item size="xs" role="listitem" heading="Deploy">
<svg slot="media" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10" /></svg>
</wds-item>
</div>
`,
})
export class ItemMarkerStatusDemo {}Marker with phases#
wds-separator with text groups the markers into phases.
import { Component } from '@angular/core';
import { WdsSeparatorComponent } from '@wds/angular/separator';
import { WdsItemComponent } from '@wds/angular/item';
@Component({
selector: 'app-item-marker-phases-demo',
imports: [WdsSeparatorComponent, WdsItemComponent],
template: `
<div class="flex w-full max-w-sm flex-col gap-2">
<wds-separator class="my-1">Plan</wds-separator>
<wds-item size="xs" heading="Read the issue and the failing test">
<svg slot="media" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" /><path d="M14 2v4a2 2 0 0 0 2 2h4" /></svg>
</wds-item>
<wds-separator class="my-1">Build</wds-separator>
<wds-item size="xs" heading="Edited src/components/tooltip/tooltip.ts">
<svg slot="media" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" /><path d="M14 2v4a2 2 0 0 0 2 2h4" /></svg>
</wds-item>
<wds-item size="xs" heading="Ran pnpm build">
<svg slot="media" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m4 17 6-6-6-6" /><path d="M12 19h8" /></svg>
</wds-item>
<wds-separator class="my-1">Verify</wds-separator>
<wds-item size="xs" heading="47 checks passed">
<svg slot="media" class="text-emerald-600" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>
</wds-item>
</div>
`,
})
export class ItemMarkerPhasesDemo {}Marker with borders#
wds-item-group with wds-item-separator lines between them, markers make a compact list, here of changed files.
import { Component } from '@angular/core';
import { WdsItemComponent, WdsItemGroupComponent, WdsItemSeparatorComponent } from '@wds/angular/item';
@Component({
selector: 'app-item-marker-files-demo',
imports: [WdsItemGroupComponent, WdsItemComponent, WdsItemSeparatorComponent],
template: `
<wds-item-group class="w-full max-w-sm [--wds-item-group-gap:8px]" aria-label="Changed files">
<wds-item size="xs" heading="src/components/tooltip/tooltip.ts">
<svg slot="media" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" /><path d="M14 2v4a2 2 0 0 0 2 2h4" /></svg>
<span slot="actions" class="text-emerald-700 tabular-nums">+312</span>
<span slot="actions" class="text-destructive tabular-nums">−0</span>
</wds-item>
<wds-item-separator></wds-item-separator>
<wds-item size="xs" heading="src/components/button/button.ts">
<svg slot="media" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" /><path d="M14 2v4a2 2 0 0 0 2 2h4" /></svg>
<span slot="actions" class="text-emerald-700 tabular-nums">+4</span>
<span slot="actions" class="text-destructive tabular-nums">−1</span>
</wds-item>
<wds-item-separator></wds-item-separator>
<wds-item size="xs" heading="src/index.ts">
<svg slot="media" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" /><path d="M14 2v4a2 2 0 0 0 2 2h4" /></svg>
<span slot="actions" class="text-emerald-700 tabular-nums">+4</span>
<span slot="actions" class="text-destructive tabular-nums">−0</span>
</wds-item>
</wds-item-group>
`,
})
export class ItemMarkerFilesDemo {}Marker as a link#
href the marker is a link: the text darkens and is underlined on hover.
import { Component } from '@angular/core';
import { WdsItemComponent } from '@wds/angular/item';
@Component({
selector: 'app-item-marker-links-demo',
imports: [WdsItemComponent],
template: `
<div class="flex w-full max-w-sm flex-col gap-2">
<wds-item size="xs" href="#" heading="Open the build log">
<svg slot="media" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 3h6v6" /><path d="M10 14 21 3" /><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h3" /></svg>
</wds-item>
<wds-item size="xs" href="#" heading="View 3 failed tests">
<svg slot="media" class="text-destructive" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10" /><path d="m15 9-6 6" /><path d="m9 9 6 6" /></svg>
</wds-item>
</div>
`,
})
export class ItemMarkerLinksDemo {}API References#
wds-item#
href the whole item is a link (stretched over the whole surface), while buttons
in the actions slot work on their own.
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
| variant | WdsItemVariant | 'default' | outline) or on a muted background (muted). |
| size | WdsItemSize | 'default' | sm reduces the spacing. xs is a marker: one line of small, muted text with an icon column and no padding
(a status, a step in a log, a changed file). |
| layout | WdsItemLayout | 'default' | tile: a square with the media centered and the title below it (e.g. an icon gallery).
Combines with variant and size. |
| media | WdsItemMedia | 'default' | icon (icon on a 32×32 background) or image (40×40 image). |
| heading | string | '' | title slot takes precedence. |
| description | string | '' | description slot takes precedence. |
| href | string | undefined | ||
| target | string | undefined | _blank. | |
| rel | string | undefined | rel. With target="_blank" it defaults to noopener noreferrer. |
Slots
| Slot | Description |
|---|---|
| (default) | |
| media | <svg> icon, image or avatar. |
| title | heading). |
| description | description), clamped to 2 lines. |
| actions | |
| header | |
| footer |
CSS parts (::part)
| Part | Description |
|---|---|
| item | |
| media | |
| content | |
| title | |
| description | |
| actions |
CSS custom properties
| Property | Description |
|---|---|
| --wds-item-radius | |
| --wds-item-description-lines |
wds-item-group#
wds-item elements (role="list").
Slots
| Slot | Description |
|---|---|
| (default) | wds-item and wds-item-separator. |
CSS custom properties
| Property | Description |
|---|---|
| --wds-item-group-gap |
wds-item-separator#
wds-item-group (decorative).
Accessibility#
Screen reader#
wds-item-group has role="list" and each wds-item directly inside it role="listitem", so screen readers announce the number of items. wds-item-separator is hidden from screen readers.
href the title is a native <a> stretched over the whole item: the link is named by the title, and the description is read as the next text. Without href the item has no role of its own.
aria-hidden="true", decorative images alt="", and icon-only buttons in the actions slot a label.
Keyboard support#
| Key | Function |
|---|---|
href, then to the controls in the actions, header and footer slots. | |