# DescriptionList

> Semantic dl/dt/dd pair with mono terminal terms and Lato body details. Two layouts - vertical grid for metadata panels, inline for compact key/value strips.

- Category: data-display
- Status: stable (since 0.3.0)
- A11y pattern: https://www.w3.org/WAI/ARIA/apg/patterns/
- Tokens: --font-mono, --font-sans, --foreground-primary, --foreground-secondary, --fs-sm, --fs-md
- Playground: https://design.freecodecamp.org/playground#description-list
- npm dependencies: `react@>=18 <20`
- Registry dependencies: [theme](https://design.freecodecamp.org/registry/theme.md)
- Files:
  - `DescriptionList.tsx` → `src/ui/description-list/DescriptionList.tsx` (raw: https://design.freecodecamp.org/registry/description-list/DescriptionList.tsx)
  - `description-list.css` → `src/ui/description-list/description-list.css` (raw: https://design.freecodecamp.org/registry/description-list/description-list.css)

## Install (copy source)

1. Ensure the theme is installed once per project - tokens.css + base.css imported globally, fonts available. See https://design.freecodecamp.org/registry/theme.md and https://design.freecodecamp.org/registry/starter.md.
2. Copy the files below into `src/ui/description-list/` (adjust to your project layout) and import the CSS once from your global stylesheet, e.g. `@import './ui/description-list/description-list.css';`.
3. Colors, spacing and type come from tokens - tailor the component by editing the copied source; recolour by editing tokens.css, not the component CSS.

## Usage

DescriptionList is the semantic pair for key/value metadata - native
`<dl>` with `<dt>` terms rendered as mono terminal eyebrows and `<dd>`
details in Lato body. The default vertical layout is a two-column grid
for settings and summary panels; the `inline` layout flows term/detail
pairs inline for compact status strips.

## Accessibility

Uses the native `dl` + `dt` + `dd` triple - screen readers announce the
relationship between each term and its detail automatically. No ARIA
needed. Order matters semantically: keep the most important pair first.

## Example

```tsx
import { DescriptionList } from './ui/description-list/DescriptionList';

<DescriptionList
  items={[
    { term: 'Username', detail: 'camper-42' },
    { term: 'Joined', detail: '2014-04-12' },
    { term: 'Certifications', detail: '3 of 14' }
  ]}
/>
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `items` | `DescriptionListItem[]` | yes | - |  |
| `layout` | `enum` | no | `vertical` |  |

## Source: DescriptionList.tsx

```tsx
import React, { forwardRef } from 'react';

export type DescriptionListLayout = 'vertical' | 'inline';

export interface DescriptionListItem {
  term: React.ReactNode;
  detail: React.ReactNode;
}

export interface DescriptionListProps extends Omit<
  React.HTMLAttributes<HTMLDListElement>,
  'children'
> {
  items: DescriptionListItem[];
  layout?: DescriptionListLayout;
}

export const DescriptionList = forwardRef<
  HTMLDListElement,
  DescriptionListProps
>(({ items, layout = 'vertical', className = '', ...rest }, ref) => {
  const classes = ['dl', layout !== 'vertical' && `dl--${layout}`, className]
    .filter(Boolean)
    .join(' ');
  return (
    <dl ref={ref} className={classes} {...rest}>
      {items.map((item, i) => (
        <React.Fragment key={i}>
          <dt className='dl__term'>{item.term}</dt>
          <dd className='dl__detail'>{item.detail}</dd>
        </React.Fragment>
      ))}
    </dl>
  );
});
DescriptionList.displayName = 'DescriptionList';
```

## Source: description-list.css

```css
.dl {
  margin: 0 0 16px;
  display: grid;
  grid-template-columns: minmax(10ch, 20%) 1fr;
  row-gap: 8px;
  column-gap: 16px;
}
.dl__term {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--foreground-secondary);
  margin: 0;
}
.dl__detail {
  font-family: var(--font-sans);
  font-size: var(--fs-md);
  color: var(--foreground-primary);
  margin: 0;
}
.dl--inline {
  display: flex;
  flex-wrap: wrap;
  column-gap: 8px;
  row-gap: 8px;
  grid-template-columns: none;
}
.dl--inline .dl__term::after {
  content: ':';
  margin-left: 2px;
}
.dl--inline .dl__detail {
  margin-right: 16px;
}
```

## HTML / vanilla variant

```html
<dl class="dl">
  <dt class="dl__term">Username</dt>
  <dd class="dl__detail">camper-42</dd>
</dl>
```

Interactive behaviours for plain HTML come from the vanilla runtime (data-uikit-* attributes): https://design.freecodecamp.org/registry/vanilla.md - or download https://design.freecodecamp.org/cdn/uikit.global.js once and self-host it (do not hotlink).

## For coding agents

This library is distributed as copyable source, not an npm package. Start at https://design.freecodecamp.org/registry/starter.md, discover components via https://design.freecodecamp.org/llms.txt, and copy files into the consuming project. Keep token names intact; recolour by editing the copied tokens.css.
