Collapsible
Animated collapsible container that can be toggled open and closed.
Subtotal$76.00
Shipping$4.50
Tax$4.00
Web preview — components render natively on iOS & Android
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "@/components/ui/collapsible";
export function MyScreen() {
const [open, setOpen] = useState(false);
return (
<Collapsible open={open} onOpenChange={setOpen}>
<CollapsibleTrigger>
<Text>{open ? "Hide" : "Show"} price breakdown</Text>
</CollapsibleTrigger>
<CollapsibleContent>
<Text>Subtotal: $76.00</Text>
<Text>Shipping: $4.50</Text>
<Text>Tax: $4.00</Text>
</CollapsibleContent>
</Collapsible>
);
}Installation#
npx @aniui/cli add collapsibleThis component requires react-native-reanimated for animations.
Usage#
app/index.tsx
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "@/components/ui/collapsible";
export function MyScreen() {
const [open, setOpen] = useState(false);
return (
<Collapsible open={open} onOpenChange={setOpen}>
<CollapsibleTrigger>
<Text>{open ? "Hide" : "Show"} price breakdown</Text>
</CollapsibleTrigger>
<CollapsibleContent>
<Text>Subtotal: $76.00</Text>
<Text>Shipping: $4.50</Text>
<Text>Tax: $4.00</Text>
</CollapsibleContent>
</Collapsible>
);
}Controlled#
Use the open and onOpenChange props for controlled behavior.
app/index.tsx
const [open, setOpen] = useState(false);
<Collapsible open={open} onOpenChange={setOpen}>
<CollapsibleTrigger>
<Text>{open ? "Hide" : "Show"} details</Text>
</CollapsibleTrigger>
<CollapsibleContent>
<Text>Controlled collapsible content.</Text>
</CollapsibleContent>
</Collapsible>Compound Components#
ComponentDescription
CollapsibleRoot container managing open/closed state
CollapsibleTriggerPressable element that toggles the content
CollapsibleContentAnimated container for collapsible content
Props#
Collapsible#
PropTypeDefault
openbooleanfalse (uncontrolled)onOpenChange(open: boolean) => void—classNamestring—Accessibility#
- Uses React Context with Reanimated FadeIn/FadeOut animations
- Trigger button announces expanded/collapsed state to screen readers.
Source#
components/ui/collapsible.tsx
import React, { createContext, useContext, useState } from "react";
import { View, Pressable } from "react-native";
import Animated from "react-native-reanimated";
import { entering, exiting } from "@/components/ui/animate";
import { cn } from "@/lib/utils";
const CollapsibleCtx = createContext<{ isOpen: boolean; toggle: () => void }>({ isOpen: false, toggle: () => {} });
export interface CollapsibleProps extends React.ComponentPropsWithoutRef<typeof View> {
className?: string;
open?: boolean;
onOpenChange?: (open: boolean) => void;
children?: React.ReactNode;
}
export function Collapsible({ open: controlledOpen, onOpenChange, className, children, ...props }: CollapsibleProps) {
const [uncontrolled, setUncontrolled] = useState(false);
const isOpen = controlledOpen ?? uncontrolled;
const toggle = () => {
const next = !isOpen;
setUncontrolled(next);
onOpenChange?.(next);
};
return (
<CollapsibleCtx.Provider value={{ isOpen, toggle }}>
<View className={cn("", className)} {...props}>{children}</View>
</CollapsibleCtx.Provider>
);
}
export interface CollapsibleTriggerProps extends React.ComponentPropsWithoutRef<typeof Pressable> {
className?: string;
children?: React.ReactNode;
}
export function CollapsibleTrigger({ className, children, ...props }: CollapsibleTriggerProps) {
const { toggle } = useContext(CollapsibleCtx);
return (
<Pressable className={cn("", className)} onPress={toggle} accessible={true} accessibilityRole="button" {...props}>
{children}
</Pressable>
);
}
export interface CollapsibleContentProps extends React.ComponentPropsWithoutRef<typeof View> {
className?: string;
children?: React.ReactNode;
}
export function CollapsibleContent({ className, children, ...props }: CollapsibleContentProps) {
const { isOpen } = useContext(CollapsibleCtx);
if (!isOpen) return null;
return (
<Animated.View entering={entering.fadeInDown} exiting={exiting.fadeOutUp}>
<View className={cn("", className)} {...props}>{children}</View>
</Animated.View>
);
}

