import { useState } from "react";
import { Text, TextInput } from "react-native";
import { Button } from "@/component-lib/button";
import { useKitTheme } from "@/component-lib/shared/native";
import { BottomSheet, BottomSheetClose } from "@/component-lib/bottom-sheet";
import { ListItem, List } from "@/component-lib/list-item";
import { Row, Section } from "./layout"; // Section and Row: page layout for the demo
export function BottomSheetDemo() {
const { tokens } = useKitTheme();
const [open, setOpen] = useState(false);
const [last, setLast] = useState("nothing yet");
const [note, setNote] = useState("");
return (
<Section title="BottomSheet">
<Row>
<BottomSheet
trigger={<Button variant="outline">Share</Button>}
title="Share invoice"
description="Pick how to send INV-2041."
footer={(close) => (
<Button variant="secondary" onPress={close}>
Cancel
</Button>
)}
>
{(close) => (
<List style={{ marginHorizontal: -16 }}>
{["Copy link", "WhatsApp", "Email", "Download PDF"].map((label) => (
<ListItem
key={label}
title={label}
onPress={() => {
setLast(label);
close();
}}
/>
))}
</List>
)}
</BottomSheet>
<Button variant="outline" onPress={() => setOpen(true)}>
Add note (controlled)
</Button>
</Row>
<Text style={{ color: tokens.muted, fontSize: tokens.fontSize - 2 }}>Last action: {last}</Text>
<BottomSheet
open={open}
onOpenChange={setOpen}
title="Add a note"
footer={
<>
<BottomSheetClose>
<Button variant="ghost">Discard</Button>
</BottomSheetClose>
<Button
onPress={() => {
setLast(note ? `note "${note}"` : "empty note");
setOpen(false);
}}
>
Save
</Button>
</>
}
>
<TextInput
value={note}
onChangeText={setNote}
placeholder="Type a note; the sheet stays above the keyboard"
placeholderTextColor={tokens.muted}
multiline
style={{
minHeight: 96,
borderWidth: 1,
borderColor: tokens.borderControl,
borderRadius: tokens.radius,
padding: 12,
color: tokens.fg,
fontSize: tokens.fontSize,
textAlignVertical: "top",
}}
/>
</BottomSheet>
</Section>
);
}Install
npx @grampro/kit@native add BottomSheetUsage
import { BottomSheet } from "@/component-lib/bottom-sheet";
<BottomSheet
trigger={<Button variant="outline">Share</Button>}
title="Share invoice"
footer={(close) => <Button onPress={close}>Done</Button>}
>
<ListItem title="Copy link" onPress={copy} />
</BottomSheet>Props
BottomSheetProps
| Prop | Type | Description |
|---|---|---|
open | boolean | |
defaultOpen | boolean | |
onOpenChange | (open: boolean) => void | |
trigger | ReactElement<{ onPress?(event: GestureResponderEvent): void }> | Pressing it opens the sheet: a Button or any element taking onPress. |
title | ReactNode | Heading, also the sheet's accessible name. |
description | ReactNode | |
footer | Renderable | Sticky actions under the scrolling content. A function receives close. |
dismissible | boolean | Tap outside, drag down and Android back close it. Default true. |
maxHeight | number | Largest height as a fraction of the screen. Default 0.9. |
scrollable | boolean | Content scrolls when taller than the sheet. Default true. |
onClosed | () => void | After the exit animation. |
style | StyleProp<ViewStyle> | |
styles | Partial<{ body: StyleProp<ViewStyle>; footer: StyleProp<ViewStyle> }> | |
children | Renderable | Content. A function receives close. |
Notes
- Built on Kit's shared
Sheet: clears the home indicator and stays above the keyboard. - No gesture or animation library: core
AnimatedandPanResponder. - Mobile only: there is no web version of this component.