-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migrate ModalDialog to Storybook (#1574)
## Summary: Using Styleguidist as a foundation, migrate the documentation for ModalDialog to Storybook. Styleguidist does not have specific examples for each building block under modal, but I decided to start adding them all with their own examples (as opposed to using subcomponents), particularly so that users can experiment with the control panel. This one was a little tricky since ModalDialog does not have a visual element. Storybook publish: https://5e1bf4b385e3fb0020b7073c-sbvqecqsiq.chromatic.com/?path=/docs/modal-building-blocks-modaldialog--default Issue: https://khanacademy.atlassian.net/browse/WB-1141 ## Test plan: - Check that all the documentation makes sense. - Check there are no typos. - Interact with the modals to confirm they all behave as expected. Author: nishasy Reviewers: jandrade, nishasy Required Reviewers: Approved By: jandrade, jandrade Checks: ✅ codecov/project, ✅ Check build sizes (ubuntu-latest, 16.x), ✅ Lint (ubuntu-latest, 16.x), ✅ Test (ubuntu-latest, 16.x, 2/2), ✅ Test (ubuntu-latest, 16.x, 1/2), ✅ Mixed content, ⚪️ Redirect rules, ⚪️ Header rules, ⚪️ Pages changed, ✅ gerald, ✅ Prime node_modules cache for primary configuration (ubuntu-latest, 16.x), ⏭ dependabot, ✅ Chromatic - Build on review PR (push) / chromatic (ubuntu-latest, 16.x), ⏭ Chromatic - Skip on dependabot PRs (push) Pull Request URL: #1574
- Loading branch information
Showing
3 changed files
with
294 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
--- | ||
--- |
287 changes: 287 additions & 0 deletions
287
packages/wonder-blocks-modal/src/components/__docs__/modal-dialog.stories.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,287 @@ | ||
// @flow | ||
import * as React from "react"; | ||
import {StyleSheet} from "aphrodite"; | ||
|
||
import Button from "@khanacademy/wonder-blocks-button"; | ||
import Color from "@khanacademy/wonder-blocks-color"; | ||
import {View} from "@khanacademy/wonder-blocks-core"; | ||
import {Strut} from "@khanacademy/wonder-blocks-layout"; | ||
import { | ||
ModalLauncher, | ||
ModalDialog, | ||
ModalPanel, | ||
} from "@khanacademy/wonder-blocks-modal"; | ||
import Spacing from "@khanacademy/wonder-blocks-spacing"; | ||
import {Body, Title} from "@khanacademy/wonder-blocks-typography"; | ||
|
||
import type {StoryComponentType} from "@storybook/react"; | ||
|
||
import ComponentInfo from "../../../../../.storybook/components/component-info.js"; | ||
import {name, version} from "../../../package.json"; | ||
|
||
const customViewports = { | ||
phone: { | ||
name: "phone", | ||
styles: { | ||
width: "320px", | ||
height: "568px", | ||
}, | ||
}, | ||
tablet: { | ||
name: "tablet", | ||
styles: { | ||
width: "640px", | ||
height: "960px", | ||
}, | ||
}, | ||
desktop: { | ||
name: "desktop", | ||
styles: { | ||
width: "1024px", | ||
height: "768px", | ||
}, | ||
}, | ||
}; | ||
|
||
export default { | ||
title: "Modal/Building Blocks/ModalDialog", | ||
component: ModalDialog, | ||
parameters: { | ||
componentSubtitle: (( | ||
<ComponentInfo name={name} version={version} /> | ||
): any), | ||
viewport: { | ||
viewports: customViewports, | ||
defaultViewport: "desktop", | ||
}, | ||
chromatic: { | ||
viewports: [320, 640, 1024], | ||
}, | ||
}, | ||
// Make the following props null in the control panel | ||
// because setting an object for a React node is | ||
// not practical to do manually. | ||
argTypes: { | ||
children: { | ||
control: {type: null}, | ||
}, | ||
above: { | ||
control: {type: null}, | ||
}, | ||
below: { | ||
control: {type: null}, | ||
}, | ||
}, | ||
}; | ||
|
||
export const Default: StoryComponentType = (args) => ( | ||
<View style={styles.previewSizer}> | ||
<View style={styles.modalPositioner}> | ||
<ModalDialog aria-labelledby="modal-title-0" {...args}> | ||
<ModalPanel | ||
content={ | ||
<> | ||
<Title id="modal-title-0">Modal Title</Title> | ||
<Strut size={Spacing.large_24} /> | ||
<Body>Here is some text in the modal.</Body> | ||
</> | ||
} | ||
/> | ||
</ModalDialog> | ||
</View> | ||
</View> | ||
); | ||
|
||
Default.args = { | ||
style: { | ||
maxWidth: 500, | ||
maxHeight: 500, | ||
}, | ||
}; | ||
|
||
export const Simple: StoryComponentType = () => ( | ||
<View style={styles.previewSizer}> | ||
<View style={styles.modalPositioner}> | ||
<ModalDialog | ||
aria-labelledby="modal-title-1" | ||
style={styles.squareDialog} | ||
> | ||
<ModalPanel | ||
content={ | ||
<> | ||
<Title id="modal-title-1">Modal Title</Title> | ||
<Strut size={Spacing.large_24} /> | ||
<Body>Here is some text in the modal.</Body> | ||
</> | ||
} | ||
/> | ||
</ModalDialog> | ||
</View> | ||
</View> | ||
); | ||
|
||
Simple.parameters = { | ||
docs: { | ||
storyDescription: `This is a basic \`<ModalDialog>\` that wraps a | ||
\`<ModalPanel>\` element. The \`<ModalDialog>\` is just a a wrapper | ||
for the visual components of the overall modal. It sets | ||
the modal's role to \`"dialog"\`. If it did not have another | ||
element as a child here (a \`<ModalPanel>\` in this case), | ||
nothing would be visible. If the \`<ModalDialog>\` were not given | ||
a \`maxHeight\` or \`maxWidth\` style, it would take up the | ||
entire viewport. To demonstrate the difference between | ||
the \`<ModalDialog>\` and the \`<ModalPanel>\` elements, the panel | ||
has been given a smaller height and width than \`<ModalDialog>\`, | ||
and \`<ModalDialog>\` has been given a dark blue background.`, | ||
}, | ||
}; | ||
|
||
export const WithAboveAndBelow: StoryComponentType = () => { | ||
const aboveStyle = { | ||
background: "url(./modal-above.png)", | ||
width: 874, | ||
height: 551, | ||
position: "absolute", | ||
top: 40, | ||
left: -140, | ||
}; | ||
|
||
const belowStyle = { | ||
background: "url(./modal-below.png)", | ||
width: 868, | ||
height: 521, | ||
position: "absolute", | ||
top: -100, | ||
left: -300, | ||
}; | ||
|
||
return ( | ||
<View style={styles.previewSizer}> | ||
<View style={styles.modalPositioner}> | ||
<ModalDialog | ||
aria-labelledby="modal-title-2" | ||
style={styles.squareDialog} | ||
above={<View style={aboveStyle} />} | ||
below={<View style={belowStyle} />} | ||
> | ||
<ModalPanel | ||
content={ | ||
<> | ||
<Title id="modal-title-2">Modal Title</Title> | ||
<Strut size={Spacing.large_24} /> | ||
<Body>Here is some text in the modal.</Body> | ||
</> | ||
} | ||
/> | ||
</ModalDialog> | ||
</View> | ||
</View> | ||
); | ||
}; | ||
|
||
WithAboveAndBelow.parameters = { | ||
docs: { | ||
storyDescription: `The \`above\` and \`below\` props work the same | ||
for \`<ModalDialog>\` as they do for \`<OnePaneDialog>\`. | ||
The element passed into the \`above\` prop is rendered in front | ||
of the modal. The element passed into the \`below\` prop is | ||
rendered behind the modal. In this example, a \`<View>\` element | ||
with a background image of a person and an orange blob is passed | ||
into the \`below\` prop. A \`<View>\` element with a background | ||
image of an arc and a blue semicircle is passed into the \`above\` | ||
prop. This results in the person's head and the orange blob | ||
peeking out from behind the modal, and the arc and semicircle | ||
going over the front of the modal.`, | ||
}, | ||
}; | ||
|
||
export const WithLauncher: StoryComponentType = () => { | ||
type MyModalProps = {| | ||
closeModal: () => void, | ||
|}; | ||
|
||
const MyModal = ({ | ||
closeModal, | ||
}: MyModalProps): React.Element<typeof ModalDialog> => ( | ||
<ModalDialog | ||
aria-labelledby="modal-title-3" | ||
style={styles.squareDialog} | ||
> | ||
<ModalPanel | ||
content={ | ||
<> | ||
<Title id="modal-title-3">Modal Title</Title> | ||
<Strut size={Spacing.large_24} /> | ||
<Body>Here is some text in the modal.</Body> | ||
</> | ||
} | ||
/> | ||
</ModalDialog> | ||
); | ||
|
||
return ( | ||
<ModalLauncher modal={MyModal}> | ||
{({openModal}) => ( | ||
<Button onClick={openModal}>Click me to open the modal</Button> | ||
)} | ||
</ModalLauncher> | ||
); | ||
}; | ||
|
||
WithLauncher.parameters = { | ||
chromatic: { | ||
// Don't take screenshots of this story since it would only show a | ||
// button and not the actual modal. | ||
disableSnapshot: true, | ||
}, | ||
docs: { | ||
storyDescription: `A modal can be launched using a launcher. Here, | ||
the launcher is a \`<Button>\` element whose \`onClick\` function | ||
opens the modal. The modal passed into the \`modal\` prop of | ||
the \`<ModalLauncher>\` element is a \`<ModalDialog>\` element. | ||
To turn an element into a launcher, wrap the element in a | ||
\`<ModalLauncher>\` element.`, | ||
}, | ||
}; | ||
|
||
const styles = StyleSheet.create({ | ||
modalPositioner: { | ||
// Checkerboard background | ||
backgroundImage: | ||
"linear-gradient(45deg, #ccc 25%, transparent 25%), linear-gradient(-45deg, #ccc 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ccc 75%), linear-gradient(-45deg, transparent 75%, #ccc 75%)", | ||
backgroundSize: "20px 20px", | ||
backgroundPosition: "0 0, 0 10px, 10px -10px, -10px 0px", | ||
|
||
flexDirection: "row", | ||
alignItems: "center", | ||
justifyContent: "center", | ||
|
||
position: "absolute", | ||
left: 0, | ||
right: 0, | ||
top: 0, | ||
bottom: 0, | ||
}, | ||
previewSizer: { | ||
height: 600, | ||
}, | ||
row: { | ||
flexDirection: "row", | ||
justifyContent: "flex-end", | ||
}, | ||
footer: { | ||
alignItems: "center", | ||
flexDirection: "row", | ||
justifyContent: "space-between", | ||
width: "100%", | ||
}, | ||
squareDialog: { | ||
maxHeight: 500, | ||
maxWidth: 500, | ||
backgroundColor: Color.darkBlue, | ||
}, | ||
smallSquarePanel: { | ||
maxHeight: 400, | ||
maxWidth: 400, | ||
}, | ||
}); |
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