-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds support for the React Native Modal on web. The app content is hidden from screen readers by setting the aria-modal flag on the modal. This focus is trapped within the modal, both when attempting to focus elsewhere using the mouse as well as when attempting to focus elsewhere using the keyboard. A built-in "Escape to close" mechanism is been implemented that calls 'onRequestClose' for the active modal. Close #1646 Fix #1020
- Loading branch information
1 parent
004683c
commit e37d6ec
Showing
13 changed files
with
1,202 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; | ||
import * as Stories from './examples'; | ||
|
||
<Meta title="Components|Modal" /> | ||
|
||
# Modal | ||
|
||
The Modal component is a basic way to present content above an enclosing view. | ||
Modals may be nested within other Modals. | ||
|
||
## Props | ||
|
||
| Name | Type | Default | | ||
| ------------------------- | -------------- | ------- | | ||
| animationType | ?AnimationType | 'none' | | ||
| children | ?any | | | ||
| onDismiss | ?Function | | | ||
| onRequestClose | ?Function | | | ||
| onShow | ?Function | | | ||
| transparent | ?boolean | false | | ||
| visible | ?boolean | true | | ||
|
||
### animationType | ||
|
||
The `animationType` prop can be used to add animation to the modal | ||
being opened or dismissed. | ||
|
||
* `none` - the modal appears without any animation. | ||
* `slide` - the modal slides up from the bottom of the screen. | ||
* `fade` - the modal fades in. | ||
|
||
By default this is `none`. | ||
|
||
<Preview withSource='none'> | ||
<Story name="propsExample-animationType"> | ||
<Stories.animatedModal /> | ||
</Story> | ||
</Preview> | ||
|
||
### onDismiss | ||
|
||
The `onDismiss` callback is called after the modal has been dismissed and is no longer visible. | ||
|
||
### onRequestClose | ||
|
||
The `onRequestClose` callback is called when the user is attempting to close the modal - | ||
such as when they hit `Escape`. | ||
|
||
Only the top-most Modal responds to hitting `Escape`. | ||
|
||
<Preview withSource='none'> | ||
<Story name="propsExample-onRequestClose"> | ||
<Stories.modalception /> | ||
</Story> | ||
</Preview> | ||
|
||
### onShow | ||
|
||
The `onShow` callback is called once the modal has been shown and may be visible. | ||
|
||
### transparent | ||
|
||
The `transparent` prop determines if the modal is rendered with a `transparent` backdrop or | ||
a `white` backdrop. | ||
|
||
<Preview withSource='none'> | ||
<Story name="propsExample-transparent"> | ||
<Stories.transparentModal /> | ||
</Story> | ||
</Preview> | ||
|
||
### visible | ||
|
||
Whether or not the modal is visible. | ||
|
||
When set to `false` the contents are not rendered & the modal removes itself | ||
from the screen. | ||
|
||
<Preview withSource='none'> | ||
<Story name="propsExample-visible"> | ||
<Stories.simpleModal /> | ||
</Story> | ||
</Preview> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import React, { useState } from 'react'; | ||
import { Modal, Text, Button, View, StyleSheet } from 'react-native'; | ||
|
||
function Gap() { | ||
return <View style={styles.gap} />; | ||
} | ||
|
||
function AnimatedModal({ animationType }) { | ||
const [isVisible, setIsVisible] = useState(false); | ||
|
||
return ( | ||
<> | ||
<Button onPress={() => setIsVisible(true)} title={`Open Modal with '${animationType}'`} /> | ||
<Modal | ||
animationType={animationType} | ||
onRequestClose={() => setIsVisible(false)} | ||
visible={isVisible} | ||
> | ||
<View style={styles.container}> | ||
<Text>Modal with "animationType" of "{animationType}"</Text> | ||
<Gap /> | ||
<Button onPress={() => setIsVisible(false)} title={'Close Modal'} /> | ||
</View> | ||
</Modal> | ||
</> | ||
); | ||
} | ||
|
||
export default function AnimatedModalStack() { | ||
return ( | ||
<> | ||
<AnimatedModal animationType={'none'} /> | ||
<Gap /> | ||
<AnimatedModal animationType={'slide'} /> | ||
<Gap /> | ||
<AnimatedModal animationType={'fade'} /> | ||
</> | ||
); | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
alignItems: 'center', | ||
flex: 1, | ||
justifyContent: 'center' | ||
}, | ||
gap: { | ||
height: 10 | ||
} | ||
}); |
52 changes: 52 additions & 0 deletions
52
packages/docs/src/components/Modal/examples/Modalception.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import React, { useState, useMemo } from 'react'; | ||
import { Modal, View, Text, Button, StyleSheet } from 'react-native'; | ||
|
||
const WIGGLE_ROOM = 128; | ||
|
||
function Gap() { | ||
return <View style={styles.gap} />; | ||
} | ||
|
||
export default function Modalception({ depth = 1 }) { | ||
const [isVisible, setIsVisible] = useState(false); | ||
|
||
const offset = useMemo(() => { | ||
return { | ||
top: Math.random() * WIGGLE_ROOM - WIGGLE_ROOM / 2, | ||
left: Math.random() * WIGGLE_ROOM - WIGGLE_ROOM / 2 | ||
}; | ||
}, []); | ||
|
||
return ( | ||
<> | ||
<Button onPress={() => setIsVisible(true)} title={'Open Modal'} /> | ||
<Modal onRequestClose={() => setIsVisible(false)} transparent visible={isVisible}> | ||
<View style={[styles.container, offset]}> | ||
<Text>This is in Modal {depth}</Text> | ||
<Gap /> | ||
{isVisible ? <Modalception depth={depth + 1} /> : null} | ||
<Gap /> | ||
<Button color="red" onPress={() => setIsVisible(false)} title={'Close Modal'} /> | ||
</View> | ||
</Modal> | ||
</> | ||
); | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
alignItems: 'center', | ||
backgroundColor: 'white', | ||
borderColor: '#eee', | ||
borderRadius: 10, | ||
borderWidth: 1, | ||
justifyContent: 'center', | ||
height: 300, | ||
margin: 'auto', | ||
padding: 30, | ||
width: 300 | ||
}, | ||
gap: { | ||
height: 10 | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import React, { useState } from 'react'; | ||
import { Modal, Text, View, Button, StyleSheet } from 'react-native'; | ||
|
||
function Gap() { | ||
return <View style={styles.gap} />; | ||
} | ||
|
||
export default function SimpleModal() { | ||
const [isVisible, setIsVisible] = useState(false); | ||
|
||
return ( | ||
<> | ||
<Button onPress={() => setIsVisible(true)} title={'Open Modal'} /> | ||
<Modal onRequestClose={() => setIsVisible(false)} visible={isVisible}> | ||
<View style={styles.container}> | ||
<Text>Hello, World!</Text> | ||
<Gap /> | ||
<Button onPress={() => setIsVisible(false)} title={'Close Modal'} /> | ||
</View> | ||
</Modal> | ||
</> | ||
); | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
alignItems: 'center', | ||
flex: 1, | ||
justifyContent: 'center' | ||
}, | ||
gap: { | ||
height: 10 | ||
} | ||
}); |
41 changes: 41 additions & 0 deletions
41
packages/docs/src/components/Modal/examples/Transparent.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import React, { useState } from 'react'; | ||
import { Modal, Text, View, Button, StyleSheet } from 'react-native'; | ||
|
||
function Gap() { | ||
return <View style={styles.gap} />; | ||
} | ||
|
||
export default function TransparentModal() { | ||
const [isVisible, setIsVisible] = useState(false); | ||
|
||
return ( | ||
<> | ||
<Button onPress={() => setIsVisible(true)} title={'Open Modal'} /> | ||
<Modal onRequestClose={() => setIsVisible(false)} transparent visible={isVisible}> | ||
<View style={styles.container}> | ||
<Text style={{ textAlign: 'center' }}>Modal with "transparent" value</Text> | ||
<Gap /> | ||
<Button onPress={() => setIsVisible(false)} title={'Close Modal'} /> | ||
</View> | ||
</Modal> | ||
</> | ||
); | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
alignItems: 'center', | ||
backgroundColor: 'white', | ||
borderColor: '#eee', | ||
borderRadius: 10, | ||
borderWidth: 1, | ||
justifyContent: 'center', | ||
height: 300, | ||
margin: 'auto', | ||
padding: 30, | ||
width: 300 | ||
}, | ||
gap: { | ||
height: 10 | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export { default as transparentModal } from './Transparent'; | ||
export { default as simpleModal } from './Simple'; | ||
export { default as animatedModal } from './Animated'; | ||
export { default as modalception } from './Modalception'; |
Oops, something went wrong.