Skip to content

Commit

Permalink
Merge pull request #4204 from tloncorp/dil/passthrough-unbound-pressable
Browse files Browse the repository at this point in the history
  • Loading branch information
davidisaaclee authored Nov 25, 2024
2 parents 6e794ec + 6847213 commit 26b1645
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 0 deletions.
93 changes: 93 additions & 0 deletions packages/app/fixtures/Pressable.fixture.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { Pressable, Text, View } from '@tloncorp/ui';
import { useValue } from 'react-cosmos/client';
import { Alert, SafeAreaView, Switch } from 'react-native';

export default {
Nested() {
const [innerPressableEnabled, setInnerPressableEnabled] = useValue(
'Enable inner press handler',
{ defaultValue: true }
);
const [siblingPressableEnabled, setSiblingPressableEnabled] = useValue(
'Enable sibling press handler',
{ defaultValue: true }
);
return (
<SafeAreaView>
<View>
<Pressable
padding={20}
backgroundColor="$negativeBackground"
onPress={() => {
Alert.alert('Outer: onPress fired');
}}
onTouchEndCapture={(event) => {
event.stopPropagation();
}}
>
<Text padding={20}>Outer view (has onPress handler)</Text>
<Pressable
padding={20}
backgroundColor="$positiveBackground"
onPress={
innerPressableEnabled
? (event) => {
event.persist();
console.log(event);
Alert.alert('Inner: onPress fired');
}
: undefined
}
>
<Text padding={20}>
Inner view{' '}
{innerPressableEnabled
? '(has onPress handler)'
: '(does not have onPress handler)'}{' '}
</Text>
</Pressable>
</Pressable>

{/* Sibling floating above the other pressables */}
<Pressable
position="absolute"
bottom={20}
right={0}
padding={20}
backgroundColor="rgba(100, 255, 100, 0.5)"
onPress={
siblingPressableEnabled
? () => {
Alert.alert('Sibling: onPress fired');
}
: undefined
}
>
<Text>
Sibling (press handler{' '}
{siblingPressableEnabled ? 'enabled' : 'disabled'})
</Text>
</Pressable>
</View>

{/* Settings panel */}
<View gap={8} padding={8}>
<View flexDirection="row" alignItems="center" gap={12}>
<Switch
value={innerPressableEnabled}
onValueChange={setInnerPressableEnabled}
/>
<Text>Enable inner press handler</Text>
</View>
<View flexDirection="row" alignItems="center" gap={12}>
<Switch
value={siblingPressableEnabled}
onValueChange={setSiblingPressableEnabled}
/>
<Text>Enable sibling press handler</Text>
</View>
</View>
</SafeAreaView>
);
},
};
9 changes: 9 additions & 0 deletions packages/ui/src/components/Pressable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ export default function Pressable({
action,
});

const hasInteractionHandler =
(action == null ? onPress : onPressLink) || onLongPress;

if (action && !to) {
throw new Error(
'The `to` prop is required when `action` is specified in `Pressable`'
Expand All @@ -76,6 +79,11 @@ export default function Pressable({
group
onPress={onPressLink ?? onPress}
onLongPress={longPressHandler}
// Pressable always blocks touches from bubbling to ancestors, even if
// no handlers are attached.
// To allow bubbling, disable the Pressable (mixin) when no handlers
// are attached.
disabled={!hasInteractionHandler}
>
{children}
</StackComponent>
Expand All @@ -87,6 +95,7 @@ export default function Pressable({
{...stackProps}
onPress={onPress}
onLongPress={longPressHandler}
disabled={!hasInteractionHandler}
>
{children}
</StackComponent>
Expand Down

0 comments on commit 26b1645

Please sign in to comment.