Arena display components, the React layer

August 20, 2026 · View on GitHub

Every display component this layer ships, under the names it binds them to. This page is an index, not a manual. How to write one is its own prompt, linked in the last column.

The rules every component below answers to are stated in ../../../../skills/design/SKILL.md before any component here, and nothing on this page restates them.

Import from the package root, never from a path inside it:

import { ArenaButton, ArenaTag } from '@dravensoft/arena-react';

A member is a prop. The main slot is children, a named slot is a prop taking a node, and an event is an on-prefixed handler. An icon is a Phosphor class-name string, never an element.

  • Every other category this layer ships: ../../INDEX.md.
  • Installing the package, declaring your skin, and what it exports besides components: ../../PACKAGE.md.
  • Takes is the members the component's API contract declares, in contract order, under this layer's own names. A member marked * is required; the prompt gives its type and its default.
  • A member whose type is an object or an enum takes one this package exports. The prompt names the type and says what it is for; the fields it holds are in the type declaration itself, which import type { … } from '@dravensoft/arena-react' brings in. That field list is in neither the prompt nor the contract, so the type is where you read it.
ComponentWhat it isTakesUsage
ArenaActivityFeedAn event feed: someone did something to something, then. Arena draws every row.label* items* busyArenaActivityFeed.prompt.md
ArenaAvatarA person or entity mark: the image when src is set, initials from name otherwise, with an optional presence dot.src name size shape statusArenaAvatar.prompt.md
ArenaBadgeStatus label: mono, uppercase, short. Carries an object's actual state or an editorial emphasis, never decoration.children tone dotArenaBadge.prompt.md
ArenaCalendarWeek or day schedule on a time grid. Colour is identity, never state.children timeZone anchorDate view dayStart dayEnd weekStartsOn hideEmptyWeekend dayInteractive onDateClick onRangeChange actionsArenaCalendar.prompt.md
ArenaCalendarEventOne event on an ArenaCalendar's schedule. Times are ISO datetimes read in the calendar's timeZone, never the reader's. ArenaCalendar draws the chip; the consumer writes one of these per event and ArenaCalendar settles where it goes.id* title* start* end* colorId interactive actionsEnabled actions disabled onClickArenaCalendarEvent.prompt.md
ArenaCardSurface container. Hairline border on the base surface scale; depth comes from the shadow, never a gradient.children interactive disabled href action title headingLevel eyebrow floating accent onClickArenaCard.prompt.md
ArenaKeyValueA list of terms and the values against them, with an optional summed row ruled off at the bottom: a basket summary, an order, an invoice, a panel of facts about a resource. It renders a real definition list, so the association between a term and its value is the platform's rather than a class name's.rows* totalArenaKeyValue.prompt.md
ArenaPeopleListA list of people, each row a face with a name and, where the list is about a quantity, a figure beside it. Standings, assignees, members, suggestions. The list owns the semantics and the row size; a row owns what it says.label* ordered size childrenArenaPeopleList.prompt.md
ArenaPersonRowOne person in an ArenaPeopleList: a face, a name, an optional line under it, an optional position in front and an optional figure behind. Its size comes from the list rather than from here.name* src secondary rank figure current actionArenaPersonRow.prompt.md
ArenaSkeletonA loading placeholder that reserves the space real content will take.variant width height lines radiusArenaSkeleton.prompt.md
ArenaStatCardOne metric on a card surface: a micro-label, the number, an optional delta pill and a sub-line.label* value* tone delta sub iconArenaStatCard.prompt.md
ArenaTableData table on the density tokens. ArenaTable draws the header row from columns, owns the grid and its keyboard, and decides where each row sits; the consumer writes one ArenaTableRow per row and one ArenaTableCell per cell, so a cell's content is a value or one of Arena's own components rather than something returned from a per-item render function. Below --bp-md it becomes one card per row, measured on its own container rather than the viewport.label* columns* children empty sort onSortChange page slice onPageChange pageControl sortControl responsiveArenaTable.prompt.md
ArenaTableCellOne cell of an ArenaTableRow. It draws the cell box (the padding, the alignment and the mono/gold treatment its column asks for, and in card mode the label/value pair or the full-width block), and shows whatever the consumer put in it. Its column config, its layout and its place in the grid's keyboard order come from ArenaTable and ArenaTableRow and are members of no contract.children href onNavigateArenaTableCell.prompt.md
ArenaTableRowOne row of an ArenaTable. The consumer writes one per row and one ArenaTableCell inside it per cell. Where the row sits, the columns its cells are set against and how the keyboard reaches them are ArenaTable's, not this component's, and are members of no contract: the same shape, and for the same reason, as an ArenaRadioGroup and its Radios sharing which one is checked.children interactive disabled onClickArenaTableRow.prompt.md
ArenaTagA pill for filters, technologies and statuses. A tone for what state a thing is in or a ramp slot for which thing it is, and an optional dismiss.children tone colorId removable disabled onRemoveArenaTag.prompt.md
ArenaUnauthCardThe panel a signed-out screen needs: sign in, check your inbox, this link expired, a two-factor code. It knows nothing about credentials on purpose; the fields are composed inside it.brand eyebrow title headingLevel children footerArenaUnauthCard.prompt.md

16 display components in this layer.