AniUI

Accordion

Expandable content sections with animated height transitions.

Yes. It uses accessibilityRole and accessibilityState.

Yes. It uses react-native-reanimated for smooth animations.

Yes. Use className to override any styles.

Web preview — components render natively on iOS & Android
import { Accordion, AccordionItem } from "@/components/ui/accordion";

export function MyScreen() {
  return (
    <Accordion defaultValue="item-1">
      <AccordionItem value="item-1" trigger="Is it accessible?">
        <Text>Yes. It uses accessibilityRole and accessibilityState.</Text>
      </AccordionItem>
      <AccordionItem value="item-2" trigger="Is it animated?">
        <Text>Yes. It uses react-native-reanimated for smooth animations.</Text>
      </AccordionItem>
      <AccordionItem value="item-3" trigger="Can I customize it?">
        <Text>Yes. Use className to override any styles.</Text>
      </AccordionItem>
    </Accordion>
  );
}

Installation#

npx @aniui/cli add accordion

This component requires react-native-reanimated for animations.

Usage#

app/index.tsx
import { Accordion, AccordionItem } from "@/components/ui/accordion";

export function MyScreen() {
  return (
    <Accordion defaultValue="item-1">
      <AccordionItem value="item-1" trigger="Is it accessible?">
        <Text>Yes. It uses accessibilityRole and accessibilityState.</Text>
      </AccordionItem>
      <AccordionItem value="item-2" trigger="Is it animated?">
        <Text>Yes. It uses react-native-reanimated for smooth animations.</Text>
      </AccordionItem>
      <AccordionItem value="item-3" trigger="Can I customize it?">
        <Text>Yes. Use className to override any styles.</Text>
      </AccordionItem>
    </Accordion>
  );
}

Compound Components#

ComponentDescription
Accordion

Root container that manages expanded state

AccordionItem

Individual collapsible section with trigger text

Props#

Accordion#

PropTypeDefault
defaultValue
string
type
"single" | "multiple"
"single"
className
string

AccordionItem#

PropTypeDefault
value
string
required
trigger
string
required
className
string

Accessibility#

  • Uses @rn-primitives/accordion for keyboard navigation and ARIA compliance.
  • Supports single and multiple open modes.
  • Each trigger has accessibilityRole="button" with accessibilityState for expanded/collapsed.

Source#

components/ui/accordion.tsx
import React from "react";
import { View, Pressable, Text } from "react-native";
import * as AccordionPrimitive from "@rn-primitives/accordion";
import Animated, { FadeIn, FadeOut } from "react-native-reanimated";
import { cn } from "@/lib/utils";

export interface AccordionProps extends React.ComponentPropsWithoutRef<typeof View> {
  className?: string;
  defaultValue?: string;
  children?: React.ReactNode;
  type?: "single" | "multiple";
}

export function Accordion({ className, defaultValue, children, type = "single", ...props }: AccordionProps) {
  return (
    <AccordionPrimitive.Root
      type={type}
      defaultValue={type === "single" ? defaultValue : defaultValue ? [defaultValue] : undefined}
      asChild
    >
      <View className={cn("", className)} {...props}>{children}</View>
    </AccordionPrimitive.Root>
  );
}

export interface AccordionItemProps extends React.ComponentPropsWithoutRef<typeof View> {
  className?: string;
  value: string;
  trigger: string;
  children?: React.ReactNode;
}

export function AccordionItem({ value, trigger, className, children, ...props }: AccordionItemProps) {
  return (
    <AccordionPrimitive.Item value={value} asChild>
      <View className={cn("border-b border-border", className)} {...props}>
        <AccordionPrimitive.Trigger asChild>
          <Pressable className="flex-row items-center justify-between px-4 py-4 min-h-12" accessible={true} accessibilityRole="button">
            <Text className="text-base font-medium text-foreground flex-1">{trigger}</Text>
            <Text className="text-muted-foreground text-lg">+</Text>
          </Pressable>
        </AccordionPrimitive.Trigger>
        <AccordionPrimitive.Content>
          <Animated.View entering={FadeIn.duration(200)} exiting={FadeOut.duration(150)}>
            <View className="px-4 pb-4">{children}</View>
          </Animated.View>
        </AccordionPrimitive.Content>
      </View>
    </AccordionPrimitive.Item>
  );
}