{"id":37768421,"url":"https://github.com/sergeymild/react-native-sheet","last_synced_at":"2026-01-16T14:49:44.820Z","repository":{"id":93523891,"uuid":"604931216","full_name":"sergeymild/react-native-sheet","owner":"sergeymild","description":"A performant interactive bottom sheet for React Native","archived":false,"fork":false,"pushed_at":"2026-01-15T03:43:12.000Z","size":7425,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-15T09:42:52.510Z","etag":null,"topics":["android","bottomsheet","ios","react-native"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sergeymild.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-02-22T04:34:46.000Z","updated_at":"2026-01-15T03:41:36.000Z","dependencies_parsed_at":"2023-08-01T10:01:55.895Z","dependency_job_id":"a81fcf1a-c329-4424-8fbb-bf018ab2c564","html_url":"https://github.com/sergeymild/react-native-sheet","commit_stats":null,"previous_names":[],"tags_count":108,"template":false,"template_full_name":null,"purl":"pkg:github/sergeymild/react-native-sheet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergeymild%2Freact-native-sheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergeymild%2Freact-native-sheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergeymild%2Freact-native-sheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergeymild%2Freact-native-sheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sergeymild","download_url":"https://codeload.github.com/sergeymild/react-native-sheet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergeymild%2Freact-native-sheet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28479402,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","bottomsheet","ios","react-native"],"created_at":"2026-01-16T14:49:43.955Z","updated_at":"2026-01-16T14:49:44.811Z","avatar_url":"https://github.com/sergeymild.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-native-sheet\n![React Native Bottom Sheet](./preview.gif)\nA high-performance, native bottom sheet component for React Native with auto-sizing and Fabric architecture support.\n\n## Features\n\n- **Native Implementation** - Built with Fabric architecture for iOS and modern Android APIs\n- **Auto-sizing** - Automatically sizes to content height with dynamic updates\n- **Landscape/Portrait Support** - Different constraints for device orientations\n- **Data Passing** - Pass data to sheets and receive values on dismiss\n- **Multiple Sheets** - Support for stacked sheets with named identifiers\n- **Dual APIs** - Both imperative and declarative approaches\n- **Global Sheet API** - Show sheets without pre-declaring components\n- **Customizable** - Control corner radius, colors, sizing constraints\n- **Dismissal Control** - Optional prevention of outside tap dismissal\n- **ScrollView Integration** - Special handling for scrollable content\n\n## Installation\n\n```sh\n//package.json\n\"react-native-sheet\":\"sergeymild/react-native-sheet#7.0.0\"\nyarn\n```\n\n## Usage\n\n### Setup\n\nWrap your app with `SheetProvider`:\n\n```tsx\nimport { SheetProvider } from 'react-native-sheet';\n\nexport default function App() {\n  return (\n    \u003cSheetProvider\u003e\n      \u003cYourApp /\u003e\n    \u003c/SheetProvider\u003e\n  );\n}\n```\n\n### Basic Example\n\n```tsx\nimport { FittedSheet, type FittedSheetRef } from 'react-native-sheet';\nimport { useRef } from 'react';\nimport { View, Text, Button } from 'react-native';\n\nexport const BasicExample = () =\u003e {\n  const sheetRef = useRef\u003cFittedSheetRef\u003e(null);\n\n  return (\n    \u003cView\u003e\n      \u003cButton\n        title=\"Open Sheet\"\n        onPress={() =\u003e sheetRef.current?.show()}\n      /\u003e\n\n      \u003cFittedSheet ref={sheetRef}\u003e\n        \u003cView style={{ padding: 20 }}\u003e\n          \u003cText\u003eHello from Bottom Sheet!\u003c/Text\u003e\n          \u003cButton\n            title=\"Close\"\n            onPress={() =\u003e sheetRef.current?.hide()}\n          /\u003e\n        \u003c/View\u003e\n      \u003c/FittedSheet\u003e\n    \u003c/View\u003e\n  );\n};\n```\n\n### Named Sheets (Imperative API)\n\n```tsx\nimport {\n  FittedSheet,\n  presentFittedSheet,\n  dismissFittedSheet\n} from 'react-native-sheet';\n\nexport const NamedExample = () =\u003e {\n  return (\n    \u003c\u003e\n      \u003cButton\n        title=\"Open Sheet\"\n        onPress={() =\u003e presentFittedSheet('mySheet')}\n      /\u003e\n\n      \u003cFittedSheet name=\"mySheet\"\u003e\n        \u003cView style={{ padding: 20 }}\u003e\n          \u003cText\u003eNamed Sheet\u003c/Text\u003e\n          \u003cButton\n            title=\"Close\"\n            onPress={() =\u003e dismissFittedSheet('mySheet')}\n          /\u003e\n        \u003c/View\u003e\n      \u003c/FittedSheet\u003e\n    \u003c/\u003e\n  );\n};\n```\n\n### Global Sheet (Imperative API without Component Declaration)\n\nFor scenarios where you need to show a sheet without pre-declaring a `FittedSheet` component, you can use the global sheet API:\n\n```tsx\nimport {\n  presentGlobalFittedSheet,\n  dismissGlobalFittedSheet\n} from 'react-native-sheet';\nimport { View, Text, Button } from 'react-native';\n\nexport const GlobalSimpleUsage = () =\u003e {\n  return (\n    \u003cView style={{ flex: 1, padding: 24 }}\u003e\n      \u003cButton\n        title=\"Present Global Sheet\"\n        onPress={() =\u003e {\n          presentGlobalFittedSheet({\n            name: 'myGlobalSheet',\n            onDismiss: () =\u003e {\n              console.log('Sheet dismissed');\n            },\n            sheetProps: {\n              params: {\n                backgroundColor: 'white',\n                topLeftRightCornerRadius: 10,\n              },\n              rootViewStyle: {\n                paddingBottom: 56,\n              },\n            },\n            children: (\n              \u003cView style={{ flexGrow: 1, padding: 20 }}\u003e\n                \u003cText\u003eGlobal Sheet Content\u003c/Text\u003e\n                \u003cButton\n                  title=\"Dismiss\"\n                  onPress={() =\u003e dismissGlobalFittedSheet('myGlobalSheet')}\n                /\u003e\n              \u003c/View\u003e\n            ),\n          });\n        }}\n      /\u003e\n\n      {/* Dismiss from outside */}\n      \u003cButton\n        title=\"Dismiss Global Sheet\"\n        onPress={() =\u003e dismissGlobalFittedSheet('myGlobalSheet')}\n      /\u003e\n    \u003c/View\u003e\n  );\n};\n```\n\n**Setup**: To enable the global sheet, add the `addGlobalSheetView` prop to `SheetProvider`:\n\n```tsx\nimport { SheetProvider } from 'react-native-sheet';\n\nexport default function App() {\n  return (\n    \u003cSheetProvider addGlobalSheetView\u003e\n      \u003cYourApp /\u003e\n    \u003c/SheetProvider\u003e\n  );\n}\n```\n\nYou can also provide default sheet properties that will be used for all global sheets:\n\n```tsx\n\u003cSheetProvider\n  addGlobalSheetView\n  globalSheetProps={{\n    params: {\n      backgroundColor: '#f5f5f5',\n      topLeftRightCornerRadius: 16,\n    },\n    rootViewStyle: {\n      padding: 16,\n    },\n  }}\n\u003e\n  \u003cYourApp /\u003e\n\u003c/SheetProvider\u003e\n```\n\n#### Advanced Global Sheet Usage\n\n**Multiple Global Sheets:**\n\nYou can present multiple global sheets simultaneously by using unique names:\n\n```tsx\nimport {\n  presentGlobalFittedSheet,\n  dismissGlobalFittedSheet\n} from 'react-native-sheet';\n\n// Present first sheet\npresentGlobalFittedSheet({\n  name: 'sheet1',\n  sheetProps: {\n    params: { backgroundColor: 'white' }\n  },\n  children: (\n    \u003cView style={{ padding: 20 }}\u003e\n      \u003cText\u003eFirst Sheet\u003c/Text\u003e\n      \u003cButton\n        title=\"Open Second Sheet\"\n        onPress={() =\u003e {\n          presentGlobalFittedSheet({\n            name: 'sheet2',\n            sheetProps: {\n              params: { backgroundColor: 'lightblue' }\n            },\n            children: (\n              \u003cView style={{ padding: 20 }}\u003e\n                \u003cText\u003eSecond Sheet\u003c/Text\u003e\n                \u003cButton\n                  title=\"Dismiss This\"\n                  onPress={() =\u003e dismissGlobalFittedSheet('sheet2')}\n                /\u003e\n                \u003cButton\n                  title=\"Dismiss First Sheet\"\n                  onPress={() =\u003e dismissGlobalFittedSheet('sheet1')}\n                /\u003e\n              \u003c/View\u003e\n            ),\n          });\n        }}\n      /\u003e\n    \u003c/View\u003e\n  ),\n});\n```\n\n**Dynamic ScrollView in Global Sheet:**\n\nWhen your sheet content loads asynchronously and includes a ScrollView, you need to attach the scrollview after it renders:\n\n```tsx\nimport {\n  presentGlobalFittedSheet,\n  attachScrollViewToGlobalFittedSheet\n} from 'react-native-sheet';\nimport { useEffect, useState } from 'react';\nimport { ScrollView, ActivityIndicator } from 'react-native';\n\nconst DynamicContent = ({ sheetName }) =\u003e {\n  const [loading, setLoading] = useState(true);\n  const [data, setData] = useState([]);\n\n  useEffect(() =\u003e {\n    // Simulate async data loading\n    setTimeout(() =\u003e {\n      setData(Array.from({ length: 20 }, (_, i) =\u003e i + 1));\n      setLoading(false);\n\n      // Attach ScrollView after it appears\n      setTimeout(() =\u003e {\n        attachScrollViewToGlobalFittedSheet(sheetName);\n      }, 100);\n    }, 2000);\n  }, [sheetName]);\n\n  if (loading) {\n    return (\n      \u003cView style={{ padding: 40 }}\u003e\n        \u003cActivityIndicator size=\"large\" /\u003e\n        \u003cText\u003eLoading data...\u003c/Text\u003e\n      \u003c/View\u003e\n    );\n  }\n\n  return (\n    \u003cScrollView style={{ padding: 20 }}\u003e\n      \u003cText\u003eScrollable Content\u003c/Text\u003e\n      {data.map(item =\u003e (\n        \u003cView key={item} style={{ padding: 16 }}\u003e\n          \u003cText\u003eItem {item}\u003c/Text\u003e\n        \u003c/View\u003e\n      ))}\n    \u003c/ScrollView\u003e\n  );\n};\n\n// Present the sheet\npresentGlobalFittedSheet({\n  name: 'dynamicSheet',\n  sheetProps: {\n    params: {\n      backgroundColor: 'white',\n      topLeftRightCornerRadius: 10,\n    },\n  },\n  children: \u003cDynamicContent sheetName=\"dynamicSheet\" /\u003e,\n});\n```\n\n**Dismissing Multiple Sheets:**\n\n```tsx\n// Dismiss all global sheets at once\ndismissGlobalFittedSheet('sheet1');\ndismissGlobalFittedSheet('sheet2');\ndismissGlobalFittedSheet('sheet3');\n```\n\n**Passing Data to Global Sheets:**\n\nSince global sheets don't support the `show(data)` / `hide(returnValue)` pattern, you can pass data using these approaches:\n\n```tsx\n// 1. Pass data via closure/variables\nconst userId = 123;\nconst userName = 'John Doe';\n\npresentGlobalFittedSheet({\n  name: 'userProfile',\n  children: (\n    \u003cView style={{ padding: 20 }}\u003e\n      \u003cText\u003eUser ID: {userId}\u003c/Text\u003e\n      \u003cText\u003eName: {userName}\u003c/Text\u003e\n    \u003c/View\u003e\n  ),\n});\n\n// 2. Return data via closure in onDismiss callback\nlet result = null;\n\npresentGlobalFittedSheet({\n  name: 'confirmDialog',\n  onDismiss: () =\u003e {\n    // Handle the result here\n    if (result?.confirmed) {\n      console.log('User confirmed!');\n    }\n  },\n  children: (\n    \u003cView style={{ padding: 20 }}\u003e\n      \u003cButton\n        title=\"Confirm\"\n        onPress={() =\u003e {\n          result = { confirmed: true };\n          dismissGlobalFittedSheet('confirmDialog');\n        }}\n      /\u003e\n    \u003c/View\u003e\n  ),\n});\n\n// 3. Use a component with useState for dynamic data\nconst FormSheet = () =\u003e {\n  const [name, setName] = useState('');\n  return (\n    \u003cView style={{ padding: 20 }}\u003e\n      \u003cTextInput value={name} onChangeText={setName} /\u003e\n      \u003cButton\n        title=\"Submit\"\n        onPress={() =\u003e {\n          console.log('Submitted:', name);\n          dismissGlobalFittedSheet('formSheet');\n        }}\n      /\u003e\n    \u003c/View\u003e\n  );\n};\n\npresentGlobalFittedSheet({\n  name: 'formSheet',\n  children: \u003cFormSheet /\u003e,\n});\n```\n\n### Passing Data (FittedSheet with Ref)\n\nFor `FittedSheet` components with refs, you can pass data using the `show(data)` method and receive return values via `hide(returnValue)`:\n\n\u003e **Note**: This pattern only works with `FittedSheet` components that have a ref. For Global Sheets, see the \"Passing Data to Global Sheets\" section above.\n\n```tsx\nimport { FittedSheet, type FittedSheetRef } from 'react-native-sheet';\nimport { useRef } from 'react';\n\nexport const DataExample = () =\u003e {\n  const sheetRef = useRef\u003cFittedSheetRef\u003e(null);\n\n  const openWithData = () =\u003e {\n    sheetRef.current?.show({ userId: 123, name: 'John' });\n  };\n\n  return (\n    \u003c\u003e\n      \u003cButton title=\"Open Sheet\" onPress={openWithData} /\u003e\n\n      \u003cFittedSheet\n        ref={sheetRef}\n        onSheetDismiss={(returnValue) =\u003e {\n          console.log('Sheet dismissed with:', returnValue);\n        }}\n      \u003e\n        {(data) =\u003e (\n          \u003cView style={{ padding: 20 }}\u003e\n            \u003cText\u003eUser: {data?.name}\u003c/Text\u003e\n            \u003cText\u003eID: {data?.userId}\u003c/Text\u003e\n            \u003cButton\n              title=\"Close with Result\"\n              onPress={() =\u003e sheetRef.current?.hide({ success: true })}\n            /\u003e\n          \u003c/View\u003e\n        )}\n      \u003c/FittedSheet\u003e\n    \u003c/\u003e\n  );\n};\n```\n\n### Customization\n\n```tsx\n\u003cFittedSheet\n  ref={sheetRef}\n  params={{\n    maxHeight: 600,\n    minHeight: 200,\n    maxPortraitWidth: 400,\n    maxLandscapeWidth: 600,\n    topLeftRightCornerRadius: 24,\n    backgroundColor: '#ffffff',\n    dismissable: true,\n  }}\n  rootViewStyle={{ padding: 16 }}\n\u003e\n  \u003cYourContent /\u003e\n\u003c/FittedSheet\u003e\n```\n\n### Multiple Sheets\n\n```tsx\nexport const MultipleExample = () =\u003e {\n  return (\n    \u003c\u003e\n      \u003cButton\n        title=\"Open First Sheet\"\n        onPress={() =\u003e presentFittedSheet('first')}\n      /\u003e\n\n      \u003cFittedSheet\n        name=\"first\"\n        params={{ backgroundColor: '#f0f0f0' }}\n      \u003e\n        \u003cView style={{ padding: 20 }}\u003e\n          \u003cText\u003eFirst Sheet\u003c/Text\u003e\n          \u003cButton\n            title=\"Open Second Sheet\"\n            onPress={() =\u003e presentFittedSheet('second')}\n          /\u003e\n        \u003c/View\u003e\n      \u003c/FittedSheet\u003e\n\n      \u003cFittedSheet\n        name=\"second\"\n        params={{ backgroundColor: '#e0e0ff' }}\n      \u003e\n        \u003cView style={{ padding: 20 }}\u003e\n          \u003cText\u003eSecond Sheet\u003c/Text\u003e\n          \u003cButton\n            title=\"Dismiss All\"\n            onPress={() =\u003e dismissFittedSheetsAll()}\n          /\u003e\n        \u003c/View\u003e\n      \u003c/FittedSheet\u003e\n    \u003c/\u003e\n  );\n};\n```\n\n## API Reference\n\n### FittedSheet Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string` | `undefined` | Optional identifier for imperative API control |\n| `params` | `SheetParams` | `{}` | Configuration options for the sheet |\n| `onSheetDismiss` | `(value?: any) =\u003e void` | `undefined` | Callback when sheet is dismissed |\n| `rootViewStyle` | `ViewStyle` | `undefined` | Style for internal root view |\n| `children` | `ReactNode \\| ((data?: any) =\u003e ReactNode)` | - | Content to render in sheet |\n\n### SheetParams\n\n| Param | Type | Default | Description |\n|-------|------|---------|-------------|\n| `applyMaxHeightToMinHeight` | `boolean` | `false` | Apply max height constraint to min height |\n| `dismissable` | `boolean` | `true` | Allow dismissing by tapping outside |\n| `maxPortraitWidth` | `number` | `undefined` | Maximum width in portrait mode |\n| `maxLandscapeWidth` | `number` | `undefined` | Maximum width in landscape mode |\n| `maxHeight` | `number` | `undefined` | Maximum height of sheet |\n| `minHeight` | `number` | `undefined` | Minimum height of sheet |\n| `topLeftRightCornerRadius` | `number` | `20` | Radius for top corners |\n| `backgroundColor` | `string` | `'white'` | Background color of sheet |\n| `isSystemUILight` | `boolean` | `undefined` | Android only - status bar styling |\n\n### FittedSheetRef Methods\n\n```typescript\ninterface FittedSheetRef {\n  show(data?: any): void;                    // Show sheet with optional data\n  hide(passThroughParam?: any): void;        // Hide sheet with optional callback param\n  attachScrollViewToSheet(): void;           // Attach scrollview for better scrolling\n}\n```\n\n### Imperative API\n\n```typescript\n// Show a named sheet\npresentFittedSheet(name: string, data?: any): void\n\n// Hide a specific named sheet\ndismissFittedSheet(name: string, passThroughParam?: any): void\n\n// Hide all sheets\ndismissFittedSheetsAll(): void\n\n// Hide the most recently presented sheet\ndismissFittedPresented(): void\n\n// Attach scrollview to a named sheet\nattachScrollViewToFittedSheet(name: string): void\n\n// Global Sheet API - Show a sheet without pre-declaring a component\npresentGlobalFittedSheet(params: {\n  name: string;\n  onDismiss?: () =\u003e void;\n  sheetProps?: SheetProps;\n  children: ReactElement | ReactElement[];\n}): void\n\n// Dismiss a specific global sheet by name\ndismissGlobalFittedSheet(name: string): void\n\n// Attach scrollview to a global sheet by name (for dynamic ScrollView content)\nattachScrollViewToGlobalFittedSheet(name: string): boolean\n```\n\n### SheetProvider Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `children` | `ReactNode` | - | Your app content |\n| `addGlobalSheetView` | `boolean` | `false` | Enable global sheet API |\n| `globalSheetProps` | `Omit\u003cSheetProps, 'children' \\| 'onSheetDismiss'\u003e` | `undefined` | Default props for global sheets |\n\n## Advanced Examples\n\n### Dynamic Content Height\n\nThe sheet automatically resizes when content height changes:\n\n```tsx\nexport const DynamicExample = () =\u003e {\n  const [items, setItems] = useState([1, 2, 3]);\n  const sheetRef = useRef\u003cFittedSheetRef\u003e(null);\n\n  return (\n    \u003cFittedSheet ref={sheetRef}\u003e\n      \u003cView style={{ padding: 20 }}\u003e\n        {items.map(item =\u003e (\n          \u003cView key={item} style={{ height: 50, marginBottom: 10 }}\u003e\n            \u003cText\u003eItem {item}\u003c/Text\u003e\n          \u003c/View\u003e\n        ))}\n        \u003cButton\n          title=\"Add Item\"\n          onPress={() =\u003e setItems([...items, items.length + 1])}\n        /\u003e\n      \u003c/View\u003e\n    \u003c/FittedSheet\u003e\n  );\n};\n```\n\n### Preventing Dismissal\n\n```tsx\n\u003cFittedSheet\n  ref={sheetRef}\n  params={{ dismissable: false }}\n\u003e\n  \u003cView style={{ padding: 20 }}\u003e\n    \u003cText\u003eThis sheet can't be dismissed by tapping outside\u003c/Text\u003e\n    \u003cButton\n      title=\"Close\"\n      onPress={() =\u003e sheetRef.current?.hide()}\n    /\u003e\n  \u003c/View\u003e\n\u003c/FittedSheet\u003e\n```\n\n### ScrollView Integration\n\nWhen using scrollable content, avoid wrapping in an additional `View`. Use a fragment instead for better performance:\n\n```tsx\nimport { ScrollView } from 'react-native';\n\nexport const ScrollExample = () =\u003e {\n  const sheetRef = useRef\u003cFittedSheetRef\u003e(null);\n\n  useEffect(() =\u003e {\n    // Attach scrollview for better scroll handling\n    sheetRef.current?.attachScrollViewToSheet();\n  }, []);\n\n  return (\n    \u003cFittedSheet ref={sheetRef}\u003e\n      \u003c\u003e\n        \u003cScrollView style={{ maxHeight: 400 }}\u003e\n          {/* Your scrollable content */}\n        \u003c/ScrollView\u003e\n      \u003c/\u003e\n    \u003c/FittedSheet\u003e\n  );\n};\n```\n\n**Important:** When using `ScrollView`, `FlatList`, or other scrollable components, do not wrap them in an additional `View`:\n\n```tsx\n// ✅ Good - use fragment\n\u003cFittedSheet ref={sheetRef}\u003e\n  \u003c\u003e\n    \u003cScrollView\u003e...\u003c/ScrollView\u003e\n  \u003c/\u003e\n\u003c/FittedSheet\u003e\n\n// ❌ Bad - avoid extra View wrapper\n\u003cFittedSheet ref={sheetRef}\u003e\n  \u003cView\u003e\n    \u003cScrollView\u003e...\u003c/ScrollView\u003e\n  \u003c/View\u003e\n\u003c/FittedSheet\u003e\n\n// ⚠️ If you must wrap ScrollView in a View, add flexGrow: 1\n\u003cFittedSheet ref={sheetRef}\u003e\n  \u003cView style={{ flexGrow: 1 }}\u003e\n    \u003cScrollView\u003e...\u003c/ScrollView\u003e\n  \u003c/View\u003e\n\u003c/FittedSheet\u003e\n```\n\n**Note:** If you need to wrap `ScrollView` in a `View` (e.g., for additional styling), make sure to add `flexGrow: 1` to the wrapper `View` style. This ensures proper height calculation for the sheet content.\n\n## Platform-Specific Notes\n\n### iOS\n- Uses native UIViewController presentation\n- Supports safe area insets automatically\n- Corner radius applied to top-left and top-right corners\n\n### Android\n- Uses Material BottomSheetDialog\n- Supports status bar styling via `isSystemUILight` param\n\n## Requirements\n\n- React Native \u003e= 0.70 (Fabric support)\n- iOS \u003e= 12.0\n- Android minSdkVersion \u003e= 21\n\n## Troubleshooting\n\n### Sheet not appearing\nMake sure your app is wrapped with `SheetProvider`:\n```tsx\n\u003cSheetProvider\u003e\n  \u003cApp /\u003e\n\u003c/SheetProvider\u003e\n```\n\n### Content not resizing\nEnsure your content has proper height constraints or use `flexGrow` instead of `flex: 1`.\n\n### Global sheet not working\nMake sure you've enabled global sheets in `SheetProvider`:\n```tsx\n\u003cSheetProvider addGlobalSheetView\u003e\n  \u003cYourApp /\u003e\n\u003c/SheetProvider\u003e\n```\n\n### ScrollView not working in global sheet\nIf you're loading ScrollView content asynchronously, you need to attach it after the content renders:\n```tsx\nattachScrollViewToGlobalFittedSheet('sheetName');\n```\nThis should be called after your ScrollView component has mounted (typically in a `useEffect` hook after data loading completes).\n\n### How to pass data to global sheets?\nGlobal sheets don't support the `show(data)` / `hide(returnValue)` pattern like FittedSheet with refs. Instead, use closures, variables, or component state:\n- **Pass data in**: Use closure variables or props in the children component\n- **Return data**: Use a closure variable and set it before calling `dismissGlobalFittedSheet`, then handle it in `onDismiss` callback\n- **Dynamic data**: Use a component with `useState` as children\n\nSee the \"Passing Data to Global Sheets\" section in the documentation for examples.\n\n## Example App\n\nTo run the example app:\n\n```sh\n# Install dependencies\nyarn\n\n# Run on iOS\nyarn example ios\n\n# Run on Android\nyarn example android\n```\n\nThe example app includes demonstrations of:\n- Basic usage\n- Named sheets\n- Global sheet API\n- Data passing\n- Multiple sheets\n- Dynamic content\n- ScrollView integration\n- Queue management\n- Custom styling\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for details on:\n- Development workflow\n- Sending pull requests\n- Code of conduct\n\n## License\n\nMIT\n\n---\n\nMade with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsergeymild%2Freact-native-sheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsergeymild%2Freact-native-sheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsergeymild%2Freact-native-sheet/lists"}