notification.stories.tsx 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. import fetchMock from 'fetch-mock'
  2. import Notification from '../js/shared/components/notification'
  3. import { postJSON } from '../js/infrastructure/fetch-json'
  4. import useAsync from '../js/shared/hooks/use-async'
  5. type Args = React.ComponentProps<typeof Notification>
  6. export const NotificationInfo = (args: Args) => {
  7. return <Notification {...args} isDismissible />
  8. }
  9. export const NotificationSuccess = (args: Args) => {
  10. return <Notification {...args} isDismissible type="success" />
  11. }
  12. export const NotificationWarning = (args: Args) => {
  13. return <Notification {...args} isDismissible type="warning" />
  14. }
  15. export const NotificationError = (args: Args) => {
  16. return <Notification {...args} isDismissible type="error" />
  17. }
  18. export const NotificationWithActionBelowContent = (args: Args) => {
  19. return (
  20. <Notification
  21. {...args}
  22. content={
  23. <div>
  24. <p>The CTA will always go below the content on small screens.</p>
  25. <p>
  26. We can also opt to always put the CTA below the content on all
  27. screens
  28. </p>
  29. </div>
  30. }
  31. isDismissible
  32. isActionBelowContent
  33. />
  34. )
  35. }
  36. export const NotificationWithTitle = (args: Args) => {
  37. return <Notification {...args} title="Some title" />
  38. }
  39. export const NotificationWithAction = (args: Args) => {
  40. return <Notification {...args} isDismissible={false} />
  41. }
  42. export const NotificationDismissible = (args: Args) => {
  43. return <Notification {...args} action={undefined} />
  44. }
  45. export const APlainNotification = (args: Args) => {
  46. return <Notification {...args} action={undefined} isDismissible={false} />
  47. }
  48. export const NotificationWithMultipleParagraphsAndActionAndDismissible = (
  49. args: Args
  50. ) => {
  51. return (
  52. <Notification
  53. {...args}
  54. content={
  55. <div>
  56. <p>
  57. <b>Lorem ipsum</b>
  58. </p>
  59. <p>
  60. Dolor sit amet, consectetur adipiscing elit. Proin lacus velit,
  61. faucibus vitae feugiat sit amet, <a href="/">Some link</a> iaculis
  62. ut mi.
  63. </p>
  64. <p>
  65. Vel eros donec ac odio tempor orci dapibus ultrices in. Fermentum
  66. iaculis eu non diam phasellus.
  67. </p>
  68. <p>Aliquam at tempor risus. Vestibulum bibendum ut </p>
  69. </div>
  70. }
  71. />
  72. )
  73. }
  74. export const NotificationWithMultipleParagraphsAndDismissible = (
  75. args: Args
  76. ) => {
  77. return (
  78. <Notification
  79. {...args}
  80. action={undefined}
  81. content={
  82. <div>
  83. <p>
  84. <b>Lorem ipsum</b>
  85. </p>
  86. <p>
  87. Dolor sit amet, consectetur adipiscing elit. Proin lacus velit,
  88. faucibus vitae feugiat sit amet, <a href="/">Some link</a> iaculis
  89. ut mi.
  90. </p>
  91. <p>
  92. Vel eros donec ac odio tempor orci dapibus ultrices in. Fermentum
  93. iaculis eu non diam phasellus.
  94. </p>
  95. <p>Aliquam at tempor risus. Vestibulum bibendum ut </p>
  96. </div>
  97. }
  98. />
  99. )
  100. }
  101. export const MultipleParagraphsAndAction = (args: Args) => {
  102. return (
  103. <Notification
  104. {...args}
  105. isDismissible={false}
  106. content={
  107. <div>
  108. <p>
  109. <b>Lorem ipsum</b>
  110. </p>
  111. <p>
  112. Dolor sit amet, consectetur adipiscing elit. Proin lacus velit,
  113. faucibus vitae feugiat sit amet, <a href="/">Some link</a> iaculis
  114. ut mi.
  115. </p>
  116. <p>
  117. Vel eros donec ac odio tempor orci dapibus ultrices in. Fermentum
  118. iaculis eu non diam phasellus.
  119. </p>
  120. <p>Aliquam at tempor risus. Vestibulum bibendum ut </p>
  121. </div>
  122. }
  123. />
  124. )
  125. }
  126. export const MultipleParagraphs = (args: Args) => {
  127. return (
  128. <Notification
  129. {...args}
  130. action={undefined}
  131. isDismissible={false}
  132. content={
  133. <div>
  134. <p>
  135. <b>Lorem ipsum</b>
  136. </p>
  137. <p>
  138. Dolor sit amet, consectetur adipiscing elit. Proin lacus velit,
  139. faucibus vitae feugiat sit amet, <a href="/">Some link</a> iaculis
  140. ut mi.
  141. </p>
  142. <p>
  143. Vel eros donec ac odio tempor orci dapibus ultrices in. Fermentum
  144. iaculis eu non diam phasellus.
  145. </p>
  146. <p>Aliquam at tempor risus. Vestibulum bibendum ut </p>
  147. </div>
  148. }
  149. />
  150. )
  151. }
  152. export const ShortText = (args: Args) => {
  153. return (
  154. <Notification
  155. {...args}
  156. action={undefined}
  157. isDismissible={false}
  158. content={<p>Lorem ipsum</p>}
  159. />
  160. )
  161. }
  162. export const ShortTextAndDismissible = (args: Args) => {
  163. return (
  164. <Notification {...args} action={undefined} content={<p>Lorem ipsum</p>} />
  165. )
  166. }
  167. export const ShortTextAndActionLinkAsButton = (args: Args) => {
  168. return (
  169. <Notification
  170. {...args}
  171. isDismissible={false}
  172. content={<p>Lorem ipsum</p>}
  173. />
  174. )
  175. }
  176. export const ShortTextAndActionAsLink = (args: Args) => {
  177. return (
  178. <Notification
  179. {...args}
  180. content={<p>Lorem ipsum</p>}
  181. action={<a href="/">An action</a>}
  182. isDismissible={false}
  183. />
  184. )
  185. }
  186. export const ShortTextAndActionAsLinkButStyledAsButton = (args: Args) => {
  187. return (
  188. <Notification
  189. {...args}
  190. content={<p>Lorem ipsum</p>}
  191. action={
  192. <a href="/" className="btn btn-secondary btn-sm">
  193. An action
  194. </a>
  195. }
  196. isDismissible={false}
  197. />
  198. )
  199. }
  200. export const LongActionButton = (args: Args) => {
  201. return (
  202. <Notification
  203. {...args}
  204. action={
  205. <button className="btn btn-secondary btn-sm">
  206. Action that has a lot of text
  207. </button>
  208. }
  209. />
  210. )
  211. }
  212. export const LongActionLink = (args: Args) => {
  213. return (
  214. <Notification
  215. {...args}
  216. action={<a href="/">Action that has a lot of text</a>}
  217. />
  218. )
  219. }
  220. export const CustomIcon = (args: Args) => {
  221. return (
  222. <Notification
  223. {...args}
  224. customIcon={<div style={{ marginTop: '-4px' }}>🎉</div>}
  225. />
  226. )
  227. }
  228. export const MultipleButtons = (args: Args) => {
  229. return (
  230. <Notification
  231. {...args}
  232. content={<p>Lorem ipsum</p>}
  233. action={
  234. <>
  235. <button className="btn btn-secondary btn-sm">button1</button>
  236. <button className="btn btn-secondary btn-sm">button2</button>
  237. </>
  238. }
  239. type="info"
  240. isActionBelowContent
  241. isDismissible
  242. />
  243. )
  244. }
  245. export const OverlayedWithCustomClass = (args: Args) => {
  246. return (
  247. <>
  248. <Notification
  249. {...args}
  250. content={
  251. <p>
  252. This can be <b>any HTML</b> passed to the component. For example,
  253. paragraphs, headers, <code>code samples</code>,{' '}
  254. <a href="/">links</a>, etc are all supported.
  255. </p>
  256. }
  257. className="ol-overlay"
  258. action={
  259. <>
  260. <button className="btn btn-secondary btn-sm">button1</button>
  261. <button className="btn btn-secondary btn-sm">button2</button>
  262. </>
  263. }
  264. type="info"
  265. isActionBelowContent
  266. isDismissible
  267. />
  268. <div>
  269. <p>we need filler content, so here are some jokes</p>
  270. <ul>
  271. <li>Did you hear about the circus fire? It was in tents!</li>
  272. <li>How do you catch a squirrel? Climb a tree and act like a nut!</li>
  273. <li>
  274. Did you hear about the guy who invented Lifesavers? They say he made
  275. a mint!
  276. </li>
  277. <li>
  278. Why couldn't the bicycle stand up by itself? It was two tired.
  279. </li>
  280. <li>
  281. did one hat say to the other?" "Stay here! I'm going on ahead.
  282. </li>
  283. <li>
  284. Why did Billy get fired from the banana factory? He kept throwing
  285. away the bent ones.
  286. </li>
  287. </ul>
  288. </div>
  289. </>
  290. )
  291. }
  292. export const SuccessFlow = (args: Args) => {
  293. console.log('.....render')
  294. fetchMock.post('express:/test-success', { status: 200 }, { delay: 250 })
  295. const { isLoading, isSuccess, runAsync } = useAsync()
  296. function handleClick() {
  297. console.log('clicked')
  298. runAsync(postJSON('/test-success')).catch(console.error)
  299. }
  300. const ctaText = isLoading ? 'Processing' : 'Click'
  301. const action = (
  302. <button
  303. className="btn btn-secondary btn-sm"
  304. onClick={() => handleClick()}
  305. disabled={isLoading}
  306. >
  307. {ctaText}
  308. </button>
  309. )
  310. const startNotification = (
  311. <Notification
  312. {...args}
  313. action={action}
  314. title="An example notification flow"
  315. content={
  316. <p>
  317. This story shows 2 notifications, and it's up to the parent component
  318. to determine which to show. There's a successful request made after
  319. clicking the action and so the parent component then renders the
  320. success notification.
  321. </p>
  322. }
  323. />
  324. )
  325. const successNotification = (
  326. <Notification
  327. {...args}
  328. action={<a href="/">Now follow this link to go home</a>}
  329. type="success"
  330. content={<p>Success! You made a successful request.</p>}
  331. />
  332. )
  333. if (isSuccess) return successNotification
  334. return startNotification
  335. }
  336. export const ContentAsAString = (args: Args) => {
  337. return <Notification {...args} content="An alert" />
  338. }
  339. export default {
  340. title: 'Shared / Components / Notification',
  341. component: Notification,
  342. args: {
  343. content: (
  344. <p>
  345. This can be <b>any HTML</b> passed to the component. For example,
  346. paragraphs, headers, <code>code samples</code>, <a href="/">links</a>,
  347. etc are all supported.
  348. </p>
  349. ),
  350. action: <button className="btn btn-secondary btn-sm">An action</button>,
  351. isDismissible: true,
  352. },
  353. }