Skip to content
Components

Metadata

Read-only label and value pairs that describe one item: its status, owner, dates, tags. The value is a slot, so it takes text or any component (Badge, Avatar with a name, a link, a small Button). Horizontal puts the labels in one column beside the values; vertical puts each label above its value.

Preview

Status
Ready
Owner
Ada Lovelace
Created
Oct 6, 2026
Tags
DesignTokens

Props

  • orientation
  • icon
import { Avatar } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { Metadata, MetadataItem } from "@/components/ui/metadata"

<Metadata className="w-full max-w-sm">
  <MetadataItem label="Status">
    <Badge variant="success">Ready</Badge>
  </MetadataItem>
  <MetadataItem label="Owner">
    <Avatar alt="" size="sm">AL</Avatar>
    Ada Lovelace
  </MetadataItem>
  <MetadataItem label="Created">Oct 6, 2026</MetadataItem>
  <MetadataItem label="Tags">
    <Badge variant="blue">Design</Badge>
    <Badge variant="purple">Tokens</Badge>
  </MetadataItem>
</Metadata>

Usage

When to use

  • Show read-only facts about one item, each with its name: status, owner, dates, tags, an ID.
  • A details panel beside the main content, with the names in one column and the values lined up next to them.
  • A row of key facts, each name above its value, such as the plan, seats and renewal date of a subscription.

When not to use

  • Values the user edits. Use Field, which links the label to the control.
  • Many records that share the same names, such as a list of projects. Use Table, with the names once in its header.
  • A status alone next to an item, with no name for it. Use Badge.

Variants

orientation

On Metadata, sets every item. horizontal: labels in one column beside the values, for a details panel. vertical: each label above its value, for a narrow column or a row of key facts. On one MetadataItem, overrides it for that item, such as a long description under horizontal rows.

  • Status
    Ready
    Owner
    Ada Lovelace
    Created
    Oct 6, 2026
    Tags
    DesignTokens

    horizontaldefault

  • Status
    Ready
    Owner
    Ada Lovelace
    Created
    Oct 6, 2026
    Tags
    DesignTokens

    vertical

import { Avatar } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { Metadata, MetadataItem } from "@/components/ui/metadata"

<Metadata className="w-full max-w-sm">
  <MetadataItem label="Status">
    <Badge variant="success">Ready</Badge>
  </MetadataItem>
  <MetadataItem label="Owner">
    <Avatar alt="" size="sm">AL</Avatar>
    Ada Lovelace
  </MetadataItem>
  <MetadataItem label="Created">Oct 6, 2026</MetadataItem>
  <MetadataItem label="Tags">
    <Badge variant="blue">Design</Badge>
    <Badge variant="purple">Tokens</Badge>
  </MetadataItem>
</Metadata>
<Metadata orientation="vertical" className="w-full max-w-sm">
  <MetadataItem label="Status">
    <Badge variant="success">Ready</Badge>
  </MetadataItem>
  <MetadataItem label="Owner">
    <Avatar alt="" size="sm">AL</Avatar>
    Ada Lovelace
  </MetadataItem>
  <MetadataItem label="Created">Oct 6, 2026</MetadataItem>
  <MetadataItem label="Tags">
    <Badge variant="blue">Design</Badge>
    <Badge variant="purple">Tokens</Badge>
  </MetadataItem>
</Metadata>

Examples

Default

Status
Ready
Owner
Ada Lovelace
Created
Oct 6, 2026
Tags
DesignTokens
import { Avatar } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { Metadata, MetadataItem } from "@/components/ui/metadata"

<Metadata className="w-full max-w-sm">
  <MetadataItem label="Status">
    <Badge variant="success">Ready</Badge>
  </MetadataItem>
  <MetadataItem label="Owner">
    <Avatar alt="" size="sm">AL</Avatar>
    Ada Lovelace
  </MetadataItem>
  <MetadataItem label="Created">Oct 6, 2026</MetadataItem>
  <MetadataItem label="Tags">
    <Badge variant="blue">Design</Badge>
    <Badge variant="purple">Tokens</Badge>
  </MetadataItem>
</Metadata>

With icons

The icon names nothing on its own, so it is hidden from screen readers. Every label gets one, or none does.

Status
In review
Owner
Ada Lovelace
Due
Oct 20, 2026
Tags
Design
import { IconCalendar, IconCircleDashed, IconTag, IconUser } from "@tabler/icons-react"
import { Avatar } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { Metadata, MetadataItem } from "@/components/ui/metadata"

<Metadata className="w-full max-w-sm">
  <MetadataItem label="Status" leadingIcon={<IconCircleDashed size={16} />}>
    <Badge variant="warning">In review</Badge>
  </MetadataItem>
  <MetadataItem label="Owner" leadingIcon={<IconUser size={16} />}>
    <Avatar alt="" size="sm">AL</Avatar>
    Ada Lovelace
  </MetadataItem>
  <MetadataItem label="Due" leadingIcon={<IconCalendar size={16} />}>Oct 20, 2026</MetadataItem>
  <MetadataItem label="Tags" leadingIcon={<IconTag size={16} />}>
    <Badge variant="blue">Design</Badge>
  </MetadataItem>
</Metadata>

Key facts in a row

Vertical items on a grid of three columns: each label above its value.

Plan
Pro
Seats
12 of 20
Renews
Nov 1, 2026
import { Metadata, MetadataItem } from "@/components/ui/metadata"

<Metadata orientation="vertical" className="w-full max-w-lg grid-cols-3">
  <MetadataItem label="Plan">Pro</MetadataItem>
  <MetadataItem label="Seats">12 of 20</MetadataItem>
  <MetadataItem label="Renews">Nov 1, 2026</MetadataItem>
</Metadata>

A long value under the rows

One vertical item in a horizontal list takes the full width, for a value that needs the room.

Status
Ready
Region
Europe
Description
Design tokens and components for teams that build their interface with an agent.
import { Badge } from "@/components/ui/badge"
import { Metadata, MetadataItem } from "@/components/ui/metadata"

<Metadata className="w-full max-w-sm">
  <MetadataItem label="Status">
    <Badge variant="success">Ready</Badge>
  </MetadataItem>
  <MetadataItem label="Region">Europe</MetadataItem>
  <MetadataItem label="Description" orientation="vertical">Design tokens and components for teams that build their interface with an agent.</MetadataItem>
</Metadata>

With an action

A value can hold a control. The label does not name it, so the button carries its own words.

Workspace ID
ws_4f2a9c
Created
Oct 6, 2026
import { Button } from "@/components/ui/button"
import { Metadata, MetadataItem } from "@/components/ui/metadata"

<Metadata className="w-full max-w-sm">
  <MetadataItem label="Workspace ID">
    <span className="font-mono">ws_4f2a9c</span>
    <Button variant="secondary" size="sm">Copy ID</Button>
  </MetadataItem>
  <MetadataItem label="Created">Oct 6, 2026</MetadataItem>
</Metadata>

Do and don't

Do

  • Use Metadata for read-only facts about one item: status, owner, dates, tags, IDs.
  • Keep labels short: one to three words, sentence case, no colon.
  • Give every item a value. When there is none, write it: None, Not set.
  • Pick horizontal for a details panel; vertical for a narrow column, or for a row of key facts with grid-cols-* on Metadata.
  • Wrap a sentence that holds a link in a span, so it stays one line of running text instead of separate pieces.

Don't

  • Don't put a form control in a value to edit it. A value the user fills in needs Field, with a label linked to the control.
  • Don't use Metadata for many records that share the same labels; use Table.
  • Don't make labels bold or colored. The value is what the user reads; the label only names it.
  • Don't mix items with and without icons in one list.

Props

NameTypeValuesDefaultDescription
orientationenumhorizontal | verticalhorizontalOn Metadata, sets every item. horizontal: labels in one column beside the values, for a details panel. vertical: each label above its value, for a narrow column or a row of key facts. On one MetadataItem, overrides it for that item, such as a long description under horizontal rows.
label requirednode--Set on MetadataItem. The name of the value: Status, Owner, Created. One to three words, sentence case, no colon.
leadingIconnode--Set on MetadataItem. Decorative Tabler icon before the label: size={16}. Leave it out for no icon. Give every item in a list an icon, or none.

Slots

NameRequiredDescription
itemsyesOne MetadataItem per pair.
valueyesThe children of MetadataItem: text, or components such as a Badge, an Avatar with the name after it, a link or a small Button. Several components sit in a row that wraps.

Anatomy

PartDescription
rootMetadata: the dl. Horizontal: a two-column grid, labels in the first column as wide as the longest label (at most 40% of the list) and values in the second. Vertical: a grid of one column, items gap-lg; add grid-cols-* to lay them in a row.
itemMetadataItem: one label and value pair, a div around a dt and a dd. Horizontal: a row on the list's two columns (subgrid). Vertical: the label above the value, gap-xs.
labelThe dt: 13px secondary text, with the optional icon before it (gap-xs). Horizontal: at least one sm control tall, text centered.
iconOptional leading icon in the label: 16px, secondary icon color, level with the first line of the label, hidden from screen readers.
valueThe dd: 14px primary text in a row that wraps (gap-sm), so text and components line up. Horizontal: at least one sm control tall, content centered, so a line of text and a 28px button both sit level with the label.

Accessibility

Role: term and definition (description list)

  • Metadata is a description list: each label is a dt and its value a dd, grouped in a div, so screen readers read every label with its value and announce the number of items.
  • The leading icon is decorative and hidden from screen readers; the label text names the value.
  • To name the whole list, put a heading above it and point aria-labelledby on Metadata at the heading.
  • Controls inside a value (a link, a Button) keep their own name and focus order. A label is not a control's name: give an icon-only button its own aria-label.

Install

npx shadcn add https://werewolf-ui.vercel.app/r/metadata.json

This also adds styles/werewolf.css, the tokens every component uses, and any other component it needs. Import that file once in your root CSS, after @import "tailwindcss", with a path relative to that CSS file (from app/globals.css it is @import "../styles/werewolf.css").