Skip to content
Source
Sign inSign up

ListChoiceRow.tsx

63 lines2.1 KB

1import type { ReactNode } from "react";
2import { Platform, View } from "react-native";
3import { useResolveClassNames } from "uniwind";
4​
5import { cn } from "../../lib/cn";
6import { SymbolView } from "./AppSymbol";
7import { ListRowLayout } from "./ListRowLayout";
8import { RadioIndicator } from "./RadioIndicator";
9import { RowPressable } from "./RowPressable";
10​
11export function ListChoiceRow(props: {
12 readonly label: string;
13 readonly leading?: ReactNode;
14 readonly description?: string;
15 readonly meta?: ReactNode;
16 readonly selected: boolean;
17 readonly separated?: boolean;
18 readonly disabled?: boolean;
19 readonly onPress: () => void;
20}) {
21 const rippleStyle = useResolveClassNames("bg-subtle-strong");
22 return (
23 <RowPressable
24 accessibilityRole="radio"
25 accessibilityLabel={props.label}
26 accessibilityHint={props.description}
27 accessibilityState={{ checked: props.selected, disabled: Boolean(props.disabled) }}
28 disabled={props.disabled}
29 onPress={props.onPress}
30 android_ripple={{ color: rippleStyle.backgroundColor }}
31 unstable_pressDelay={Platform.OS === "android" ? 50 : undefined}
32 // Like UIKit and Material lists, only the checkmark or radio marks the selected row.
33 className={cn("bg-grouped-card", props.separated && "border-t border-border-subtle")}
34 >
35 <ListRowLayout
36 label={props.label}
37 leading={props.leading}
38 description={props.description}
39 meta={props.meta}
40 disabled={props.disabled}
41 accessory={
42 <View
43 accessibilityElementsHidden
44 importantForAccessibility="no-hide-descendants"
45 className="size-6 items-center justify-center"
46 >
47 {Platform.OS === "android" ? (
48 <RadioIndicator selected={props.selected} />
49 ) : props.selected ? (
50 <SymbolView
51 name="checkmark"
52 size={18}
53 tintColorClassName="accent-primary-text"
54 type="monochrome"
55 weight="semibold"
56 />
57 ) : null}
58 </View>
59 }
60 />
61 </RowPressable>
62 );