AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
A bottom sheet for React Native that works the same on Android as it does on iOS and web.
Content-sized by default, gesture-driven, and rendered above tab bars and navigators. Ships with two ready-made sheets — an options menu and a confirmation dialog — on top of the primitive.
Install the peer dependencies first, then the package. The order matters — see Troubleshooting if you skip it.
Bare React Native — pick versions your React Native supports, for example on RN 0.81:檢視完整 README ↗A bottom sheet for React Native that works the same on Android as it does on iOS and web.
Content-sized by default, gesture-driven, and rendered above tab bars and navigators. Ships with two ready-made sheets — an options menu and a confirmation dialog — on top of the primitive.
Install the peer dependencies first, then the package. The order matters — see Troubleshooting if you skip it.
Expo:
npx expo install react-native-reanimated react-native-gesture-handler react-native-safe-area-context
npm install react-native-kp-bottom-sheet
Bare React Native — pick versions your React Native supports, for example on RN 0.81:
npm install react-native-reanimated@~4.1.1 [email protected] react-native-gesture-handler@~2.28.0 react-native-safe-area-context@~5.6.0
npm install react-native-kp-bottom-sheet
react-native-worklets is separate because Reanimated 4 requires it; Expo installs it for you, bare projects have to ask.
<Modal>?Because drag-to-dismiss silently stops working on Android.
React Native's <Modal> renders into a separate native surface, and react-native-gesture-handler's GestureDetector cannot see through it — even inside a GestureHandlerRootView. Nothing errors. The sheet just refuses to drag on Android while working perfectly on iOS and web, which is a miserable thing to debug.
So this package renders the sheet as an ordinary absolutely-positioned view instead. That fixes the gesture, but costs you Modal's other freebie: an ordinary view obeys ordinary stacking rules, and a zIndex only reorders siblings under the same parent — so a sheet opened from a screen nested inside a tab navigator can never paint over the tab bar, which lives several levels up.
Which is what SheetProvider is for. Sheets are declared deep in your tree and rendered at the app root. That is also why setup has a required step.
Wrap the app once, as high up as you can:
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { SheetProvider } from 'react-native-kp-bottom-sheet';
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<SafeAreaProvider>
<SheetProvider>
<Navigation />
</SheetProvider>
</SafeAreaProvider>
</GestureHandlerRootView>
);
}
Forget it and any sheet below will throw a message telling you so in development.
import { useState } from 'react';
import { Button, Text } from 'react-native';
import { Sheet } from 'react-native-kp-bottom-sheet';
function Screen() {
const [open, setOpen] = useState(false);
return (
<>
<Button title="Open" onPress={() => setOpen(true)} />
<Sheet visible={open} onClose={() => setOpen(false)}>
<Text>Anything at all.</Text>
</Sheet>
</>
);
}
The sheet is a controlled component and renders nothing where you put it. onClose fires on backdrop tap, drag-down and Android hardware back; flip your own state there.
Height is driven by the content — the surface is an ordinary View, so it wraps whatever is inside it, capped at maxHeight. Reach for a fixed height only when the content is a list that should always open at a set size.
Pass dragHandleOnly whenever the sheet holds a ScrollView or FlatList:
<Sheet visible={open} onClose={close} height="70%" dragHandleOnly>
<FlatList data={items} renderItem={renderItem} />
</Sheet>
Without it the sheet's own pan gesture competes with the list's scrolling, and a downward drag on a list that is scrolled part-way moves the sheet instead of the list. Dragging by the handle alone has nothing to compete with.
Sheet props| Prop | Type | Default | |
|---|---|---|---|
visible | boolean | — | Required. |
onClose | () => void | — | Backdrop tap, drag-down, or hardware back. |
height | number | "60%" | — | Fixed height. Omit to size to content. |
maxHeight | number | "60%" | "88%" | Ceiling for content-sized sheets. |
dismissible | boolean | true | false pins the sheet open — no drag, no backdrop tap, no back. |
dragHandleOnly | boolean | false | Drag by the handle only. Set it for scrollable content. |
showHandle | boolean | true | Hides the drag pill. |
style | ViewStyle | — | Applied to the sheet surface. |
Percentages resolve against the live window, so a sheet opened after a rotation, in split-screen, or on an unfolded foldable is sized against the window it is actually in.
ActionSheetAn options menu — the "Edit / Delete" you get from a list row.
import { Pencil, Trash2 } from 'lucide-react-native';
import { ActionSheet } from 'react-native-kp-bottom-sheet';
<ActionSheet
visible={open}
onClose={() => setOpen(false)}
title="Home"
subtitle="221B Baker Street"
items={[
{ key: 'edit', label: 'Edit address', icon: <Pencil size={20} />, onPress: edit },
{ key: 'delete', label: 'Delete', icon: <Trash2 size={20} />, danger: true, onPress: remove },
]}
/>;
icon is any node, so the package pulls in no icon library of its own. danger tints the tile and label. Pass title wherever the sheet is opened from a list — "Delete" alone does not say which row.
ConfirmSheetA confirmation dialog, for when the platform alert feels off-brand.
<ConfirmSheet
visible={open}
title="Delete this card?"
description="You will need to add it again to use it."
confirmLabel="Delete"
tone="danger"
onCancel={() => setOpen(false)}
onConfirm={async () => {
await api.deleteCard(id);
setOpen(false);
}}
/>
While onConfirm is in flight the button shows a spinner and the sheet refuses to close — dragging it away mid-request would leave your loading state stranded.
SheetProvider takes a partial override, merged over the defaults:
<SheetProvider theme={{ surface: '#111827', textPrimary: '#F9FAFB', primary: '#22D3EE', radius: 20 }}>
Tokens: surface, border, backdrop, handle, primary, primaryTint, danger, dangerTint, textPrimary, textSecondary, radius. Import defaultSheetTheme to see the values, or useSheetTheme() to read the merged result in your own sheet content.
For a one-off, style on any sheet wins over the theme.
SheetProvider renders its host as its own last child. If your app has a wrapper the sheets should escape — a max-width frame on tablet and web, say — put the host where you want it:
<SheetProvider host={false}>
<View style={styles.backdropColumn}>
<View style={styles.appFrame}>
<Navigation />
</View>
<SheetPortalHost />
</View>
</SheetProvider>
ERESOLVE unable to resolve dependency tree on installCould not resolve dependency:
peer react-native@"0.83 - 0.87" from [email protected]
peer react-native-reanimated@">=3.6.0" from react-native-kp-bottom-sheet
Your project doesn't have Reanimated yet, so npm went to fetch it — and npm picks the newest version satisfying >=3.6.0, which is currently 4.6.x. That version requires a newer React Native than yours, and the two demands can't both be met.
Install a Reanimated your React Native supports first, then this package. See Install above. With a compatible version already present, npm sees it satisfies >=3.6.0 and stops reaching for the newest.
No peer range here can prevent this: the conflict is between Reanimated and your React Native version, not with this package.
Don't reach for --force or --legacy-peer-deps. They silence the message while installing the incompatible Reanimated anyway, trading a clear error at install time for a native crash at runtime.
Check that <GestureHandlerRootView style={{ flex: 1 }}> wraps your app — gestures fail silently without it. And if you have wrapped this sheet in a React Native <Modal> yourself, unwrap it; that reintroduces the exact problem this package exists to avoid.
visible is trueThere's no <SheetProvider> above the sheet. In development it throws saying so; in production it fails quietly.
Pass dragHandleOnly. See Sheets containing a list.
Snap points. Every sheet here is single-height, open or closed. Keyboard avoidance for inputs inside a sheet is likewise left to you for now.
MIT