@lifesg/react-design-system 4.0.0-alpha.12 → 4.0.0-alpha.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (323) hide show
  1. package/breadcrumb/breadcrumb.js +1 -1
  2. package/breadcrumb/breadcrumb.js.map +1 -1
  3. package/breadcrumb/breadcrumb.styles.d.ts +0 -8
  4. package/breadcrumb/breadcrumb.styles.js +1 -1
  5. package/breadcrumb/breadcrumb.styles.js.map +1 -1
  6. package/breadcrumb/breadcrumb.styles_1blzn8n.css +7 -0
  7. package/breadcrumb/types.d.ts +2 -13
  8. package/cjs/breadcrumb/breadcrumb.js +1 -1
  9. package/cjs/breadcrumb/breadcrumb.js.map +1 -1
  10. package/cjs/breadcrumb/breadcrumb.styles.js +1 -1
  11. package/cjs/breadcrumb/breadcrumb.styles.js.map +1 -1
  12. package/cjs/breadcrumb/breadcrumb.styles_1blzn8n.css +7 -0
  13. package/cjs/drawer/drawer.js +1 -1
  14. package/cjs/drawer/drawer.js.map +1 -1
  15. package/cjs/drawer/drawer.styles.js +1 -1
  16. package/cjs/drawer/drawer.styles.js.map +1 -1
  17. package/{drawer/drawer.styles_94hx3y.css → cjs/drawer/drawer.styles_a4bwe0.css} +6 -3
  18. package/cjs/external/dompurify/dist/purify.es.js +4 -2
  19. package/cjs/external/dompurify/dist/purify.es.js.map +1 -1
  20. package/cjs/file-upload/file-list/file-list.js +1 -1
  21. package/cjs/file-upload/file-list/file-list.js.map +1 -1
  22. package/cjs/file-upload/file-list/file-list.styles.js +1 -1
  23. package/cjs/file-upload/file-list/file-list.styles.js.map +1 -1
  24. package/cjs/file-upload/file-list/file-list.styles_1xbypnh.css +2 -0
  25. package/cjs/file-upload/file-list-item/file-item-actions.js +2 -0
  26. package/cjs/file-upload/file-list-item/file-item-actions.js.map +1 -0
  27. package/cjs/file-upload/file-list-item/file-item-actions.styles.js +2 -0
  28. package/cjs/file-upload/file-list-item/file-item-actions.styles.js.map +1 -0
  29. package/cjs/file-upload/file-list-item/file-item-actions.styles_1quulgy.css +8 -0
  30. package/cjs/file-upload/file-list-item/file-item-details.js +2 -0
  31. package/cjs/file-upload/file-list-item/file-item-details.js.map +1 -0
  32. package/cjs/file-upload/file-list-item/file-item-details.styles.js +2 -0
  33. package/cjs/file-upload/file-list-item/file-item-details.styles.js.map +1 -0
  34. package/cjs/file-upload/file-list-item/file-item-details.styles_1ce9akx.css +7 -0
  35. package/cjs/file-upload/file-list-item/file-list-item.js +1 -1
  36. package/cjs/file-upload/file-list-item/file-list-item.js.map +1 -1
  37. package/cjs/file-upload/file-list-item/file-list-item.styles.js +1 -1
  38. package/cjs/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
  39. package/cjs/file-upload/file-list-item/file-list-item.styles_x3a500.css +10 -0
  40. package/cjs/file-upload/file-list-item/use-truncated-name.js +2 -0
  41. package/cjs/file-upload/file-list-item/use-truncated-name.js.map +1 -0
  42. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js +1 -1
  43. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
  44. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js +1 -1
  45. package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js.map +1 -1
  46. package/{local-nav/local-nav-dropdown/local-nav-dropdown.styles_uhd4xl.css → cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles_kpel1m.css} +9 -6
  47. package/cjs/local-nav/local-nav-menu/local-nav-menu.js +1 -1
  48. package/cjs/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
  49. package/cjs/local-nav/local-nav-menu/local-nav-menu.styles.js +1 -1
  50. package/cjs/local-nav/local-nav-menu/local-nav-menu.styles.js.map +1 -1
  51. package/cjs/local-nav/local-nav-menu/local-nav-menu.styles_67fcyc.css +8 -0
  52. package/cjs/menu/menu-content.js +1 -1
  53. package/cjs/menu/menu-content.js.map +1 -1
  54. package/cjs/menu/menu-content.styles.js +1 -1
  55. package/cjs/menu/menu-content.styles.js.map +1 -1
  56. package/cjs/menu/menu-content.styles_1r8oxtk.css +5 -0
  57. package/cjs/menu/menu-item.styles.js +1 -1
  58. package/cjs/menu/menu-item.styles.js.map +1 -1
  59. package/cjs/menu/{menu-item.styles_liyed8.css → menu-item.styles_eut2j9.css} +1 -1
  60. package/cjs/menu/menu-link.styles.js +1 -1
  61. package/cjs/menu/menu-link.styles.js.map +1 -1
  62. package/cjs/menu/menu-link.styles_rng7n7.css +2 -0
  63. package/cjs/menu/menu-section.js +1 -1
  64. package/cjs/menu/menu-section.js.map +1 -1
  65. package/cjs/menu/menu-section.styles.js +1 -1
  66. package/cjs/menu/menu-section.styles.js.map +1 -1
  67. package/cjs/menu/menu-section.styles_1n0ppxl.css +5 -0
  68. package/cjs/modal-v2/slots/slot-styles.js +1 -1
  69. package/cjs/modal-v2/slots/slot-styles.js.map +1 -1
  70. package/cjs/modal-v2/slots/{slot-styles_ayb9il.css → slot-styles_ygu6zc.css} +1 -1
  71. package/cjs/navbar/navbar-items.js +1 -1
  72. package/cjs/navbar/navbar-items.js.map +1 -1
  73. package/cjs/notification-banner/notification-banner-hoc.js +1 -1
  74. package/cjs/notification-banner/notification-banner-hoc.js.map +1 -1
  75. package/cjs/pagination/pagination.js +1 -1
  76. package/cjs/pagination/pagination.js.map +1 -1
  77. package/cjs/shared/dropdown-list/dropdown-label.js +1 -1
  78. package/cjs/shared/dropdown-list/dropdown-label.js.map +1 -1
  79. package/cjs/shared/fade-wrapper/fade-wrapper.js +1 -1
  80. package/cjs/shared/fade-wrapper/fade-wrapper.js.map +1 -1
  81. package/cjs/theme/tokens/colour.js +1 -1
  82. package/cjs/theme/tokens/colour.js.map +1 -1
  83. package/cjs/theme/tokens/radius.js +1 -1
  84. package/cjs/theme/tokens/radius.js.map +1 -1
  85. package/codemods/run-codemod.js +8 -2
  86. package/codemods/run-codemod.js.map +1 -1
  87. package/codemods/run-codemod.ts +13 -4
  88. package/drawer/drawer.d.ts +1 -1
  89. package/drawer/drawer.js +1 -1
  90. package/drawer/drawer.js.map +1 -1
  91. package/drawer/drawer.styles.d.ts +3 -0
  92. package/drawer/drawer.styles.js +1 -1
  93. package/drawer/drawer.styles.js.map +1 -1
  94. package/{cjs/drawer/drawer.styles_94hx3y.css → drawer/drawer.styles_a4bwe0.css} +6 -3
  95. package/drawer/types.d.ts +7 -0
  96. package/external/dompurify/dist/purify.es.js +4 -2
  97. package/external/dompurify/dist/purify.es.js.map +1 -1
  98. package/file-upload/file-list/file-list.js +1 -1
  99. package/file-upload/file-list/file-list.js.map +1 -1
  100. package/file-upload/file-list/file-list.styles.d.ts +0 -1
  101. package/file-upload/file-list/file-list.styles.js +1 -1
  102. package/file-upload/file-list/file-list.styles.js.map +1 -1
  103. package/file-upload/file-list/file-list.styles_1xbypnh.css +2 -0
  104. package/file-upload/file-list-item/file-item-actions.d.ts +30 -0
  105. package/file-upload/file-list-item/file-item-actions.js +2 -0
  106. package/file-upload/file-list-item/file-item-actions.js.map +1 -0
  107. package/file-upload/file-list-item/file-item-actions.styles.d.ts +6 -0
  108. package/file-upload/file-list-item/file-item-actions.styles.js +2 -0
  109. package/file-upload/file-list-item/file-item-actions.styles.js.map +1 -0
  110. package/file-upload/file-list-item/file-item-actions.styles_1quulgy.css +8 -0
  111. package/file-upload/file-list-item/file-item-details.d.ts +15 -0
  112. package/file-upload/file-list-item/file-item-details.js +2 -0
  113. package/file-upload/file-list-item/file-item-details.js.map +1 -0
  114. package/file-upload/file-list-item/file-item-details.styles.d.ts +7 -0
  115. package/file-upload/file-list-item/file-item-details.styles.js +2 -0
  116. package/file-upload/file-list-item/file-item-details.styles.js.map +1 -0
  117. package/file-upload/file-list-item/file-item-details.styles_1ce9akx.css +7 -0
  118. package/file-upload/file-list-item/file-list-item.d.ts +1 -7
  119. package/file-upload/file-list-item/file-list-item.js +1 -1
  120. package/file-upload/file-list-item/file-list-item.js.map +1 -1
  121. package/file-upload/file-list-item/file-list-item.styles.d.ts +6 -13
  122. package/file-upload/file-list-item/file-list-item.styles.js +1 -1
  123. package/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
  124. package/file-upload/file-list-item/file-list-item.styles_x3a500.css +10 -0
  125. package/file-upload/file-list-item/types.d.ts +10 -3
  126. package/file-upload/file-list-item/use-truncated-name.d.ts +1 -0
  127. package/file-upload/file-list-item/use-truncated-name.js +2 -0
  128. package/file-upload/file-list-item/use-truncated-name.js.map +1 -0
  129. package/input-group/types.d.ts +4 -1
  130. package/input-select/types.d.ts +1 -0
  131. package/local-nav/local-nav-dropdown/local-nav-dropdown.js +1 -1
  132. package/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
  133. package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.d.ts +3 -0
  134. package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js +1 -1
  135. package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js.map +1 -1
  136. package/{cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles_uhd4xl.css → local-nav/local-nav-dropdown/local-nav-dropdown.styles_kpel1m.css} +9 -6
  137. package/local-nav/local-nav-menu/local-nav-menu.js +1 -1
  138. package/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
  139. package/local-nav/local-nav-menu/local-nav-menu.styles.d.ts +3 -0
  140. package/local-nav/local-nav-menu/local-nav-menu.styles.js +1 -1
  141. package/local-nav/local-nav-menu/local-nav-menu.styles.js.map +1 -1
  142. package/local-nav/local-nav-menu/local-nav-menu.styles_67fcyc.css +8 -0
  143. package/local-nav/types.d.ts +17 -0
  144. package/masked-input/types.d.ts +1 -2
  145. package/menu/menu-content.js +1 -1
  146. package/menu/menu-content.js.map +1 -1
  147. package/menu/menu-content.styles.d.ts +1 -0
  148. package/menu/menu-content.styles.js +1 -1
  149. package/menu/menu-content.styles.js.map +1 -1
  150. package/menu/menu-content.styles_1r8oxtk.css +5 -0
  151. package/menu/menu-item.styles.js +1 -1
  152. package/menu/menu-item.styles.js.map +1 -1
  153. package/menu/{menu-item.styles_liyed8.css → menu-item.styles_eut2j9.css} +1 -1
  154. package/menu/menu-link.styles.js +1 -1
  155. package/menu/menu-link.styles.js.map +1 -1
  156. package/menu/menu-link.styles_rng7n7.css +2 -0
  157. package/menu/menu-section.d.ts +1 -1
  158. package/menu/menu-section.js +1 -1
  159. package/menu/menu-section.js.map +1 -1
  160. package/menu/menu-section.styles.d.ts +7 -0
  161. package/menu/menu-section.styles.js +1 -1
  162. package/menu/menu-section.styles.js.map +1 -1
  163. package/menu/menu-section.styles_1n0ppxl.css +5 -0
  164. package/menu/menu.d.ts +1 -1
  165. package/menu/types.d.ts +10 -2
  166. package/modal-v2/slots/slot-styles.js +1 -1
  167. package/modal-v2/slots/slot-styles.js.map +1 -1
  168. package/modal-v2/slots/{slot-styles_ayb9il.css → slot-styles_ygu6zc.css} +1 -1
  169. package/navbar/navbar-items.js +1 -1
  170. package/navbar/navbar-items.js.map +1 -1
  171. package/navbar/types.d.ts +9 -0
  172. package/notification-banner/notification-banner-hoc.js +1 -1
  173. package/notification-banner/notification-banner-hoc.js.map +1 -1
  174. package/package.json +3 -4
  175. package/pagination/pagination.js +1 -1
  176. package/pagination/pagination.js.map +1 -1
  177. package/pagination/types.d.ts +8 -1
  178. package/scripts/cli.js +18 -0
  179. package/select-histogram/types.d.ts +1 -0
  180. package/shared/dropdown-list/dropdown-label.d.ts +2 -2
  181. package/shared/dropdown-list/dropdown-label.js +1 -1
  182. package/shared/dropdown-list/dropdown-label.js.map +1 -1
  183. package/shared/dropdown-list/types.d.ts +6 -2
  184. package/shared/fade-wrapper/fade-wrapper.js +1 -1
  185. package/shared/fade-wrapper/fade-wrapper.js.map +1 -1
  186. package/shared/fade-wrapper/types.d.ts +1 -0
  187. package/shared/styles/index.d.ts +5 -0
  188. package/skills/fds-build/SKILL.md +167 -0
  189. package/skills/fds-build/catalogue.md +181 -0
  190. package/skills/fds-build/evals/evals.json +519 -0
  191. package/skills/fds-build/resources/components/accordion.md +128 -0
  192. package/skills/fds-build/resources/components/alert.md +54 -0
  193. package/skills/fds-build/resources/components/animation.md +18 -0
  194. package/skills/fds-build/resources/components/avatar.md +10 -0
  195. package/skills/fds-build/resources/components/badge.md +18 -0
  196. package/skills/fds-build/resources/components/box-container.md +61 -0
  197. package/skills/fds-build/resources/components/breadcrumb.md +60 -0
  198. package/skills/fds-build/resources/components/button.md +74 -0
  199. package/skills/fds-build/resources/components/calendar.md +113 -0
  200. package/skills/fds-build/resources/components/card.md +43 -0
  201. package/skills/fds-build/resources/components/checkbox.md +53 -0
  202. package/skills/fds-build/resources/components/countdown-timer.md +20 -0
  203. package/skills/fds-build/resources/components/data-table.md +142 -0
  204. package/skills/fds-build/resources/components/date-navigator.md +25 -0
  205. package/skills/fds-build/resources/components/divider.md +23 -0
  206. package/skills/fds-build/resources/components/drawer.md +78 -0
  207. package/skills/fds-build/resources/components/error-display.md +137 -0
  208. package/skills/fds-build/resources/components/feedback-rating.md +61 -0
  209. package/skills/fds-build/resources/components/file-download.md +54 -0
  210. package/skills/fds-build/resources/components/file-upload.md +105 -0
  211. package/skills/fds-build/resources/components/filter.md +228 -0
  212. package/skills/fds-build/resources/components/footer.md +94 -0
  213. package/skills/fds-build/resources/components/form-date-input.md +85 -0
  214. package/skills/fds-build/resources/components/form-date-range-input.md +146 -0
  215. package/skills/fds-build/resources/components/form-e-signature.md +55 -0
  216. package/skills/fds-build/resources/components/form-input.md +65 -0
  217. package/skills/fds-build/resources/components/form-masked-input.md +69 -0
  218. package/skills/fds-build/resources/components/form-multi-select.md +100 -0
  219. package/skills/fds-build/resources/components/form-nested-multi-select.md +159 -0
  220. package/skills/fds-build/resources/components/form-nested-select.md +151 -0
  221. package/skills/fds-build/resources/components/form-otp-verification.md +175 -0
  222. package/skills/fds-build/resources/components/form-phone-number-input.md +87 -0
  223. package/skills/fds-build/resources/components/form-predictive-text-input.md +108 -0
  224. package/skills/fds-build/resources/components/form-select.md +103 -0
  225. package/skills/fds-build/resources/components/form-slider.md +116 -0
  226. package/skills/fds-build/resources/components/form-textarea.md +116 -0
  227. package/skills/fds-build/resources/components/form-time-range-picker.md +98 -0
  228. package/skills/fds-build/resources/components/form-timepicker.md +77 -0
  229. package/skills/fds-build/resources/components/form-unit-number-input.md +138 -0
  230. package/skills/fds-build/resources/components/fullscreen-image-carousel.md +159 -0
  231. package/skills/fds-build/resources/components/histogram-slider.md +41 -0
  232. package/skills/fds-build/resources/components/icon.md +167 -0
  233. package/skills/fds-build/resources/components/image-button.md +12 -0
  234. package/skills/fds-build/resources/components/input.md +51 -0
  235. package/skills/fds-build/resources/components/language-switcher.md +15 -0
  236. package/skills/fds-build/resources/components/layout.md +156 -0
  237. package/skills/fds-build/resources/components/link-list.md +120 -0
  238. package/skills/fds-build/resources/components/local-nav.md +119 -0
  239. package/skills/fds-build/resources/components/masthead.md +14 -0
  240. package/skills/fds-build/resources/components/menu.md +109 -0
  241. package/skills/fds-build/resources/components/modal.md +150 -0
  242. package/skills/fds-build/resources/components/navbar.md +270 -0
  243. package/skills/fds-build/resources/components/notification-banner.md +106 -0
  244. package/skills/fds-build/resources/components/pagination.md +104 -0
  245. package/skills/fds-build/resources/components/pill.md +55 -0
  246. package/skills/fds-build/resources/components/popover.md +80 -0
  247. package/skills/fds-build/resources/components/progress-indicator.md +47 -0
  248. package/skills/fds-build/resources/components/radio-button.md +66 -0
  249. package/skills/fds-build/resources/components/schedule.md +78 -0
  250. package/skills/fds-build/resources/components/sidenav.md +183 -0
  251. package/skills/fds-build/resources/components/singpass-button.md +14 -0
  252. package/skills/fds-build/resources/components/smart-app-banner.md +28 -0
  253. package/skills/fds-build/resources/components/tab.md +107 -0
  254. package/skills/fds-build/resources/components/table.md +65 -0
  255. package/skills/fds-build/resources/components/tag.md +68 -0
  256. package/skills/fds-build/resources/components/text-list.md +44 -0
  257. package/skills/fds-build/resources/components/time-slot-bar-week.md +66 -0
  258. package/skills/fds-build/resources/components/time-slot-bar.md +57 -0
  259. package/skills/fds-build/resources/components/time-slot-week-view.md +70 -0
  260. package/skills/fds-build/resources/components/timeline.md +69 -0
  261. package/skills/fds-build/resources/components/timetable.md +123 -0
  262. package/skills/fds-build/resources/components/toast.md +72 -0
  263. package/skills/fds-build/resources/components/toggle.md +119 -0
  264. package/skills/fds-build/resources/components/typography.md +86 -0
  265. package/skills/fds-build/resources/components/uneditable-section.md +84 -0
  266. package/skills/fds-build/resources/foundations/layout-composition-patterns.md +53 -0
  267. package/skills/fds-build/resources/foundations/tokens.md +547 -0
  268. package/skills/fds-build/resources/patterns/states.md +300 -0
  269. package/skills/fds-build/resources/setup/setup.md +202 -0
  270. package/skills/fds-build/resources/templates/form.md +427 -0
  271. package/skills/fds-build/resources/templates/listing.md +435 -0
  272. package/theme/styles/a11y-playground.css +52 -40
  273. package/theme/styles/bookingsg.css +52 -40
  274. package/theme/styles/careercompass.css +52 -40
  275. package/theme/styles/ccube.css +52 -40
  276. package/theme/styles/imda.css +52 -40
  277. package/theme/styles/lifesg.css +52 -40
  278. package/theme/styles/mylegacy.css +52 -40
  279. package/theme/styles/oneservice.css +52 -40
  280. package/theme/styles/pa.css +28 -22
  281. package/theme/styles/rbs.css +52 -40
  282. package/theme/styles/sgw-digital-lobby.css +52 -40
  283. package/theme/styles/smgs.css +52 -40
  284. package/theme/styles/spf.css +28 -27
  285. package/theme/styles/sportsg-orange.css +52 -40
  286. package/theme/styles/supportgowhere.css +52 -40
  287. package/theme/styles/tote-board.css +52 -40
  288. package/theme/styles/vica.css +52 -40
  289. package/theme/styles/websg.css +52 -40
  290. package/theme/styles/wise.css +52 -40
  291. package/theme/styles/wogaa.css +52 -40
  292. package/theme/tokens/colour.d.ts +6 -0
  293. package/theme/tokens/colour.js +1 -1
  294. package/theme/tokens/colour.js.map +1 -1
  295. package/theme/tokens/radius.d.ts +3 -0
  296. package/theme/tokens/radius.js +1 -1
  297. package/theme/tokens/radius.js.map +1 -1
  298. package/breadcrumb/breadcrumb.styles_1nl4aua.css +0 -18
  299. package/cjs/breadcrumb/breadcrumb.styles_1nl4aua.css +0 -18
  300. package/cjs/file-upload/file-item-edit.js +0 -2
  301. package/cjs/file-upload/file-item-edit.js.map +0 -1
  302. package/cjs/file-upload/file-item-edit.styles.js +0 -2
  303. package/cjs/file-upload/file-item-edit.styles.js.map +0 -1
  304. package/cjs/file-upload/file-item-edit.styles_19bvztn.css +0 -11
  305. package/cjs/file-upload/file-list/file-list.styles_1w7so98.css +0 -3
  306. package/cjs/file-upload/file-list-item/file-list-item.styles_kgtfke.css +0 -17
  307. package/cjs/local-nav/local-nav-menu/local-nav-menu.styles_pq19dh.css +0 -5
  308. package/cjs/menu/menu-content.styles_p7ijll.css +0 -2
  309. package/cjs/menu/menu-link.styles_hfxoez.css +0 -2
  310. package/cjs/menu/menu-section.styles_g7my4d.css +0 -3
  311. package/file-upload/file-item-edit.d.ts +0 -14
  312. package/file-upload/file-item-edit.js +0 -2
  313. package/file-upload/file-item-edit.js.map +0 -1
  314. package/file-upload/file-item-edit.styles.d.ts +0 -9
  315. package/file-upload/file-item-edit.styles.js +0 -2
  316. package/file-upload/file-item-edit.styles.js.map +0 -1
  317. package/file-upload/file-item-edit.styles_19bvztn.css +0 -11
  318. package/file-upload/file-list/file-list.styles_1w7so98.css +0 -3
  319. package/file-upload/file-list-item/file-list-item.styles_kgtfke.css +0 -17
  320. package/local-nav/local-nav-menu/local-nav-menu.styles_pq19dh.css +0 -5
  321. package/menu/menu-content.styles_p7ijll.css +0 -2
  322. package/menu/menu-link.styles_hfxoez.css +0 -2
  323. package/menu/menu-section.styles_g7my4d.css +0 -3
@@ -0,0 +1,150 @@
1
+ # ModalV2
2
+
3
+ Import: `import { ModalV2 } from "@lifesg/react-design-system/modal-v2"`
4
+
5
+ ## When to use
6
+
7
+ Use for focused interactions that interrupt the user's flow — confirmations, detail views, or short multi-field forms that do not warrant a new page.
8
+
9
+ > **Note:** `Modal` is deprecated. Use `ModalV2` — it provides improved scroll behaviour, proper focus management via `@floating-ui/react`, and a composable slot-based API.
10
+
11
+ ## Sub-components
12
+
13
+ `ModalV2`, `ModalV2.Card`, `ModalV2.Header`, `ModalV2.Content`, `ModalV2.Footer`, `ModalV2.CloseButton`
14
+
15
+ ## Variants
16
+
17
+ | Use case | Structure |
18
+ | ------------------- | ---------------------------------------------------------------- |
19
+ | Confirmation dialog | `ModalV2.Header` + `ModalV2.Content` + `ModalV2.Footer` |
20
+ | Detail view | `ModalV2.Header` (close only, no title) + `ModalV2.Content` |
21
+ | Short form | `ModalV2.Header` + `ModalV2.Content` (fields) + `ModalV2.Footer` |
22
+
23
+ ## Usage
24
+
25
+ ### Confirmation dialog
26
+
27
+ ```tsx
28
+ import { useState } from "react";
29
+ import { ModalV2 } from "@lifesg/react-design-system/modal-v2";
30
+ import { Button } from "@lifesg/react-design-system/button";
31
+ import { Typography } from "@lifesg/react-design-system/typography";
32
+
33
+ const ConfirmDeleteModal = () => {
34
+ const [show, setShow] = useState(false);
35
+
36
+ const handleClose = () => setShow(false);
37
+
38
+ const handleConfirm = () => {
39
+ // perform action
40
+ setShow(false);
41
+ };
42
+
43
+ return (
44
+ <>
45
+ <Button onClick={() => setShow(true)}>Delete item</Button>
46
+
47
+ <ModalV2
48
+ show={show}
49
+ onClose={handleClose}
50
+ enableOverlayClick
51
+ onOverlayClick={handleClose}
52
+ >
53
+ <ModalV2.Card>
54
+ <ModalV2.Header title="Delete this item?" />
55
+ <ModalV2.Content>
56
+ <Typography.BodyBL>
57
+ This action cannot be undone.
58
+ </Typography.BodyBL>
59
+ </ModalV2.Content>
60
+ <ModalV2.Footer
61
+ primaryButton={
62
+ <Button onClick={handleConfirm}>Confirm</Button>
63
+ }
64
+ secondaryButton={
65
+ <Button styleType="secondary" onClick={handleClose}>
66
+ Cancel
67
+ </Button>
68
+ }
69
+ />
70
+ </ModalV2.Card>
71
+ </ModalV2>
72
+ </>
73
+ );
74
+ };
75
+ ```
76
+
77
+ ### Detail view (close button only, no title)
78
+
79
+ ```tsx
80
+ <ModalV2 show={show} onClose={handleClose}>
81
+ <ModalV2.Card>
82
+ <ModalV2.Header />
83
+ <ModalV2.Content>
84
+ <Typography.BodyBL>Supplementary details here.</Typography.BodyBL>
85
+ </ModalV2.Content>
86
+ </ModalV2.Card>
87
+ </ModalV2>
88
+ ```
89
+
90
+ ## Props — `ModalCardProps`
91
+
92
+ | Prop | Type | Default | Description |
93
+ | ------------- | --------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- |
94
+ | `children` \* | `React.ReactNode` | — | — |
95
+ | `elementRef` | `React.Ref<HTMLDivElement>` | — | Ref to the modal card DOM element. When used within `Modal`, the default `ref` is not available and you can specify this instead. |
96
+ | `fullscreen` | `boolean` | — | When `true`, the card expands to fill the viewport with no border-radius, padding, or box-shadow. |
97
+
98
+ ## Props — `ModalHeaderProps`
99
+
100
+ | Prop | Type | Default | Description |
101
+ | --------------------- | ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------ |
102
+ | `title` | `string` | — | Heading text rendered in the header. Always centered regardless of `closeButtonPosition`. Omit for a close-button-only header. |
103
+ | `closeButtonPosition` | `"left" \| "right"` | "right" | Which side of the header the close button is placed on. The title alignment adjusts automatically. |
104
+
105
+ ## Props — `ModalContentProps`
106
+
107
+ | Prop | Type | Default | Description |
108
+ | ------------- | ----------------- | ------- | ----------- |
109
+ | `children` \* | `React.ReactNode` | — | — |
110
+
111
+ ## Props — `ModalFooterProps`
112
+
113
+ | Prop | Type | Default | Description |
114
+ | ----------------- | ----------------- | ------- | ----------------------------------------------- |
115
+ | `primaryButton` | `React.ReactNode` | — | Node rendered in the primary action position. |
116
+ | `secondaryButton` | `React.ReactNode` | — | Node rendered in the secondary action position. |
117
+
118
+ ## Props — `ModalV2Props`
119
+
120
+ | Prop | Type | Default | Description |
121
+ | ----------------------- | ------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
122
+ | `show` \* | `boolean` | false | Controls whether the modal is visible. |
123
+ | `children` \* | `React.JSX.Element` | — | The content of the modal. The parent element must be a valid HTML element or a component that forwards a ref to a valid HTML element. |
124
+ | `animationFrom` | `ModalAnimationDirection` | "bottom" | Direction from which the modal animates in and out. |
125
+ | `enableOverlayClick` | `boolean` | true | Whether clicking the overlay backdrop triggers `onOverlayClick`. The caller is responsible for dismissing the modal in the callback. |
126
+ | `rootComponentId` | `string` | — | The `id` of the DOM element to portal the modal into. |
127
+ | `zIndex` | `number` | — | The z-index applied to the overlay stack. |
128
+ | `onClose` | `(() => void)` | — | Called when the modal is dismissed via the Escape key and close button. |
129
+ | `onOverlayClick` | `(() => void)` | — | Called when the overlay backdrop is clicked and `enableOverlayClick` is `true`. |
130
+ | `dismissKeyboardOnShow` | `boolean` | true | Blurs the currently focused element when the modal becomes visible, dismissing the on-screen keyboard on mobile to prevent it from obscuring the modal. |
131
+ | `disableInitialFocus` | `boolean` | false | Disables automatic focus on the modal container when it opens. When `true`, the consumer is responsible for focusing an element within the modal. |
132
+
133
+ ## Rules
134
+
135
+ - Always pass `onClose` to `ModalV2` — it is used by `ModalV2.Header` / `ModalV2.CloseButton` via context.
136
+ - Always wrap content in `ModalV2.Card` — it handles internal layout of slots.
137
+ - Use `ModalV2.Header` (not `ModalV2.CloseButton`) when the modal has a title — the header provides the close button automatically.
138
+ - Use `ModalV2.CloseButton` only for custom layouts where `ModalV2.Header` is not present.
139
+ - Pass action buttons to `ModalV2.Footer` via `primaryButton` / `secondaryButton` — do not place them inside `ModalV2.Content`.
140
+ - Provide `enableOverlayClick` + `onOverlayClick` together to allow overlay dismissal.
141
+ - Use `animationFrom="bottom"` for mobile-friendly sheet-style modals.
142
+ - Keep modal content focused — one task or decision per modal.
143
+
144
+ ## Anti-patterns
145
+
146
+ - Do not use the deprecated `Modal` — use `ModalV2`.
147
+ - Do not pass a Fragment as the direct child of `ModalV2` — use `ModalV2.Card` or a forwardRef component.
148
+ - Do not put buttons inside `ModalV2.Content` — use `ModalV2.Footer`.
149
+ - Do not stack modals unless using `zIndex` explicitly.
150
+ - Do not use modals for complex multi-step forms — navigate to a dedicated page instead.
@@ -0,0 +1,270 @@
1
+ # Navbar
2
+
3
+ Import: `import { Navbar } from "@lifesg/react-design-system/navbar"`
4
+
5
+ ## When to use
6
+
7
+ Place at the top of every page. Required on all pages. Automatically collapses navigation items into a hamburger drawer on mobile.
8
+
9
+ ## Variants
10
+
11
+ | `layout` | When to use |
12
+ | ----------- | ----------------------------------------------- |
13
+ | `"default"` | Centered content container — standard pages |
14
+ | `"stretch"` | Full-width content — must match Footer `layout` |
15
+
16
+ ## Usage
17
+
18
+ ### Complete Navbar with link items, a submenu, and an action button
19
+
20
+ `NavItemProps` is a discriminated union on `itemType`. The default (no `itemType`) is a link item. Use `itemType: "component"` for custom elements like an avatar with a dropdown.
21
+
22
+ ```tsx
23
+ import { useState } from "react";
24
+ import { Navbar } from "@lifesg/react-design-system/navbar";
25
+
26
+ const AppNavbar = () => {
27
+ const [selectedId, setSelectedId] = useState("home");
28
+
29
+ return (
30
+ <Navbar
31
+ masthead
32
+ selectedId={selectedId}
33
+ onItemClick={(item) => item.id && setSelectedId(item.id)}
34
+ items={{
35
+ desktop: [
36
+ // itemType defaults to "link"
37
+ {
38
+ id: "home",
39
+ children: "Home",
40
+ href: "/",
41
+ },
42
+ {
43
+ id: "guides",
44
+ children: "Guides",
45
+ href: "/guides",
46
+ // subMenu items share the same shape as top-level link items
47
+ subMenu: [
48
+ {
49
+ id: "guides-start",
50
+ children: "Getting started",
51
+ href: "/guides/start",
52
+ },
53
+ {
54
+ id: "guides-api",
55
+ children: "API reference",
56
+ href: "/guides/api",
57
+ },
58
+ ],
59
+ },
60
+ {
61
+ // itemType: "component" — renders arbitrary JSX; no href or id needed
62
+ itemType: "component",
63
+ children: <UserAvatar />,
64
+ },
65
+ ],
66
+ }}
67
+ actionButtons={{
68
+ desktop: [
69
+ {
70
+ type: "button",
71
+ args: { children: "Log in", styleType: "secondary" },
72
+ },
73
+ ],
74
+ }}
75
+ resources={{
76
+ primary: { brandName: "MyService", logoSrc: "/logo.svg" },
77
+ }}
78
+ />
79
+ );
80
+ };
81
+ ```
82
+
83
+ Key points:
84
+
85
+ - Omit `itemType` (or set `itemType: "link"`) for standard anchor items.
86
+ - `subMenu` accepts the same `NavItemCommonProps` shape as top-level items.
87
+ - `itemType: "component"` items take `children: JSX.Element`; they do not accept `id`, `href`, or `subMenu`.
88
+ - `selectedId` matches against the `id` field of link items to highlight the active page.
89
+
90
+ ## Props — `NavItemLinkProps`
91
+
92
+ | Prop | Type | Default | Description |
93
+ | ---------------- | -------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
94
+ | `itemType` | `"link"` | — | — |
95
+ | `subMenu` | `NavItemCommonProps<T>[]` | — | — |
96
+ | `subMenuColumns` | `number` | — | Renders `subMenu` as a multi-column layout on desktop. Items flow vertically (top-to-bottom) within each column before wrapping to the next. Has no effect on the mobile drawer, which always renders `subMenu` as an expandable vertical list. |
97
+ | `id` \* | `string` | — | — |
98
+ | `options` | `T` | — | Arbitrary data passed through to callback arguments such as `onItemClick`. |
99
+ | `weight` | `TypographyWeight` | "regular" | Font weight of the link text. |
100
+ | `external` | `boolean` | — | Appends an external-link icon after the link text to signal that the destination is outside the current site. |
101
+ | `underlineStyle` | `TypographyUnderlineStyle` | "underline" | Text-decoration style for the link. |
102
+
103
+ ## Props — `NavItemComponentProps`
104
+
105
+ | Prop | Type | Default | Description |
106
+ | ------------- | ------------- | ------- | ----------- |
107
+ | `itemType` \* | `"component"` | — | — |
108
+ | `children` \* | `JSX.Element` | — | — |
109
+
110
+ ## Props — `NavItemCommonProps`
111
+
112
+ | Prop | Type | Default | Description |
113
+ | ---------------- | -------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------- |
114
+ | `id` \* | `string` | — | — |
115
+ | `options` | `T` | — | Arbitrary data passed through to callback arguments such as `onItemClick`. |
116
+ | `weight` | `TypographyWeight` | "regular" | Font weight of the link text. |
117
+ | `external` | `boolean` | — | Appends an external-link icon after the link text to signal that the destination is outside the current site. |
118
+ | `underlineStyle` | `TypographyUnderlineStyle` | "underline" | Text-decoration style for the link. |
119
+
120
+ ## Props — `NavItemsProps`
121
+
122
+ | Prop | Type | Default | Description |
123
+ | ------------ | ------------------- | ------- | -------------------------------------------------------------------------- |
124
+ | `desktop` \* | `NavItemProps<T>[]` | — | Items rendered in the desktop navbar. |
125
+ | `mobile` | `NavItemProps<T>[]` | — | Items rendered in the mobile drawer. Falls back to `desktop` when omitted. |
126
+
127
+ ## Props — `NavbarActionButtonDownloadProps`
128
+
129
+ | Prop | Type | Default | Description |
130
+ | --------------- | ------------- | ------- | ------------------------------------------------------------------------------------------------------ |
131
+ | `type` \* | `"download"` | — | — |
132
+ | `args` | `ButtonProps` | — | — |
133
+ | `uncollapsible` | `boolean` | false | When `true`, the button remains visible outside the mobile drawer rather than being collapsed into it. |
134
+
135
+ ## Props — `NavbarActionButtonCtaProps`
136
+
137
+ | Prop | Type | Default | Description |
138
+ | --------------- | ------------- | ------- | ------------------------------------------------------------------------------------------------------ |
139
+ | `type` \* | `"button"` | — | — |
140
+ | `args` \* | `ButtonProps` | — | — |
141
+ | `uncollapsible` | `boolean` | false | When `true`, the button remains visible outside the mobile drawer rather than being collapsed into it. |
142
+
143
+ ## Props — `NavbarActionButtonComponentProps`
144
+
145
+ | Prop | Type | Default | Description |
146
+ | --------------- | ---------------------------- | ------- | ------------------------------------------------------------------------------------------------------ |
147
+ | `type` \* | `"component"` | — | — |
148
+ | `args` | `NavbarButtonComponentProps` | — | — |
149
+ | `uncollapsible` | `boolean` | false | When `true`, the button remains visible outside the mobile drawer rather than being collapsed into it. |
150
+
151
+ ## Props — `NavbarActionButtonsProps`
152
+
153
+ | Prop | Type | Default | Description |
154
+ | ------------ | --------------------- | ------- | ----------------------------------------------------------------------------------- |
155
+ | `desktop` \* | `NavbarButtonProps[]` | — | Action buttons rendered in the desktop navbar. |
156
+ | `mobile` | `NavbarButtonProps[]` | — | Action buttons rendered in the mobile drawer. Falls back to `desktop` when omitted. |
157
+
158
+ ## Props — `NavbarBrandingProps`
159
+
160
+ | Prop | Type | Default | Description |
161
+ | -------------- | -------- | ------- | ----------------------------------------------------------- |
162
+ | `brandName` \* | `string` | — | The name of the brand, used for accessibility and alt text. |
163
+ | `logoSrc` \* | `string` | — | The source URL for the brand logo image. |
164
+
165
+ ## Props — `NavbarResourcesProps`
166
+
167
+ | Prop | Type | Default | Description |
168
+ | ----------- | --------------------- | ------- | ------------------------------------------------------------------- |
169
+ | `primary` | `NavbarBrandingProps` | — | When omitted, a default logo derived from the active theme is used. |
170
+ | `secondary` | `NavbarBrandingProps` | — | When omitted, the secondary brand slot is hidden. |
171
+
172
+ ## Props — `NavbarSharedProps`
173
+
174
+ | Prop | Type | Default | Description |
175
+ | ------------------- | -------------------------- | ------- | -------------------------------------------------------------------------- |
176
+ | `resources` | `NavbarResourcesProps` | — | Branding and logo resources for the navbar. |
177
+ | `actionButtons` | `NavbarActionButtonsProps` | — | Action buttons rendered in the navbar and mobile drawer. |
178
+ | `hideNavBranding` | `boolean` | false | Hides all brand logos from the navbar and drawer. |
179
+ | `hideLinkIndicator` | `boolean` | false | Hides the active-item underline indicator across desktop and drawer views. |
180
+
181
+ ## Props — `NavbarDrawerProps`
182
+
183
+ | Prop | Type | Default | Description |
184
+ | ------------------- | ------------------------------------------------------------------------------ | ------- | ----------------------------------------------------------------------------------- |
185
+ | `show` \* | `boolean` | — | Controls whether the drawer is visible. |
186
+ | `children` \* | `JSX.Element \| JSX.Element[]` | — | — |
187
+ | `onClose` | `(() => void)` | — | Called when the drawer requests to be closed via the close button or overlay click. |
188
+ | `onBrandClick` | `\| (( event: React.MouseEvent<HTMLAnchorElement>, type: BrandType ) => void)` | — | Called when a brand logo inside the drawer is clicked. |
189
+ | `drawerLabel` | `string` | — | Accessible label announced for the mobile navigation drawer. |
190
+ | `mobileMenuRef` | `React.RefObject<HTMLButtonElement>` | — | Ref to the mobile menu button used to return focus when the drawer closes. |
191
+ | `resources` | `NavbarResourcesProps` | — | Branding and logo resources for the navbar. |
192
+ | `actionButtons` | `NavbarActionButtonsProps` | — | Action buttons rendered in the navbar and mobile drawer. |
193
+ | `hideNavBranding` | `boolean` | false | Hides all brand logos from the navbar and drawer. |
194
+ | `hideLinkIndicator` | `boolean` | false | Hides the active-item underline indicator across desktop and drawer views. |
195
+
196
+ ## Props — `NavbarProps`
197
+
198
+ | Prop | Type | Default | Description |
199
+ | --------------------------- | --------------------------------------------------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
200
+ | `items` \* | `NavItemsProps<T>` | — | — |
201
+ | `className` | `string` | — | — |
202
+ | `id` | `string` | — | — |
203
+ | `selectedId` | `string` | — | The currently selected navigation item identifier. Must match the `id` of one of the rendered items. |
204
+ | `compress` | `boolean` | false | Reduces the height and logo size of the navbar. |
205
+ | `fixed` | `boolean` | true | Pins the navbar to the top of the viewport while the page scrolls. |
206
+ | `drawerDismissalExclusions` | `DrawerDismissalMethod[]` | — | Drawer dismissal methods that should be suppressed. The drawer will not close when the user performs any of the listed actions. |
207
+ | `hideNavElements` | `boolean` | false | Hides nav items and action buttons, leaving only the brand area visible. |
208
+ | `onBrandClick` | `((type: BrandType) => void)` | — | Called when a brand logo is clicked. `type` identifies which brand slot was activated. |
209
+ | `onItemClick` | `\| ((item: NavItemProps<T> \| NavItemCommonProps<T>) => void)` | — | Called when a navigation item is activated from the desktop bar or the mobile drawer. The item's full props object is passed as the argument. |
210
+ | `onActionButtonClick` | `\| ((actionButton: NavbarButtonProps) => void)` | — | Called when an action button without its own `onClick` handler is activated. The button's full props object is passed as the argument. |
211
+ | `masthead` | `boolean` | true | Renders the `Masthead` (SGDS official government banner) above the navbar. |
212
+ | `layout` | `"default" \| "stretch"` | "default" | Controls how the navbar content fills its container. `"stretch"` expands to the full container width; `"default"` uses the standard content width. |
213
+ | `headerLabel` | `string` | "Main navigation menu" | Accessible label announced for the main navigation header. |
214
+ | `drawerLabel` | `string` | — | Accessible label announced for the mobile navigation drawer. |
215
+ | `resources` | `NavbarResourcesProps` | — | Branding and logo resources for the navbar. |
216
+ | `actionButtons` | `NavbarActionButtonsProps` | — | Action buttons rendered in the navbar and mobile drawer. |
217
+ | `hideNavBranding` | `boolean` | false | Hides all brand logos from the navbar and drawer. |
218
+ | `hideLinkIndicator` | `boolean` | false | Hides the active-item underline indicator across desktop and drawer views. |
219
+
220
+ ## Props — `NavItemProps`
221
+
222
+ | Prop | Type | Default | Description |
223
+ | ------------- | ------------- | ------- | ----------- |
224
+ | `itemType` \* | `"component"` | — | — |
225
+ | `children` \* | `JSX.Element` | — | — |
226
+
227
+ ## Props — `NavbarButtonProps`
228
+
229
+ | Prop | Type | Default | Description |
230
+ | --------------- | ------------- | ------- | ------------------------------------------------------------------------------------------------------ |
231
+ | `type` \* | `"download"` | — | — |
232
+ | `args` | `ButtonProps` | — | — |
233
+ | `uncollapsible` | `boolean` | false | When `true`, the button remains visible outside the mobile drawer rather than being collapsed into it. |
234
+
235
+ ## Props — `NavbarDrawerApi`
236
+
237
+ | Prop | Type | Default | Description |
238
+ | ------------------ | ------------ | ------- | ----------------------------------------------------------------------------- |
239
+ | `dismissDrawer` \* | `() => void` | — | Programmatically closes the mobile navigation drawer with its exit animation. |
240
+
241
+ ## Props — `NavbarDrawerHandle`
242
+
243
+ | Prop | Type | Default | Description |
244
+ | ------------------ | ------------ | ------- | ----------------------------------------------------------------------------- |
245
+ | `dismissDrawer` \* | `() => void` | — | Programmatically closes the mobile navigation drawer with its exit animation. |
246
+
247
+ ## Rules
248
+
249
+ - Always set `masthead` — all government services must display the masthead.
250
+ - Always provide a meaningful `id` on each `NavItemCommonProps` item — used by `selectedId` to highlight the active page.
251
+ - `items.desktop` is required; the component crashes without it.
252
+ - `items.mobile` is optional — falls back to `desktop` if omitted.
253
+ - `layout` must match the `Footer` `layout` prop; do not mix `"default"` and `"stretch"`.
254
+ - Limit action buttons to 2–3 maximum.
255
+ - Use SVG format for brand logos.
256
+ - When using `fixed`, add corresponding top padding to page content to prevent overlap.
257
+ - Set `uncollapsible: true` on action buttons that must remain visible on mobile (e.g. avatar).
258
+ - Use `itemType: "component"` for custom nav elements such as an avatar with a `Menu` dropdown.
259
+ - Pass `type: "component"` with `args: { render: <Element /> }` for custom action button elements.
260
+ - `BrandType` is `"primary" | "secondary"` — passed to `onBrandClick`.
261
+ - The `"download"` button type is pre-programmed for LifeSG purposes.
262
+ - `NavbarButtonComponentProps` accepts a `render: JSX.Element` field for custom components.
263
+
264
+ ## Anti-patterns
265
+
266
+ - Do not omit `masthead` — it is required for government compliance.
267
+ - Do not supply a custom `resources.primary.logoSrc` unless the service has its own brand logo — omit `resources` to let the theme render its built-in logo.
268
+ - Do not use `hideNavElements` as a default state — it is for special page states only (e.g. maintenance).
269
+ - Do not use `fixed: false` unless the layout explicitly requires a non-fixed header.
270
+ - Do not add more than 3 action buttons — the navbar becomes visually cluttered.
@@ -0,0 +1,106 @@
1
+ # NotificationBanner
2
+
3
+ Import: `import { NotificationBanner } from "@lifesg/react-design-system/notification-banner"`
4
+
5
+ ## When to use
6
+
7
+ Use for notices that must always be visible to the user — maintenance windows, policy changes, mandatory announcements. Unlike Toast, it does not auto-dismiss. Unlike Alert, it applies to the entire page, not a specific section.
8
+
9
+ ## Sub-components
10
+
11
+ - `NotificationBanner.Link` — Inherits `TypographyLinkProps`. Use for links within banner content.
12
+
13
+ ## HOC
14
+
15
+ ```ts
16
+ withNotificationBanner(data: NotificationContentAttributes[])
17
+ ```
18
+
19
+ ### NotificationContentAttributes
20
+
21
+ | Prop | Type | Default | Description |
22
+ | ----------------- | ------------------------------------------ | ------- | ------------------------------------------------ |
23
+ | `type` | `"text"` \| `"link"` | — | Type of content — required |
24
+ | `content` | `string` | — | Text content — required |
25
+ | `otherAttributes` | `TypographyLinkProps` \| `TypographyProps` | — | Additional props passed to the content component |
26
+
27
+ ## Usage
28
+
29
+ ```tsx
30
+ import { NotificationBanner } from "@lifesg/react-design-system/notification-banner";
31
+
32
+ <NotificationBanner dismissible sticky onDismiss={() => {}}>
33
+ Scheduled maintenance on 1 Feb 2026, 2–4 AM.{" "}
34
+ <NotificationBanner.Link href="/status">
35
+ View status
36
+ </NotificationBanner.Link>
37
+ </NotificationBanner>;
38
+ ```
39
+
40
+ ## Props — `NotificationBannerProps`
41
+
42
+ | Prop | Type | Default | Description |
43
+ | -------------------- | ----------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
44
+ | `children` | `React.ReactNode` | — | — |
45
+ | `dismissible` | `boolean` | true | Whether the dismiss button is rendered. The caller is responsible for dismissing the banner in the callback. |
46
+ | `visible` | `boolean` | true | Controls the visibility of the banner. |
47
+ | `sticky` | `boolean` | true | Whether the banner sticks to the top of the viewport while the page scrolls. |
48
+ | `icon` | `JSX.Element` | — | An optional icon element rendered at the leading edge of the banner. |
49
+ | `onDismiss` | `(() => void)` | — | Called when the user activates the dismiss button and `dismissible` is `true`. |
50
+ | `maxCollapsedHeight` | `number` | — | Maximum height in pixels for the content area. When the rendered content exceeds this value, the overflow is clipped. |
51
+ | `actionButton` | `React.ButtonHTMLAttributes<HTMLButtonElement>` | — | An action button rendered inside the content area. When `actionButton.onClick` is provided it stops propagation to the banner's own `onClick` handler. |
52
+
53
+ ## Props — `NotificationBannerWithForwardedRefProps`
54
+
55
+ | Prop | Type | Default | Description |
56
+ | -------------------- | ----------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
57
+ | `forwardedRef` | `React.Ref<HTMLDivElement>` | — | — |
58
+ | `children` | `React.ReactNode` | — | — |
59
+ | `dismissible` | `boolean` | true | Whether the dismiss button is rendered. The caller is responsible for dismissing the banner in the callback. |
60
+ | `visible` | `boolean` | true | Controls the visibility of the banner. |
61
+ | `sticky` | `boolean` | true | Whether the banner sticks to the top of the viewport while the page scrolls. |
62
+ | `icon` | `JSX.Element` | — | An optional icon element rendered at the leading edge of the banner. |
63
+ | `onDismiss` | `(() => void)` | — | Called when the user activates the dismiss button and `dismissible` is `true`. |
64
+ | `maxCollapsedHeight` | `number` | — | Maximum height in pixels for the content area. When the rendered content exceeds this value, the overflow is clipped. |
65
+ | `actionButton` | `React.ButtonHTMLAttributes<HTMLButtonElement>` | — | An action button rendered inside the content area. When `actionButton.onClick` is provided it stops propagation to the banner's own `onClick` handler. |
66
+
67
+ ## Props — `ContentLinkAttributes`
68
+
69
+ | Prop | Type | Default | Description |
70
+ | ---------------- | -------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------- |
71
+ | `weight` | `TypographyWeight` | "regular" | Font weight of the link text. |
72
+ | `external` | `boolean` | — | Appends an external-link icon after the link text to signal that the destination is outside the current site. |
73
+ | `underlineStyle` | `TypographyUnderlineStyle` | "underline" | Text-decoration style for the link. |
74
+
75
+ ## Props — `ContentTextAttributes`
76
+
77
+ | Prop | Type | Default | Description |
78
+ | ----------- | ------------------ | --------- | ------------------------------------------------------------------------------------------------------------------- |
79
+ | `weight` | `TypographyWeight` | "regular" | Font weight of the rendered text. |
80
+ | `inline` | `boolean` | — | Renders the element as an inline `span`. When `true`, the `as` prop is ignored and `maxLines` clamping is disabled. |
81
+ | `paragraph` | `boolean` | — | Adds a bottom margin to separate the element from following content. |
82
+ | `maxLines` | `number` | — | Clamps visible text to the given number of lines, truncating the remainder. |
83
+ | `as` | `T` | — | Overrides the rendered HTML element, e.g. `"h2"`. |
84
+
85
+ ## Props — `NotificationContentAttributes`
86
+
87
+ | Prop | Type | Default | Description |
88
+ | ----------------- | ---------------------------------------- | ------- | ---------------------------------------------------------------- |
89
+ | `type` \* | `ContentType` | — | Determines how `content` is rendered inside the banner. |
90
+ | `content` \* | `string` | — | The text string or link label to display. |
91
+ | `otherAttributes` | `TypographyLinkProps \| TypographyProps` | — | Additional props forwarded to the rendered text or link element. |
92
+
93
+ ## Rules
94
+
95
+ - Place directly below the Navbar — above all page content.
96
+ - Use for page-wide or system-wide notices only — not for section-specific messages.
97
+ - Use `dismissible={false}` for mandatory notices users must not be able to dismiss.
98
+ - Use `NotificationBanner.Link` for all links within the banner — renders with the external link indicator automatically.
99
+ - Use `maxCollapsedHeight` for long notices to avoid overwhelming the layout.
100
+ - Use the `withNotificationBanner` HOC for banner content driven from a backend or external data source.
101
+
102
+ ## Anti-patterns
103
+
104
+ - Using NotificationBanner for section-specific messages — use Alert instead.
105
+ - Using raw anchor tags inside banner content — use `NotificationBanner.Link`.
106
+ - Placing the banner below page content — it must sit directly below the Navbar.