@chassis-ui/react 0.0.0-20260831090525

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 (275) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +65 -0
  3. package/dist/index.d.ts +5909 -0
  4. package/dist/index.js +2 -0
  5. package/dist/style.css +1 -0
  6. package/package.json +114 -0
  7. package/src/components/accordion/Accordion.tsx +190 -0
  8. package/src/components/accordion/AccordionBody.tsx +46 -0
  9. package/src/components/accordion/AccordionHeader.tsx +21 -0
  10. package/src/components/accordion/AccordionItem.tsx +59 -0
  11. package/src/components/accordion/context.ts +8 -0
  12. package/src/components/accordion/index.ts +8 -0
  13. package/src/components/autocomplete/Autocomplete.tsx +464 -0
  14. package/src/components/autocomplete/AutocompleteGroup.tsx +20 -0
  15. package/src/components/autocomplete/AutocompleteItem.tsx +18 -0
  16. package/src/components/autocomplete/index.ts +6 -0
  17. package/src/components/avatar/Avatar.tsx +134 -0
  18. package/src/components/avatar/AvatarImage.tsx +19 -0
  19. package/src/components/avatar/AvatarStack.tsx +98 -0
  20. package/src/components/avatar/index.ts +6 -0
  21. package/src/components/badge/Badge.tsx +94 -0
  22. package/src/components/badge/index.ts +2 -0
  23. package/src/components/breadcrumb/Breadcrumb.tsx +59 -0
  24. package/src/components/breadcrumb/BreadcrumbItem.tsx +38 -0
  25. package/src/components/breadcrumb/index.ts +4 -0
  26. package/src/components/button/Button.tsx +229 -0
  27. package/src/components/button/index.ts +2 -0
  28. package/src/components/button-group/ButtonGroup.tsx +55 -0
  29. package/src/components/button-group/ButtonToolbar.tsx +47 -0
  30. package/src/components/button-group/index.ts +4 -0
  31. package/src/components/calendar/Calendar.scss +57 -0
  32. package/src/components/calendar/Calendar.tsx +324 -0
  33. package/src/components/calendar/CalendarMonthBlock.tsx +57 -0
  34. package/src/components/calendar/CalendarMonthGrid.tsx +92 -0
  35. package/src/components/calendar/CalendarMonthYearPicker.tsx +162 -0
  36. package/src/components/calendar/CalendarNavButton.tsx +24 -0
  37. package/src/components/calendar/CalendarWeekGrid.tsx +58 -0
  38. package/src/components/calendar/CalendarYearGrid.tsx +126 -0
  39. package/src/components/calendar/RangeCalendar.scss +95 -0
  40. package/src/components/calendar/RangeCalendar.tsx +361 -0
  41. package/src/components/calendar/index.ts +5 -0
  42. package/src/components/card/Card.tsx +173 -0
  43. package/src/components/card/CardBody.tsx +75 -0
  44. package/src/components/card/CardFooter.tsx +47 -0
  45. package/src/components/card/CardGroup.tsx +51 -0
  46. package/src/components/card/CardHeader.tsx +47 -0
  47. package/src/components/card/CardImage.tsx +70 -0
  48. package/src/components/card/CardImageOverlay.tsx +47 -0
  49. package/src/components/card/CardLink.tsx +40 -0
  50. package/src/components/card/CardSubtitle.tsx +47 -0
  51. package/src/components/card/CardText.tsx +47 -0
  52. package/src/components/card/CardTitle.tsx +47 -0
  53. package/src/components/card/index.ts +22 -0
  54. package/src/components/carousel/Carousel.tsx +742 -0
  55. package/src/components/carousel/CarouselControlButton.tsx +74 -0
  56. package/src/components/carousel/CarouselControlNext.tsx +22 -0
  57. package/src/components/carousel/CarouselControlPrev.tsx +22 -0
  58. package/src/components/carousel/CarouselIndicators.tsx +44 -0
  59. package/src/components/carousel/CarouselInner.tsx +56 -0
  60. package/src/components/carousel/CarouselItem.tsx +51 -0
  61. package/src/components/carousel/CarouselOverlay.tsx +51 -0
  62. package/src/components/carousel/CarouselPlayPause.tsx +61 -0
  63. package/src/components/carousel/carouselEngine.ts +170 -0
  64. package/src/components/carousel/context.ts +29 -0
  65. package/src/components/carousel/index.ts +21 -0
  66. package/src/components/checkbox/Checkbox.tsx +236 -0
  67. package/src/components/checkbox/CheckboxGroup.tsx +145 -0
  68. package/src/components/checkbox/context.ts +14 -0
  69. package/src/components/checkbox/index.ts +4 -0
  70. package/src/components/chip/Chip.tsx +183 -0
  71. package/src/components/chip/index.ts +2 -0
  72. package/src/components/chip-input/ChipInput.tsx +363 -0
  73. package/src/components/chip-input/ChipList.tsx +95 -0
  74. package/src/components/chip-input/index.ts +2 -0
  75. package/src/components/close-button/CloseButton.tsx +205 -0
  76. package/src/components/close-button/index.ts +2 -0
  77. package/src/components/collapse/Collapse.tsx +128 -0
  78. package/src/components/collapse/index.ts +2 -0
  79. package/src/components/color-input/ColorInput.tsx +106 -0
  80. package/src/components/color-input/index.ts +2 -0
  81. package/src/components/combobox/Combobox.tsx +320 -0
  82. package/src/components/combobox/ComboboxGroup.tsx +27 -0
  83. package/src/components/combobox/ComboboxItem.tsx +44 -0
  84. package/src/components/combobox/ComboboxListBox.tsx +98 -0
  85. package/src/components/combobox/index.ts +6 -0
  86. package/src/components/datepicker/CalendarToggleButton.tsx +58 -0
  87. package/src/components/datepicker/ClearButton.tsx +35 -0
  88. package/src/components/datepicker/DateField.tsx +54 -0
  89. package/src/components/datepicker/DatePicker.scss +51 -0
  90. package/src/components/datepicker/DatePicker.tsx +574 -0
  91. package/src/components/datepicker/DateRangePicker.scss +11 -0
  92. package/src/components/datepicker/DateRangePicker.tsx +343 -0
  93. package/src/components/datepicker/index.ts +4 -0
  94. package/src/components/datepicker/renderDatePickerShell.tsx +104 -0
  95. package/src/components/drawer/Drawer.tsx +211 -0
  96. package/src/components/drawer/DrawerBody.tsx +47 -0
  97. package/src/components/drawer/DrawerFooter.tsx +51 -0
  98. package/src/components/drawer/DrawerHeader.tsx +60 -0
  99. package/src/components/drawer/DrawerTitle.tsx +49 -0
  100. package/src/components/drawer/index.ts +10 -0
  101. package/src/components/file-input/FileInput.tsx +100 -0
  102. package/src/components/file-input/index.ts +2 -0
  103. package/src/components/flex/Flex.tsx +134 -0
  104. package/src/components/flex/index.ts +2 -0
  105. package/src/components/floating-input/FloatingInput.tsx +94 -0
  106. package/src/components/floating-input/index.ts +2 -0
  107. package/src/components/form/Form.tsx +26 -0
  108. package/src/components/form/FormFeedback.tsx +64 -0
  109. package/src/components/form/FormHelp.tsx +46 -0
  110. package/src/components/form/FormLabel.tsx +26 -0
  111. package/src/components/form/index.ts +8 -0
  112. package/src/components/form/renderFormCheck.tsx +86 -0
  113. package/src/components/form-field/FormField.tsx +84 -0
  114. package/src/components/form-field/index.ts +2 -0
  115. package/src/components/form-field/renderFormField.tsx +74 -0
  116. package/src/components/grid/Col.tsx +69 -0
  117. package/src/components/grid/Container.tsx +59 -0
  118. package/src/components/grid/Grid.tsx +86 -0
  119. package/src/components/grid/GridItem.tsx +123 -0
  120. package/src/components/grid/Row.tsx +71 -0
  121. package/src/components/grid/gap.ts +8 -0
  122. package/src/components/grid/index.ts +10 -0
  123. package/src/components/icon/Icon.tsx +74 -0
  124. package/src/components/icon/index.ts +2 -0
  125. package/src/components/input-adorn/InputAdorn.tsx +55 -0
  126. package/src/components/input-adorn/index.ts +2 -0
  127. package/src/components/input-group/InputGroup.tsx +50 -0
  128. package/src/components/input-group/InputGroupAddon.tsx +50 -0
  129. package/src/components/input-group/index.ts +4 -0
  130. package/src/components/link/Link.tsx +148 -0
  131. package/src/components/link/index.ts +2 -0
  132. package/src/components/list/List.tsx +193 -0
  133. package/src/components/list/ListItem.tsx +91 -0
  134. package/src/components/list/index.ts +4 -0
  135. package/src/components/menu/Menu.tsx +398 -0
  136. package/src/components/menu/MenuDivider.tsx +19 -0
  137. package/src/components/menu/MenuHeader.tsx +55 -0
  138. package/src/components/menu/MenuItem.tsx +85 -0
  139. package/src/components/menu/MenuItemDef.ts +83 -0
  140. package/src/components/menu/MenuList.tsx +142 -0
  141. package/src/components/menu/MenuSubmenu.tsx +284 -0
  142. package/src/components/menu/MenuSubmenuBack.tsx +39 -0
  143. package/src/components/menu/MenuText.tsx +47 -0
  144. package/src/components/menu/MenuToggle.tsx +148 -0
  145. package/src/components/menu/index.ts +19 -0
  146. package/src/components/menu/menuNavigation.ts +106 -0
  147. package/src/components/menu/submenuGroup.ts +43 -0
  148. package/src/components/modal/Modal.tsx +162 -0
  149. package/src/components/modal/ModalBody.tsx +47 -0
  150. package/src/components/modal/ModalFooter.tsx +51 -0
  151. package/src/components/modal/ModalHeader.tsx +60 -0
  152. package/src/components/modal/ModalTitle.tsx +49 -0
  153. package/src/components/modal/index.ts +10 -0
  154. package/src/components/nav/Nav.tsx +97 -0
  155. package/src/components/nav/NavItem.tsx +42 -0
  156. package/src/components/nav/NavLink.tsx +48 -0
  157. package/src/components/nav/NavTitle.tsx +22 -0
  158. package/src/components/nav/index.ts +7 -0
  159. package/src/components/navbar/Navbar.tsx +112 -0
  160. package/src/components/navbar/NavbarBrand.tsx +55 -0
  161. package/src/components/navbar/NavbarNav.tsx +47 -0
  162. package/src/components/navbar/NavbarText.tsx +47 -0
  163. package/src/components/navbar/NavbarToggler.tsx +34 -0
  164. package/src/components/navbar/index.ts +10 -0
  165. package/src/components/notification/Notification.scss +15 -0
  166. package/src/components/notification/Notification.tsx +187 -0
  167. package/src/components/notification/NotificationIcon.tsx +21 -0
  168. package/src/components/notification/NotificationStack.tsx +66 -0
  169. package/src/components/notification/NotificationText.tsx +47 -0
  170. package/src/components/notification/NotificationTitle.tsx +47 -0
  171. package/src/components/notification/context.ts +14 -0
  172. package/src/components/notification/index.ts +17 -0
  173. package/src/components/notification/notificationQueue.ts +48 -0
  174. package/src/components/otp-input/OtpBox.tsx +68 -0
  175. package/src/components/otp-input/OtpInput.tsx +341 -0
  176. package/src/components/otp-input/index.ts +2 -0
  177. package/src/components/pagination/Pagination.tsx +199 -0
  178. package/src/components/pagination/PaginationItem.tsx +133 -0
  179. package/src/components/pagination/index.ts +4 -0
  180. package/src/components/password-strength/PasswordStrength.tsx +155 -0
  181. package/src/components/password-strength/index.ts +2 -0
  182. package/src/components/password-strength/strengthScore.ts +79 -0
  183. package/src/components/placeholder/Placeholder.tsx +178 -0
  184. package/src/components/placeholder/index.ts +2 -0
  185. package/src/components/popover/Popover.tsx +243 -0
  186. package/src/components/popover/index.ts +2 -0
  187. package/src/components/progress/Progress.tsx +154 -0
  188. package/src/components/progress/ProgressBar.tsx +88 -0
  189. package/src/components/progress/index.ts +4 -0
  190. package/src/components/radio/Radio.tsx +88 -0
  191. package/src/components/radio/RadioGroup.tsx +142 -0
  192. package/src/components/radio/context.ts +14 -0
  193. package/src/components/radio/index.ts +4 -0
  194. package/src/components/range-input/RangeInput.tsx +109 -0
  195. package/src/components/range-input/index.ts +2 -0
  196. package/src/components/select/Select.tsx +277 -0
  197. package/src/components/select/index.ts +2 -0
  198. package/src/components/skeleton/Skeleton.tsx +89 -0
  199. package/src/components/skeleton/SkeletonLoader.tsx +91 -0
  200. package/src/components/skeleton/index.ts +4 -0
  201. package/src/components/spinner/Spinner.tsx +77 -0
  202. package/src/components/spinner/index.ts +2 -0
  203. package/src/components/stack/Stack.tsx +81 -0
  204. package/src/components/stack/index.ts +2 -0
  205. package/src/components/stepper/Stepper.tsx +172 -0
  206. package/src/components/stepper/StepperItem.tsx +66 -0
  207. package/src/components/stepper/index.ts +4 -0
  208. package/src/components/switch/Switch.tsx +246 -0
  209. package/src/components/switch/index.ts +2 -0
  210. package/src/components/table/Table.css +39 -0
  211. package/src/components/table/Table.tsx +390 -0
  212. package/src/components/table/TableBody.tsx +25 -0
  213. package/src/components/table/TableCell.tsx +27 -0
  214. package/src/components/table/TableColumn.tsx +31 -0
  215. package/src/components/table/TableHeader.tsx +26 -0
  216. package/src/components/table/TableRow.tsx +24 -0
  217. package/src/components/table/index.ts +12 -0
  218. package/src/components/tabs/Tab.tsx +36 -0
  219. package/src/components/tabs/TabList.tsx +76 -0
  220. package/src/components/tabs/TabPanel.tsx +68 -0
  221. package/src/components/tabs/Tabs.tsx +136 -0
  222. package/src/components/tabs/context.ts +24 -0
  223. package/src/components/tabs/index.ts +8 -0
  224. package/src/components/text-input/TextInput.tsx +188 -0
  225. package/src/components/text-input/index.ts +2 -0
  226. package/src/components/textarea/Textarea.tsx +145 -0
  227. package/src/components/textarea/index.ts +2 -0
  228. package/src/components/toast/Toast.tsx +219 -0
  229. package/src/components/toast/ToastBody.tsx +64 -0
  230. package/src/components/toast/ToastFooter.tsx +47 -0
  231. package/src/components/toast/ToastHeader.tsx +104 -0
  232. package/src/components/toast/ToastIcon.tsx +21 -0
  233. package/src/components/toast/Toaster.tsx +87 -0
  234. package/src/components/toast/context.ts +14 -0
  235. package/src/components/toast/index.ts +18 -0
  236. package/src/components/toast/toastQueue.ts +56 -0
  237. package/src/components/tooltip/Tooltip.tsx +155 -0
  238. package/src/components/tooltip/index.ts +2 -0
  239. package/src/global.d.ts +2 -0
  240. package/src/hooks/index.ts +57 -0
  241. package/src/hooks/useAutoDismiss.ts +88 -0
  242. package/src/hooks/useButtonSemantics.ts +33 -0
  243. package/src/hooks/useControllableState.ts +24 -0
  244. package/src/hooks/useDialogElement.ts +216 -0
  245. package/src/hooks/useDisabledAnchorGuard.ts +22 -0
  246. package/src/hooks/useDismissibleTransition.ts +126 -0
  247. package/src/hooks/useDrawer.ts +9 -0
  248. package/src/hooks/useFloatingOverlay.ts +115 -0
  249. package/src/hooks/useForkedRef.ts +50 -0
  250. package/src/hooks/useFormField.ts +89 -0
  251. package/src/hooks/useIsomorphicLayoutEffect.ts +9 -0
  252. package/src/hooks/useModal.ts +9 -0
  253. package/src/hooks/useNotification.ts +10 -0
  254. package/src/hooks/useOverlayPlacement.ts +93 -0
  255. package/src/hooks/usePagination.ts +85 -0
  256. package/src/hooks/useToast.ts +9 -0
  257. package/src/hooks/useToastRegionQueue.ts +27 -0
  258. package/src/index.ts +276 -0
  259. package/src/types.ts +133 -0
  260. package/src/utils/breakpoints.ts +43 -0
  261. package/src/utils/comboboxCollection.tsx +152 -0
  262. package/src/utils/dateRangePresets.ts +6 -0
  263. package/src/utils/dialogTransition.ts +39 -0
  264. package/src/utils/focusRedirect.ts +29 -0
  265. package/src/utils/isWholeUnitDisabled.ts +17 -0
  266. package/src/utils/mergeIsDateUnavailable.ts +15 -0
  267. package/src/utils/overlayPlacement.ts +93 -0
  268. package/src/utils/pointerInteraction.ts +21 -0
  269. package/src/utils/polymorphic.ts +36 -0
  270. package/src/utils/renderMenuItemContent.tsx +62 -0
  271. package/src/utils/setVisibleRangeStart.ts +64 -0
  272. package/src/utils/spacingClassName.ts +14 -0
  273. package/src/utils/suppressFocusRingGlobally.ts +69 -0
  274. package/src/utils/validationClassName.ts +8 -0
  275. package/src/utils/virtualFocusStyle.ts +16 -0
@@ -0,0 +1,48 @@
1
+ import React, { ElementType, ForwardRefRenderFunction, ReactElement } from 'react'
2
+ import classNames from 'classnames'
3
+
4
+ import { createPolymorphicComponent, PolymorphicRef } from '../../utils/polymorphic'
5
+ import { LinkProps, Link } from '../link/Link'
6
+
7
+ type NavLinkOwnProps = {
8
+ /**
9
+ * Toggle the active state for the component.
10
+ */
11
+ active?: boolean
12
+ /**
13
+ * A string of all className you want applied to the component.
14
+ */
15
+ className?: string
16
+ /**
17
+ * Toggle the disabled state for the component.
18
+ */
19
+ disabled?: boolean
20
+ }
21
+
22
+ export type NavLinkProps<C extends ElementType = 'a'> = LinkProps<C> & NavLinkOwnProps
23
+
24
+ type NavLinkComponent = (<C extends ElementType = 'a'>(
25
+ props: NavLinkProps<C> & { ref?: PolymorphicRef<C> }
26
+ ) => ReactElement | null) & { displayName?: string }
27
+
28
+ function NavLinkRender<C extends ElementType = 'a'>(
29
+ { children, className, ...rest }: NavLinkProps<C>,
30
+ ref: PolymorphicRef<C>
31
+ ) {
32
+ const _className = classNames('nav-link', className)
33
+
34
+ return (
35
+ <Link
36
+ className={_className}
37
+ {...(rest as Record<string, unknown>)}
38
+ ref={ref as PolymorphicRef<ElementType>}
39
+ >
40
+ {children}
41
+ </Link>
42
+ )
43
+ }
44
+
45
+ export const NavLink = createPolymorphicComponent<NavLinkComponent>(
46
+ NavLinkRender as ForwardRefRenderFunction<Element, NavLinkProps<ElementType>>,
47
+ 'NavLink'
48
+ )
@@ -0,0 +1,22 @@
1
+ import React, { forwardRef, HTMLAttributes } from 'react'
2
+ import classNames from 'classnames'
3
+
4
+ export interface NavTitleProps extends HTMLAttributes<HTMLLIElement> {
5
+ /**
6
+ * A string of all className you want applied to the component.
7
+ */
8
+ className?: string
9
+ }
10
+
11
+ export const NavTitle = forwardRef<HTMLLIElement, NavTitleProps>(
12
+ ({ children, className, ...rest }, ref) => {
13
+ const _className = classNames('nav-title', className)
14
+ return (
15
+ <li className={_className} {...rest} ref={ref}>
16
+ {children}
17
+ </li>
18
+ )
19
+ }
20
+ )
21
+
22
+ NavTitle.displayName = 'NavTitle'
@@ -0,0 +1,7 @@
1
+ export { Nav } from './Nav'
2
+ export type { NavProps, NavItemDef } from './Nav'
3
+ export { NavItem } from './NavItem'
4
+ export { NavLink } from './NavLink'
5
+ export type { NavLinkProps } from './NavLink'
6
+ export { NavTitle } from './NavTitle'
7
+ export type { NavTitleProps } from './NavTitle'
@@ -0,0 +1,112 @@
1
+ import React, { ElementType, ForwardRefRenderFunction, ReactElement } from 'react'
2
+ import classNames from 'classnames'
3
+
4
+ import {
5
+ createPolymorphicComponent,
6
+ PolymorphicComponentProps,
7
+ PolymorphicRef
8
+ } from '../../utils/polymorphic'
9
+ import { Breakpoint, ContextColor, ContextStyle } from '../../types'
10
+
11
+ type NavbarOwnProps<C extends ElementType> = {
12
+ /**
13
+ * A string of all className you want applied to the component.
14
+ */
15
+ className?: string
16
+ /**
17
+ * Sets the color of the component to one of Chassis context colors.
18
+ */
19
+ color?: ContextColor
20
+ /**
21
+ * Component used for the root node. Either a string to use a HTML element or a component.
22
+ */
23
+ component?: C
24
+ /**
25
+ * Defines optional container wrapping children elements.
26
+ */
27
+ container?: boolean | 'small' | 'medium' | 'large' | 'xlarge' | '2xlarge' | 'fluid'
28
+ /**
29
+ * Opts this navbar into the framework's dark or light theming, independent of the page's own
30
+ * theme.
31
+ */
32
+ 'data-cx-theme'?: 'dark' | 'light'
33
+ /**
34
+ * Renders inline at and above this breakpoint, as a drawer below it. `true` renders inline at
35
+ * every width; omit to keep the drawer at every width.
36
+ */
37
+ expand?: boolean | Breakpoint
38
+ /**
39
+ * Place component in non-static positions.
40
+ */
41
+ placement?: 'fixed-top' | 'fixed-bottom' | 'sticky-top' | 'sticky-bottom'
42
+ /**
43
+ * Blurs and saturates whatever sits behind the navbar — useful when it's positioned over a
44
+ * hero image, video, or scrollable content.
45
+ */
46
+ translucent?: boolean
47
+ /**
48
+ * Sets the context style of the component. `basic` (the default) renders with no extra class.
49
+ */
50
+ variant?: ContextStyle
51
+ }
52
+
53
+ export type NavbarProps<C extends ElementType = 'nav'> = PolymorphicComponentProps<
54
+ C,
55
+ NavbarOwnProps<C>
56
+ >
57
+
58
+ type NavbarComponent = (<C extends ElementType = 'nav'>(
59
+ props: NavbarProps<C> & { ref?: PolymorphicRef<C> }
60
+ ) => ReactElement | null) & { displayName?: string }
61
+
62
+ function NavbarRender<C extends ElementType = 'nav'>(
63
+ {
64
+ children,
65
+ className,
66
+ color,
67
+ component,
68
+ container,
69
+ expand,
70
+ placement,
71
+ translucent,
72
+ variant,
73
+ ...rest
74
+ }: NavbarProps<C>,
75
+ ref: PolymorphicRef<C>
76
+ ) {
77
+ const Component = component ?? 'nav'
78
+ const _className = classNames(
79
+ 'navbar',
80
+ color,
81
+ {
82
+ context: !!color,
83
+ solid: variant === 'solid',
84
+ smooth: variant === 'smooth',
85
+ outline: variant === 'outline',
86
+ translucent,
87
+ [typeof expand === 'boolean' ? 'navbar-expand' : `${expand}:navbar-expand`]: expand
88
+ },
89
+ placement,
90
+ className
91
+ )
92
+
93
+ let content
94
+ if (container) {
95
+ content = (
96
+ <div className={`container${container !== true ? '-' + container : ''}`}>{children}</div>
97
+ )
98
+ } else {
99
+ content = children
100
+ }
101
+
102
+ return (
103
+ <Component className={_className} {...rest} ref={ref}>
104
+ {content}
105
+ </Component>
106
+ )
107
+ }
108
+
109
+ export const Navbar = createPolymorphicComponent<NavbarComponent>(
110
+ NavbarRender as ForwardRefRenderFunction<Element, NavbarProps<ElementType>>,
111
+ 'Navbar'
112
+ )
@@ -0,0 +1,55 @@
1
+ import React, { ElementType, ForwardRefRenderFunction, ReactElement } from 'react'
2
+ import classNames from 'classnames'
3
+
4
+ import {
5
+ createPolymorphicComponent,
6
+ PolymorphicComponentProps,
7
+ PolymorphicRef
8
+ } from '../../utils/polymorphic'
9
+
10
+ type NavbarBrandOwnProps<C extends ElementType> = {
11
+ /**
12
+ * A string of all className you want applied to the component.
13
+ */
14
+ className?: string
15
+ /**
16
+ * Component used for the root node. Either a string to use a HTML element or a component.
17
+ * Defaults to `span`, or `a` when `href` is set.
18
+ */
19
+ component?: C
20
+ /**
21
+ * The href attribute specifies the URL of the page the link goes to. Defaults `component` to
22
+ * `a`.
23
+ */
24
+ href?: string
25
+ }
26
+
27
+ export type NavbarBrandProps<C extends ElementType = 'span'> = PolymorphicComponentProps<
28
+ C,
29
+ NavbarBrandOwnProps<C>
30
+ >
31
+
32
+ type NavbarBrandComponent = (<C extends ElementType = 'span'>(
33
+ props: NavbarBrandProps<C> & { ref?: PolymorphicRef<C> }
34
+ ) => ReactElement | null) & { displayName?: string }
35
+
36
+ function NavbarBrandRender<C extends ElementType = 'span'>(
37
+ { children, component, className, href, ...rest }: NavbarBrandProps<C>,
38
+ ref: PolymorphicRef<C>
39
+ ) {
40
+ // Only defaults to `a` when `component` wasn't explicitly passed — an explicit `component`
41
+ // (even alongside `href`) always wins.
42
+ const Component = (component ?? (href ? 'a' : 'span')) as ElementType
43
+ const _className = classNames('navbar-brand', className)
44
+
45
+ return (
46
+ <Component className={_className} href={href} {...rest} ref={ref}>
47
+ {children}
48
+ </Component>
49
+ )
50
+ }
51
+
52
+ export const NavbarBrand = createPolymorphicComponent<NavbarBrandComponent>(
53
+ NavbarBrandRender as ForwardRefRenderFunction<Element, NavbarBrandProps<ElementType>>,
54
+ 'NavbarBrand'
55
+ )
@@ -0,0 +1,47 @@
1
+ import React, { ElementType, ForwardRefRenderFunction, ReactElement } from 'react'
2
+ import classNames from 'classnames'
3
+
4
+ import {
5
+ createPolymorphicComponent,
6
+ PolymorphicComponentProps,
7
+ PolymorphicRef
8
+ } from '../../utils/polymorphic'
9
+
10
+ type NavbarNavOwnProps<C extends ElementType> = {
11
+ /**
12
+ * A string of all className you want applied to the component.
13
+ */
14
+ className?: string
15
+ /**
16
+ * Component used for the root node. Either a string to use a HTML element or a component.
17
+ */
18
+ component?: C
19
+ }
20
+
21
+ export type NavbarNavProps<C extends ElementType = 'ul'> = PolymorphicComponentProps<
22
+ C,
23
+ NavbarNavOwnProps<C>
24
+ >
25
+
26
+ type NavbarNavComponent = (<C extends ElementType = 'ul'>(
27
+ props: NavbarNavProps<C> & { ref?: PolymorphicRef<C> }
28
+ ) => ReactElement | null) & { displayName?: string }
29
+
30
+ function NavbarNavRender<C extends ElementType = 'ul'>(
31
+ { children, component, className, ...rest }: NavbarNavProps<C>,
32
+ ref: PolymorphicRef<C>
33
+ ) {
34
+ const Component = component ?? 'ul'
35
+ const _className = classNames('navbar-nav', className)
36
+
37
+ return (
38
+ <Component className={_className} {...rest} ref={ref}>
39
+ {children}
40
+ </Component>
41
+ )
42
+ }
43
+
44
+ export const NavbarNav = createPolymorphicComponent<NavbarNavComponent>(
45
+ NavbarNavRender as ForwardRefRenderFunction<Element, NavbarNavProps<ElementType>>,
46
+ 'NavbarNav'
47
+ )
@@ -0,0 +1,47 @@
1
+ import React, { ElementType, ForwardRefRenderFunction, ReactElement } from 'react'
2
+ import classNames from 'classnames'
3
+
4
+ import {
5
+ createPolymorphicComponent,
6
+ PolymorphicComponentProps,
7
+ PolymorphicRef
8
+ } from '../../utils/polymorphic'
9
+
10
+ type NavbarTextOwnProps<C extends ElementType> = {
11
+ /**
12
+ * A string of all className you want applied to the base component.
13
+ */
14
+ className?: string
15
+ /**
16
+ * Component used for the root node. Either a string to use a HTML element or a component.
17
+ */
18
+ component?: C
19
+ }
20
+
21
+ export type NavbarTextProps<C extends ElementType = 'span'> = PolymorphicComponentProps<
22
+ C,
23
+ NavbarTextOwnProps<C>
24
+ >
25
+
26
+ type NavbarTextComponent = (<C extends ElementType = 'span'>(
27
+ props: NavbarTextProps<C> & { ref?: PolymorphicRef<C> }
28
+ ) => ReactElement | null) & { displayName?: string }
29
+
30
+ function NavbarTextRender<C extends ElementType = 'span'>(
31
+ { children, className, component, ...rest }: NavbarTextProps<C>,
32
+ ref: PolymorphicRef<C>
33
+ ) {
34
+ const Component = component ?? 'span'
35
+ const _className = classNames('navbar-text', className)
36
+
37
+ return (
38
+ <Component className={_className} {...rest} ref={ref}>
39
+ {children}
40
+ </Component>
41
+ )
42
+ }
43
+
44
+ export const NavbarText = createPolymorphicComponent<NavbarTextComponent>(
45
+ NavbarTextRender as ForwardRefRenderFunction<Element, NavbarTextProps<ElementType>>,
46
+ 'NavbarText'
47
+ )
@@ -0,0 +1,34 @@
1
+ import React, { forwardRef, HTMLAttributes } from 'react'
2
+ import classNames from 'classnames'
3
+
4
+ import { Icon } from '../icon/Icon'
5
+
6
+ export interface NavbarTogglerProps extends HTMLAttributes<HTMLButtonElement> {
7
+ /**
8
+ * A string of all className you want applied to the base component.
9
+ */
10
+ className?: string
11
+ /**
12
+ * The accessible label announced by assistive technology when no children are provided.
13
+ */
14
+ label?: string
15
+ }
16
+
17
+ export const NavbarToggler = forwardRef<HTMLButtonElement, NavbarTogglerProps>(
18
+ ({ children, className, label = 'Toggle navigation', ...rest }, ref) => {
19
+ const _className = classNames('button icon-only navbar-toggler', className)
20
+
21
+ return (
22
+ <button type="button" className={_className} {...rest} ref={ref}>
23
+ {children ?? (
24
+ <>
25
+ <Icon name="bars-outline" className="navbar-toggler-icon" />
26
+ <span className="visually-hidden">{label}</span>
27
+ </>
28
+ )}
29
+ </button>
30
+ )
31
+ }
32
+ )
33
+
34
+ NavbarToggler.displayName = 'NavbarToggler'
@@ -0,0 +1,10 @@
1
+ export { Navbar } from './Navbar'
2
+ export type { NavbarProps } from './Navbar'
3
+ export { NavbarBrand } from './NavbarBrand'
4
+ export type { NavbarBrandProps } from './NavbarBrand'
5
+ export { NavbarNav } from './NavbarNav'
6
+ export type { NavbarNavProps } from './NavbarNav'
7
+ export { NavbarText } from './NavbarText'
8
+ export type { NavbarTextProps } from './NavbarText'
9
+ export { NavbarToggler } from './NavbarToggler'
10
+ export type { NavbarTogglerProps } from './NavbarToggler'
@@ -0,0 +1,15 @@
1
+ /*
2
+ * `Notification` applies chassis-css's generic `.fade` utility (`_transitions.scss`) for its base
3
+ * opacity transition and `:not(.show) { opacity: 0 }` resting state — no chassis-css edit needed
4
+ * for that part. `../chassis-css/scss/_notification.scss` has no `.showing` equivalent of its own
5
+ * (unlike `_toast.scss`'s `.toast.showing { opacity: 0 }`), since a persistent banner has no
6
+ * built-in notion of a fade transition. This file adds just that one Toast-parity rule, so the
7
+ * entering/exiting halfway state (both `show` and `showing` present, per `Notification.tsx`'s
8
+ * `getTransitionClass`) renders at opacity 0 instead of snapping straight to `.fade`'s `1`.
9
+ */
10
+
11
+ @layer components {
12
+ .notification.showing {
13
+ opacity: 0;
14
+ }
15
+ }
@@ -0,0 +1,187 @@
1
+ import React, { ElementType, forwardRef, HTMLAttributes, ReactNode } from 'react'
2
+ import classNames from 'classnames'
3
+ import { mergeProps } from 'react-aria'
4
+ import { Transition } from 'react-transition-group'
5
+
6
+ import { ContextColor } from '../../types'
7
+ import { CloseButton } from '../close-button/CloseButton'
8
+ import { useAutoDismiss, useDismissibleTransition } from '../../hooks'
9
+ import { NotificationContext } from './context'
10
+ import { NotificationIcon } from './NotificationIcon'
11
+ import { NotificationText } from './NotificationText'
12
+ import { NotificationTitle } from './NotificationTitle'
13
+ import './Notification.scss'
14
+
15
+ export interface NotificationProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
16
+ /**
17
+ * Optional trailing content — e.g. a row of `Button`s — rendered after `text`/`children`.
18
+ */
19
+ actions?: ReactNode
20
+ /**
21
+ * Automatically dismiss the notification after `delay`. The timer pauses while the pointer
22
+ * or focus is on the notification, and only starts once the notification is visible.
23
+ * Defaults to `false` — unlike `Toast`, notifications are persistent banners by default.
24
+ */
25
+ autohide?: boolean
26
+ /**
27
+ * A string of all className you want applied to the component.
28
+ */
29
+ className?: string
30
+ /**
31
+ * Overrides the dismiss button's accessible name (defaults to `'Close'`). Set this for
32
+ * non-English UIs.
33
+ */
34
+ closeLabel?: string
35
+ /**
36
+ * Sets the color of the component to one of Chassis context colors.
37
+ */
38
+ color?: ContextColor
39
+ /**
40
+ * Delay in ms before an `autohide` notification dismisses itself.
41
+ */
42
+ delay?: number
43
+ /**
44
+ * Optionally add a close button to the notification and allow it to self dismiss.
45
+ */
46
+ dismissible?: boolean
47
+ /**
48
+ * Leading icon. A string is rendered as `<NotificationIcon name={icon} />`; pass any other
49
+ * node for a fully custom icon. Automatically top-aligns with `title` when both are set —
50
+ * a custom icon node is responsible for its own alignment.
51
+ */
52
+ icon?: string | ReactNode
53
+ /**
54
+ * Applies the solid context style to the notification.
55
+ */
56
+ solid?: boolean
57
+ /**
58
+ * Message body, rendered via a single `<NotificationText>`. For multi-block content, compose
59
+ * `children` manually instead — `text` wraps everything in one element.
60
+ */
61
+ text?: ReactNode
62
+ /**
63
+ * Heading, rendered via `<NotificationTitle>`.
64
+ */
65
+ title?: ReactNode
66
+ /**
67
+ * Element or component used for the `title` heading. Passed through to `NotificationTitle`'s
68
+ * own `component` prop. Defaults to `'h4'`.
69
+ */
70
+ titleComponent?: ElementType
71
+ /**
72
+ * Callback fired when the component requests to be closed.
73
+ */
74
+ onClose?: () => void
75
+ /**
76
+ * Callback fired when the component requests to be shown.
77
+ */
78
+ onShow?: () => void
79
+ /**
80
+ * ARIA live-region role. Use `status` (the default) for confirmation, progress, and
81
+ * informational messages, which announce politely. Use `alert` for messages that need
82
+ * immediate attention — validation errors, failed operations — which interrupt speech.
83
+ */
84
+ role?: 'status' | 'alert'
85
+ /**
86
+ * Toggle the visibility of component.
87
+ */
88
+ visible?: boolean
89
+ }
90
+
91
+ export const Notification = forwardRef<HTMLDivElement, NotificationProps>(
92
+ (
93
+ {
94
+ actions,
95
+ autohide = false,
96
+ children,
97
+ className,
98
+ closeLabel = 'Close',
99
+ color = 'primary',
100
+ delay = 5000,
101
+ dismissible,
102
+ icon,
103
+ solid,
104
+ text,
105
+ title,
106
+ titleComponent = 'h4',
107
+ role = 'status',
108
+ visible = true,
109
+ onClose,
110
+ onShow,
111
+ ...rest
112
+ },
113
+ ref
114
+ ) => {
115
+ const {
116
+ close,
117
+ entered,
118
+ forkedRef,
119
+ getTransitionClass,
120
+ textId,
121
+ titleId,
122
+ transitionProps,
123
+ visible: _visible
124
+ } = useDismissibleTransition({ onClose, onShow, ref, visible })
125
+
126
+ // Gated on `entered`, not just `_visible` (see `Toast`'s identical comment) — the entrance
127
+ // transition finishing is what `autohide`'s JSDoc means by "the timer starts once the
128
+ // notification is visible".
129
+ const autoDismissProps = useAutoDismiss({
130
+ enabled: autohide,
131
+ delay,
132
+ visible: _visible && entered,
133
+ onHide: close
134
+ })
135
+
136
+ const _className = classNames(
137
+ 'notification',
138
+ 'fade',
139
+ color,
140
+ {
141
+ solid
142
+ },
143
+ className
144
+ )
145
+
146
+ return (
147
+ <Transition {...transitionProps} mountOnEnter timeout={150}>
148
+ {(state) => {
149
+ const transitionClass = getTransitionClass(state)
150
+ return (
151
+ <NotificationContext.Provider value={{ visible: _visible, close }}>
152
+ <div
153
+ className={classNames(_className, transitionClass)}
154
+ role={role}
155
+ aria-labelledby={title ? titleId : undefined}
156
+ aria-describedby={title && text ? textId : undefined}
157
+ {...mergeProps(rest, autoDismissProps)}
158
+ ref={forkedRef}
159
+ >
160
+ {icon &&
161
+ (typeof icon === 'string' ? (
162
+ <NotificationIcon
163
+ name={icon}
164
+ className={title ? 'align-self-start' : undefined}
165
+ />
166
+ ) : (
167
+ icon
168
+ ))}
169
+ {title && (
170
+ <NotificationTitle id={titleId} component={titleComponent}>
171
+ {title}
172
+ </NotificationTitle>
173
+ )}
174
+ {text && <NotificationText id={textId}>{text}</NotificationText>}
175
+ {children}
176
+ {actions}
177
+ {dismissible && <CloseButton label={closeLabel} onClick={close} />}
178
+ </div>
179
+ </NotificationContext.Provider>
180
+ )
181
+ }}
182
+ </Transition>
183
+ )
184
+ }
185
+ )
186
+
187
+ Notification.displayName = 'Notification'
@@ -0,0 +1,21 @@
1
+ import React, { forwardRef } from 'react'
2
+ import classNames from 'classnames'
3
+
4
+ import { Icon, IconProps } from '../icon/Icon'
5
+
6
+ export type NotificationIconProps = IconProps & {
7
+ /**
8
+ * A string of all className you want applied to the base component.
9
+ */
10
+ className?: string
11
+ }
12
+
13
+ export const NotificationIcon = forwardRef<HTMLSpanElement | SVGSVGElement, NotificationIconProps>(
14
+ ({ className, ...rest }, ref) => {
15
+ const _className = classNames('notification-icon', className)
16
+
17
+ return <Icon className={_className} {...rest} ref={ref} />
18
+ }
19
+ )
20
+
21
+ NotificationIcon.displayName = 'NotificationIcon'
@@ -0,0 +1,66 @@
1
+ import React, { forwardRef, HTMLAttributes } from 'react'
2
+
3
+ import { useToastRegionQueue } from '../../hooks'
4
+ import { Stack } from '../stack'
5
+ import { Notification } from './Notification'
6
+ import { notificationQueue } from './notificationQueue'
7
+
8
+ export interface NotificationStackProps extends HTMLAttributes<HTMLDivElement> {
9
+ /**
10
+ * A string of all className you want applied to the base component.
11
+ */
12
+ className?: string
13
+ /**
14
+ * Queued notifications show newest-first by default — the typical toast pattern. Set
15
+ * `reverse` for a chronological transcript instead, oldest-first.
16
+ */
17
+ reverse?: boolean
18
+ }
19
+
20
+ // Renders the shared `notificationQueue` (see `notificationQueue.ts` — `addNotification()` is
21
+ // how notifications get added to it from anywhere in the app) plus any statically-passed
22
+ // `children`, e.g. a permanently pinned notification alongside dynamic ones — the same static
23
+ // children still render with nothing queued, so this doubles as a plain grouping/spacing
24
+ // wrapper for hand-placed notifications. Unlike `Toaster`, this always renders in normal
25
+ // document flow rather than a fixed/portaled overlay — Chassis notifications are in-page
26
+ // banners, not floating toasts.
27
+ export const NotificationStack = forwardRef<HTMLDivElement, NotificationStackProps>(
28
+ ({ children, className, reverse, ...rest }, ref) => {
29
+ const { forkedRef, regionProps, state } = useToastRegionQueue(notificationQueue, ref)
30
+
31
+ if (state.visibleToasts.length === 0 && !children) {
32
+ return null
33
+ }
34
+
35
+ // The queue is already newest-first (each add unshifts); `reverse` opts into chronological
36
+ // order instead.
37
+ const queued = reverse ? [...state.visibleToasts].reverse() : state.visibleToasts
38
+
39
+ return (
40
+ <Stack
41
+ direction="vertical"
42
+ gap="small"
43
+ className={className}
44
+ {...regionProps}
45
+ {...rest}
46
+ ref={forkedRef}
47
+ >
48
+ {children}
49
+ {queued.map((item) => {
50
+ const { children: notificationChildren, ...notificationProps } = item.content
51
+ return (
52
+ <Notification
53
+ key={item.key}
54
+ {...notificationProps}
55
+ onClose={() => state.close(item.key)}
56
+ >
57
+ {notificationChildren}
58
+ </Notification>
59
+ )
60
+ })}
61
+ </Stack>
62
+ )
63
+ }
64
+ )
65
+
66
+ NotificationStack.displayName = 'NotificationStack'