suiss/uim · React Native Component

Item

A flexible row for lists and settings, with slots for media, a title, a description and trailing actions.

Item is an open-source mobile component from suiss/uim for React Native and Expo, with SwiftUI and Jetpack Compose versions built from the same design tokens. The @esuiss/uim CLI copies its source into your project, so you own the code.

iOS
Item on iOS in light mode

Item is a row that renders as a Pressable with the button role when it has onPress or onLongPress, and as a plain View with the listitem role otherwise. It has three variants (default, outline, muted) and three sizes (default, sm, xs).

ItemGroup stacks items as a list. Its inset variant joins them into one rounded card with square inner corners, which suits settings screens; add ItemSeparator between rows to draw an inset divider.

Installation

$ pnpm dlx @esuiss/uim@latest add item

The CLI also adds what it builds on: Icon, Text.

Manual

  1. Install the dependencies:
npx expo install class-variance-authority cn
  1. Add the pieces it builds on: Icon, Text, and the primitives components/primitives/types.tsx, components/primitives/use-render.tsx.

  2. Copy the source into components/ui/item.tsx:

uniwind/components/ui/item.tsx
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "cn"
import * as React from "react"
import { Pressable, View, type ViewProps } from "react-native"
import type { RenderProp } from "@/components/primitives/types"
import { useRender } from "@/components/primitives/use-render"
import { IconClassContext } from "@/components/ui/icon"
import { Text, TextClassContext } from "@/components/ui/text"

type ItemSize = "default" | "sm" | "xs"

const ItemGroupContext = React.createContext<{ inset: boolean }>({
  inset: false,
})

const ItemContext = React.createContext<{ size: ItemSize }>({
  1. Update the import paths to match your project.

Usage

import { ItemGroup, ItemSeparator, Item, ItemMedia, ItemContent, ItemTitle, ItemDescription, ItemActions, ItemHeader, ItemFooter } from "@/components/ui/item"
<View className="gap-4">
  <Item variant="outline">
    <ItemContent>
      <ItemTitle>Basic item</ItemTitle>
      <ItemDescription>
        A simple item with a title and a description.
      </ItemDescription>
    </ItemContent>
    <ItemActions>
      <Button variant="outline" size="sm">
        <Text>Action</Text>
      </Button>
    </ItemActions>
  </Item>
  <Item variant="muted" size="sm" onPress={() => {}}>
    <ItemMedia variant="icon">
      <Icon as={ShieldCheckIcon} />
    </ItemMedia>
    <ItemContent>
      <ItemTitle>Your profile has been verified.</ItemTitle>
    </ItemContent>
    <ItemActions>
      <Icon as={CaretRightIcon} className="size-4 text-label-secondary" />
    </ItemActions>
  </Item>
  <Item variant="outline" size="xs">
    <ItemHeader>
      <ItemTitle>Header</ItemTitle>
      <Badge>
        <Text>New</Text>
      </Badge>
    </ItemHeader>
    <ItemContent>
      <ItemDescription>
        Items can carry a header and a footer.
      </ItemDescription>
    </ItemContent>
    <ItemFooter>
      <Text className="text-sm text-label-secondary">Footer</Text>
    </ItemFooter>
  </Item>
</View>

Compose a row from ItemMedia, ItemContent (holding ItemTitle and ItemDescription) and ItemActions. Use ItemHeader and ItemFooter for full-width rows above or below the main content.

ItemMedia with variant="icon" sizes icons to 16 points; variant="image" makes a square thumbnail that shrinks with the item size. ItemTitle truncates to one line and ItemDescription to two by default; override with numberOfLines. Text inside ItemActions picks up a secondary color.

Pass render to render the row as another component while keeping the item styles.

Examples

Inset group

Pressable rows in an inset group, with colored icon tiles, separators and trailing chevrons.

iOS
Item (inset group) on iOS in light mode

API Reference

ItemGroup

List container for items.

ExtendsViewProps
PropType
About
default stacks items with a gap; inset joins them into one rounded card.
Type
"default""inset"
Default
"default"

ItemSeparator

Divider between items, inset inside an inset group.

ExtendsViewProps

Item

The row itself, pressable when given a press handler.

ExtendsItemProps

ItemMedia

Leading icon, image or avatar.

ExtendsViewProps
PropType
About
default, icon for 16-point icons, or image for a square thumbnail.
Type
"default""icon""image"
Default
"default"

ItemContent

Flexible column for the title and description.

ExtendsViewProps

ItemTitle

Single-line title.

ExtendsReact.ComponentProps<typeof Text>

ItemDescription

Secondary text, up to two lines.

ExtendsReact.ComponentProps<typeof Text>

ItemActions

Trailing row for values, buttons or chevrons.

ExtendsViewProps

ItemHeader

Full-width row above the content.

ExtendsViewProps

ItemFooter

Full-width row below the content.

ExtendsViewProps

Accessibility

  • ItemGroup has the list role.
  • A static Item has the listitem role; an item with onPress or onLongPress has the button role and shows a pressed background.
  • disabled dims the item and blocks presses.
  • ItemSeparator is hidden from VoiceOver and TalkBack.

Notes

  • Uses bg-surface-secondary for inset groups and the muted variant, border-separator for outline, and bg-item-pressed for the pressed state.
  • Colors follow the system appearance.