@infonomic/uikit 5.43.1 → 6.0.0

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 (210) hide show
  1. package/README.md +1 -1
  2. package/dist/components/accordion/accordion.d.ts +9 -9
  3. package/dist/components/accordion/accordion.d.ts.map +1 -1
  4. package/dist/components/accordion/accordion.js +4 -4
  5. package/dist/components/accordion/accordion.module.css +6 -5
  6. package/dist/components/accordion/accordion_module.css +4 -4
  7. package/dist/components/avatar/avatar.js +2 -2
  8. package/dist/components/badge/badge.d.ts +5 -13
  9. package/dist/components/badge/badge.d.ts.map +1 -1
  10. package/dist/components/badge/badge.js +12 -9
  11. package/dist/components/button/button-group.d.ts +9 -7
  12. package/dist/components/button/button-group.d.ts.map +1 -1
  13. package/dist/components/button/button-group.js +26 -36
  14. package/dist/components/button/button.d.ts +6 -13
  15. package/dist/components/button/button.d.ts.map +1 -1
  16. package/dist/components/button/button.js +19 -18
  17. package/dist/components/button/button.module.css +32 -54
  18. package/dist/components/button/button_module.css +7 -10
  19. package/dist/components/button/combo-button.d.ts +1 -1
  20. package/dist/components/button/combo-button.d.ts.map +1 -1
  21. package/dist/components/button/combo-button.js +13 -9
  22. package/dist/components/button/combo-button.module.css +16 -7
  23. package/dist/components/button/combo-button_module.css +22 -4
  24. package/dist/components/button/icon-button.d.ts +2 -3
  25. package/dist/components/button/icon-button.d.ts.map +1 -1
  26. package/dist/components/card/card.d.ts +5 -12
  27. package/dist/components/card/card.d.ts.map +1 -1
  28. package/dist/components/card/card.js +13 -9
  29. package/dist/components/chips/chip.d.ts +5 -11
  30. package/dist/components/chips/chip.d.ts.map +1 -1
  31. package/dist/components/chips/chip.js +36 -28
  32. package/dist/components/chips/chip.module.css +22 -36
  33. package/dist/components/chips/chip_module.css +3 -6
  34. package/dist/components/dropdown/dropdown.d.ts +28 -14
  35. package/dist/components/dropdown/dropdown.d.ts.map +1 -1
  36. package/dist/components/dropdown/dropdown.js +34 -20
  37. package/dist/components/forms/calendar.d.ts +1 -1
  38. package/dist/components/forms/calendar.d.ts.map +1 -1
  39. package/dist/components/forms/calendar.js +38 -29
  40. package/dist/components/forms/checkbox.astro +13 -8
  41. package/dist/components/forms/checkbox.d.ts +6 -2
  42. package/dist/components/forms/checkbox.d.ts.map +1 -1
  43. package/dist/components/forms/checkbox.js +11 -7
  44. package/dist/components/forms/checkbox.module.css +20 -20
  45. package/dist/components/forms/checkbox_module.css +13 -10
  46. package/dist/components/forms/input.module.css +10 -11
  47. package/dist/components/forms/input_module.css +3 -5
  48. package/dist/components/forms/radio-group.d.ts +6 -5
  49. package/dist/components/forms/radio-group.d.ts.map +1 -1
  50. package/dist/components/forms/radio-group.js +9 -4
  51. package/dist/components/forms/radio-group.module.css +13 -22
  52. package/dist/components/forms/radio-group_module.css +6 -24
  53. package/dist/components/forms/select.d.ts +4 -5
  54. package/dist/components/forms/select.d.ts.map +1 -1
  55. package/dist/components/forms/select.js +27 -29
  56. package/dist/components/forms/select.module.css +22 -22
  57. package/dist/components/forms/select.module.js +15 -15
  58. package/dist/components/forms/select_module.css +15 -15
  59. package/dist/components/hamburger/hamburger.astro +23 -15
  60. package/dist/components/hamburger/hamburger.d.ts +8 -6
  61. package/dist/components/hamburger/hamburger.d.ts.map +1 -1
  62. package/dist/components/hamburger/hamburger.js +18 -22
  63. package/dist/components/hamburger/hamburger.module.css +142 -0
  64. package/dist/components/hamburger/hamburger.module.js +10 -0
  65. package/dist/components/hamburger/hamburger_module.css +169 -0
  66. package/dist/components/notifications/@types/toast.d.ts +9 -7
  67. package/dist/components/notifications/@types/toast.d.ts.map +1 -1
  68. package/dist/components/notifications/toast.d.ts +12 -16
  69. package/dist/components/notifications/toast.d.ts.map +1 -1
  70. package/dist/components/notifications/toast.js +73 -57
  71. package/dist/components/notifications/toast.module.css +151 -177
  72. package/dist/components/notifications/toast.module.js +8 -12
  73. package/dist/components/notifications/toast_module.css +114 -159
  74. package/dist/components/pager/first-button.d.ts +2 -2
  75. package/dist/components/pager/first-button.d.ts.map +1 -1
  76. package/dist/components/pager/first-button.js +23 -16
  77. package/dist/components/pager/last-button.d.ts +2 -2
  78. package/dist/components/pager/last-button.d.ts.map +1 -1
  79. package/dist/components/pager/last-button.js +23 -16
  80. package/dist/components/pager/next-button.d.ts +2 -2
  81. package/dist/components/pager/next-button.d.ts.map +1 -1
  82. package/dist/components/pager/next-button.js +27 -20
  83. package/dist/components/pager/number-button.d.ts +2 -2
  84. package/dist/components/pager/number-button.d.ts.map +1 -1
  85. package/dist/components/pager/number-button.js +28 -23
  86. package/dist/components/pager/pagination.d.ts +8 -13
  87. package/dist/components/pager/pagination.d.ts.map +1 -1
  88. package/dist/components/pager/previous-button.d.ts +2 -2
  89. package/dist/components/pager/previous-button.d.ts.map +1 -1
  90. package/dist/components/pager/previous-button.js +25 -18
  91. package/dist/components/scroll-area/scroll-area.d.ts +2 -2
  92. package/dist/components/scroll-area/scroll-area.d.ts.map +1 -1
  93. package/dist/components/scroll-area/scroll-area.js +4 -2
  94. package/dist/components/tabs/tabs.d.ts +13 -13
  95. package/dist/components/tabs/tabs.d.ts.map +1 -1
  96. package/dist/components/tabs/tabs.js +8 -8
  97. package/dist/components/tabs/tabs.module.css +8 -17
  98. package/dist/components/tabs/tabs_module.css +2 -6
  99. package/dist/components/tooltip/tooltip.d.ts +6 -8
  100. package/dist/components/tooltip/tooltip.d.ts.map +1 -1
  101. package/dist/components/tooltip/tooltip.js +49 -20
  102. package/dist/components/tooltip/tooltip.module.css +43 -10
  103. package/dist/components/tooltip/tooltip.module.js +7 -1
  104. package/dist/components/tooltip/tooltip_module.css +36 -4
  105. package/dist/hooks/use-focus-trap/index.d.ts +2 -0
  106. package/dist/hooks/use-focus-trap/index.d.ts.map +1 -0
  107. package/dist/hooks/use-focus-trap/index.js +1 -0
  108. package/dist/hooks/use-focus-trap/scope-tab.d.ts +11 -0
  109. package/dist/hooks/use-focus-trap/scope-tab.d.ts.map +1 -0
  110. package/dist/hooks/use-focus-trap/scope-tab.js +19 -0
  111. package/dist/hooks/use-focus-trap/tabbable.d.ts +14 -0
  112. package/dist/hooks/use-focus-trap/tabbable.d.ts.map +1 -0
  113. package/dist/hooks/use-focus-trap/tabbable.js +36 -0
  114. package/dist/hooks/use-focus-trap/use-focus-trap.d.ts +11 -0
  115. package/dist/hooks/use-focus-trap/use-focus-trap.d.ts.map +1 -0
  116. package/dist/hooks/use-focus-trap/use-focus-trap.js +45 -0
  117. package/dist/icons/chevron-up-icon.d.ts +7 -0
  118. package/dist/icons/chevron-up-icon.d.ts.map +1 -0
  119. package/dist/icons/chevron-up-icon.js +27 -0
  120. package/dist/lib/ripple.d.ts +25 -0
  121. package/dist/lib/ripple.d.ts.map +1 -0
  122. package/dist/lib/ripple.js +53 -0
  123. package/dist/loaders/@types/index.d.ts.map +1 -0
  124. package/dist/loaders/ellipses.d.ts +1 -1
  125. package/dist/loaders/ellipses.d.ts.map +1 -1
  126. package/dist/loaders/ring.d.ts +1 -1
  127. package/dist/loaders/ring.d.ts.map +1 -1
  128. package/dist/loaders/spinner.d.ts +1 -1
  129. package/dist/loaders/spinner.d.ts.map +1 -1
  130. package/dist/styles/components-vanilla.css +1 -1
  131. package/dist/styles/styles.css +1 -1
  132. package/dist/widgets/datepicker/datepicker.d.ts +1 -1
  133. package/dist/widgets/datepicker/datepicker.d.ts.map +1 -1
  134. package/dist/widgets/datepicker/datepicker.js +118 -116
  135. package/dist/widgets/datepicker/datepicker.module.css +6 -5
  136. package/dist/widgets/datepicker/datepicker_module.css +4 -4
  137. package/dist/widgets/drawer/drawer-wrapper.d.ts.map +1 -1
  138. package/dist/widgets/drawer/drawer-wrapper.js +1 -1
  139. package/dist/widgets/modal/modal-wrapper.d.ts.map +1 -1
  140. package/dist/widgets/modal/modal-wrapper.js +1 -1
  141. package/package.json +21 -29
  142. package/src/astro.d.ts +2 -2
  143. package/src/components/accordion/accordion.module.css +6 -5
  144. package/src/components/accordion/accordion.stories.tsx +10 -13
  145. package/src/components/accordion/accordion.tsx +13 -13
  146. package/src/components/avatar/avatar.tsx +2 -2
  147. package/src/components/badge/badge.tsx +20 -29
  148. package/src/components/button/button-group.tsx +60 -44
  149. package/src/components/button/button.module.css +32 -54
  150. package/src/components/button/button.tsx +35 -47
  151. package/src/components/button/combo-button.module.css +16 -7
  152. package/src/components/button/combo-button.tsx +17 -9
  153. package/src/components/button/icon-button.tsx +3 -5
  154. package/src/components/card/card.tsx +20 -32
  155. package/src/components/chips/chip.module.css +22 -36
  156. package/src/components/chips/chip.stories.tsx +2 -2
  157. package/src/components/chips/chip.tsx +59 -57
  158. package/src/components/dropdown/dropdown.stories.tsx +2 -4
  159. package/src/components/dropdown/dropdown.tsx +86 -40
  160. package/src/components/forms/calendar.tsx +43 -33
  161. package/src/components/forms/checkbox-group.tsx +1 -1
  162. package/src/components/forms/checkbox.astro +13 -8
  163. package/src/components/forms/checkbox.module.css +20 -20
  164. package/src/components/forms/checkbox.tsx +11 -6
  165. package/src/components/forms/input.module.css +10 -11
  166. package/src/components/forms/radio-group.module.css +13 -22
  167. package/src/components/forms/radio-group.tsx +13 -11
  168. package/src/components/forms/select.module.css +22 -22
  169. package/src/components/forms/select.tsx +36 -33
  170. package/src/components/hamburger/hamburger.astro +23 -15
  171. package/src/components/hamburger/hamburger.module.css +142 -0
  172. package/src/components/hamburger/hamburger.stories.tsx +35 -0
  173. package/src/components/hamburger/hamburger.tsx +37 -29
  174. package/src/components/notifications/@types/toast.ts +9 -7
  175. package/src/components/notifications/toast.module.css +151 -177
  176. package/src/components/notifications/toast.stories.tsx +21 -23
  177. package/src/components/notifications/toast.tsx +90 -86
  178. package/src/components/pager/first-button.tsx +24 -26
  179. package/src/components/pager/last-button.tsx +24 -25
  180. package/src/components/pager/next-button.tsx +24 -23
  181. package/src/components/pager/number-button.tsx +37 -36
  182. package/src/components/pager/pagination.tsx +4 -11
  183. package/src/components/pager/previous-button.tsx +24 -24
  184. package/src/components/scroll-area/scroll-area.tsx +3 -3
  185. package/src/components/tabs/tabs.module.css +8 -17
  186. package/src/components/tabs/tabs.stories.tsx +5 -5
  187. package/src/components/tabs/tabs.tsx +17 -16
  188. package/src/components/tooltip/tooltip.module.css +43 -10
  189. package/src/components/tooltip/tooltip.stories.tsx +4 -4
  190. package/src/components/tooltip/tooltip.tsx +56 -28
  191. package/src/hooks/use-focus-trap/index.ts +1 -0
  192. package/src/hooks/use-focus-trap/scope-tab.ts +48 -0
  193. package/src/hooks/use-focus-trap/tabbable.ts +72 -0
  194. package/src/hooks/use-focus-trap/use-focus-trap.ts +83 -0
  195. package/src/icons/chevron-up-icon.tsx +37 -0
  196. package/src/lib/ripple.ts +95 -0
  197. package/src/loaders/ellipses.tsx +1 -1
  198. package/src/loaders/ring.tsx +1 -1
  199. package/src/loaders/spinner.tsx +1 -1
  200. package/src/styles/components/hamburger.css +8 -6
  201. package/src/styles/functional/colors.css +97 -202
  202. package/src/styles/theme/theme.css +1 -1
  203. package/src/widgets/datepicker/datepicker.module.css +6 -5
  204. package/src/widgets/datepicker/datepicker.tsx +137 -135
  205. package/src/widgets/drawer/drawer-wrapper.tsx +1 -1
  206. package/src/widgets/modal/modal-wrapper.tsx +1 -1
  207. package/dist/loaders/types/index.d.ts.map +0 -1
  208. /package/dist/loaders/{types → @types}/index.d.ts +0 -0
  209. /package/dist/loaders/{types → @types}/index.js +0 -0
  210. /package/src/loaders/{types → @types}/index.ts +0 -0
@@ -1,17 +1,104 @@
1
1
  @layer infonomic-base,
2
- infonomic-functional,
3
- infonomic-utilities,
4
- infonomic-theme,
5
- infonomic-typography,
6
- infonomic-components;
2
+ infonomic-functional,
3
+ infonomic-utilities,
4
+ infonomic-theme,
5
+ infonomic-typography,
6
+ infonomic-components;
7
7
 
8
8
  @layer infonomic-components {
9
- /* Positions are relative to the toast viewport which is set
10
- globally in components/toast.css */
9
+ /* ============================================
10
+ Viewport fixed-position container for toasts.
11
+ Position classes are applied here.
12
+ ============================================ */
13
+
14
+ .viewport,
15
+ :global(.infonomic-toast-viewport) {
16
+ --viewport-padding: 16px;
17
+ position: fixed;
18
+ display: flex;
19
+ flex-direction: column;
20
+ gap: 8px;
21
+ z-index: var(--z-index-toast);
22
+ outline: none;
23
+ }
24
+
25
+ /* Mobile: full-width at all positions */
26
+
27
+ .top-left,
28
+ :global(.infonomic-toast-top-left) {
29
+ top: 88px;
30
+ right: var(--viewport-padding);
31
+ left: var(--viewport-padding);
32
+ }
33
+
34
+ .top-right,
35
+ :global(.infonomic-toast-top-right) {
36
+ top: 88px;
37
+ right: var(--viewport-padding);
38
+ left: var(--viewport-padding);
39
+ }
40
+
41
+ .bottom-left,
42
+ :global(.infonomic-toast-bottom-left) {
43
+ bottom: var(--viewport-padding);
44
+ right: var(--viewport-padding);
45
+ left: var(--viewport-padding);
46
+ }
47
+
48
+ .bottom-right,
49
+ :global(.infonomic-toast-bottom-right) {
50
+ bottom: var(--viewport-padding);
51
+ right: var(--viewport-padding);
52
+ left: var(--viewport-padding);
53
+ }
54
+
55
+ @media (min-width: 48rem) {
56
+
57
+ .bottom-right,
58
+ :global(.infonomic-toast-bottom-right) {
59
+ bottom: var(--viewport-padding);
60
+ right: var(--viewport-padding);
61
+ left: auto;
62
+ width: 100%;
63
+ max-width: 390px;
64
+ }
65
+
66
+ .bottom-left,
67
+ :global(.infonomic-toast-bottom-left) {
68
+ bottom: var(--viewport-padding);
69
+ left: var(--viewport-padding);
70
+ right: auto;
71
+ width: 100%;
72
+ max-width: 390px;
73
+ }
74
+
75
+ .top-left,
76
+ :global(.infonomic-toast-top-left) {
77
+ top: 88px;
78
+ left: var(--viewport-padding);
79
+ right: auto;
80
+ bottom: auto;
81
+ width: 100%;
82
+ max-width: 390px;
83
+ }
84
+
85
+ .top-right,
86
+ :global(.infonomic-toast-top-right) {
87
+ top: 88px;
88
+ right: var(--viewport-padding);
89
+ bottom: auto;
90
+ left: auto;
91
+ width: 100%;
92
+ max-width: 390px;
93
+ }
94
+ }
95
+
96
+ /* ============================================
97
+ Root — individual toast wrapper
98
+ ============================================ */
11
99
 
12
100
  .root,
13
101
  :global(.infonomic-toast-root) {
14
- position: fixed;
15
102
  display: flex;
16
103
  flex-direction: column;
17
104
  gap: var(--gap-1);
@@ -23,51 +110,83 @@
23
110
  border-style: var(--border-style-solid);
24
111
  border-radius: var(--border-radius-md);
25
112
  box-shadow: var(--shadow-sm);
113
+ transform: translateX(var(--toast-swipe-movement-x, 0)) translateY(var(--toast-swipe-movement-y, 0));
114
+ transition:
115
+ transform 200ms ease-out,
116
+ opacity 150ms ease-in;
26
117
  }
27
118
 
28
119
  :global(.dark),
29
120
  :global([data-theme="dark"]) {
121
+
30
122
  .root,
31
123
  :global(.infonomic-toast-root) {
32
124
  background: var(--canvas-800);
33
125
  }
34
126
  }
35
127
 
36
- .root[data-state="open"],
37
- :global(.infonomic-toast-root[data-state="open"]) {
38
- animation: slideInFromBottom 150ms cubic-bezier(0.16, 1, 0.3, 1);
128
+ /* Entry animation */
129
+ .root[data-starting-style],
130
+ :global(.infonomic-toast-root[data-starting-style]) {
131
+ opacity: 0;
132
+ transform: translateY(calc(100% + var(--viewport-padding)));
133
+ }
134
+
135
+ @media (min-width: 48rem) {
136
+
137
+ .viewport.top-right .root[data-starting-style],
138
+ .viewport.bottom-right .root[data-starting-style],
139
+ :global(.infonomic-toast-viewport.top-right .infonomic-toast-root[data-starting-style]),
140
+ :global(.infonomic-toast-viewport.bottom-right .infonomic-toast-root[data-starting-style]) {
141
+ opacity: 0;
142
+ transform: translateX(calc(100% + var(--viewport-padding)));
143
+ }
144
+
145
+ .viewport.top-left .root[data-starting-style],
146
+ .viewport.bottom-left .root[data-starting-style],
147
+ :global(.infonomic-toast-viewport.top-left .infonomic-toast-root[data-starting-style]),
148
+ :global(.infonomic-toast-viewport.bottom-left .infonomic-toast-root[data-starting-style]) {
149
+ opacity: 0;
150
+ transform: translateX(calc(-100% - var(--viewport-padding)));
151
+ }
39
152
  }
40
153
 
41
- .root[data-state="closed"],
42
- :global(.infonomic-toast-root[data-state="closed"]) {
43
- animation: hide 100ms ease-in;
154
+ /* Exit animation */
155
+ .root[data-ending-style],
156
+ :global(.infonomic-toast-root[data-ending-style]) {
157
+ opacity: 0;
44
158
  }
45
159
 
46
- .root[data-swipe="move"],
47
- :global(.infonomic-toast-root[data-swipe="move"]) {
48
- transform: translateX(var(--radix-toast-swipe-move-x));
160
+ .root[data-ending-style][data-swipe-direction="right"],
161
+ :global(.infonomic-toast-root[data-ending-style][data-swipe-direction="right"]) {
162
+ transform: translateX(calc(var(--toast-swipe-movement-x, 0) + 100% + var(--viewport-padding)));
49
163
  }
50
164
 
51
- .root[data-swipe="cancel"],
52
- :global(.infonomic-toast-root[data-swipe="cancel"]) {
53
- transform: translateX(0);
54
- transition: transform 200ms ease-out;
165
+ .root[data-ending-style][data-swipe-direction="left"],
166
+ :global(.infonomic-toast-root[data-ending-style][data-swipe-direction="left"]) {
167
+ transform: translateX(calc(var(--toast-swipe-movement-x, 0) - 100% - var(--viewport-padding)));
55
168
  }
56
169
 
57
- .root.top-right[data-swipe="end"],
58
- .root.bottom-right[data-swipe="end"],
59
- :global(.infonomic-toast-root.top-right[data-swipe="end"]),
60
- :global(.infonomic-toast-root.bottom-right[data-swipe="end"]) {
61
- animation: swipeOutToRight 100ms ease-out;
170
+ .root[data-ending-style][data-swipe-direction="down"],
171
+ :global(.infonomic-toast-root[data-ending-style][data-swipe-direction="down"]) {
172
+ transform: translateY(calc(var(--toast-swipe-movement-y, 0) + 150%));
62
173
  }
63
174
 
64
- .root.top-left[data-swipe="end"],
65
- .root.bottom-left[data-swipe="end"],
66
- :global(.infonomic-toast-root.top-left[data-swipe="end"]),
67
- :global(.infonomic-toast-root.bottom-left[data-swipe="end"]) {
68
- animation: swipeOutToLeft 100ms ease-out;
175
+ /* ============================================
176
+ Content — overflow container for stacking
177
+ ============================================ */
178
+
179
+ .content,
180
+ :global(.infonomic-toast-content) {
181
+ display: flex;
182
+ flex-direction: column;
183
+ gap: var(--gap-1);
69
184
  }
70
185
 
186
+ /* ============================================
187
+ Header / Close / Title / Description / Action
188
+ ============================================ */
189
+
71
190
  .header,
72
191
  :global(.infonomic-toast-header) {
73
192
  display: flex;
@@ -122,149 +241,4 @@
122
241
  justify-content: end;
123
242
  padding: 0 12px 0 12px;
124
243
  }
125
-
126
- /* Positions are relative to the toast viewport which is set
127
- globally in components/toast.css */
128
-
129
- .top-left,
130
- :global(.infonomic-toast-top-left) {
131
- top: 88px;
132
- right: 16px;
133
- left: 16px;
134
- }
135
-
136
- .top-right,
137
- :global(.infonomic-toast-top-right) {
138
- top: 88px;
139
- right: 16px;
140
- left: 16px;
141
- }
142
-
143
- .bottom-left,
144
- :global(.infonomic-toast-bottom-left) {
145
- bottom: 16px;
146
- right: 16px;
147
- left: 16px;
148
- }
149
-
150
- .bottom-right,
151
- :global(.infonomic-toast-bottom-right) {
152
- bottom: 16px;
153
- right: 16px;
154
- left: 16px;
155
- }
156
-
157
- @media (min-width: 48rem) {
158
- .root.top-right[data-state="open"],
159
- .root.bottom-right[data-state="open"],
160
- :global(.infonomic-toast-root.top-right[data-state="open"]),
161
- :global(.infonomic-toast-root.bottom-right[data-state="open"]) {
162
- animation: slideInFromRight 150ms cubic-bezier(0.16, 1, 0.3, 1);
163
- }
164
-
165
- .root.top-left[data-state="open"],
166
- .root.bottom-left[data-state="open"],
167
- :global(.infonomic-toast-root.top-left[data-state="open"]),
168
- :global(.infonomic-toast-root.bottom-left[data-state="open"]) {
169
- animation: slideInFromLeft 150ms cubic-bezier(0.16, 1, 0.3, 1);
170
- }
171
-
172
- .bottom-right,
173
- :global(.infonomic-toast-bottom-right) {
174
- bottom: 16px;
175
- right: 16px;
176
- left: auto;
177
- width: 100%;
178
- max-width: 390px;
179
- }
180
-
181
- .bottom-left,
182
- :global(.infonomic-toast-bottom-left) {
183
- bottom: 16px;
184
- left: 16px;
185
- right: auto;
186
- width: 100%;
187
- max-width: 390px;
188
- }
189
-
190
- .top-left,
191
- :global(.infonomic-toast-top-left) {
192
- top: 88px;
193
- left: 16px;
194
- right: auto;
195
- bottom: auto;
196
- width: 100%;
197
- max-width: 390px;
198
- }
199
-
200
- .top-right,
201
- :global(.infonomic-toast-top-right) {
202
- top: 88px;
203
- right: 16px;
204
- bottom: auto;
205
- left: auto;
206
- width: 100%;
207
- max-width: 390px;
208
- }
209
- }
210
-
211
- @keyframes slideInFromRight {
212
- from {
213
- transform: translateX(calc(100% + var(--viewport-padding)));
214
- }
215
-
216
- to {
217
- transform: translateX(0);
218
- }
219
- }
220
-
221
- @keyframes slideInFromLeft {
222
- from {
223
- transform: translateX(calc(-100% - var(--viewport-padding)));
224
- }
225
-
226
- to {
227
- transform: translateX(0);
228
- }
229
- }
230
-
231
- @keyframes slideInFromBottom {
232
- from {
233
- transform: translateY(calc(100% + var(--viewport-padding)));
234
- }
235
-
236
- to {
237
- transform: translateY(0);
238
- }
239
- }
240
-
241
- @keyframes swipeOutToRight {
242
- from {
243
- transform: translateX(var(--radix-toast-swipe-end-x));
244
- }
245
-
246
- to {
247
- transform: translateX(calc(100% + var(--viewport-padding)));
248
- }
249
- }
250
-
251
- @keyframes swipeOutToLeft {
252
- from {
253
- transform: translateX(var(--radix-toast-swipe-end-x));
254
- }
255
-
256
- to {
257
- transform: translateX(calc(-100% - var(--viewport-padding)));
258
- }
259
- }
260
-
261
- @keyframes hide {
262
- from {
263
- opacity: 1;
264
- }
265
-
266
- to {
267
- opacity: 0;
268
- }
269
- }
270
- }
244
+ }
@@ -1,42 +1,40 @@
1
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1
+ import type React from 'react'
2
2
 
3
- import React from 'react'
4
-
5
- import type { Meta } from '@storybook/react-vite'
3
+ import type { Meta, StoryObj } from '@storybook/react-vite'
6
4
 
7
5
  import { Button } from '../button/button.js'
8
- import { Toast as ToastComponent } from './toast.js'
6
+ import { useToastManager } from './toast.js'
9
7
 
10
- export const Toast = (): React.JSX.Element => {
11
- const [toast, setToast] = React.useState(false)
8
+ function ToastDemo(): React.JSX.Element {
9
+ const toastManager = useToastManager()
12
10
 
13
11
  const handleOpenToastClick = (): void => {
14
- setToast(!toast)
12
+ toastManager.add({
13
+ title: 'Note',
14
+ description:
15
+ 'This is a test Toast notification that should appear when the button is clicked.',
16
+ data: {
17
+ intent: 'success',
18
+ iconType: 'success',
19
+ icon: true,
20
+ close: true,
21
+ },
22
+ })
15
23
  }
16
24
 
17
25
  return (
18
26
  <div style={{ maxWidth: '600px', margin: '2rem 0' }}>
19
27
  <Button onClick={handleOpenToastClick}>Open Toast</Button>
20
- <ToastComponent
21
- title="Note"
22
- iconType="success"
23
- intent="success"
24
- position="bottom-right"
25
- message="This is a test Toast modal that should appear when the button is clicked."
26
- open={toast}
27
- onOpenChange={setToast}
28
- />
29
28
  </div>
30
29
  )
31
30
  }
32
31
 
33
- const meta: Meta<typeof Toast> = {
34
- /* 👇 The title prop is optional.
35
- * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
36
- * to learn how to generate automatic titles
37
- */
32
+ export const Toast: StoryObj = {
33
+ render: () => <ToastDemo />,
34
+ }
35
+
36
+ const meta: Meta = {
38
37
  title: 'Components/Toast',
39
- component: ToastComponent,
40
38
  }
41
39
 
42
40
  export default meta
@@ -2,9 +2,8 @@
2
2
 
3
3
  import React from 'react'
4
4
 
5
- import { useFocusTrap, useMergedRef } from '@mantine/hooks'
5
+ import { Toast as ToastPrimitive } from '@base-ui/react/toast'
6
6
  import cx from 'classnames'
7
- import { Toast as ToastPrimitive } from 'radix-ui'
8
7
 
9
8
  import { CloseIcon } from '../../icons/close-icon'
10
9
  import { DangerIcon } from '../../icons/danger-icon'
@@ -13,7 +12,7 @@ import { SuccessIcon } from '../../icons/success-icon'
13
12
  import { WarningIcon } from '../../icons/warning-icon'
14
13
  import { Button } from '../button/button.js'
15
14
  import styles from './toast.module.css'
16
- import type { IconType, Intent, OnOpenChange, Position } from './@types/toast.js'
15
+ import type { Position, ToastData } from './@types/toast.js'
17
16
 
18
17
  const toastIcons = {
19
18
  success: SuccessIcon,
@@ -22,105 +21,110 @@ const toastIcons = {
22
21
  danger: DangerIcon,
23
22
  }
24
23
 
25
- export interface ToastProps extends React.InputHTMLAttributes<HTMLLIElement> {
26
- intent?: Intent
24
+ // Re-export Base UI toast utilities
25
+ export const useToastManager = ToastPrimitive.useToastManager<ToastData>
26
+ export const createToastManager = ToastPrimitive.createToastManager<ToastData>
27
+
28
+ export interface ToastProviderProps {
29
+ children: React.ReactNode
30
+ timeout?: number
31
+ limit?: number
32
+ toastManager?: ReturnType<typeof createToastManager>
33
+ }
34
+
35
+ export function ToastProvider({
36
+ children,
37
+ timeout = 5000,
38
+ limit = 3,
39
+ toastManager,
40
+ }: ToastProviderProps) {
41
+ return (
42
+ <ToastPrimitive.Provider timeout={timeout} limit={limit} toastManager={toastManager}>
43
+ {children}
44
+ </ToastPrimitive.Provider>
45
+ )
46
+ }
47
+
48
+ export interface ToastViewportProps {
27
49
  position?: Position
28
- title: string
29
- message: string
30
- icon?: boolean
31
- iconType?: IconType
32
- close?: boolean
33
- open: boolean
34
- onOpenChange: OnOpenChange
35
50
  className?: string
36
51
  }
37
52
 
38
- export const ToastProvider = ToastPrimitive.Provider
39
- export const ToastViewport = ToastPrimitive.Viewport
40
-
41
- // Important!: see comments in app/ui/components/notifications/styles/toast.ts regarding toast position
53
+ export function ToastViewport({ position = 'bottom-right', className }: ToastViewportProps) {
54
+ const { toasts } = ToastPrimitive.useToastManager<ToastData>()
55
+ return (
56
+ <ToastPrimitive.Portal>
57
+ <ToastPrimitive.Viewport
58
+ className={cx('infonomic-toast-viewport', styles.viewport, styles[position], className)}
59
+ >
60
+ {toasts.map((toast) => (
61
+ <ToastItem key={toast.id} toast={toast} />
62
+ ))}
63
+ </ToastPrimitive.Viewport>
64
+ </ToastPrimitive.Portal>
65
+ )
66
+ }
42
67
 
43
- export const Toast = function Toast({
44
- ref,
45
- intent = 'success',
46
- position = 'bottom-right',
47
- title,
48
- message,
49
- icon = true,
50
- iconType = 'success',
51
- close = true,
52
- open,
53
- onOpenChange,
54
- className,
55
- }: ToastProps & {
56
- ref?: React.RefObject<HTMLLIElement>
68
+ function ToastItem({
69
+ toast,
70
+ }: {
71
+ toast: ToastPrimitive.Root.ToastObject<ToastData>
57
72
  }) {
73
+ const {
74
+ intent = 'success',
75
+ iconType = 'success',
76
+ icon = true,
77
+ close = true,
78
+ } = toast.data ?? {}
58
79
  const eventDateRef = React.useRef(new Date())
59
- const timerRef = React.useRef(0)
60
- const focusTrapRef = useFocusTrap()
61
- const mergedRef = useMergedRef(ref, focusTrapRef)
62
80
  const Icon = toastIcons[iconType as keyof typeof toastIcons]
63
81
 
64
- const handleOnClose = (): void => {
65
- if (onOpenChange != null) onOpenChange(false)
66
- }
67
-
68
- const _handleOnChange = (open: boolean): void => {
69
- console.log('handleOnChange', { open })
70
- if (open) {
71
- timerRef.current = window.setTimeout(() => {
72
- onOpenChange(false)
73
- }, 5000)
74
- } else {
75
- window.clearTimeout(timerRef.current)
76
- }
77
- }
82
+ const swipeDirection = React.useMemo<
83
+ React.ComponentProps<typeof ToastPrimitive.Root>['swipeDirection']
84
+ >(() => ['down', 'right'], [])
78
85
 
79
86
  return (
80
87
  <ToastPrimitive.Root
81
- ref={mergedRef}
82
- className={cx('infonomic-toast', styles.root, styles[position])}
83
- open={open}
84
- onOpenChange={onOpenChange}
88
+ toast={toast}
89
+ swipeDirection={swipeDirection}
90
+ className={cx('infonomic-toast', styles.root)}
85
91
  >
86
- <div className={cx('infonomic-toast-header', styles.header)}>
87
- <time dateTime={eventDateRef.current.toISOString()} className="text-sm">
88
- {new Intl.DateTimeFormat('default', {
89
- hour12: true,
90
- hour: 'numeric',
91
- minute: 'numeric',
92
- }).format(eventDateRef.current)}
93
- </time>
94
- {close === true && (
95
- <ToastPrimitive.Close aria-label="Close" asChild>
96
- <Button
97
- intent={intent}
98
- tabIndex={0}
99
- variant="filled"
100
- aria-label="Close"
101
- className={cx('infonomic-toast-close', styles.close)}
102
- type="button"
103
- onClick={handleOnClose}
92
+ <ToastPrimitive.Content className={cx('infonomic-toast-content', styles.content)}>
93
+ <div className={cx('infonomic-toast-header', styles.header)}>
94
+ <time dateTime={eventDateRef.current.toISOString()} className="text-sm">
95
+ {new Intl.DateTimeFormat('default', {
96
+ hour12: true,
97
+ hour: 'numeric',
98
+ minute: 'numeric',
99
+ }).format(eventDateRef.current)}
100
+ </time>
101
+ {close && (
102
+ <ToastPrimitive.Close
103
+ render={
104
+ <Button
105
+ intent={intent}
106
+ tabIndex={0}
107
+ variant="filled"
108
+ aria-label="Close"
109
+ className={cx('infonomic-toast-close', styles.close)}
110
+ type="button"
111
+ />
112
+ }
104
113
  >
105
114
  <CloseIcon height="12px" width="12px" />
106
- </Button>
107
- </ToastPrimitive.Close>
108
- )}
109
- </div>
110
- <ToastPrimitive.Title className={cx('infonomic-toast-title', styles.title)}>
111
- {icon != null && <Icon />}
112
- {title}
113
- </ToastPrimitive.Title>
114
- <ToastPrimitive.Description className={cx('infonomic-toast-description', styles.description)}>
115
- {message}
116
- </ToastPrimitive.Description>
117
- {/* <ToastPrimitive.Action className={styles.action} asChild altText="Goto schedule to undo">
118
- <div>
119
- <Button intent="primary" tabIndex={0} size="sm" variant="filled">
120
- Undo
121
- </Button>
115
+ </ToastPrimitive.Close>
116
+ )}
122
117
  </div>
123
- </ToastPrimitive.Action> */}
118
+ <ToastPrimitive.Title className={cx('infonomic-toast-title', styles.title)}>
119
+ {icon && Icon && <Icon />}
120
+ {toast.title}
121
+ </ToastPrimitive.Title>
122
+ <ToastPrimitive.Description
123
+ className={cx('infonomic-toast-description', styles.description)}
124
+ >
125
+ {toast.description}
126
+ </ToastPrimitive.Description>
127
+ </ToastPrimitive.Content>
124
128
  </ToastPrimitive.Root>
125
129
  )
126
130
  }