Skip to content

List Item

Grouped row (with a settings-row specialization) that synthesizes accessible names from primitive content when interactive.

  • Category: Data display
  • Status: stable public Registry/export-map component family
  • Targets: iOS · Android · Web, subject to the compatibility contract
  • Prerequisites: @beemvp/beeui-ui installed (or this component’s source copied via the Registry CLI below) and, on Web, the BeeUI Tailwind/Uniwind theme CSS loaded — see Start for full platform setup.
  • Source: packages/ui/src/components/list-item.tsx
import { ListItem, SettingsItem } from '@beemvp/beeui-ui';

There is no documented deep/private source import. For source ownership from a BeeUI checkout:

Terminal window
pnpm beeui add list-item

Registry (used throughout this page) is BeeUI’s source-ownership manifest — registry/registry.json — that the pnpm beeui/@beemvp/beeui-cli CLI reads to copy a component’s real source into your app and rewrite its internal imports; it is not an npm package index. This component’s own Registry entry: registry/registry.json.

  • Family exports: ListItem SettingsItem
    • Also routed here, outside the Registry family:
      • list-item
    • Package export subpath: @beemvp/beeui-ui/list-item

Exported types: ListItemProps, SettingsItemProps

The generated API inventory is mechanically joined to packages/ui/src/index.ts, Registry metadata, and the component reference contract. Each type’s field table below is parsed directly from that source, not a second hand-maintained copy; for the fuller behavior narrative see the canonical component behavior catalog.

Press behavior is opt-in (onPress makes the row interactive); an interactive row without an explicit accessibilityLabel synthesizes one from its primitive title/description/trailing content, while non-interactive rows never hide complex descendant content. active marks a row as the current/selected item (e.g. the active sidebar entry) — a purely visual/accessibility-state flag that does not change press behavior.

Prop Type Default Description
active boolean false Marks this row as the current/selected item — e.g. the active sidebar link, or a selected row in a master/detail list. Adds a tokenized selected background plus accessibilityState.selected (native) and aria-current (Web, since accessibilityState is not forwarded to the DOM there — see the aria-current prop below). Defaults to false.
className string — Extra utility classes, merged after the component’s own via cn(...), so they win on conflict. An escape hatch for source-owned and application work, not a cross-engine portability guarantee.
description React.ReactNode — Secondary supporting text rendered beneath the primary label or title.
descriptionClassName string — Applied to the description Text when description is a plain string or number; ignored if description is a custom element.
leading React.ReactNode — Rendered before the title/description column, shrink-to-content (e.g. an icon or avatar).
title (required) React.ReactNode — The primary heading text for this surface.
titleClassName string — Applied to the title Text when title is a plain string or number; ignored if title is a custom element.
trailing React.ReactNode — Content rendered at the end of the row, after the primary content — actions, badges or status.

Also carries every prop of Omit<PressableProps, 'accessibilityRole' | 'accessibilityState' | 'children' | 'role'> — that upstream contract is not reproduced here.

Prop Type Default Description
trailing React.ReactNode — Content rendered at the end of the row, after the primary content — actions, badges or status.
value React.ReactNode — Rendered muted, end-aligned before trailing (e.g. the current setting’s selected option). Plain string/number renders as Text; anything else renders as-is.

Also carries every prop of Omit<ListItemProps, 'trailing'> — documented on the List Item page, not reproduced here.

The executable fixtures below are the source-grounded usage examples; consumers should not infer state ownership from DOM structure or another UI library.

  • No additional provider is required by this family. BeeUIProvider remains the recommended application root.
  • Peer/native dependencies visible to this Registry item: react, react-native
  • Registry dependency closure: box, core-cn, list-group, text, theme
  • Safe-area ownership remains explicit: shell surfaces touching system edges opt into SafeArea; components do not silently invent app-shell insets.
  • Web consumers load the BeeUI semantic theme CSS as documented in Web onboarding.

This family ships no platform-specific file, and its own source takes no Platform branch.

The same public family is exposed across the supported target matrix; meaningful platform differences remain governed by the compatibility contract.

Evidence classes are not equal and this page does not blur them: Web behavior is exercised in a real browser, while iOS and Android carry package/export and native-compile evidence, which is not device-runtime proof. The compatibility contract records which class each claim rests on.

  • Roles this family assigns: button, listitem — set in list-item.tsx by the components themselves, not by the caller.
  • Accessibility states and properties it sets: accessibilityLabel, accessible, current, disabled, selected — read from list-item.tsx.

Keyboard/focus behavior, announcements, Dynamic Type/Web zoom, RTL and reduced-motion expectations are not derived here — see Accessibility overview, Keyboard & focus, RTL/localization and Large text & zoom. BeeUI does not claim universal accessibility certification from automated tests.

  • Style axes: none of its own — its appearance comes from tokens and your own classes; it also carries Omit<PressableProps, 'accessibilityRole' | 'accessibilityState' | 'children' | 'role'>.
  • Class-name surfaces: className, descriptionClassName, titleClassName.

Colors, spacing and typography come from semantic tokens rather than from values written here — see Theming and Density. A className is an escape hatch for source-owned and application work, not a cross-engine portability guarantee.

Each link below opens the Showcase at that exact example, not at the top of the gallery:

  • basic — smallest meaningful complete usage
  • composition — the composition example

The Showcase links demonstrate Web behavior; use the native-preview guide for real simulator/emulator/device paths.

This frame loads the real BeeUI Web Showcase on demand; it is not a second docs-only implementation. It proves browser behavior only. Use native preview for iOS/Android simulator, emulator or device paths.

  • Family root / primary export: ListItem
    • Public composition parts / helpers:
      • SettingsItem
    • Exported type surface:
      • ListItemProps
      • SettingsItemProps

The tree above is ordinary document structure so it remains readable with keyboard and assistive technology; it is derived from the real public export family rather than a canvas-only diagram.

These are the parts of the typechecked runtime Showcase fixture behind this live preview — apps/showcase/component-gallery/component-gallery.tsx, 1103 lines — where List Item is actually used: 28 lines in 2 places. Each block is copied verbatim from the line range named above it, so it is the same executable source, not a retelling of it. The rest of that file exercises other families and is not reproduced here.

Imports the examples below need (a filtered subset of the fixture’s own top-level imports):

import { Badge, ListItem, SettingsItem, Switch } from '@beemvp/beeui-ui';
import * as React from 'react';
import { useUniwind } from 'uniwind';

lines 1015–1019:

<ListItem
description="Portable component system"
onPress={() => undefined}
title="BeeUI"
/>

Fixture state this block reads (same file, lines 458, 461):

const { theme } = useUniwind();
const [notifications, setNotifications] = React.useState(true);

lines 1058–1080:

<ListItem
description="Open your profile"
onPress={() => undefined}
title="Profile"
trailing={<Badge variant="success">Active</Badge>}
/>
<SettingsItem
description="Changes app appearance"
onPress={() => undefined}
title="Appearance"
value={theme}
/>
<SettingsItem
description="Native preference control"
title="Push notifications"
trailing={
<Switch
accessibilityLabel="Push notifications"
onValueChange={setNotifications}
value={notifications}
/>
}
/>

Open the fixture itself for the full surrounding component. For a smaller app-specific example, start from the imports and fixture-state blocks above and keep only the state your screen owns.

A row with no onPress is rendered non-interactive and disabled — disabled alone can never make it pressable. The synthesized accessible name is all-or-nothing: if title, description or trailing is anything but a plain string or number, no name is synthesized at all.