You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Its Surface has overflow: 'hidden', and a parent that clips also clips the
hitSlop. So tapping 3dp outside an IconButton misses on both iOS and Android,
even though it asks for 6 or 10. The prop does nothing.
On web there is no hitSlop at all. react-native-web dropped it in 0.13.0:
The hitSlop prop has been removed. This caused incorrect hit targets for mouse
interactions.
Pressable landed in the same release and never had it. So anything using hitSlop
to reach 48dp gets nothing on web.
Also there is no token for this. src/theme/tokens/sys/state.ts has focusIndicator but no size values, so 40dp is written out per component and 48dp
does not exist anywhere.
Expected behaviour
Targets should be at least 48dp.
Two things that are easy to get wrong:
It is an invisible expansion outside the component, not a resize. The 40dp state
layer on Checkbox and Switch is correct and should stay. Compose does the same
thing, it grows the target past the component's bounds.
Open the Checkbox screen and tap 3dp outside the box. Nothing. Tap the middle, it
toggles.
Same on Radio Button and Icon Button.
Icon Button is the interesting one: 3dp outside is well inside the hitSlop it
passes, and it still misses.
On web, inspect an IconButton. No hitSlop anywhere in the DOM.
Preview
Nothing to show. A good build and a bad one look identical, only the tap areas
differ. That is probably why this went unnoticed.
What have you tried so far?
Tapped just outside and in the middle of each one, on all three platforms, so a
miss means the area is small and not that the handler is broken.
Checked it is the Surface clipping that kills IconButton's hitSlop. Putting overflow: 'hidden' on the touchable itself is fine, on a parent it is not. Checkbox is ok because its overflow: 'hidden' is on a child.
CSS pseudo elements do not help on web, ::before gets clipped the same as a real
child. The clipping has to move instead.
material-web solves web with an invisible absolutely positioned child at max(48px, 100%). Worth noting it does not give a chip's close icon 48dp, that
stays 24 x 24.
Current behaviour
Touch targets are smaller than the 48dp MD3 asks for. The touch area is just the
box the component draws, nothing more.
Measured on iOS 18.3, Android 15 and web. Same numbers on all three.
CheckboxRadioButtonIconButton(defaultsize={24})Chipclose iconTap 1dp outside any of them and nothing happens.
IconButtonalready tries to fix this and it does not work:Its
Surfacehasoverflow: 'hidden', and a parent that clips also clips thehitSlop. So tapping 3dp outside an
IconButtonmisses on both iOS and Android,even though it asks for 6 or 10. The prop does nothing.
On web there is no hitSlop at all. react-native-web dropped it in 0.13.0:
Pressablelanded in the same release and never had it. So anything using hitSlopto reach 48dp gets nothing on web.
Also there is no token for this.
src/theme/tokens/sys/state.tshasfocusIndicatorbut no size values, so 40dp is written out per component and 48dpdoes not exist anywhere.
Expected behaviour
Targets should be at least 48dp.
Two things that are easy to get wrong:
layer on
CheckboxandSwitchis correct and should stay. Compose does the samething, it grows the target past the component's bounds.
and should get nothing. Same split as TouchableRipple exposes non-interactive surfaces as disabled controls #5070.
How to reproduce?
cd example && yarn starttoggles.
passes, and it still misses.
IconButton. No hitSlop anywhere in the DOM.Preview
Nothing to show. A good build and a bad one look identical, only the tap areas
differ. That is probably why this went unnoticed.
What have you tried so far?
miss means the area is small and not that the handler is broken.
Surfaceclipping that killsIconButton's hitSlop. Puttingoverflow: 'hidden'on the touchable itself is fine, on a parent it is not.Checkboxis ok because itsoverflow: 'hidden'is on a child.::beforegets clipped the same as a realchild. The clipping has to move instead.
max(48px, 100%). Worth noting it does not give a chip's close icon 48dp, thatstays 24 x 24.
Your Environment
main)