Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A disabled Pressable gets a focused state when it's children are focused #2757

Closed
1 task done
KristineTrona opened this issue Jan 24, 2025 · 2 comments
Closed
1 task done
Labels

Comments

@KristineTrona
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Describe the issue

Clicking on a Pressable with disabled={true} does not trigger it to go into a focused state, however clicking on it's children does.

Expected behavior

If the Pressable is disabled, the same behavior should be applied to it's children elements and tapping them should not cause the pressable's onFocus event to fire.

Steps to reproduce

  1. Create a Pressable with a Text child
  2. Set its disabled state to true, add onPress, onFocus, onBlur events to toggle the focused state of the Pressable.
  3. Notice that tapping the Pressable does nor fire onPress or onFocus events, since the button is disabled, however tapping the Text element fires onFocus

Test case

https://snack.expo.dev/@kristinetrona/tenacious-green-soda?platform=web

Additional comments

Example code:
import { Text, SafeAreaView, Pressable, StyleSheet } from 'react-native';
import { useState } from 'react';

export default function App() {

  const [isDisabled, setIsDisabled] = useState(false)
  const [isFocused, setIsFocused] = useState(false)

  const onPress = () => {
    console.log("Button pressed")
  }

  const onFocus = () => {
    setIsFocused(true)
  }

  const onBlur = () => {
    setIsFocused(false)
  }

  const onToggleDisabledState = () => {
    setIsDisabled((prevState) => !prevState)
  }

  return (
    <SafeAreaView style={styles.container}>

      <Text style={styles.disabledText}>
       {`isDisabled: ${isDisabled}`}
      </Text>

      <Pressable 
        style={[styles.button, isFocused && styles.focusedButton, isDisabled && styles.disabledButton]}
        disabled={isDisabled}
        onPress={onPress}
        onFocus={onFocus}
        onBlur={onBlur}>
        <Text>{`Button isFocused: ${isFocused}`}</Text>
      </Pressable>

      <Pressable style={styles.disableToggleButton} onPress={onToggleDisabledState}>
        <Text>Toggle disable</Text>
      </Pressable>

    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
  disabledText: {
    marginBottom: 32,
  },  
  button: {
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'pink', 
    padding: 8,
  },
  focusedButton: {
    backgroundColor: 'orange', 
  },
  disabledButton: {
    backgroundColor: 'grey'
  },
  disableToggleButton: {
    marginTop: 32,
    padding: 8,
    alignItems: 'center', 
    justifyContent: 'center',
    borderColor: 'black',
    borderWidth: 1
  }
});
See screen recording:
Screen.Recording.2025-01-24.at.12.14.24.mov
@dongqi-yan
Copy link

In the source code of Pressable component, the disabled prop is assigned to aria-disabled.:
return ( <View {...rest} {...pressEventHandlers} aria-disabled={disabled} onBlur={blurHandler} onContextMenu={contextMenuHandler} onFocus={focusHandler} onKeyDown={keyDownHandler} ref={setRef} style={[ disabled ? styles.disabled : styles.active, typeof style === 'function' ? style(interactionState) : style ]} tabIndex={_tabIndex} > {typeof children === 'function' ? children(interactionState) : children} </View> );
The difference between aria-disabled and disabled is:
• aria-disabled="true" is used only for accessibility tools (such as screen readers) to inform the user that the component is disabled and not interactive.
• disabled={true} will disable the component’s interactive functionality, preventing the user from performing actions like clicking or inputting, and it will also affect the component’s appearance (for example, the button might appear gray).

So, I think you should control the styles and behavior of disabled in your own project:

`
const onFocus = () => {
if (isDisabled) return
setIsFocused(true)
}

const onBlur = () => {
if (isDisabled) return
setIsFocused(false)
}
`

@KristineTrona
Copy link
Author

@dongqi-yan thanks for the explanation. The suggested change works for this, so will close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants