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
4 changes: 4 additions & 0 deletions src/components/Toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,10 @@ export const Toast: FC<Props> = ({
zIndex: toast.visible ? 9999 : undefined,
alignItems: 'center',
justifyContent: 'center',
pointerEvents: Platform.select({
web: 'auto',
default: undefined,
}),
},
style,
!toast.disableShadow && ConstructShadow('#181821', 0.15, false),
Expand Down
9 changes: 7 additions & 2 deletions src/components/Toasts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { useKeyboard } from '../utils';

type Props = {
overrideDarkMode?: boolean;
overrideScreenReaderEnabled?: boolean;
extraInsets?: ExtraInsets;
onToastShow?: (toast: T) => void;
onToastHide?: (toast: T, reason?: DismissReason) => void;
Expand All @@ -46,6 +47,7 @@ type Props = {

export const Toasts: FunctionComponent<Props> = ({
overrideDarkMode,
overrideScreenReaderEnabled,
extraInsets,
onToastHide,
onToastPress,
Expand All @@ -69,7 +71,7 @@ export const Toasts: FunctionComponent<Props> = ({
const insets = useSafeAreaInsets();
const safeAreaFrame = useSafeAreaFrame();
const dimensions = useWindowDimensions();
const isScreenReaderEnabled = useScreenReader();
const isScreenReaderEnabled = useScreenReader(overrideScreenReaderEnabled);
const { keyboardShown: keyboardVisible, keyboardHeight } = useKeyboard();

// Fix for Android bottom inset bug: https://github.com/facebook/react-native/issues/47080
Expand All @@ -92,7 +94,10 @@ export const Toasts: FunctionComponent<Props> = ({
left: insets.left + (extraInsets?.left ?? 0),
right: insets.right + (extraInsets?.right ?? 0),
bottom: insets.bottom + bugFixDelta + (extraInsets?.bottom ?? 0) + 16,
pointerEvents: 'box-none',
pointerEvents: Platform.select({
web: 'none',
default: 'box-none',
}),
}}
>
{toasts.map((t) => (
Expand Down
32 changes: 28 additions & 4 deletions src/utils/useScreenReader.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,40 @@
import { useEffect, useState } from 'react';
import { AccessibilityInfo } from 'react-native';
import { AccessibilityInfo, Platform } from 'react-native';

export const useScreenReader = () => {
/**
* Hook to detect if a screen reader is enabled on the device.
*
* @param override - Optional boolean to override the detected screen reader state.
* When provided, this value will be returned instead of the detected state.
* Useful for testing or forcing a specific screen reader state.
* @returns {boolean} True if screen reader is enabled (or overridden to true), false otherwise.
*
* @example
* // Auto-detect screen reader
* const isScreenReaderEnabled = useScreenReader();
*
* @example
* // Force screen reader to be enabled
* const isScreenReaderEnabled = useScreenReader(true);
*
* @example
* // Force screen reader to be disabled
* const isScreenReaderEnabled = useScreenReader(false);
*/
export const useScreenReader = (override?: boolean) => {
const [isScreenReaderEnabled, setIsScreenReaderEnabled] = useState(false);
useEffect(() => {
AccessibilityInfo.isScreenReaderEnabled()
.then(setIsScreenReaderEnabled)
.then((isEnabled) => {
if (Platform.OS !== 'web') {
setIsScreenReaderEnabled(isEnabled);
}
})
.catch(() => {
setIsScreenReaderEnabled(false);
});
}, []);
return isScreenReaderEnabled;
return override !== undefined ? override : isScreenReaderEnabled;
};

export const announceForAccessibility = (message: string) => {
Expand Down
18 changes: 18 additions & 0 deletions website/docs/components/toasts.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,24 @@ toast("Quick message", { duration: 2000 });

Override the system dark mode. If a value is supplied (I.e. `true` or `false`), then the toast components will use that value for the dark mode. For example, if `overrideDarkMode = {false}`, dark mode will be disabled, regardless of the system's preferences.

### overrideScreenReaderEnabled
`boolean | undefined`

Override the detected screen reader state. When set, this forces the component to behave as if the screen reader is enabled or disabled, regardless of the actual device state.

- `true`: Component behaves as if screen reader is enabled (toasts will be hidden unless `preventScreenReaderFromHiding` is also `true`)
- `false`: Component behaves as if screen reader is disabled (toasts will always be shown)
- `undefined` (default): Auto-detect screen reader state from the device

This is useful for testing or forcing specific behavior in your app.

```js
// Force toasts to show even if screen reader is enabled
<Toasts overrideScreenReaderEnabled={false} />
```

See the [Accessibility](/features/accessibility#overriding-screen-reader-detection) section for more details.

### extraInsets
`object`

Expand Down
23 changes: 23 additions & 0 deletions website/docs/features/accessibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,26 @@ Bottom-positioned toasts will automatically move with the keyboard. This behavio
## Screen Reader Support

If the device's screen reader is enabled, react-native-toast will not show the toast. It will announce the toast message to the user using the announceAccessibility method.

### Overriding Screen Reader Detection

You can override the detected screen reader state using the `overrideScreenReaderEnabled` prop on the `<Toasts />` component. This is useful for testing or when you want to force a specific behavior regardless of the actual screen reader state.

```js
// Force the component to behave as if screen reader is disabled
<Toasts overrideScreenReaderEnabled={false} />
```

```js
// Force the component to behave as if screen reader is enabled
<Toasts overrideScreenReaderEnabled={true} />
```

When `overrideScreenReaderEnabled` is set:
- `true`: Toasts will be hidden (unless `preventScreenReaderFromHiding` is also `true`)
- `false`: Toasts will always be shown, even if a screen reader is actually enabled
- `undefined` (default): Auto-detect the screen reader state from the device

This prop works independently from `preventScreenReaderFromHiding`:
- If you set `overrideScreenReaderEnabled={true}` and `preventScreenReaderFromHiding={true}`, toasts will still be shown
- If you set `overrideScreenReaderEnabled={false}`, toasts will always be shown regardless of `preventScreenReaderFromHiding`