suiss/uim · Interaction

Section Index

An A to Z bar on the side of a scrolling list that jumps to sections on tap or drag.

Section Index is an open-source mobile interaction 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
Section Index on iOS in light mode

SectionIndex pairs a scroll view of lettered sections with SectionIndexBar, a column of letters on the end edge. Tapping a letter scrolls to that section; dragging along the bar scrubs through sections and shows the current letter in a large bubble beside the finger.

When the bar is too short for every letter, it shows a subset with • between them. Use it for long alphabetical lists such as contacts.

Installation

$ pnpm dlx @esuiss/uim@latest add section-index

The CLI also adds what it builds on: Text.

Manual

  1. Install the dependencies:
npx expo install cn react-native-reanimated react-native-worklets
  1. Add the pieces it builds on: Text, and the primitives components/primitives/section-index.tsx, components/primitives/use-render.tsx.

  2. Copy the source into components/interactions/section-index.tsx:

uniwind/components/interactions/section-index.tsx
import { cn } from "cn"
import type * as React from "react"
import { View } from "react-native"
import { FadeOut, ReduceMotion, ZoomIn } from "react-native-reanimated"
import * as SectionIndexPrimitive from "@/components/primitives/section-index"
import { resolveClassName } from "@/components/primitives/use-render"
import { AnimatedView } from "@/components/ui/animated-view"
import { Text } from "@/components/ui/text"

function SectionIndex({
  className,
  ...props
}: React.ComponentProps<typeof SectionIndexPrimitive.Root>) {
  return (
    <SectionIndexPrimitive.Root
      className={(state) => cn("relative", resolveClassName(className, state))}
  1. Update the import paths to match your project.

Usage

import { SectionIndex, SectionIndexScrollView, SectionIndexSection, SectionIndexHeader, SectionIndexBar } from "@/components/interactions/section-index"
<ContactsExample className="h-[520px]" />

Put a SectionIndexScrollView and a SectionIndexBar inside SectionIndex. Wrap each group in a SectionIndexSection with its letter as value, and start it with a SectionIndexHeader.

The bar shows A to Z and # by default; pass letters to match your sections. onValueChange is called with the letter when the user jumps.

Examples

Compact

A short list where the bar collapses letters into dots.

iOS
Section Index (compact) on iOS in light mode

API Reference

SectionIndex

The root that tracks section positions.

ExtendsReact.ComponentProps<typeof SectionIndexPrimitive.Root>

SectionIndexScrollView

The scroll view that holds the sections.

ExtendsReact.ComponentProps<typeof SectionIndexPrimitive.ScrollView>

SectionIndexSection

One section, registered by its value.

ExtendsReact.ComponentProps<typeof SectionIndexPrimitive.Section>

SectionIndexHeader

A section heading; string children are styled.

ExtendsReact.ComponentProps<typeof View>

SectionIndexBar

The letter bar with the drag bubble.

ExtendsReact.ComponentProps<typeof SectionIndexPrimitive.Bar>

Accessibility

  • The bar is adjustable: swiping up or down with a screen reader moves to the previous or next section, and the current letter is announced as its value.
  • SectionIndexHeader has the heading role.

Notes

  • A selection haptic plays on each letter change from touch, if the app provides an adapter through HapticsProvider.
  • Letters use text-link; the bubble uses bg-surface-raised.
  • The bubble animation respects the system reduce motion setting.