import { useState } from "react";
import { Text, View } from "react-native";
import { Avatar } from "@/component-lib/avatar";
import { Badge } from "@/component-lib/badge";
import { useKitTheme } from "@/component-lib/shared/native";
import { Switch } from "@/component-lib/switch";
import { List, ListItem, ListSection } from "@/component-lib/list-item";
import { Section } from "./layout"; // Section and Row: page layout for the demo
/** A coloured rounded square with a letter: a settings-style icon without SVG. */
function Tile({ color, letter }: { color: string; letter: string }) {
return (
<View style={{ width: 28, height: 28, borderRadius: 7, backgroundColor: color, alignItems: "center", justifyContent: "center" }}>
<Text style={{ color: "#fff", fontWeight: "800", fontSize: 13 }}>{letter}</Text>
</View>
);
}
export function ListItemDemo() {
const { tokens } = useKitTheme();
const [push, setPush] = useState(true);
const [taps, setTaps] = useState(0);
return (
<>
<Section title="ListSection · inset (settings)">
<ListSection header="Account" footer={`Opened ${taps} time${taps === 1 ? "" : "s"}. Rows with a chevron open a screen.`}>
<ListItem leading={<Tile color="#2563eb" letter="L" />} title="Language" value="English" chevron onPress={() => setTaps((n) => n + 1)} />
<ListItem
leading={<Tile color="#15803d" letter="N" />}
title="Push notifications"
trailing={<Switch aria-label="Push notifications" checked={push} onCheckedChange={setPush} />}
/>
<ListItem leading={<Tile color="#b45309" letter="₹" />} title="Currency" value="INR (₹)" chevron onPress={() => setTaps((n) => n + 1)} />
<ListItem title="Sign out" destructive onPress={() => setTaps((n) => n + 1)} />
</ListSection>
</Section>
<Section title="List · plain (inbox)">
<List style={{ marginHorizontal: -16 }}>
<ListItem
leading={<Avatar name="Anand Remanan" size="md" />}
title="Anand Remanan"
description="Invoice INV-2041 is ready for review. The totals changed after the GST update."
trailing={<Badge variant="accent">New</Badge>}
onPress={() => setTaps((n) => n + 1)}
/>
<ListItem
leading={<Avatar name="Gita Hari" size="md" />}
title="Gita Hari"
description="Shared the Q3 ledger with you."
value="09:41"
onPress={() => setTaps((n) => n + 1)}
/>
<ListItem leading={<Avatar name="Old Account" size="md" />} title="Old account" description="Archived" disabled />
</List>
<Text style={{ color: tokens.muted, fontSize: tokens.fontSize - 2 }}>Long descriptions stop at two lines.</Text>
</Section>
</>
);
}Install
npx @grampro/kit@native add ListItemUsage
import { ListItem, ListSection } from "@/component-lib/list-item";
<ListSection header="Account" footer="Signed in as anand@example.com">
<ListItem title="Language" value="English" chevron onPress={openLanguage} />
<ListItem title="Notifications" trailing={<Switch checked={on} onCheckedChange={setOn} />} />
<ListItem title="Sign out" destructive onPress={signOut} />
</ListSection>Props
ListItemProps
| Prop | Type | Description |
|---|---|---|
leading | ReactNode | Icon or avatar before the text. |
title (required) | ReactNode | |
description | ReactNode | Supporting text under the title. |
numberOfLines | number | Lines of description before truncating. Default 2. |
value | ReactNode | Settings-style value text at the end, e.g. "English". |
trailing | ReactNode | Anything at the end: a Switch, a Badge, a button. |
chevron | boolean | A disclosure chevron at the end: the row opens something. |
destructive | boolean | Red text for delete / sign out rows. |
disabled | boolean | |
onPress | (event: GestureResponderEvent) => void | |
onLongPress | (event: GestureResponderEvent) => void | |
style | StyleProp<ViewStyle> | ((state: { pressed: boolean }) => StyleProp<ViewStyle>) | |
styles | Partial<{ leading: StyleProp<ViewStyle>; title: StyleProp<TextStyle>; description: Styl… |
ListProps
| Prop | Type | Description |
|---|---|---|
variant | ListVariant | plain: full-width rows. inset: a rounded card of rows (iOS settings). Default plain. |
divided | boolean | Hairlines between rows, inset past the leading slot. Default true. |
style | StyleProp<ViewStyle> | |
children | ReactNode |
ListSectionProps
| Prop | Type | Description |
|---|---|---|
header | ReactNode | Small caps label above the group. |
footer | ReactNode | Explanatory text below the group. |
variant | ListVariant | |
divided | boolean | |
style | StyleProp<ViewStyle> | |
children | ReactNode |
Notes
- Rows are at least 44dp tall (56dp with a description).
- A pressable row with a chevron is announced as a link, otherwise as a button.
ListSectiondefaults to the roundedinsetlook of iOS settings.- Mobile only: there is no web version of this component.