@wix/design-system
Version:
@wix/design-system
486 lines (425 loc) • 14.8 kB
Markdown
## Feature Examples
### Structure
- description: <p><code>FullScreenModalLayout</code> is built from three components:</p><li><code>FullScreenModalLayout.Header</code></li><li><code>FullScreenModalLayout.Content</code></li><li><code>FullScreenModalLayout.Footer</code></li>
- example:
```jsx
() => {
const [isOpen, setIsOpen] = React.useState(false);
const closeModal = () => setIsOpen(false);
return (
<Box padding="20px" gap="20px" direction="vertical">
<Button onClick={() => setIsOpen(true)}>Open Modal</Button>
<Modal isOpen={isOpen} onRequestClose={closeModal}>
<FullScreenModalLayout>
<FullScreenModalLayout.Header
startNode={
<Box border="1px dashed" padding="SP2">
1 Node slot
</Box>
}
endNode={
<Box border="1px dashed" padding="SP2">
2 Node slot
</Box>
}
>
<Box direction="vertical" gap="SP1">
<Text>Modal title goes here</Text>
<Text size="small" secondary>
Subtitle goes here
</Text>
</Box>
</FullScreenModalLayout.Header>
<FullScreenModalLayout.Content padding>
<Box
border="1px dashed"
height="240px"
padding="SP4"
direction="vertical"
align="space-between"
>
<Box direction="vertical" align="center" gap="SP2">
<Text>Modal content starts here</Text>
<TextButton onClick={closeModal}>Close modal</TextButton>
</Box>
<Text>Modal content ends here</Text>
</Box>
</FullScreenModalLayout.Content>
<FullScreenModalLayout.Footer>
<Box border="1px dashed" padding="SP3">
<Text>Footer is sticky</Text>
</Box>
</FullScreenModalLayout.Footer>
</FullScreenModalLayout>
</Modal>
</Box>
);
};
```
### Animation
- description: <p>Control <code>FullScreenModalLayout</code> animation styles using <code>Modal</code> transition property:</p><p><code>zoomIn</code> (default) - the modal appears from the middle of the screen</p><li><code>moveVertical</code> - the modal slides in from the bottom </li><li><code>moveHorizontal</code> - the modal slides in from the right side of the screen</li>
- example:
```jsx
() => {
const ModalWithButton = ({
isOpen: isOpenProp = false,
buttonLabel,
transition,
children,
}: {
isOpen?: boolean;
buttonLabel: string;
transition: 'moveHorizontal' | 'moveVertical';
children: ({
isOpen,
close,
}: {
isOpen: boolean;
close: () => void;
}) => React.ReactNode;
}) => {
const [isOpen, setIsOpen] = React.useState(isOpenProp);
const close = React.useCallback(() => setIsOpen(false), []);
return (
<>
<Button onClick={() => setIsOpen(true)}>{buttonLabel}</Button>
<Modal transition={transition} isOpen={isOpen} onRequestClose={close}>
{children({ isOpen, close })}
</Modal>
</>
);
};
return (
<StorybookComponents.Stack>
<ModalWithButton
buttonLabel="Horizontal transition"
transition="moveHorizontal"
>
{({ close }) => (
<FullScreenModalLayout>
<FullScreenModalLayout.Header
startNode={
<CloseButton skin="dark" size="large" onClick={close} />
}
endNode={
<TextButton size="small" onClick={close}>
Save
</TextButton>
}
>
<Text size="small" weight="normal" ellipsis>
Modal Title
</Text>
</FullScreenModalLayout.Header>
<FullScreenModalLayout.Content padding>
<Text>This is the main content area with padding.</Text>
</FullScreenModalLayout.Content>
<FullScreenModalLayout.Footer>
<Text>Footer</Text>
</FullScreenModalLayout.Footer>
</FullScreenModalLayout>
)}
</ModalWithButton>
<ModalWithButton
buttonLabel="Vertical transition"
transition="moveVertical"
>
{({ close }) => (
<FullScreenModalLayout>
<FullScreenModalLayout.Header
startNode={
<CloseButton skin="dark" size="large" onClick={close} />
}
endNode={
<TextButton size="small" onClick={close}>
Save
</TextButton>
}
>
<Text size="small" weight="normal" ellipsis>
Modal Title
</Text>
</FullScreenModalLayout.Header>
<FullScreenModalLayout.Content padding>
<Text>This is the main content area with padding.</Text>
</FullScreenModalLayout.Content>
<FullScreenModalLayout.Footer>
<Text>Footer</Text>
</FullScreenModalLayout.Footer>
</FullScreenModalLayout>
)}
</ModalWithButton>
</StorybookComponents.Stack>
);
};
```
## Common Use Case Examples
### Long forms
- description: <p>It is recommended to use <code>FullScreenModalLayout.Footer</code> for modals that are longer. This way the main actions are always visible to users</p>
- example:
```jsx
() => {
const [isOpen, setIsOpen] = React.useState(false);
const openModal = () => setIsOpen(true);
const closeModal = () => setIsOpen(false);
return (
<StorybookComponents.Stack>
<Button onClick={openModal} prefixIcon={<Icons.Add />}>
New dish
</Button>
<Modal
isOpen={isOpen}
onRequestClose={closeModal}
transition="moveVertical"
>
<FullScreenModalLayout>
{/* HEADER */}
<FullScreenModalLayout.Header
startNode={
<CloseButton skin="dark" size="large" onClick={closeModal} />
}
endNode={
<TextButton size="small" onClick={closeModal}>
Save
</TextButton>
}
>
<Text size="small" weight="normal">
New dish
</Text>
</FullScreenModalLayout.Header>
{/* CONTENT */}
<FullScreenModalLayout.Content padding>
<Box direction="vertical" gap="24px">
<FormField label="Image">
<ImageViewer width="100%" height="176px" />
</FormField>
<FormField label="Name">
<Input value="My New Dish" />
</FormField>
<FormField label="Price">
<Input value="0" prefix={<Input.Affix>$</Input.Affix>} />
</FormField>
<FormField label="Description">
<InputArea
placeholder="Describe your dish in a few sentences."
resizable
rows={3}
/>
</FormField>
<FormField
label="Dietary preferences"
infoContent="Choose which dietary preferences your dish is appropriate for."
>
<Box direction="vertical" gap="12px">
<Checkbox>No salt</Checkbox>
<Checkbox>Vegan</Checkbox>
<Checkbox>Vegetarian</Checkbox>
<Checkbox>Gluten free</Checkbox>
<Checkbox>Organic</Checkbox>
<Checkbox>Spicy</Checkbox>
</Box>
</FormField>
<FormField label="Visibility">
<Checkbox checked>Visible on site</Checkbox>
</FormField>
<FormField label="Availability">
<Checkbox checked>In stock</Checkbox>
</FormField>
</Box>
</FullScreenModalLayout.Content>
{/* FOOTER */}
<FullScreenModalLayout.Footer>
<StorybookComponents.Stack spacing="12px" width="100%">
<Button fullWidth priority="secondary" onClick={closeModal}>
Cancel
</Button>
<Button fullWidth onClick={closeModal}>
Create dish
</Button>
</StorybookComponents.Stack>
</FullScreenModalLayout.Footer>
</FullScreenModalLayout>
</Modal>
</StorybookComponents.Stack>
);
};
```
### Push screens
- description: <p>You can use <code>FullScreenModalLayout</code> as push screens</p>
- example:
```jsx
() => {
const [isOpen, setIsOpen] = React.useState(false);
const [newsletter, setNewsletter] = React.useState(true);
const open = () => setIsOpen(true);
const close = () => setIsOpen(false);
return (
<StorybookComponents.Stack>
<Button onClick={open}>Show upgrade message</Button>
<Modal
isOpen={isOpen}
onRequestClose={close}
transition="moveHorizontal"
>
<FullScreenModalLayout>
{/* Header */}
<FullScreenModalLayout.Header
startNode={
<CloseButton skin="dark" size="large" onClick={close} />
}
>
<Text size="small" weight="normal">
Upgrade to accept payments
</Text>
</FullScreenModalLayout.Header>
{/* Content */}
<FullScreenModalLayout.Content padding>
<Layout cols={1} alignItems="vertical" gap="24px">
{/* Intro text */}
<Text size="small">
Unlock secure online payments and help your business grow with a Business Basic plan.
</Text>
{/* Benefits list */}
<Box direction="vertical" gap="12px">
<Text weight="bold">What you get:</Text>
<Box direction="vertical" gap="6px">
<Text size="small">• Accept credit and debit card payments</Text>
<Text size="small">• Automated invoice and tax handling</Text>
<Text size="small">• Faster payouts to your bank</Text>
</Box>
</Box>
{/* Optional settings */}
<FormField label="Notifications">
<ToggleSwitch
checked={newsletter}
onChange={() => setNewsletter(!newsletter)}
/>
</FormField>
<Box>
<Text size="small" secondary>
Enabling notifications helps you stay updated on payouts and payment changes.
</Text>
</Box>
</Layout>
</FullScreenModalLayout.Content>
{/* Footer */}
<FullScreenModalLayout.Footer>
<StorybookComponents.Stack spacing="12px" width="100%">
<Button
fullWidth
priority="secondary"
onClick={close}
>
Not now
</Button>
<Button
fullWidth
skin="premium"
onClick={close}
>
Upgrade
</Button>
</StorybookComponents.Stack>
</FullScreenModalLayout.Footer>
</FullScreenModalLayout>
</Modal>
</StorybookComponents.Stack>
);
};
```
### Multiple actions
- description: <p></p>
- example:
```jsx
() => {
const [shown, setShown] = React.useState(false);
const openModal = () => setShown(true);
const closeModal = () => setShown(false);
return (
<Layout>
<Cell span={6}>
<Card>
<Box
direction="vertical"
gap="1"
paddingTop="2"
paddingLeft="4"
paddingRight="4"
paddingBottom="2"
>
<Text secondary>From name:</Text>
<Text weight="bold">User 1</Text>
<Text secondary>Reply-to email:</Text>
<Text weight="bold">user1@mail.com</Text>
</Box>
<Divider />
<Box padding="12px" align="center">
<TextButton onClick={openModal}>Confirm Email</TextButton>
</Box>
{/* Full Screen Modal */}
<Modal
isOpen={shown}
onRequestClose={closeModal}
transition="moveVertical"
>
<FullScreenModalLayout>
{/* HEADER */}
<FullScreenModalLayout.Header
startNode={
<CloseButton
skin="dark"
size="large"
onClick={closeModal}
/>
}
endNode={
<TextButton size="small" onClick={closeModal}>
Change Details
</TextButton>
}
>
<Text size="small" weight="normal">
Confirm your email address
</Text>
</FullScreenModalLayout.Header>
{/* CONTENT */}
<FullScreenModalLayout.Content padding>
<StorybookComponents.Stack flexDirection="column" spacing="24px">
<Text>
To make changes to your sender details, please confirm
your email address.
<br />
A confirmation code was sent to <b>user1@mail.com</b>.
</Text>
<FormField label="Confirmation Code">
<Input placeholder="XX-XXX-XX" />
</FormField>
<Text>
Didn’t get the code? <a>Send again</a>
</Text>
</StorybookComponents.Stack>
</FullScreenModalLayout.Content>
{/* FOOTER */}
<FullScreenModalLayout.Footer>
<StorybookComponents.Stack spacing="12px" width="100%">
<Button fullWidth onClick={closeModal}>
Confirm
</Button>
<Button
fullWidth
priority="secondary"
onClick={closeModal}
>
Cancel
</Button>
</StorybookComponents.Stack>
</FullScreenModalLayout.Footer>
</FullScreenModalLayout>
</Modal>
</Card>
</Cell>
</Layout>
);
};
```