@@ -2,6 +2,7 @@ import * as React from 'react';
22import {
33 ColorValue ,
44 GestureResponderEvent ,
5+ Platform ,
56 StyleSheet ,
67 View ,
78} from 'react-native' ;
@@ -23,7 +24,11 @@ import {
2324 FloatingActionButtonSize ,
2425 FloatingActionButtonTokens ,
2526 FloatingActionButtonVariant ,
27+ FOCUS_RING_INSET ,
28+ FOCUS_RING_THICKNESS ,
29+ webNoOutline ,
2630} from './tokens' ;
31+ import { useFocusRing } from './useFocusRing' ;
2732import { resolveColors } from './utils' ;
2833import { useLocale } from '../../core/locale' ;
2934import { useInternalTheme } from '../../core/theming' ;
@@ -242,33 +247,56 @@ const MenuItem = ({
242247 const { height, iconSize, leading, trailing, iconLabelGap, shape } =
243248 FloatingActionButtonMenuTokens . listItem ;
244249 const borderRadius = resolveCornerRadius ( theme , shape ) ;
250+
251+ const { focusedSV, onFocus, onBlur } = useFocusRing ( ) ;
252+ const focusRingStyle = useAnimatedStyle ( ( ) => ( {
253+ opacity : focusedSV . value ? 1 : 0 ,
254+ } ) ) ;
255+
245256 return (
246- < View
247- style = { [
248- styles . menuItem ,
249- { height, borderRadius, backgroundColor : colors . container } ,
250- ] }
251- >
252- < TouchableRipple
253- borderless
254- onPress = { onPress }
255- accessibilityRole = "button"
256- accessibilityLabel = { accessibilityLabel ?? label }
257- style = { { borderRadius } }
258- testID = { testID }
257+ < View style = { styles . menuItemWrapper } >
258+ < View
259+ style = { [
260+ styles . menuItem ,
261+ { height, borderRadius, backgroundColor : colors . container } ,
262+ ] }
259263 >
260- < FabContent
261- icon = { icon }
262- label = { label }
263- contentColor = { colors . content }
264- height = { height }
265- iconSize = { iconSize }
266- leading = { leading }
267- trailing = { trailing }
268- iconLabelGap = { iconLabelGap }
264+ < TouchableRipple
265+ borderless
266+ onPress = { onPress }
267+ onFocus = { onFocus }
268+ onBlur = { onBlur }
269+ accessibilityRole = "button"
270+ accessibilityLabel = { accessibilityLabel ?? label }
271+ style = { [
272+ { borderRadius } ,
273+ Platform . OS === 'web' ? webNoOutline : null ,
274+ ] }
269275 testID = { testID }
270- />
271- </ TouchableRipple >
276+ >
277+ < FabContent
278+ icon = { icon }
279+ label = { label }
280+ contentColor = { colors . content }
281+ height = { height }
282+ iconSize = { iconSize }
283+ leading = { leading }
284+ trailing = { trailing }
285+ iconLabelGap = { iconLabelGap }
286+ testID = { testID }
287+ />
288+ </ TouchableRipple >
289+ </ View >
290+ < Animated . View
291+ style = { [
292+ styles . menuItemFocusRing ,
293+ {
294+ borderColor : theme . colors . secondary ,
295+ borderRadius : borderRadius + FOCUS_RING_INSET ,
296+ } ,
297+ focusRingStyle ,
298+ ] }
299+ />
272300 </ View >
273301 ) ;
274302} ;
@@ -690,9 +718,21 @@ const styles = StyleSheet.create({
690718 itemsEnd : {
691719 right : 0 ,
692720 } ,
721+ menuItemWrapper : {
722+ position : 'relative' ,
723+ } ,
693724 menuItem : {
694725 overflow : 'hidden' ,
695726 } ,
727+ menuItemFocusRing : {
728+ position : 'absolute' ,
729+ top : - FOCUS_RING_INSET ,
730+ left : - FOCUS_RING_INSET ,
731+ right : - FOCUS_RING_INSET ,
732+ bottom : - FOCUS_RING_INSET ,
733+ borderWidth : FOCUS_RING_THICKNESS ,
734+ pointerEvents : 'none' ,
735+ } ,
696736 triggerSlot : {
697737 justifyContent : 'flex-start' ,
698738 } ,
0 commit comments