@mich8060/chg-design-system 0.1.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 (260) hide show
  1. package/.github/workflows/figma-sync.yml +30 -0
  2. package/ARCHITECTURE_FIX.md +241 -0
  3. package/LICENSE +21 -0
  4. package/README.lib.md +103 -0
  5. package/README.md +177 -0
  6. package/figma.config.json +9 -0
  7. package/package.json +67 -0
  8. package/package.lib.json +49 -0
  9. package/public/data/figma-variables.json +40026 -0
  10. package/public/favicon.ico +0 -0
  11. package/public/index.html +46 -0
  12. package/public/logo192.png +0 -0
  13. package/public/logo512.png +0 -0
  14. package/public/manifest.json +25 -0
  15. package/public/robots.txt +3 -0
  16. package/public/styles/tokens.css +1994 -0
  17. package/scripts/index.js +896 -0
  18. package/scripts/publish-lib.js +150 -0
  19. package/scripts/validate.js +94 -0
  20. package/src/App.css +457 -0
  21. package/src/App.css.map +1 -0
  22. package/src/App.js +161 -0
  23. package/src/App.scss +548 -0
  24. package/src/App.test.js +8 -0
  25. package/src/assets/images/.gitkeep +0 -0
  26. package/src/assets/images/doctors/Avatar-1.png +0 -0
  27. package/src/assets/images/doctors/Avatar-10.png +0 -0
  28. package/src/assets/images/doctors/Avatar-11.png +0 -0
  29. package/src/assets/images/doctors/Avatar-12.png +0 -0
  30. package/src/assets/images/doctors/Avatar-13.png +0 -0
  31. package/src/assets/images/doctors/Avatar-14.png +0 -0
  32. package/src/assets/images/doctors/Avatar-15.png +0 -0
  33. package/src/assets/images/doctors/Avatar-16.png +0 -0
  34. package/src/assets/images/doctors/Avatar-17.png +0 -0
  35. package/src/assets/images/doctors/Avatar-18.png +0 -0
  36. package/src/assets/images/doctors/Avatar-19.png +0 -0
  37. package/src/assets/images/doctors/Avatar-2.png +0 -0
  38. package/src/assets/images/doctors/Avatar-20.png +0 -0
  39. package/src/assets/images/doctors/Avatar-21.png +0 -0
  40. package/src/assets/images/doctors/Avatar-3.png +0 -0
  41. package/src/assets/images/doctors/Avatar-4.png +0 -0
  42. package/src/assets/images/doctors/Avatar-5.png +0 -0
  43. package/src/assets/images/doctors/Avatar-6.png +0 -0
  44. package/src/assets/images/doctors/Avatar-7.png +0 -0
  45. package/src/assets/images/doctors/Avatar-8.png +0 -0
  46. package/src/assets/images/doctors/Avatar-9.png +0 -0
  47. package/src/assets/images/doctors/Avatar.png +0 -0
  48. package/src/assets/images/doctors/index.js +141 -0
  49. package/src/data/figma-variables.json +90305 -0
  50. package/src/index.js +20 -0
  51. package/src/index.scss +10 -0
  52. package/src/pages/AccordionDemo.jsx +206 -0
  53. package/src/pages/AccordionDemo.scss +34 -0
  54. package/src/pages/ActionMenuDemo.jsx +957 -0
  55. package/src/pages/ActionMenuDemo.scss +34 -0
  56. package/src/pages/AvatarDemo.jsx +328 -0
  57. package/src/pages/AvatarDemo.scss +40 -0
  58. package/src/pages/BadgeDemo.jsx +254 -0
  59. package/src/pages/BadgeDemo.scss +40 -0
  60. package/src/pages/BorderRadiusDemo.jsx +112 -0
  61. package/src/pages/BorderRadiusDemo.scss +50 -0
  62. package/src/pages/BrandingDemo.jsx +117 -0
  63. package/src/pages/BreadcrumbDemo.jsx +172 -0
  64. package/src/pages/ButtonDemo.jsx +708 -0
  65. package/src/pages/ButtonDemo.scss +34 -0
  66. package/src/pages/CheckboxDemo.jsx +194 -0
  67. package/src/pages/ChipDemo.jsx +359 -0
  68. package/src/pages/ChipDemo.scss +40 -0
  69. package/src/pages/ColorsDemo.jsx +566 -0
  70. package/src/pages/ColorsDemo.scss +243 -0
  71. package/src/pages/ComponentsUsage.jsx +401 -0
  72. package/src/pages/DatepickerDemo.jsx +223 -0
  73. package/src/pages/DividerDemo.jsx +337 -0
  74. package/src/pages/DotStatusDemo.jsx +223 -0
  75. package/src/pages/DropdownDemo.jsx +229 -0
  76. package/src/pages/FieldDemo.jsx +253 -0
  77. package/src/pages/FigmaVariablesDemo.jsx +426 -0
  78. package/src/pages/FigmaVariablesDemo.scss +316 -0
  79. package/src/pages/FileUploadDemo.jsx +186 -0
  80. package/src/pages/FlexDemo.jsx +144 -0
  81. package/src/pages/FlexDemo.scss +119 -0
  82. package/src/pages/FontInstallation.jsx +252 -0
  83. package/src/pages/FontInstallation.scss +40 -0
  84. package/src/pages/Home.jsx +3156 -0
  85. package/src/pages/IconDemo.jsx +1680 -0
  86. package/src/pages/ImageAspectDemo.jsx +152 -0
  87. package/src/pages/InputDemo.jsx +245 -0
  88. package/src/pages/Installation.jsx +257 -0
  89. package/src/pages/Installation.scss +40 -0
  90. package/src/pages/KeyDemo.jsx +184 -0
  91. package/src/pages/MenuDemo.jsx +139 -0
  92. package/src/pages/MicroCalendarDemo.jsx +165 -0
  93. package/src/pages/PaginationDemo.jsx +176 -0
  94. package/src/pages/PillToggleDemo.jsx +212 -0
  95. package/src/pages/ProgressCircleDemo.jsx +206 -0
  96. package/src/pages/ProgressIndicatorDemo.jsx +227 -0
  97. package/src/pages/RadioDemo.jsx +282 -0
  98. package/src/pages/ShadowsDemo.jsx +118 -0
  99. package/src/pages/ShadowsDemo.scss +93 -0
  100. package/src/pages/SliderDemo.jsx +226 -0
  101. package/src/pages/SpacingDemo.jsx +160 -0
  102. package/src/pages/SpacingDemo.scss +107 -0
  103. package/src/pages/StatusDemo.jsx +196 -0
  104. package/src/pages/StepsDemo.jsx +308 -0
  105. package/src/pages/TableDemo.jsx +376 -0
  106. package/src/pages/TabsDemo.jsx +221 -0
  107. package/src/pages/ToastDemo.jsx +195 -0
  108. package/src/pages/ToggleDemo.jsx +187 -0
  109. package/src/pages/TokensDemo.jsx +637 -0
  110. package/src/pages/TokensDemo.scss +270 -0
  111. package/src/pages/TokensUsage.jsx +220 -0
  112. package/src/pages/TooltipDemo.jsx +170 -0
  113. package/src/pages/TypographyDemo.jsx +229 -0
  114. package/src/pages/TypographyDemo.scss +105 -0
  115. package/src/pages/UtilitiesDemo.jsx +381 -0
  116. package/src/pages/UtilitiesDemo.scss +214 -0
  117. package/src/reportWebVitals.js +13 -0
  118. package/src/setupTests.js +5 -0
  119. package/src/styles/_typography.scss +932 -0
  120. package/src/styles/_utilities.scss +3635 -0
  121. package/src/styles/_variables.scss +887 -0
  122. package/src/styles/prism-custom.css +206 -0
  123. package/src/styles/prism-custom.css.map +1 -0
  124. package/src/styles/prism-custom.scss +205 -0
  125. package/src/styles/tokens.css +4416 -0
  126. package/src/styles/tokens.css.map +1 -0
  127. package/src/styles/tokens.scss +1456 -0
  128. package/src/ui/Accordion/Accordion.jsx +70 -0
  129. package/src/ui/Accordion/Accordion.scss +82 -0
  130. package/src/ui/Accordion/index.js +1 -0
  131. package/src/ui/ActionMenu/ActionMenu.jsx +383 -0
  132. package/src/ui/ActionMenu/ActionMenu.scss +198 -0
  133. package/src/ui/ActionMenu/index.js +1 -0
  134. package/src/ui/Avatar/Avatar.jsx +49 -0
  135. package/src/ui/Avatar/Avatar.scss +82 -0
  136. package/src/ui/Avatar/index.js +1 -0
  137. package/src/ui/Badge/Badge.jsx +64 -0
  138. package/src/ui/Badge/Badge.scss +84 -0
  139. package/src/ui/Badge/index.js +1 -0
  140. package/src/ui/Branding/Branding.jsx +65 -0
  141. package/src/ui/Branding/Branding.scss +116 -0
  142. package/src/ui/Branding/index.js +1 -0
  143. package/src/ui/Breadcrumb/Breadcrumb.jsx +162 -0
  144. package/src/ui/Breadcrumb/Breadcrumb.scss +46 -0
  145. package/src/ui/Breadcrumb/index.js +2 -0
  146. package/src/ui/Button/Button.figma.tsx +49 -0
  147. package/src/ui/Button/Button.jsx +135 -0
  148. package/src/ui/Button/Button.scss +188 -0
  149. package/src/ui/Button/index.js +1 -0
  150. package/src/ui/Card/Card.jsx +25 -0
  151. package/src/ui/Card/Card.scss +47 -0
  152. package/src/ui/Card/index.js +1 -0
  153. package/src/ui/Checkbox/Checkbox.jsx +70 -0
  154. package/src/ui/Checkbox/Checkbox.scss +96 -0
  155. package/src/ui/Checkbox/index.js +1 -0
  156. package/src/ui/Chip/Chip.jsx +104 -0
  157. package/src/ui/Chip/Chip.scss +118 -0
  158. package/src/ui/Chip/index.js +1 -0
  159. package/src/ui/CopyButton/CopyButton.jsx +102 -0
  160. package/src/ui/CopyButton/CopyButton.scss +56 -0
  161. package/src/ui/CopyButton/index.js +1 -0
  162. package/src/ui/Datepicker/Datepicker.jsx +326 -0
  163. package/src/ui/Datepicker/Datepicker.scss +187 -0
  164. package/src/ui/Datepicker/index.js +2 -0
  165. package/src/ui/Divider/Divider.jsx +89 -0
  166. package/src/ui/Divider/Divider.scss +112 -0
  167. package/src/ui/Divider/index.js +1 -0
  168. package/src/ui/DotStatus/DotStatus.jsx +64 -0
  169. package/src/ui/DotStatus/DotStatus.scss +87 -0
  170. package/src/ui/DotStatus/index.js +1 -0
  171. package/src/ui/Dropdown/Dropdown.jsx +200 -0
  172. package/src/ui/Dropdown/Dropdown.scss +156 -0
  173. package/src/ui/Dropdown/index.js +1 -0
  174. package/src/ui/Field/Field.jsx +89 -0
  175. package/src/ui/Field/Field.scss +119 -0
  176. package/src/ui/Field/index.js +1 -0
  177. package/src/ui/FileUpload/FileUpload.figma.tsx +28 -0
  178. package/src/ui/FileUpload/FileUpload.jsx +153 -0
  179. package/src/ui/FileUpload/FileUpload.scss +78 -0
  180. package/src/ui/FileUpload/index.js +2 -0
  181. package/src/ui/Flex/Flex.jsx +42 -0
  182. package/src/ui/Flex/Flex.scss +119 -0
  183. package/src/ui/Flex/index.js +1 -0
  184. package/src/ui/Icon/Icon.figma.tsx +22 -0
  185. package/src/ui/Icon/Icon.jsx +47 -0
  186. package/src/ui/Icon/index.js +1 -0
  187. package/src/ui/ImageAspect/ImageAspect.jsx +56 -0
  188. package/src/ui/ImageAspect/ImageAspect.scss +62 -0
  189. package/src/ui/ImageAspect/index.js +1 -0
  190. package/src/ui/Input/Input.figma.tsx +35 -0
  191. package/src/ui/Input/Input.jsx +68 -0
  192. package/src/ui/Input/Input.scss +64 -0
  193. package/src/ui/Input/index.js +2 -0
  194. package/src/ui/Key/Key.jsx +37 -0
  195. package/src/ui/Key/Key.scss +34 -0
  196. package/src/ui/Key/index.js +1 -0
  197. package/src/ui/Menu/Menu.jsx +389 -0
  198. package/src/ui/Menu/Menu.scss +382 -0
  199. package/src/ui/Menu/index.js +1 -0
  200. package/src/ui/MicroCalendar/MicroCalendar.jsx +392 -0
  201. package/src/ui/MicroCalendar/MicroCalendar.scss +277 -0
  202. package/src/ui/MicroCalendar/index.js +1 -0
  203. package/src/ui/Pagination/Pagination.jsx +237 -0
  204. package/src/ui/Pagination/Pagination.scss +182 -0
  205. package/src/ui/Pagination/index.js +1 -0
  206. package/src/ui/PillToggle/PillToggle.jsx +56 -0
  207. package/src/ui/PillToggle/PillToggle.scss +84 -0
  208. package/src/ui/PillToggle/index.js +1 -0
  209. package/src/ui/Playground/Playground.jsx +524 -0
  210. package/src/ui/Playground/Playground.scss +310 -0
  211. package/src/ui/Playground/index.js +2 -0
  212. package/src/ui/ProgressCircle/ProgressCircle.jsx +147 -0
  213. package/src/ui/ProgressCircle/ProgressCircle.scss +143 -0
  214. package/src/ui/ProgressCircle/index.js +1 -0
  215. package/src/ui/ProgressIndicator/ProgressIndicator.jsx +92 -0
  216. package/src/ui/ProgressIndicator/ProgressIndicator.scss +133 -0
  217. package/src/ui/ProgressIndicator/index.js +1 -0
  218. package/src/ui/Radio/Radio.jsx +57 -0
  219. package/src/ui/Radio/Radio.scss +84 -0
  220. package/src/ui/Radio/index.js +1 -0
  221. package/src/ui/Slider/Slider.jsx +283 -0
  222. package/src/ui/Slider/Slider.scss +156 -0
  223. package/src/ui/Slider/index.js +1 -0
  224. package/src/ui/Status/Status.jsx +66 -0
  225. package/src/ui/Status/Status.scss +90 -0
  226. package/src/ui/Status/index.js +1 -0
  227. package/src/ui/Steps/Steps.jsx +201 -0
  228. package/src/ui/Steps/Steps.scss +240 -0
  229. package/src/ui/Steps/index.js +1 -0
  230. package/src/ui/Table/Table.jsx +143 -0
  231. package/src/ui/Table/Table.scss +90 -0
  232. package/src/ui/Table/index.js +1 -0
  233. package/src/ui/Tabs/TabItem.jsx +86 -0
  234. package/src/ui/Tabs/Tabs.figma.tsx +30 -0
  235. package/src/ui/Tabs/Tabs.jsx +318 -0
  236. package/src/ui/Tabs/Tabs.scss +164 -0
  237. package/src/ui/Tabs/Untitled +1 -0
  238. package/src/ui/Tabs/index.js +3 -0
  239. package/src/ui/Tag/Tag.figma.tsx +29 -0
  240. package/src/ui/Tag/Tag.jsx +93 -0
  241. package/src/ui/Tag/Tag.scss +229 -0
  242. package/src/ui/Tag/index.js +2 -0
  243. package/src/ui/Textarea/Textarea.figma.tsx +35 -0
  244. package/src/ui/Textarea/Textarea.jsx +68 -0
  245. package/src/ui/Textarea/Textarea.scss +69 -0
  246. package/src/ui/Textarea/index.js +2 -0
  247. package/src/ui/Toast/Toast.jsx +75 -0
  248. package/src/ui/Toast/Toast.scss +132 -0
  249. package/src/ui/Toast/index.js +2 -0
  250. package/src/ui/Toggle/Toggle.jsx +73 -0
  251. package/src/ui/Toggle/Toggle.scss +139 -0
  252. package/src/ui/Toggle/index.js +1 -0
  253. package/src/ui/Tooltip/Tooltip.figma.tsx +24 -0
  254. package/src/ui/Tooltip/Tooltip.jsx +123 -0
  255. package/src/ui/Tooltip/Tooltip.scss +80 -0
  256. package/src/ui/Tooltip/index.js +2 -0
  257. package/src/ui/index.js +63 -0
  258. package/src/utils/formatDate.js +27 -0
  259. package/src/utils/headerVariants.js +69 -0
  260. package/vite.config.lib.js +55 -0
@@ -0,0 +1,237 @@
1
+ import React, { useState } from "react";
2
+ import Icon from "../Icon/Icon";
3
+ import "./Pagination.scss";
4
+
5
+ /**
6
+ * Pagination component
7
+ * @param {number} currentPage - Current active page (1-indexed)
8
+ * @param {number} totalPages - Total number of pages
9
+ * @param {function} onPageChange - Callback when page changes: (page: number) => void
10
+ * @param {string} variant - Variant style: "default" | "underline" | "with-jump" | "underline-with-jump" | "underline-double"
11
+ * @param {boolean} showFirstLast - Show first/last page buttons (for variants with double buttons)
12
+ * @param {string} className - Additional CSS classes
13
+ */
14
+ export default function Pagination({
15
+ currentPage = 1,
16
+ totalPages = 10,
17
+ onPageChange,
18
+ variant = "default",
19
+ showFirstLast = false,
20
+ className = "",
21
+ }) {
22
+ const [jumpToPage, setJumpToPage] = useState(currentPage.toString());
23
+
24
+ // Ensure currentPage is within valid range
25
+ const safeCurrentPage = Math.max(1, Math.min(currentPage, totalPages));
26
+
27
+ // Calculate which page numbers to show
28
+ const getPageNumbers = () => {
29
+ const pages = [];
30
+ const maxVisible = 5; // Show up to 5 page numbers
31
+
32
+ if (totalPages <= maxVisible) {
33
+ // Show all pages if total is small
34
+ for (let i = 1; i <= totalPages; i++) {
35
+ pages.push(i);
36
+ }
37
+ } else {
38
+ // Always show first page
39
+ pages.push(1);
40
+
41
+ // Calculate start and end of middle range
42
+ let start = Math.max(2, safeCurrentPage - 1);
43
+ let end = Math.min(totalPages - 1, safeCurrentPage + 1);
44
+
45
+ // Adjust if we're near the beginning
46
+ if (safeCurrentPage <= 3) {
47
+ end = Math.min(4, totalPages - 1);
48
+ }
49
+
50
+ // Adjust if we're near the end
51
+ if (safeCurrentPage >= totalPages - 2) {
52
+ start = Math.max(2, totalPages - 3);
53
+ }
54
+
55
+ // Add ellipsis before middle range if needed
56
+ if (start > 2) {
57
+ pages.push("ellipsis-start");
58
+ }
59
+
60
+ // Add middle range
61
+ for (let i = start; i <= end; i++) {
62
+ pages.push(i);
63
+ }
64
+
65
+ // Add ellipsis after middle range if needed
66
+ if (end < totalPages - 1) {
67
+ pages.push("ellipsis-end");
68
+ }
69
+
70
+ // Always show last page
71
+ if (totalPages > 1) {
72
+ pages.push(totalPages);
73
+ }
74
+ }
75
+
76
+ return pages;
77
+ };
78
+
79
+ const handlePageClick = (page) => {
80
+ if (page !== safeCurrentPage && page >= 1 && page <= totalPages && onPageChange) {
81
+ onPageChange(page);
82
+ }
83
+ };
84
+
85
+ const handlePrevious = () => {
86
+ if (safeCurrentPage > 1) {
87
+ handlePageClick(safeCurrentPage - 1);
88
+ }
89
+ };
90
+
91
+ const handleNext = () => {
92
+ if (safeCurrentPage < totalPages) {
93
+ handlePageClick(safeCurrentPage + 1);
94
+ }
95
+ };
96
+
97
+ const handleFirst = () => {
98
+ handlePageClick(1);
99
+ };
100
+
101
+ const handleLast = () => {
102
+ handlePageClick(totalPages);
103
+ };
104
+
105
+ const handleJumpSubmit = (e) => {
106
+ e.preventDefault();
107
+ const page = parseInt(jumpToPage, 10);
108
+ if (page >= 1 && page <= totalPages) {
109
+ handlePageClick(page);
110
+ } else {
111
+ setJumpToPage(safeCurrentPage.toString());
112
+ }
113
+ };
114
+
115
+ const handleJumpChange = (e) => {
116
+ setJumpToPage(e.target.value);
117
+ };
118
+
119
+ const pageNumbers = getPageNumbers();
120
+ const isUnderlineVariant =
121
+ variant === "underline" ||
122
+ variant === "underline-with-jump" ||
123
+ variant === "underline-double";
124
+ const showJumpInput =
125
+ variant === "with-jump" || variant === "underline-with-jump";
126
+ const showDoubleButtons =
127
+ variant === "with-jump" ||
128
+ variant === "underline-with-jump" ||
129
+ variant === "underline-double" ||
130
+ showFirstLast;
131
+
132
+ return (
133
+ <nav className={`pagination ${className}`} aria-label="Pagination">
134
+ <div className={`pagination__container ${isUnderlineVariant ? "pagination__container--underline" : ""} ${showDoubleButtons ? "pagination__container--double" : ""}`}>
135
+ {/* First page button (only for double button variants) */}
136
+ {showDoubleButtons && (
137
+ <button
138
+ type="button"
139
+ className="pagination__cap pagination__cap--first"
140
+ onClick={handleFirst}
141
+ disabled={safeCurrentPage === 1}
142
+ aria-label="First page"
143
+ >
144
+ <Icon name="CaretDoubleLeft" size={16} />
145
+ </button>
146
+ )}
147
+
148
+ {/* Previous page button */}
149
+ <button
150
+ type="button"
151
+ className="pagination__cap pagination__cap--prev"
152
+ onClick={handlePrevious}
153
+ disabled={safeCurrentPage === 1}
154
+ aria-label="Previous page"
155
+ >
156
+ <Icon name="CaretLeft" size={16} />
157
+ </button>
158
+
159
+ {/* Page numbers */}
160
+ {pageNumbers.map((page, index) => {
161
+ if (page === "ellipsis-start" || page === "ellipsis-end") {
162
+ return (
163
+ <button
164
+ key={`ellipsis-${index}`}
165
+ type="button"
166
+ className="pagination__item pagination__item--ellipsis"
167
+ disabled
168
+ aria-hidden="true"
169
+ >
170
+ ...
171
+ </button>
172
+ );
173
+ }
174
+
175
+ const isActive = page === safeCurrentPage;
176
+
177
+ return (
178
+ <button
179
+ key={page}
180
+ type="button"
181
+ className={`pagination__item ${
182
+ isActive ? "pagination__item--active" : ""
183
+ } ${isUnderlineVariant ? "pagination__item--underline" : ""}`}
184
+ onClick={() => handlePageClick(page)}
185
+ aria-label={`Page ${page}`}
186
+ aria-current={isActive ? "page" : undefined}
187
+ >
188
+ {page}
189
+ </button>
190
+ );
191
+ })}
192
+
193
+ {/* Jump to page input (for variants that include it) */}
194
+ {showJumpInput && (
195
+ <div className="pagination__jump">
196
+ <form onSubmit={handleJumpSubmit}>
197
+ <input
198
+ type="number"
199
+ className="pagination__jump-input"
200
+ value={jumpToPage}
201
+ onChange={handleJumpChange}
202
+ min="1"
203
+ max={totalPages}
204
+ aria-label="Jump to page"
205
+ />
206
+ </form>
207
+ <span className="pagination__jump-label">of {totalPages}</span>
208
+ </div>
209
+ )}
210
+
211
+ {/* Next page button */}
212
+ <button
213
+ type="button"
214
+ className="pagination__cap pagination__cap--next"
215
+ onClick={handleNext}
216
+ disabled={safeCurrentPage === totalPages}
217
+ aria-label="Next page"
218
+ >
219
+ <Icon name="CaretRight" size={16} />
220
+ </button>
221
+
222
+ {/* Last page button (only for double button variants) */}
223
+ {showDoubleButtons && (
224
+ <button
225
+ type="button"
226
+ className="pagination__cap pagination__cap--last"
227
+ onClick={handleLast}
228
+ disabled={safeCurrentPage === totalPages}
229
+ aria-label="Last page"
230
+ >
231
+ <Icon name="CaretDoubleRight" size={16} />
232
+ </button>
233
+ )}
234
+ </div>
235
+ </nav>
236
+ );
237
+ }
@@ -0,0 +1,182 @@
1
+ @use "../../styles/typography" as *;
2
+
3
+ .pagination {
4
+ display: inline-flex;
5
+ align-items: center;
6
+
7
+ &__container {
8
+ display: flex;
9
+ align-items: stretch;
10
+ height: 48px;
11
+
12
+ &--underline {
13
+ // For underline variants, items use top border only
14
+ }
15
+
16
+ &--double {
17
+ // For double button variants, caps use top border only
18
+ }
19
+ }
20
+
21
+ &__cap {
22
+ @include uds-body-16;
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: center;
26
+ width: 47px;
27
+ height: 100%;
28
+ padding: 0;
29
+ background: var(--uds-surface-primary);
30
+ border: var(--uds-border-width-1) solid var(--uds-border-primary);
31
+ color: var(--uds-text-primary);
32
+ cursor: pointer;
33
+ transition: all var(--uds-animation-duration-200) var(--uds-animation-ease-standard);
34
+
35
+ &:first-child {
36
+ border-top-left-radius: var(--uds-radius-8);
37
+ border-bottom-left-radius: var(--uds-radius-8);
38
+ }
39
+
40
+ &:last-child {
41
+ border-top-right-radius: var(--uds-radius-8);
42
+ border-bottom-right-radius: var(--uds-radius-8);
43
+ }
44
+
45
+ &:not(:last-child) {
46
+ margin-right: -1px;
47
+ }
48
+
49
+ &:hover:not(:disabled) {
50
+ background: var(--uds-surface-secondary);
51
+ color: var(--uds-text-primary);
52
+ }
53
+
54
+ &:active:not(:disabled) {
55
+ background: var(--uds-surface-tertiary);
56
+ }
57
+
58
+ &:disabled {
59
+ opacity: 0.5;
60
+ cursor: not-allowed;
61
+ }
62
+
63
+ // For variants with double buttons, use top border only
64
+ .pagination__container--double & {
65
+ border: none;
66
+ border-top: var(--uds-border-width-1) solid var(--uds-border-primary);
67
+ }
68
+ }
69
+
70
+ &__item {
71
+ @include uds-body-16;
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: center;
75
+ min-width: 47px;
76
+ height: 100%;
77
+ padding: var(--uds-spacing-12) var(--uds-spacing-18);
78
+ background: var(--uds-surface-primary);
79
+ border: var(--uds-border-width-1) solid var(--uds-border-primary);
80
+ border-left: none;
81
+ color: var(--uds-text-primary);
82
+ cursor: pointer;
83
+ transition: all var(--uds-animation-duration-200) var(--uds-animation-ease-standard);
84
+
85
+ &:not(:last-child) {
86
+ margin-right: -1px;
87
+ }
88
+
89
+ &:hover:not(:disabled):not(&--active) {
90
+ background: var(--uds-surface-secondary);
91
+ color: var(--uds-text-primary);
92
+ }
93
+
94
+ &:active:not(:disabled):not(&--active) {
95
+ background: var(--uds-surface-tertiary);
96
+ }
97
+
98
+ &--active {
99
+ background: var(--uds-button-surface-primary-default);
100
+ border-color: var(--uds-button-border-primary-default);
101
+ color: var(--uds-button-text-default);
102
+ font-weight: 600;
103
+ cursor: default;
104
+
105
+ &.pagination__item--underline {
106
+ background: var(--uds-surface-primary);
107
+ border: var(--uds-border-width-1) solid var(--uds-border-primary);
108
+ border-top: 2px solid var(--uds-button-border-primary-default);
109
+ border-left: none;
110
+ color: var(--uds-button-border-primary-default);
111
+ font-weight: 600;
112
+ padding-top: calc(var(--uds-spacing-12) - 2px);
113
+ }
114
+ }
115
+
116
+ &--underline {
117
+ // Base underline variant styling - only top border for non-active items
118
+ background: var(--uds-surface-primary);
119
+ border: none;
120
+ border-top: var(--uds-border-width-1) solid var(--uds-border-primary);
121
+ border-left: none;
122
+ color: var(--uds-text-primary);
123
+ }
124
+
125
+ &--ellipsis {
126
+ cursor: default;
127
+ color: var(--uds-text-primary);
128
+ border-top: var(--uds-border-width-1) solid var(--uds-border-primary);
129
+ border-left: none;
130
+
131
+ &:hover {
132
+ background: var(--uds-surface-primary);
133
+ }
134
+ }
135
+ }
136
+
137
+ &__jump {
138
+ display: flex;
139
+ align-items: center;
140
+ gap: var(--uds-spacing-8);
141
+ padding: var(--uds-spacing-6) var(--uds-spacing-12);
142
+ background: var(--uds-surface-primary);
143
+ border: var(--uds-border-width-1) solid var(--uds-border-primary);
144
+ border-left: none;
145
+ margin-right: -1px;
146
+
147
+ &-input {
148
+ @include uds-body-14;
149
+ width: 45px;
150
+ height: 36px;
151
+ padding: var(--uds-spacing-8) var(--uds-spacing-12);
152
+ background: var(--uds-surface-primary);
153
+ border: var(--uds-border-width-1) solid var(--uds-border-primary);
154
+ border-radius: var(--uds-radius-4);
155
+ color: var(--uds-text-primary);
156
+ text-align: center;
157
+ outline: none;
158
+ transition: all var(--uds-animation-duration-200) var(--uds-animation-ease-standard);
159
+
160
+ &:focus {
161
+ border-color: var(--uds-border-focus);
162
+ box-shadow: 0 0 0 3px var(--uds-border-focus-soft);
163
+ }
164
+
165
+ &::-webkit-inner-spin-button,
166
+ &::-webkit-outer-spin-button {
167
+ -webkit-appearance: none;
168
+ margin: 0;
169
+ }
170
+
171
+ &[type="number"] {
172
+ -moz-appearance: textfield;
173
+ }
174
+ }
175
+
176
+ &-label {
177
+ @include uds-body-14-semibold;
178
+ color: var(--uds-text-primary);
179
+ white-space: nowrap;
180
+ }
181
+ }
182
+ }
@@ -0,0 +1 @@
1
+ export { default } from "./Pagination";
@@ -0,0 +1,56 @@
1
+ import React from "react";
2
+ import "./PillToggle.scss";
3
+
4
+ const BASE_CLASS = "uds-pill-toggle";
5
+
6
+ /**
7
+ * PillToggle component for switching between selected and unselected states
8
+ * @param {string} label - The text content of the toggle
9
+ * @param {boolean} selected - Whether the toggle is selected
10
+ * @param {function} onChange - Callback function when toggle state changes
11
+ * @param {string} id - Unique identifier for the toggle input
12
+ * @param {boolean} disabled - Whether the toggle is disabled
13
+ * @param {string} className - Additional CSS classes
14
+ * @param {object} props - Additional props to pass to the toggle
15
+ */
16
+ export default function PillToggle({
17
+ label = "Label States",
18
+ selected = false,
19
+ onChange,
20
+ id,
21
+ disabled = false,
22
+ className = "",
23
+ ...props
24
+ }) {
25
+ const toggleId =
26
+ id || `pill-toggle-${Math.random().toString(36).substr(2, 9)}`;
27
+
28
+ const handleChange = (event) => {
29
+ if (!disabled && onChange) {
30
+ onChange(event.target.checked);
31
+ }
32
+ };
33
+
34
+ const classNames = [
35
+ BASE_CLASS,
36
+ selected && `${BASE_CLASS}--selected`,
37
+ disabled && `${BASE_CLASS}--disabled`,
38
+ className,
39
+ ]
40
+ .filter(Boolean)
41
+ .join(" ");
42
+
43
+ return (
44
+ <label className={classNames} htmlFor={toggleId} {...props}>
45
+ <input
46
+ type="checkbox"
47
+ id={toggleId}
48
+ className={`${BASE_CLASS}__input`}
49
+ checked={selected}
50
+ onChange={handleChange}
51
+ disabled={disabled}
52
+ />
53
+ <span className={`${BASE_CLASS}__label`}>{label}</span>
54
+ </label>
55
+ );
56
+ }
@@ -0,0 +1,84 @@
1
+ @use "../../styles/typography" as *;
2
+
3
+ .uds-pill-toggle {
4
+ @include uds-body-16-medium;
5
+ position: relative;
6
+ display: inline-flex;
7
+ align-items: center;
8
+ justify-content: center;
9
+ padding-inline: var(--uds-spacing-16);
10
+ padding-block: var(--uds-spacing-8);
11
+ border: var(--uds-border-width-1) solid var(--uds-border-primary);
12
+ background-color: var(--uds-surface-primary);
13
+ color: var(--uds-text-primary);
14
+ border-radius: 999px; // Fully rounded pill shape
15
+ cursor: pointer;
16
+ user-select: none;
17
+ transition: all var(--uds-animation-duration-200) var(--uds-animation-ease-standard);
18
+ box-sizing: border-box;
19
+ white-space: nowrap;
20
+ width: fit-content;
21
+ height: fit-content;
22
+ min-height: 40px;
23
+
24
+ &__input {
25
+ opacity: 0;
26
+ width: 0;
27
+ height: 0;
28
+ position: absolute;
29
+
30
+ &:focus-visible + .uds-pill-toggle__label {
31
+ outline: var(--uds-focus-ring-width) solid var(--uds-focus-ring-border);
32
+ outline-offset: var(--uds-focus-ring-offset);
33
+ border-radius: 4px;
34
+ }
35
+ }
36
+
37
+ &__label {
38
+ display: inline-block;
39
+ white-space: nowrap;
40
+ text-align: center;
41
+ line-height: var(--uds-line-height-24);
42
+ }
43
+
44
+ // Unselected state (default) - hover and active
45
+ &:hover:not(.uds-pill-toggle--disabled):not(.uds-pill-toggle--selected) {
46
+ border-color: var(--uds-border-secondary);
47
+ background-color: var(--uds-surface-secondary);
48
+ }
49
+
50
+ &:active:not(.uds-pill-toggle--disabled):not(.uds-pill-toggle--selected) {
51
+ border-color: var(--uds-border-tertiary);
52
+ background-color: var(--uds-surface-tertiary);
53
+ }
54
+
55
+ // Selected state
56
+ &--selected {
57
+ background-color: var(--uds-surface-brand-primary);
58
+ border-color: var(--uds-border-brand-primary);
59
+ color: var(--uds-text-inverse, white);
60
+
61
+ &:hover:not(.uds-pill-toggle--disabled) {
62
+ background-color: var(--uds-surface-brand-secondary);
63
+ border-color: var(--uds-border-brand-primary);
64
+ }
65
+
66
+ &:active:not(.uds-pill-toggle--disabled) {
67
+ background-color: var(--uds-surface-brand-tertiary);
68
+ border-color: var(--uds-border-brand-primary);
69
+ }
70
+ }
71
+
72
+ // Disabled state
73
+ &--disabled {
74
+ cursor: not-allowed;
75
+ opacity: 0.6;
76
+ pointer-events: none;
77
+ }
78
+
79
+ // Focus state
80
+ &:focus-visible {
81
+ outline: solid var(--uds-focus-ring-width) var(--uds-focus-ring-border);
82
+ outline-offset: var(--uds-focus-ring-offset);
83
+ }
84
+ }
@@ -0,0 +1 @@
1
+ export { default } from "./PillToggle";