|
| 1 | +/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ |
| 2 | +/* eslint-disable jsx-a11y/label-has-associated-control */ |
| 3 | +/* eslint-disable @typescript-eslint/explicit-function-return-type */ |
| 4 | +import { Title } from '@storybook/addon-docs'; |
| 5 | +import type { StoryFn, Meta } from '@storybook/react'; |
| 6 | +import React from 'react'; |
| 7 | +import { useToast } from './useToast'; |
| 8 | +import { Toast } from './Toast'; |
| 9 | +import type { ToastProps } from './'; |
| 10 | +import { ToastContainer } from './'; |
| 11 | +import StoryPageWrapper from '~utils/storybook/StoryPageWrapper'; |
| 12 | +import { Sandbox } from '~utils/storybook/Sandbox'; |
| 13 | +import { Box } from '~components/Box'; |
| 14 | +import { Button } from '~components/Button'; |
| 15 | +import { Heading, Text } from '~components/Typography'; |
| 16 | + |
| 17 | +const Page = (): React.ReactElement => { |
| 18 | + return ( |
| 19 | + <StoryPageWrapper |
| 20 | + componentName="Toast" |
| 21 | + componentDescription="Toast is a feedback element to display temporary short messages in the interface" |
| 22 | + figmaURL="https://www.figma.com/file/jubmQL9Z8V7881ayUD95ps/Blade-DSL?type=design&node-id=75839-1125191&mode=design&t=SLxhqgKm27oCjSYV-4" |
| 23 | + > |
| 24 | + <Title>Usage</Title> |
| 25 | + <Sandbox> |
| 26 | + {` |
| 27 | + import { ToastContainer, useToast } from '@razorpay/blade/components'; |
| 28 | +
|
| 29 | + function App(): React.ReactElement { |
| 30 | + const toast = useToast(); |
| 31 | +
|
| 32 | + // Integrating Blade Toast in your App |
| 33 | + // 1. Render the ToastContainer component at the root of your app |
| 34 | + // 2. Utilize the methods exposed via useToast hook to show/dismiss toasts |
| 35 | + return ( |
| 36 | + <Box> |
| 37 | + <ToastContainer /> |
| 38 | + <Button |
| 39 | + onClick={() => { |
| 40 | + toast.show({ content: 'Payment successful', color: 'positive' }) |
| 41 | + }} |
| 42 | + > |
| 43 | + Show Toast |
| 44 | + </Button> |
| 45 | + </Box> |
| 46 | + ); |
| 47 | + } |
| 48 | + |
| 49 | + export default App; |
| 50 | + `} |
| 51 | + </Sandbox> |
| 52 | + </StoryPageWrapper> |
| 53 | + ); |
| 54 | +}; |
| 55 | + |
| 56 | +export default { |
| 57 | + title: 'Components/Toast', |
| 58 | + component: Toast, |
| 59 | + tags: ['autodocs'], |
| 60 | + argTypes: { |
| 61 | + isVisible: { |
| 62 | + table: { |
| 63 | + disable: true, |
| 64 | + }, |
| 65 | + }, |
| 66 | + id: { |
| 67 | + table: { |
| 68 | + disable: true, |
| 69 | + }, |
| 70 | + }, |
| 71 | + }, |
| 72 | + parameters: { |
| 73 | + docs: { |
| 74 | + page: Page, |
| 75 | + }, |
| 76 | + }, |
| 77 | +} as Meta<ToastProps>; |
| 78 | + |
| 79 | +const texts = { |
| 80 | + negative: 'Unable to fetch merchant details', |
| 81 | + positive: 'Customer details failed successfully', |
| 82 | + notice: 'Your KYC is pending', |
| 83 | + information: 'Your transaction will be settled in 3 business days', |
| 84 | + neutral: 'Your transaction will be settled in 3 business days', |
| 85 | +} as const; |
| 86 | + |
| 87 | +const BasicToastTemplate: StoryFn<ToastProps> = (args) => { |
| 88 | + const toast = useToast(); |
| 89 | + |
| 90 | + if (args.type === 'promotional') { |
| 91 | + args.content = <Text size="small">{args.content}</Text>; |
| 92 | + } |
| 93 | + |
| 94 | + return ( |
| 95 | + <Box height="80vh"> |
| 96 | + <Text marginBottom="spacing.3" color="surface.text.gray.subtle"> |
| 97 | + After changing storybook controls, press the show "toast button" to see changes |
| 98 | + </Text> |
| 99 | + <Button |
| 100 | + onClick={() => { |
| 101 | + toast.show(args); |
| 102 | + }} |
| 103 | + > |
| 104 | + Show Toast |
| 105 | + </Button> |
| 106 | + <ToastContainer /> |
| 107 | + </Box> |
| 108 | + ); |
| 109 | +}; |
| 110 | + |
| 111 | +BasicToastTemplate.storyName = 'Basic'; |
| 112 | +export const Basic = BasicToastTemplate.bind({}); |
| 113 | +Basic.args = { |
| 114 | + color: 'neutral', |
| 115 | + type: 'informational', |
| 116 | + autoDismiss: false, |
| 117 | + content: 'Payment successful', |
| 118 | + action: { |
| 119 | + text: 'Okay', |
| 120 | + onClick: ({ toastId }) => console.log(toastId), |
| 121 | + }, |
| 122 | +}; |
| 123 | + |
| 124 | +const ToastVariantsTemplate: StoryFn<ToastProps> = () => { |
| 125 | + const toast = useToast(); |
| 126 | + const hasPromoToast = toast.toasts.some((t) => t.type === 'promotional'); |
| 127 | + |
| 128 | + const showInformationalToast = ({ color }: { color: ToastProps['color'] }) => { |
| 129 | + toast.show({ |
| 130 | + content: texts[color!], |
| 131 | + color, |
| 132 | + action: { |
| 133 | + text: 'Okay', |
| 134 | + onClick: ({ toastId }) => toast.dismiss(toastId), |
| 135 | + }, |
| 136 | + onDismissButtonClick: ({ toastId }) => console.log(`${toastId} Dismissed!`), |
| 137 | + }); |
| 138 | + }; |
| 139 | + |
| 140 | + const showPromotionalToast = () => { |
| 141 | + toast.show({ |
| 142 | + type: 'promotional', |
| 143 | + content: ( |
| 144 | + <Box display="flex" gap="spacing.3" flexDirection="column"> |
| 145 | + <Heading>Introducing TurboUPI</Heading> |
| 146 | + <img |
| 147 | + loading="lazy" |
| 148 | + width="100%" |
| 149 | + height="100px" |
| 150 | + alt="Promotional Toast" |
| 151 | + style={{ objectFit: 'cover', borderRadius: '8px' }} |
| 152 | + src="https://d6xcmfyh68wv8.cloudfront.net/blog-content/uploads/2023/05/Features-blog.png" |
| 153 | + /> |
| 154 | + <Text weight="semibold">Lightning-fast payments with the new Razorpay Turbo UPI</Text> |
| 155 | + <Text size="xsmall"> |
| 156 | + Turbo UPI allows end-users to complete their payment in-app, with no redirections or |
| 157 | + dependence on third-party UPI apps. With Turbo UPI, payments will be 5x faster with a |
| 158 | + significantly-improved success rate of 10%! |
| 159 | + </Text> |
| 160 | + </Box> |
| 161 | + ), |
| 162 | + action: { |
| 163 | + text: 'Try TurboUPI', |
| 164 | + onClick: ({ toastId }) => toast.dismiss(toastId), |
| 165 | + }, |
| 166 | + onDismissButtonClick: ({ toastId }) => console.log(`${toastId} Dismissed!`), |
| 167 | + }); |
| 168 | + }; |
| 169 | + |
| 170 | + return ( |
| 171 | + <Box height="80vh"> |
| 172 | + <Text>Show Informational Toasts:</Text> |
| 173 | + <Box display="flex" gap="spacing.3" marginY="spacing.5"> |
| 174 | + <Button variant="tertiary" onClick={() => showInformationalToast({ color: 'positive' })}> |
| 175 | + Positive |
| 176 | + </Button> |
| 177 | + <Button variant="tertiary" onClick={() => showInformationalToast({ color: 'negative' })}> |
| 178 | + Negative |
| 179 | + </Button> |
| 180 | + <Button variant="tertiary" onClick={() => showInformationalToast({ color: 'notice' })}> |
| 181 | + Notice |
| 182 | + </Button> |
| 183 | + <Button variant="tertiary" onClick={() => showInformationalToast({ color: 'information' })}> |
| 184 | + Information |
| 185 | + </Button> |
| 186 | + <Button variant="tertiary" onClick={() => showInformationalToast({ color: 'neutral' })}> |
| 187 | + Neutral |
| 188 | + </Button> |
| 189 | + </Box> |
| 190 | + <Text>Show Promotional Toasts:</Text> |
| 191 | + <Text size="small" color="surface.text.gray.muted"> |
| 192 | + Note: There can only be 1 promotional toast at a time |
| 193 | + </Text> |
| 194 | + <Box display="flex" gap="spacing.3" marginY="spacing.5"> |
| 195 | + <Button |
| 196 | + variant="tertiary" |
| 197 | + onClick={() => showPromotionalToast()} |
| 198 | + isDisabled={hasPromoToast} |
| 199 | + > |
| 200 | + Promotional |
| 201 | + </Button> |
| 202 | + </Box> |
| 203 | + <ToastContainer /> |
| 204 | + </Box> |
| 205 | + ); |
| 206 | +}; |
| 207 | + |
| 208 | +export const ToastVariants = ToastVariantsTemplate.bind({}); |
| 209 | +ToastVariants.storyName = 'Toast Variants'; |
0 commit comments