Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
BottomSheet,
Form,
Host,
List,
Picker,
RNHostView,
Section,
Expand Down Expand Up @@ -43,6 +44,15 @@ export default function BottomSheetScreen() {
const [backgroundInteractionEnabled, setBackgroundInteractionEnabled] = React.useState(false);
const [dismissDisabled, setDismissDisabled] = React.useState(false);

const [showSelectionTracking, setShowSelectionTracking] = React.useState(false);
const selectionDetents: PresentationDetent[] = [
{ height: 300 },
{ fraction: 0.3 },
'medium',
'large',
];
const [selectedDetent, setSelectedDetent] = React.useState<PresentationDetent>('medium');

const [showRNContent, setShowRNContent] = React.useState(false);
const [showRNContentWithFlex1, setShowRNContentWithFlex1] = React.useState(false);
const [counter, setCounter] = React.useState(0);
Expand Down Expand Up @@ -117,6 +127,13 @@ export default function BottomSheetScreen() {
/>
</Section>

<Section title="Selection Tracking">
<Button
label="Open Selection Tracking Sheet"
onPress={() => setShowSelectionTracking(true)}
/>
</Section>

<Section title="React Native Content">
<Text modifiers={[foregroundStyle('secondaryLabel')]}>
Sheet with React Native views inside
Expand Down Expand Up @@ -182,6 +199,34 @@ export default function BottomSheetScreen() {
</Group>
</BottomSheet>

{/* Selection Tracking Sheet */}
<BottomSheet
isPresented={showSelectionTracking}
onIsPresentedChange={setShowSelectionTracking}>
<Group
modifiers={[
presentationDetents(selectionDetents, {
selection: selectedDetent,
onSelectionChange: setSelectedDetent,
}),
presentationDragIndicator('visible'),
]}>
<List>
<Section title="Change Detent">
<Button label="Height 300" onPress={() => setSelectedDetent({ height: 300 })} />
<Button label="Fraction 0.3" onPress={() => setSelectedDetent({ fraction: 0.3 })} />
<Button label="Medium" onPress={() => setSelectedDetent('medium')} />
<Button label="Large" onPress={() => setSelectedDetent('large')} />
</Section>
<Section title="Current">
<Text modifiers={[foregroundStyle('secondaryLabel')]}>
{formatDetent(selectedDetent)}
</Text>
</Section>
</List>
</Group>
</BottomSheet>

{/* React Native Content Sheet */}
<BottomSheet isPresented={showRNContent} onIsPresentedChange={setShowRNContent} fitToContents>
<Group modifiers={[presentationDragIndicator('visible')]}>
Expand Down
63 changes: 61 additions & 2 deletions docs/pages/versions/unversioned/sdk/ui/swift-ui/bottomsheet.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export default function BottomSheetFitsContentExample() {

### Bottom sheet with presentation detents

Use the [`presentationDetents`](/modifiers/#presentationdetentsdetents) modifier on `Group` to control the available heights. You can use:
Use the [`presentationDetents`](modifiers/#presentationdetentsdetents-options) modifier on `Group` to control the available heights. You can use:

- `'medium'`: System medium height (approximately half screen)
- `'large'`: System large height (full screen)
Expand Down Expand Up @@ -101,6 +101,65 @@ export default function BottomSheetWithDetentsExample() {
}
```

### Bottom sheet with detent selection tracking

Pass `selection` and `onSelectionChange` options to [`presentationDetents`](modifiers/#presentationdetentsdetents-options) to programmatically control which detent the sheet snaps to.

```tsx BottomSheetWithDetentSelectionExample.tsx
import { useState } from 'react';
import { Host, BottomSheet, Button, List, Section, Text, VStack, Group } from '@expo/ui/swift-ui';
import {
presentationDetents,
presentationDragIndicator,
foregroundStyle,
} from '@expo/ui/swift-ui/modifiers';
import type { PresentationDetent } from '@expo/ui/swift-ui/modifiers';

export default function BottomSheetWithDetentSelectionExample() {
const [isPresented, setIsPresented] = useState(false);
const detents: PresentationDetent[] = [{ height: 300 }, { fraction: 0.3 }, 'medium', 'large'];
const [selectedDetent, setSelectedDetent] = useState<PresentationDetent>('medium');

const formatDetent = (detent: PresentationDetent): string => {
if (typeof detent === 'string') return detent;
if ('fraction' in detent) return `Fraction ${detent.fraction}`;
return `Height ${detent.height}`;
};

return (
<Host style={{ flex: 1 }}>
<VStack>
<Button label="Show Sheet" onPress={() => setIsPresented(true)} />
<BottomSheet isPresented={isPresented} onIsPresentedChange={setIsPresented}>
<Group
modifiers={[
presentationDetents(detents, {
selection: selectedDetent,
onSelectionChange: setSelectedDetent,
}),
presentationDragIndicator('visible'),
]}>
<List>
<Section title="Change Detent">
<Button label="Height 300" onPress={() => setSelectedDetent({ height: 300 })} />
<Button label="Fraction 0.3" onPress={() => setSelectedDetent({ fraction: 0.3 })} />
<Button label="Medium" onPress={() => setSelectedDetent('medium')} />
<Button label="Large" onPress={() => setSelectedDetent('large')} />
</Section>
<Section title="Current">
<Text modifiers={[foregroundStyle('secondaryLabel')]}>
{formatDetent(selectedDetent)}
</Text>
</Section>
</List>
</Group>
</BottomSheet>
</VStack>
</Host>
);
}
```

### Bottom sheet with background interaction

Use the [`presentationBackgroundInteraction`](modifiers/#presentationbackgroundinteractioninteraction) modifier to allow interactions with content behind the sheet.
Expand Down Expand Up @@ -224,7 +283,7 @@ export default function BottomSheetWithRNContentExample() {

### Bottom sheet with flexible React Native content

When using React Native content with `flex: 1`, omit the `matchContents` prop on `RNHostView` and use [`presentationDetents`](modifiers/#presentationdetentsdetents) to control the sheet height.
When using React Native content with `flex: 1`, omit the `matchContents` prop on `RNHostView` and use [`presentationDetents`](modifiers/#presentationdetentsdetents-options) to control the sheet height.

```tsx BottomSheetWithFlexRNContentExample.tsx
import { useState } from 'react';
Expand Down
63 changes: 61 additions & 2 deletions docs/pages/versions/v55.0.0/sdk/ui/swift-ui/bottomsheet.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export default function BottomSheetFitsContentExample() {

### Bottom sheet with presentation detents

Use the [`presentationDetents`](/modifiers/#presentationdetentsdetents) modifier on `Group` to control the available heights. You can use:
Use the [`presentationDetents`](modifiers/#presentationdetentsdetents-options) modifier on `Group` to control the available heights. You can use:

- `'medium'`: System medium height (approximately half screen)
- `'large'`: System large height (full screen)
Expand Down Expand Up @@ -101,6 +101,65 @@ export default function BottomSheetWithDetentsExample() {
}
```

### Bottom sheet with detent selection tracking

Pass `selection` and `onSelectionChange` options to [`presentationDetents`](modifiers/#presentationdetentsdetents-options) to programmatically control which detent the sheet snaps to.

```tsx BottomSheetWithDetentSelectionExample.tsx
import { useState } from 'react';
import { Host, BottomSheet, Button, List, Section, Text, VStack, Group } from '@expo/ui/swift-ui';
import {
presentationDetents,
presentationDragIndicator,
foregroundStyle,
} from '@expo/ui/swift-ui/modifiers';
import type { PresentationDetent } from '@expo/ui/swift-ui/modifiers';

export default function BottomSheetWithDetentSelectionExample() {
const [isPresented, setIsPresented] = useState(false);
const detents: PresentationDetent[] = [{ height: 300 }, { fraction: 0.3 }, 'medium', 'large'];
const [selectedDetent, setSelectedDetent] = useState<PresentationDetent>('medium');

const formatDetent = (detent: PresentationDetent): string => {
if (typeof detent === 'string') return detent;
if ('fraction' in detent) return `Fraction ${detent.fraction}`;
return `Height ${detent.height}`;
};

return (
<Host style={{ flex: 1 }}>
<VStack>
<Button label="Show Sheet" onPress={() => setIsPresented(true)} />
<BottomSheet isPresented={isPresented} onIsPresentedChange={setIsPresented}>
<Group
modifiers={[
presentationDetents(detents, {
selection: selectedDetent,
onSelectionChange: setSelectedDetent,
}),
presentationDragIndicator('visible'),
]}>
<List>
<Section title="Change Detent">
<Button label="Height 300" onPress={() => setSelectedDetent({ height: 300 })} />
<Button label="Fraction 0.3" onPress={() => setSelectedDetent({ fraction: 0.3 })} />
<Button label="Medium" onPress={() => setSelectedDetent('medium')} />
<Button label="Large" onPress={() => setSelectedDetent('large')} />
</Section>
<Section title="Current">
<Text modifiers={[foregroundStyle('secondaryLabel')]}>
{formatDetent(selectedDetent)}
</Text>
</Section>
</List>
</Group>
</BottomSheet>
</VStack>
</Host>
);
}
```

### Bottom sheet with background interaction

Use the [`presentationBackgroundInteraction`](modifiers/#presentationbackgroundinteractioninteraction) modifier to allow interactions with content behind the sheet.
Expand Down Expand Up @@ -224,7 +283,7 @@ export default function BottomSheetWithRNContentExample() {

### Bottom sheet with flexible React Native content

When using React Native content with `flex: 1`, omit the `matchContents` prop on `RNHostView` and use [`presentationDetents`](modifiers/#presentationdetentsdetents) to control the sheet height.
When using React Native content with `flex: 1`, omit the `matchContents` prop on `RNHostView` and use [`presentationDetents`](modifiers/#presentationdetentsdetents-options) to control the sheet height.

```tsx BottomSheetWithFlexRNContentExample.tsx
import { useState } from 'react';
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/expo-ui/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

- [iOS] - Support `Section` `footer` prop with `title` prop. ([#42966](https://github.com/expo/expo/pull/42966) by [@nishan](https://github.com/intergalacticspacehighway))
- [iOS] Added `contentTransition` modifier. ([#42980](https://github.com/expo/expo/pull/42980) by [@nishan](https://github.com/intergalacticspacehighway))
- [iOS] Added `selection` and `onSelectionChange` to `presentationDetents` modifier for programmatic control of bottom sheet detents. ([#42910](https://github.com/expo/expo/pull/42910) by [@nishan](https://github.com/intergalacticspacehighway))

### 🐛 Bug fixes

Expand Down
4 changes: 4 additions & 0 deletions packages/expo-ui/build/swift-ui/modifiers/createModifier.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading