Skip to content
ShineUI
Install

DescriptionList

Facts about one record.

<sui-description-list>DataStable

About

Key and value pairs for record inspectors and detail panes, rendered as a real dl of dt and dd pairs. Rows draw hairlines with a fixed term column; columns draw a grid of sunken cells with small uppercase labels. Display only; sui-config-list is the interactive sibling.

Usage

<sui-description-list></sui-description-list> <script type="module"> import { defineCustomElements } from "@shineui/core/loader"; import "@shineui/core/shineui.css"; defineCustomElements(); const el = document.querySelector("sui-description-list"); el.items = [ { term: "Invoice", detail: "INV-1043", copy: true }, { term: "Customer", detail: "Silver Hills Church" }, { term: "Due", detail: "Sep 7, 2026" }, { term: "Balance", detail: "$6,420.00", strong: true }, ]; /* SuiDescriptionItem[] */ el.addEventListener("suiCopy", (e) => console.log(e.detail)); </script>
import { SuiDescriptionList } from "@shineui/react"; import "@shineui/core/shineui.css"; export function Example() { const items = [ { term: "Invoice", detail: "INV-1043", copy: true }, { term: "Customer", detail: "Silver Hills Church" }, { term: "Due", detail: "Sep 7, 2026" }, { term: "Balance", detail: "$6,420.00", strong: true }, ]; /* SuiDescriptionItem[] */ return <SuiDescriptionList items={items} onSuiCopy={(e) => console.log(e.detail)} />; }
<script setup> import { SuiDescriptionList } from "@shineui/vue"; import "@shineui/core/shineui.css"; const items = [ { term: "Invoice", detail: "INV-1043", copy: true }, { term: "Customer", detail: "Silver Hills Church" }, { term: "Due", detail: "Sep 7, 2026" }, { term: "Balance", detail: "$6,420.00", strong: true }, ]; // SuiDescriptionItem[] const onChange = (e) => console.log(e.detail); </script> <template> <SuiDescriptionList :items="items" @sui-copy="onChange" /> </template>
import { Component } from "@angular/core"; import { SuiDescriptionList } from "@shineui/angular"; @Component({ standalone: true, imports: [SuiDescriptionList], template: `<sui-description-list [items]="items" (suiCopy)="onChange($event)"></sui-description-list>`, }) export class Example { items = [ { term: "Invoice", detail: "INV-1043", copy: true }, { term: "Customer", detail: "Silver Hills Church" }, { term: "Due", detail: "Sep 7, 2026" }, { term: "Balance", detail: "$6,420.00", strong: true }, ]; // SuiDescriptionItem[] onChange(e: CustomEvent) { console.log(e.detail); } }

Basic

layout="rows" is the default: hairline rows with a fixed term column, for a detail pane beside a record. strong bolds a total; copy adds a copy control after the value.

<div style="max-width:420px"><sui-description-list></sui-description-list></div>
// setup(root): properties and events setup(root) { root.querySelector('sui-description-list').items = invoiceFacts(); }

Two columns

layout="columns" stacks each term over its detail and flows them across the given number of tracks, for a summary header rather than an inspector rail.

<div style="max-width:520px"><sui-description-list id="dl-cols" layout="columns" columns="2"></sui-description-list></div>
// setup(root): properties and events setup(root) { root.querySelector('#dl-cols').items = [ { term: 'Invoice', detail: 'INV-1043', copy: true }, { term: 'Customer', detail: 'Silver Hills Church' }, { term: 'Issued', detail: 'Aug 8, 2026' }, { term: 'Due', detail: 'Sep 7, 2026' }, { term: 'Terms', detail: 'Net 30' }, { term: 'Balance', detail: '$6,420.00', strong: true }, ]; }

An element as the value

A detail may be a string, a number or an HTMLElement, mounted as it is; that is how a status pill, a link or an inline control sits in the value column, and what it paints past its box on hover or focus is never clipped. A long text value wraps rather than truncating. term-width widens the term column.

<div style="max-width:460px"><sui-description-list id="dl-node" term-width="180"></sui-description-list></div>
// setup(root): properties and events setup(root) { const doc = root.ownerDocument; const pill = doc.createElement('sui-tag'); pill.setAttribute('label', 'Overdue'); pill.setAttribute('severity', 'critical'); const priority = doc.createElement('sui-select'); priority.setAttribute('variant', 'quiet'); priority.setAttribute('label', 'Priority'); priority.setAttribute('size', 'sm'); priority.options = [ { label: 'Urgent', value: 'urgent', icon: 'fa-solid fa-angles-up' }, { label: 'High', value: 'high', icon: 'fa-solid fa-angle-up' }, { label: 'Normal', value: 'normal', icon: 'fa-solid fa-minus' }, ]; priority.value = 'high'; root.querySelector('#dl-node').items = [ { term: 'Invoice', detail: 'INV-1043', copy: true }, { term: 'Collection status', detail: pill }, { term: 'Priority', detail: priority }, { term: 'Days outstanding', detail: 45 }, { term: 'Reference', detail: 'PO-2211-RIVERBEND-DENTAL-GROUP-SEPTEMBER-STATEMENT-ROLLUP' }, { term: 'Balance', detail: '$6,420.00', strong: true }, ]; }

Copy and copy failure

Each copy control is named for its own row ("Copy Invoice"), and a polite status region announces "Copied". suiCopy follows a confirmed clipboard write; when the write fails the element shows no "Copied" state and emits suiCopyError with the same item.

Nothing copied yet.
<div style="display:grid;gap:10px;max-width:420px"> <code id="dl-log" style="font:460 12px/1.6 var(--font-sans);color:var(--ink-muted)">Nothing copied yet.</code> <sui-description-list id="dl-events"></sui-description-list> </div>
// setup(root): properties and events setup(root) { const el = root.querySelector('#dl-events'); const log = root.querySelector('#dl-log'); el.items = [ { term: 'Invoice', detail: 'INV-1043', copy: true }, { term: 'Customer', detail: 'Silver Hills Church', copy: true }, { term: 'Balance', detail: '$6,420.00', strong: true, copy: true }, ]; el.addEventListener('suiCopy', (e) => { log.textContent = `Copied ${e.detail.term}: ${e.detail.detail}`; }); el.addEventListener('suiCopyError', (e) => { log.textContent = `Could not copy ${e.detail.term}. Nothing reached the clipboard.`; }); }

Keyboard

KeyAction
TabMoves through the copy controls, one per item marked copy; the terms and values take no focus.
Enter SpaceCopies the value, swaps the icon to a check, announces Copied through a polite live region and emits suiCopy with the item; a blocked clipboard emits suiCopyError instead.

API

<sui-description-list>

Properties

PropertyAttributeTypeDefaultDescription
columnscolumnsnumber2Grid column count in the columns layout.
itemsproperty onlySuiDescriptionItem[][]The pairs to show. An item with copy gets a copy control after its value, a sui-tooltip named "Copy" that writes the value text to the clipboard (a hidden textarea where navigator.clipboard is absent). Property, not attribute.
layoutlayout"columns" | "rows"'rows'rows (hairline rows, fixed term width) or columns (grid of sunken cells).
termWidthterm-widthnumber150Term column width in px in the rows layout.

Events

EventDetailReactVueDescription
suiCopystringonSuiCopy@sui-copyFires after a value reaches the clipboard, together with the short "Copied" state on the control; detail is the copied text, as on every element that copies.
suiCopyErrorstringonSuiCopyError@sui-copy-errorFires when the write failed and no "Copied" state was shown; detail is the text that was not copied.

Types

SuiDescriptionItem interfaceOne term and detail pair. detail may be text, a number or a DOM node.
termstringThe label (dt).
detailstring | number | HTMLElementThe value (dd). Strings and numbers render as text, and a long one wraps; an HTMLElement is mounted as-is, and what it paints past its box, an inline control's hover fill or a button's focus ring say, is never clipped by the value cell.
copy?booleanShows a copy control after the value; copies its text and emits suiCopy.
strong?booleanBold (700) value for totals and balances.

Theming

Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.

See also