@ethlete/components 1.0.0-next.77 → 1.0.0-next.79

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 (318) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/design/accordion.ts +73 -0
  3. package/design/avatar.ts +90 -0
  4. package/design/badge.ts +48 -0
  5. package/design/banner.ts +77 -0
  6. package/design/bracket.ts +457 -0
  7. package/design/breadcrumb.ts +145 -0
  8. package/design/button.ts +49 -0
  9. package/design/calendar.ts +306 -0
  10. package/design/card.ts +92 -0
  11. package/design/carousel.ts +240 -0
  12. package/design/chart.ts +512 -0
  13. package/design/checkbox.ts +275 -0
  14. package/design/chip.ts +64 -0
  15. package/design/config.json +22 -0
  16. package/design/control.ts +19 -0
  17. package/design/copy-button.ts +59 -0
  18. package/design/description-list.ts +41 -0
  19. package/design/dialog.ts +214 -0
  20. package/design/divider.ts +27 -0
  21. package/design/empty-state.ts +45 -0
  22. package/design/floating-action.ts +55 -0
  23. package/design/form-field.ts +40 -1
  24. package/design/grid.ts +148 -0
  25. package/design/icon-set.ts +19 -0
  26. package/design/icon.ts +9 -0
  27. package/design/input.ts +86 -0
  28. package/design/kbd.ts +19 -0
  29. package/design/loader.ts +152 -0
  30. package/design/masonry.ts +115 -0
  31. package/design/match.ts +131 -0
  32. package/design/menu.ts +143 -0
  33. package/design/notification.ts +129 -0
  34. package/design/otp-input.ts +107 -0
  35. package/design/pagination.ts +120 -0
  36. package/design/picture.ts +80 -0
  37. package/design/progress-steps.ts +79 -0
  38. package/design/query-error.ts +60 -0
  39. package/design/radio-group.ts +132 -0
  40. package/design/scheduler.ts +369 -0
  41. package/design/scrollable.ts +218 -0
  42. package/design/scrollbar.ts +47 -0
  43. package/design/sdk/assets/fallback.svg +1 -0
  44. package/design/sdk/assets/tall.svg +1 -0
  45. package/design/sdk/assets/wide.svg +1 -0
  46. package/design/sdk/components/accent-on-light/accent-on-light.css +35 -0
  47. package/design/sdk/components/accent-on-light/accent-on-light.ts +10 -0
  48. package/design/sdk/components/accent-on-light/shared/controls.ts +46 -0
  49. package/design/sdk/components/accordion/accordion.css +17 -0
  50. package/design/sdk/components/accordion/accordion.ts +64 -0
  51. package/design/sdk/components/avatar/avatar.css +14 -0
  52. package/design/sdk/components/avatar/avatar.ts +78 -0
  53. package/design/sdk/components/badge/badge.css +13 -0
  54. package/design/sdk/components/badge/badge.ts +52 -0
  55. package/design/sdk/components/banner/banner.css +18 -0
  56. package/design/sdk/components/banner/banner.ts +87 -0
  57. package/design/sdk/components/bracket/bracket.css +59 -0
  58. package/design/sdk/components/bracket/bracket.ts +143 -0
  59. package/design/sdk/components/breadcrumb/breadcrumb.css +25 -0
  60. package/design/sdk/components/breadcrumb/breadcrumb.ts +81 -0
  61. package/design/sdk/components/button/button.css +33 -0
  62. package/design/sdk/components/button/button.ts +82 -0
  63. package/design/sdk/components/calendar/calendar.css +33 -0
  64. package/design/sdk/components/calendar/calendar.ts +96 -0
  65. package/design/sdk/components/card/card.css +19 -0
  66. package/design/sdk/components/card/card.ts +61 -0
  67. package/design/sdk/components/carousel/carousel.css +44 -0
  68. package/design/sdk/components/carousel/carousel.ts +74 -0
  69. package/design/sdk/components/chart/chart.css +56 -0
  70. package/design/sdk/components/chart/chart.ts +98 -0
  71. package/design/sdk/components/chip/chip.css +18 -0
  72. package/design/sdk/components/chip/chip.ts +76 -0
  73. package/design/sdk/components/copy-button/copy-button.css +14 -0
  74. package/design/sdk/components/copy-button/copy-button.ts +59 -0
  75. package/design/sdk/components/description-list/description-list.css +7 -0
  76. package/design/sdk/components/description-list/description-list.ts +53 -0
  77. package/design/sdk/components/dialog/dialog.css +29 -0
  78. package/design/sdk/components/dialog/dialog.ts +78 -0
  79. package/design/sdk/components/divider/divider.css +26 -0
  80. package/design/sdk/components/divider/divider.ts +43 -0
  81. package/design/sdk/components/empty-state/empty-state.css +15 -0
  82. package/design/sdk/components/empty-state/empty-state.ts +56 -0
  83. package/design/sdk/components/floating-action/floating-action.css +51 -0
  84. package/design/sdk/components/floating-action/floating-action.ts +63 -0
  85. package/design/sdk/components/form-field/form-field.ts +118 -0
  86. package/design/sdk/components/grid/grid.css +17 -0
  87. package/design/sdk/components/grid/grid.ts +80 -0
  88. package/design/sdk/components/input/input.css +75 -0
  89. package/design/sdk/components/input/input.ts +79 -0
  90. package/design/sdk/components/kbd/kbd.css +25 -0
  91. package/design/sdk/components/kbd/kbd.ts +57 -0
  92. package/design/sdk/components/loader/loader.css +37 -0
  93. package/design/sdk/components/loader/loader.ts +68 -0
  94. package/design/sdk/components/masonry/masonry.css +7 -0
  95. package/design/sdk/components/masonry/masonry.ts +42 -0
  96. package/design/sdk/components/match/match.css +25 -0
  97. package/design/sdk/components/match/match.ts +76 -0
  98. package/design/sdk/components/menu/menu.css +22 -0
  99. package/design/sdk/components/menu/menu.ts +91 -0
  100. package/design/sdk/components/notification/notification.css +32 -0
  101. package/design/sdk/components/notification/notification.ts +106 -0
  102. package/design/sdk/components/otp-input/otp-input.css +35 -0
  103. package/design/sdk/components/otp-input/otp-input.ts +64 -0
  104. package/design/sdk/components/pagination/pagination.css +14 -0
  105. package/design/sdk/components/pagination/pagination.ts +75 -0
  106. package/design/sdk/components/picture/picture.css +37 -0
  107. package/design/sdk/components/picture/picture.ts +96 -0
  108. package/design/sdk/components/progress-steps/progress-steps.css +37 -0
  109. package/design/sdk/components/progress-steps/progress-steps.ts +91 -0
  110. package/design/sdk/components/query-error/query-error.css +33 -0
  111. package/design/sdk/components/query-error/query-error.ts +120 -0
  112. package/design/sdk/components/scheduler/scheduler.css +55 -0
  113. package/design/sdk/components/scheduler/scheduler.ts +239 -0
  114. package/design/sdk/components/scrollable/scrollable.css +58 -0
  115. package/design/sdk/components/scrollable/scrollable.ts +133 -0
  116. package/design/sdk/components/scrollbar/scrollbar.css +78 -0
  117. package/design/sdk/components/scrollbar/scrollbar.ts +123 -0
  118. package/design/sdk/components/select/select.css +5 -0
  119. package/design/sdk/components/select/select.ts +16 -0
  120. package/design/sdk/components/select/shared/select-part.ts +75 -0
  121. package/design/sdk/components/select-panel/select-panel.css +3 -0
  122. package/design/sdk/components/select-panel/select-panel.ts +124 -0
  123. package/design/sdk/components/skeleton/skeleton.css +22 -0
  124. package/design/sdk/components/skeleton/skeleton.ts +50 -0
  125. package/design/sdk/components/slider/slider.css +52 -0
  126. package/design/sdk/components/slider/slider.ts +86 -0
  127. package/design/sdk/components/standings/standings.css +33 -0
  128. package/design/sdk/components/standings/standings.ts +130 -0
  129. package/design/sdk/components/stat-tile/stat-tile.css +15 -0
  130. package/design/sdk/components/stat-tile/stat-tile.ts +84 -0
  131. package/design/sdk/components/stream/stream.css +48 -0
  132. package/design/sdk/components/stream/stream.ts +38 -0
  133. package/design/sdk/components/switch/switch.css +35 -0
  134. package/design/sdk/components/switch/switch.ts +63 -0
  135. package/design/sdk/components/table/table.css +67 -0
  136. package/design/sdk/components/table/table.ts +160 -0
  137. package/design/sdk/components/tabs/tabs.css +13 -0
  138. package/design/sdk/components/tabs/tabs.ts +74 -0
  139. package/design/sdk/components/textarea/textarea.css +116 -0
  140. package/design/sdk/components/textarea/textarea.ts +64 -0
  141. package/design/sdk/components/timeline/timeline.css +30 -0
  142. package/design/sdk/components/timeline/timeline.ts +87 -0
  143. package/design/sdk/components/toolbar/toolbar.css +24 -0
  144. package/design/sdk/components/toolbar/toolbar.ts +87 -0
  145. package/design/sdk/components/tooltip/tooltip.css +15 -0
  146. package/design/sdk/components/tooltip/tooltip.ts +28 -0
  147. package/design/sdk/components/tree/selected-tint.css +15 -0
  148. package/design/sdk/components/tree/tree.ts +70 -0
  149. package/design/sdk/fixtures.ts +0 -0
  150. package/design/sdk/foundations/colors/colors.css +632 -0
  151. package/design/sdk/foundations/colors/colors.ts +188 -0
  152. package/design/sdk/foundations/colors/overrides.json +19 -0
  153. package/design/sdk/foundations/colors/shared/contrast.ts +120 -0
  154. package/design/sdk/foundations/elevation/elevation.css +6 -0
  155. package/design/sdk/foundations/elevation/elevation.ts +11 -0
  156. package/design/sdk/foundations/elevation/shared/elevation/scene.css +101 -0
  157. package/design/sdk/foundations/elevation/shared/elevation/scene.ts +74 -0
  158. package/design/sdk/foundations/icons/icons.ts +119 -0
  159. package/design/select.ts +113 -28
  160. package/design/skeleton.ts +67 -0
  161. package/design/slider.ts +155 -0
  162. package/design/standings.ts +161 -0
  163. package/design/stat-tile.ts +109 -0
  164. package/design/stream.ts +92 -0
  165. package/design/switch.ts +83 -0
  166. package/design/table.ts +302 -0
  167. package/design/tabs.ts +75 -0
  168. package/design/textarea.ts +92 -0
  169. package/design/timeline.ts +52 -0
  170. package/design/toolbar.ts +95 -0
  171. package/design/tooltip.ts +87 -0
  172. package/design/tree.ts +106 -0
  173. package/fesm2022/ethlete-components.mjs +240 -199
  174. package/fesm2022/ethlete-components.mjs.map +1 -1
  175. package/package.json +1 -1
  176. package/src/lib/accordion/accordion.component.css +2 -1
  177. package/src/lib/avatar/avatar.component.css +10 -0
  178. package/src/lib/badge/badge.component.css +2 -2
  179. package/src/lib/banner/banner.component.css +3 -1
  180. package/src/lib/breadcrumb/breadcrumb-outlet.component.css +5 -0
  181. package/src/lib/breadcrumb/breadcrumb.component.css +5 -1
  182. package/src/lib/button/button.component.css +19 -0
  183. package/src/lib/button/icon-button.component.css +19 -20
  184. package/src/lib/button/split-button.component.css +5 -1
  185. package/src/lib/calendar/calendar.component.css +13 -3
  186. package/src/lib/card/card.component.css +4 -0
  187. package/src/lib/carousel/carousel-autoplay-styles.component.css +1 -1
  188. package/src/lib/carousel/carousel.component.css +2 -2
  189. package/src/lib/chart/chart-axis.component.css +3 -3
  190. package/src/lib/chip/chip.component.css +8 -2
  191. package/src/lib/description-list/description-list.component.css +2 -1
  192. package/src/lib/empty-state/empty-state.component.css +4 -0
  193. package/src/lib/floating-action/floating-action-styles.component.css +27 -0
  194. package/src/lib/focus-ring/focus-ring-styles.component.css +4 -1
  195. package/src/lib/forms/checkbox/checkbox.component.css +31 -5
  196. package/src/lib/forms/color-input/color-input.component.css +3 -1
  197. package/src/lib/forms/color-input/color-picker-panel.component.css +6 -2
  198. package/src/lib/forms/date-time/date-input/date-input.component.css +1 -1
  199. package/src/lib/forms/date-time/date-time-input/date-time-input.component.css +1 -1
  200. package/src/lib/forms/date-time/duration-input/duration-input.component.css +1 -1
  201. package/src/lib/forms/date-time/range-input-shell-styles.component.css +1 -1
  202. package/src/lib/forms/date-time/time-input/time-input.component.css +1 -1
  203. package/src/lib/forms/description/description.component.css +7 -0
  204. package/src/lib/forms/dropzone/dropzone.component.css +26 -0
  205. package/src/lib/forms/form-field/form-field-control-suffix-styles.component.css +4 -2
  206. package/src/lib/forms/form-field/form-field-text-shell-styles.component.css +74 -17
  207. package/src/lib/forms/form-field/form-field-textarea-styles.component.css +62 -0
  208. package/src/lib/forms/form-field/form-field.component.css +6 -0
  209. package/src/lib/forms/form-field/headless/label.directive.css +1 -1
  210. package/src/lib/forms/input/input.component.css +6 -2
  211. package/src/lib/forms/input/number-input.component.css +2 -2
  212. package/src/lib/forms/input/password-input.component.css +4 -3
  213. package/src/lib/forms/otp-input/otp-input.component.css +23 -4
  214. package/src/lib/forms/phone-input/phone-input.component.css +4 -3
  215. package/src/lib/forms/rating/rating.component.css +2 -1
  216. package/src/lib/forms/rich-text-editor/rich-text-editor.component.css +1 -1
  217. package/src/lib/forms/select/select-option-styles.component.css +3 -2
  218. package/src/lib/forms/selection-card-styles.component.css +3 -2
  219. package/src/lib/forms/selection-list/checkbox-group/checkbox-group-select-all.component.css +4 -2
  220. package/src/lib/forms/selection-list/checkbox-group/checkbox-option.component.css +4 -2
  221. package/src/lib/forms/selection-list/radio-group/radio.component.css +5 -2
  222. package/src/lib/forms/selection-list/segmented-button-group/segmented-button.component.css +2 -1
  223. package/src/lib/forms/slider/range-slider.component.css +98 -6
  224. package/src/lib/forms/slider/slider.component.css +96 -4
  225. package/src/lib/forms/switch/switch.component.css +47 -4
  226. package/src/lib/forms/tag-input/tag-input.component.css +2 -2
  227. package/src/lib/forms/textarea/textarea-autosize-styles.component.css +2 -3
  228. package/src/lib/forms/textarea/textarea.component.css +7 -2
  229. package/src/lib/grid/grid-item-toolbar.component.css +10 -0
  230. package/src/lib/grid/grid-item.component.css +6 -1
  231. package/src/lib/icon/headless/align-icons.ts +30 -0
  232. package/src/lib/icon/headless/arrow-out-up-right-icon.ts +17 -0
  233. package/src/lib/icon/headless/arrow-right-icon.ts +23 -0
  234. package/src/lib/icon/headless/arrow-up-icon.ts +30 -0
  235. package/src/lib/icon/headless/arrows-left-right-icon.ts +31 -0
  236. package/src/lib/icon/headless/bold-icon.ts +11 -0
  237. package/src/lib/icon/headless/calendar-icon.ts +21 -0
  238. package/src/lib/icon/headless/check-icon.ts +14 -0
  239. package/src/lib/icon/headless/chevron-icon.ts +14 -0
  240. package/src/lib/icon/headless/circle-check-icon.ts +14 -0
  241. package/src/lib/icon/headless/circle-info-icon.ts +14 -0
  242. package/src/lib/icon/headless/clipboard-check-icon.ts +28 -0
  243. package/src/lib/icon/headless/clock-icon.ts +21 -0
  244. package/src/lib/icon/headless/code-block-icon.ts +15 -0
  245. package/src/lib/icon/headless/code-icon.ts +14 -0
  246. package/src/lib/icon/headless/ellipsis-icon.ts +13 -0
  247. package/src/lib/icon/headless/ellipsis-vertical-icon.ts +13 -0
  248. package/src/lib/icon/headless/eye-icons.ts +27 -0
  249. package/src/lib/icon/headless/eyedropper-icon.ts +22 -0
  250. package/src/lib/icon/headless/file-icon.ts +16 -0
  251. package/src/lib/icon/headless/filter-icon.ts +11 -0
  252. package/src/lib/icon/headless/floppy-disk-icon.ts +27 -0
  253. package/src/lib/icon/headless/focus-frame-icon.ts +16 -0
  254. package/src/lib/icon/headless/grid-2x2-icon.ts +17 -0
  255. package/src/lib/icon/headless/heading-1-icon.ts +11 -0
  256. package/src/lib/icon/headless/heading-2-icon.ts +11 -0
  257. package/src/lib/icon/headless/heading-3-icon.ts +11 -0
  258. package/src/lib/icon/headless/icon-definition.ts +14 -0
  259. package/src/lib/icon/headless/image-icon.ts +14 -0
  260. package/src/lib/icon/headless/italic-icon.ts +19 -0
  261. package/src/lib/icon/headless/link-icon.ts +17 -0
  262. package/src/lib/icon/headless/list-bulleted-icon.ts +14 -0
  263. package/src/lib/icon/headless/list-numbered-icon.ts +14 -0
  264. package/src/lib/icon/headless/location-icon.ts +21 -0
  265. package/src/lib/icon/headless/lock-icon.ts +14 -0
  266. package/src/lib/icon/headless/minus-icon.ts +14 -0
  267. package/src/lib/icon/headless/paragraph-icon.ts +11 -0
  268. package/src/lib/icon/headless/pause-icon.ts +11 -0
  269. package/src/lib/icon/headless/pencil-icon.ts +21 -0
  270. package/src/lib/icon/headless/play-icon.ts +10 -0
  271. package/src/lib/icon/headless/plus-icon.ts +21 -0
  272. package/src/lib/icon/headless/quote-icon.ts +15 -0
  273. package/src/lib/icon/headless/rotate-right-icon.ts +16 -0
  274. package/src/lib/icon/headless/star-icon.ts +14 -0
  275. package/src/lib/icon/headless/strikethrough-icon.ts +18 -0
  276. package/src/lib/icon/headless/table-icon.ts +15 -0
  277. package/src/lib/icon/headless/thumbtack-icon.ts +18 -0
  278. package/src/lib/icon/headless/times-icon.ts +14 -0
  279. package/src/lib/icon/headless/trash-icon.ts +24 -0
  280. package/src/lib/icon/headless/triangle-exclamation-icon.ts +14 -0
  281. package/src/lib/icon/headless/trophy-icon.ts +24 -0
  282. package/src/lib/icon/headless/underline-icon.ts +12 -0
  283. package/src/lib/icon/headless/undo-redo-icons.ts +24 -0
  284. package/src/lib/icon/headless/upload-icon.ts +16 -0
  285. package/src/lib/loader/brand-loader/brand-loader.component.css +4 -1
  286. package/src/lib/loader/progress-bar/progress-bar.component.css +1 -1
  287. package/src/lib/loader/spinner/spinner-styles.component.css +1 -1
  288. package/src/lib/match/match-card.component.css +9 -3
  289. package/src/lib/match/match-score.component.css +4 -1
  290. package/src/lib/menu/menu-selection-item.component.css +1 -1
  291. package/src/lib/menu/menu.component.css +5 -0
  292. package/src/lib/overlay/overlay-container.component.css +4 -0
  293. package/src/lib/pagination/pagination.component.css +4 -0
  294. package/src/lib/progress-steps/progress-step.component.css +4 -4
  295. package/src/lib/query-error/query-error.component.css +4 -0
  296. package/src/lib/scheduler/scheduler-appointment-styles.component.css +21 -5
  297. package/src/lib/scheduler/scheduler-month-view.component.css +4 -2
  298. package/src/lib/scheduler/scheduler-time-grid-view.component.css +8 -2
  299. package/src/lib/scrollable/headless/scrollable-navigation.component.css +1 -1
  300. package/src/lib/standings/standings-pick.component.css +1 -1
  301. package/src/lib/standings/standings.component.css +10 -10
  302. package/src/lib/stat-tile/stat-tile-sparkline.component.css +1 -1
  303. package/src/lib/stream/consent/stream-consent.component.css +99 -0
  304. package/src/lib/stream/error/stream-player-error.component.css +100 -0
  305. package/src/lib/stream/loading/stream-player-loading.component.css +16 -0
  306. package/src/lib/stream/pip/pip-slot-placeholder.component.css +68 -0
  307. package/src/lib/stream/stream-player-slot-styles.component.css +4 -0
  308. package/src/lib/table/table-resize-grip.component.css +2 -1
  309. package/src/lib/table/table-select-cell.component.css +45 -15
  310. package/src/lib/table/table.component.css +15 -5
  311. package/src/lib/tabs/tab-bar-styles.component.css +1 -1
  312. package/src/lib/tabs/tabs/tab-group.component.css +111 -0
  313. package/src/lib/time-picker/time-picker.component.css +2 -1
  314. package/src/lib/timeline/timeline-item.component.css +5 -1
  315. package/src/lib/toolbar/toolbar.component.css +4 -0
  316. package/src/lib/tooltip/tooltip.component.css +14 -0
  317. package/src/lib/tree/tree.component.css +2 -2
  318. package/types/ethlete-components.d.ts +62 -53
@@ -0,0 +1,79 @@
1
+ import { textInput, type TextInputMockOptions, textInputStyles } from '@ethlete/components/design/input';
2
+ import { definePart, drawing } from '@design-system';
3
+ import frame from './input.css?inline';
4
+
5
+ type Props = { field: TextInputMockOptions };
6
+
7
+ const email = (extra: Partial<TextInputMockOptions> = {}): Props => ({
8
+ field: { id: 'email', label: 'Email', placeholder: 'name@example.com', ...extra },
9
+ });
10
+
11
+ const VALUE = 'lena.hoffmann@example.com';
12
+
13
+ const INVALID = {
14
+ required: true,
15
+ value: 'lena.hoffmann@',
16
+ error: 'Enter a valid email address.',
17
+ errorColor: 'danger',
18
+ } satisfies Partial<TextInputMockOptions>;
19
+
20
+ export default definePart({
21
+ note: 'scale of the decided shape, Q182, lead merge',
22
+ madeBy: ['claude-opus-5-5'],
23
+ states: {
24
+ empty: email({ placeholder: undefined }),
25
+ placeholder: email(),
26
+ filled: email({ value: VALUE }),
27
+ hover: email({ force: 'hover' }),
28
+ 'hover-filled': email({ value: VALUE, force: 'hover' }),
29
+ focus: email({ focused: true, force: 'focus-visible' }),
30
+ 'focus-filled': email({ value: VALUE, focused: true, force: 'focus-visible' }),
31
+ 'focus-hover': email({ value: VALUE, focused: true, force: ['focus-visible', 'hover'] }),
32
+ hint: email({ hint: 'We only use it to sign you in.' }),
33
+ description: email({ description: 'Your team sees this address on your profile.' }),
34
+ required: email({ required: true, hint: 'We only use it to sign you in.' }),
35
+ invalid: email(INVALID),
36
+ 'invalid-hover': email({ ...INVALID, force: 'hover' }),
37
+ 'invalid-focus': email({ ...INVALID, focused: true, force: 'focus-visible' }),
38
+ 'invalid-focus-hover': email({ ...INVALID, focused: true, force: ['focus-visible', 'hover'] }),
39
+ disabled: email({ disabled: true }),
40
+ 'disabled-filled': email({ value: VALUE, disabled: true }),
41
+ readonly: email({ value: VALUE, readonly: true }),
42
+ 'readonly-hover': email({ value: VALUE, readonly: true, force: 'hover' }),
43
+ 'readonly-focus': email({ value: VALUE, readonly: true, focused: true, force: 'focus-visible' }),
44
+ long: email({ value: 'lena.hoffmann-schulze.marketing-department@example-company.com' }),
45
+ 'icon-affixes': {
46
+ field: { id: 'key', label: 'API key', placeholder: 'sk-…', prefixIcon: 'lock', suffixIcon: 'check' },
47
+ },
48
+ 'text-affixes': {
49
+ field: { id: 'site', label: 'Website', value: 'example.com', prefix: 'https://', suffix: '.de' },
50
+ },
51
+ 'text-prefix': {
52
+ field: { id: 'price', label: 'Price', value: '1,250.00', prefix: '€' },
53
+ },
54
+ search: {
55
+ field: { id: 'search', label: 'Search', type: 'search', value: 'running shoes' },
56
+ },
57
+ password: {
58
+ field: { id: 'password', label: 'Password', type: 'password', value: 'correct-horse' },
59
+ },
60
+ 'align-end': {
61
+ field: { id: 'amount', label: 'Amount', value: '1,250.00', textAlign: 'end', suffix: 'EUR' },
62
+ },
63
+ mixed: {
64
+ field: { id: 'title', label: 'Title', value: 'shared draft title', mixed: true, mixedLabel: 'Mixed values' },
65
+ },
66
+ 'no-label': {
67
+ field: { id: 'quick', placeholder: 'Search…', prefixIcon: 'lock' },
68
+ },
69
+ 'size-sm': email({ value: VALUE, size: 'sm' }),
70
+ 'size-lg': email({ value: VALUE, size: 'lg' }),
71
+ 'align-center': email({ value: VALUE, textAlign: 'center' }),
72
+ },
73
+ widths: [320, 360, 640],
74
+ render: (props: Props) =>
75
+ drawing({
76
+ body: `<div class="t-frame">${textInput(props.field)}</div>`,
77
+ styles: [textInputStyles, frame].join('\n'),
78
+ }),
79
+ });
@@ -0,0 +1,25 @@
1
+ .kbd-frame {
2
+ padding: 2.4rem 1.6rem;
3
+ background: var(--et-surface-background-solid);
4
+ color: var(--et-surface-color-solid);
5
+ }
6
+
7
+ .kbd-text {
8
+ margin: 0;
9
+ font-size: 1.4rem;
10
+ line-height: 1.6;
11
+ }
12
+
13
+ .kbd-list {
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: 1.2rem;
17
+ font-size: 1.3rem;
18
+ }
19
+
20
+ .kbd-row {
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: space-between;
24
+ gap: 1.6rem;
25
+ }
@@ -0,0 +1,57 @@
1
+ import { kbd, kbdStyles } from '@ethlete/components/design/kbd';
2
+ import { definePart, drawing } from '@design-system';
3
+ import frame from './kbd.css?inline';
4
+
5
+ type Platform = 'apple' | 'other';
6
+
7
+ type Props = {
8
+ form: 'single' | 'combo' | 'in-text' | 'shortcut-list';
9
+ platform: Platform;
10
+ };
11
+
12
+ const MOD = { apple: '⌘', other: 'Ctrl' } as const;
13
+ const SHIFT = { apple: '⇧', other: 'Shift' } as const;
14
+ const ALT = { apple: '⌥', other: 'Alt' } as const;
15
+
16
+ const SHORTCUTS = (p: Platform) => [
17
+ { label: 'Save', keys: [MOD[p], 'S'] },
18
+ { label: 'Undo', keys: [MOD[p], 'Z'] },
19
+ { label: 'Redo', keys: [MOD[p], SHIFT[p], 'Z'] },
20
+ { label: 'Move up a level', keys: [ALT[p], '↑'] },
21
+ { label: 'Next page', keys: ['PgDn'] },
22
+ { label: 'Zoom in', keys: [MOD[p], '+'] },
23
+ ];
24
+
25
+ const render = ({ form, platform: p }: Props) => {
26
+ switch (form) {
27
+ case 'single':
28
+ return kbd({ keys: ['Esc'] });
29
+ case 'combo':
30
+ return kbd({ keys: [MOD[p], 'K'] });
31
+ case 'in-text':
32
+ return `<p class="kbd-text">Press ${kbd({ keys: [MOD[p], 'K'] })} to open the palette, then ${kbd({ keys: ['Esc'] })} to dismiss it.</p>`;
33
+ case 'shortcut-list':
34
+ return `<div class="kbd-list">${SHORTCUTS(p)
35
+ .map(({ label, keys }) => `<div class="kbd-row"><span>${label}</span>${kbd({ keys })}</div>`)
36
+ .join('')}</div>`;
37
+ }
38
+ };
39
+
40
+ export default definePart({
41
+ note: "Today's look",
42
+ madeBy: ['claude-opus-5-5'],
43
+ states: {
44
+ single: { form: 'single', platform: 'apple' },
45
+ 'combo-apple': { form: 'combo', platform: 'apple' },
46
+ 'combo-other': { form: 'combo', platform: 'other' },
47
+ 'in-text': { form: 'in-text', platform: 'apple' },
48
+ 'shortcut-list-apple': { form: 'shortcut-list', platform: 'apple' },
49
+ 'shortcut-list-other': { form: 'shortcut-list', platform: 'other' },
50
+ },
51
+ widths: [480],
52
+ render: (props: Props) =>
53
+ drawing({
54
+ body: `<div class="kbd-frame">${render(props)}</div>`,
55
+ styles: [kbdStyles, frame].join('\n'),
56
+ }),
57
+ });
@@ -0,0 +1,37 @@
1
+ .loader-frame {
2
+ padding: 2.4rem 1.6rem;
3
+ background: var(--et-surface-background-solid);
4
+ color: var(--et-surface-color-solid);
5
+ }
6
+
7
+ .loader-row {
8
+ display: flex;
9
+ align-items: center;
10
+ gap: 2.4rem;
11
+ }
12
+
13
+ .loader-column {
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: 2rem;
17
+ }
18
+
19
+ @layer components {
20
+ .et-spinner.et-color--brand {
21
+ --et-spinner-color: var(--et-theme-color-ink-solid);
22
+ }
23
+
24
+ .et-progress-bar.et-color--brand {
25
+ --et-progress-bar-indicator-color: var(--et-theme-color-ink-solid);
26
+ }
27
+
28
+ .et-brand-loader .et-brand-loader__outline {
29
+ stroke: var(--et-theme-color-ink-solid);
30
+ }
31
+
32
+ .et-brand-loader .et-brand-loader__fill {
33
+ stroke: var(--et-theme-color-ink-solid);
34
+ stroke-width: 0.7;
35
+ stroke-linejoin: round;
36
+ }
37
+ }
@@ -0,0 +1,68 @@
1
+ import { brandLoader, loaderStyles, progressBar, spinner } from '@ethlete/components/design/loader';
2
+ import { definePart, drawing } from '@design-system';
3
+ import frame from './loader.css?inline';
4
+
5
+ type Props = {
6
+ form: 'spinner' | 'spinner-determinate' | 'spinner-themed' | 'progress-bar' | 'progress-bar-themed' | 'brand-loader';
7
+ };
8
+
9
+ const row = (items: string[]) => `<div class="loader-row">${items.join('')}</div>`;
10
+
11
+ const column = (items: string[]) => `<div class="loader-column">${items.join('')}</div>`;
12
+
13
+ const render = ({ form }: Props) => {
14
+ switch (form) {
15
+ case 'spinner':
16
+ return row([
17
+ spinner(),
18
+ spinner({ diameter: 45, strokeWidth: 2 }),
19
+ spinner({ diameter: 45, strokeWidth: 2, track: true }),
20
+ spinner({ diameter: 72, strokeWidth: 4, track: true }),
21
+ ]);
22
+ case 'spinner-determinate':
23
+ return row([
24
+ spinner({ diameter: 45, strokeWidth: 2, track: true, value: 0 }),
25
+ spinner({ diameter: 45, strokeWidth: 2, track: true, value: 65 }),
26
+ spinner({ diameter: 45, strokeWidth: 2, track: true, value: 100 }),
27
+ spinner({ diameter: 45, strokeWidth: 2, value: 65 }),
28
+ ]);
29
+ case 'spinner-themed':
30
+ return row([
31
+ spinner({ diameter: 45, strokeWidth: 2, track: true, color: 'brand' }),
32
+ spinner({ diameter: 45, strokeWidth: 2, track: true, value: 65, color: 'brand' }),
33
+ spinner({ diameter: 45, strokeWidth: 2, track: true, color: 'danger' }),
34
+ spinner({ diameter: 45, strokeWidth: 2, track: true, color: 'warning' }),
35
+ ]);
36
+ case 'progress-bar':
37
+ return column([progressBar({ value: 42 }), progressBar({ value: 100 }), progressBar()]);
38
+ case 'progress-bar-themed':
39
+ return column([
40
+ progressBar({ value: 42, color: 'brand' }),
41
+ progressBar({ color: 'brand' }),
42
+ progressBar({ value: 42, color: 'danger' }),
43
+ progressBar({ value: 42, color: 'warning' }),
44
+ ]);
45
+ case 'brand-loader':
46
+ return row([brandLoader()]);
47
+ }
48
+ };
49
+
50
+ export default definePart({
51
+ note: 'Decided rules only',
52
+ madeBy: ['claude-opus-5-5'],
53
+ states: {
54
+ spinner: { form: 'spinner' },
55
+ 'spinner-determinate': { form: 'spinner-determinate' },
56
+ 'spinner-themed': { form: 'spinner-themed' },
57
+ 'progress-bar': { form: 'progress-bar' },
58
+ 'progress-bar-themed': { form: 'progress-bar-themed' },
59
+ 'brand-loader': { form: 'brand-loader' },
60
+ },
61
+ checks: { skip: ['CLIPPED'] },
62
+ widths: [480],
63
+ render: (props: Props) =>
64
+ drawing({
65
+ body: `<div class="loader-frame">${render(props)}</div>`,
66
+ styles: [loaderStyles, frame].join('\n'),
67
+ }),
68
+ });
@@ -0,0 +1,7 @@
1
+ .t-frame {
2
+ box-sizing: border-box;
3
+ padding: 1.6rem;
4
+ background: var(--et-surface-background-solid);
5
+ color: var(--et-surface-color-solid);
6
+ font-size: 1.4rem;
7
+ }
@@ -0,0 +1,42 @@
1
+ import { masonry, MasonryMockItem, masonryStyles } from '@ethlete/components/design/masonry';
2
+ import { definePart, drawing } from '@design-system';
3
+ import frame from './masonry.css?inline';
4
+
5
+ type Props = {
6
+ items: 'rest' | 'uneven' | 'few';
7
+ width?: number;
8
+ columnWidth?: number;
9
+ dir?: 'rtl';
10
+ };
11
+
12
+ const tiles = (heights: readonly number[]): MasonryMockItem[] =>
13
+ heights.map((height, index) => ({ title: `Card ${index + 1}`, subtitle: `Height ${height}`, height }));
14
+
15
+ const ITEMS = {
16
+ rest: tiles([120, 160, 140, 180, 120, 150, 140, 110]),
17
+ uneven: tiles([80, 260, 120, 60, 200, 90, 170, 70, 130]),
18
+ few: tiles([120, 160, 100]),
19
+ };
20
+
21
+ export default definePart({
22
+ note: "Today's look",
23
+ madeBy: ['claude-opus-5-5'],
24
+ states: {
25
+ rest: { items: 'rest', columnWidth: 130 },
26
+ uneven: { items: 'uneven', columnWidth: 130 },
27
+ narrow: { items: 'rest', columnWidth: 130, width: 280 },
28
+ 'single-column': { items: 'few' },
29
+ rtl: { items: 'rest', columnWidth: 130, dir: 'rtl' },
30
+ },
31
+ widths: [480],
32
+ render: (props: Props) =>
33
+ drawing({
34
+ body: `<div class="t-frame">${masonry({
35
+ items: ITEMS[props.items],
36
+ width: props.width,
37
+ columnWidth: props.columnWidth,
38
+ dir: props.dir,
39
+ })}</div>`,
40
+ styles: [masonryStyles, frame].join('\n'),
41
+ }),
42
+ });
@@ -0,0 +1,25 @@
1
+ .t-frame {
2
+ box-sizing: border-box;
3
+ padding: 1.6rem;
4
+ background: var(--et-surface-background-solid);
5
+ color: var(--et-surface-color-solid);
6
+ font-size: 1.4rem;
7
+ }
8
+
9
+ @layer components {
10
+ .et-match-card.et-focus-ring {
11
+ --_et-focus-ring-color: var(--et-theme-color-ink-solid);
12
+ }
13
+
14
+ .et-match-card:where([data-winner='home']) .et-match-card-side:where([data-side='home']),
15
+ .et-match-card:where([data-winner='away']) .et-match-card-side:where([data-side='away']) {
16
+ --_et-match-card-side-marker-color: light-dark(
17
+ var(--et-theme-color-ink-solid),
18
+ var(--et-theme-color-primary-solid)
19
+ );
20
+ }
21
+
22
+ .et-match-card-live-dot {
23
+ background: light-dark(var(--et-theme-color-ink-solid), var(--et-theme-color-primary-solid));
24
+ }
25
+ }
@@ -0,0 +1,76 @@
1
+ import { matchCard, MatchMockOptions, matchStyles } from '@ethlete/components/design/match';
2
+ import { definePart, drawing } from '@design-system';
3
+ import frame from './match.css?inline';
4
+
5
+ type Props = { card: MatchMockOptions };
6
+
7
+ const HOME = { name: 'Northbridge Rovers', code: 'NBR', subtitle: 'Northbridge', seed: 1 };
8
+ const AWAY = { name: 'Harbor City', code: 'HBC', subtitle: 'Harbor', seed: 4 };
9
+
10
+ const finished: MatchMockOptions = {
11
+ home: HOME,
12
+ away: AWAY,
13
+ status: 'finished',
14
+ homeScore: 2,
15
+ awayScore: 1,
16
+ winnerSide: 'home',
17
+ label: 'Matchday 12',
18
+ startTime: '10/31/2026 8:00 PM',
19
+ };
20
+
21
+ export default definePart({
22
+ note: 'scale of the decided shape, Q182, lead merge',
23
+ madeBy: ['claude-opus-5-5'],
24
+ states: {
25
+ finished: { card: finished },
26
+ live: {
27
+ card: {
28
+ home: HOME,
29
+ away: AWAY,
30
+ status: 'live',
31
+ homeScore: 1,
32
+ awayScore: 1,
33
+ label: 'Matchday 12',
34
+ liveColor: 'danger',
35
+ },
36
+ },
37
+ scheduled: {
38
+ card: { home: HOME, away: AWAY, status: 'scheduled', label: 'Matchday 13', startTime: '11/07/2026 6:30 PM' },
39
+ },
40
+ series: {
41
+ card: {
42
+ home: HOME,
43
+ away: AWAY,
44
+ status: 'finished',
45
+ homeScore: 1,
46
+ awayScore: 2,
47
+ winnerSide: 'away',
48
+ gameScores: [
49
+ { home: 13, away: 11 },
50
+ { home: 9, away: 13 },
51
+ { home: 10, away: 13 },
52
+ ],
53
+ label: 'Semi-final, best of 3',
54
+ showSeeds: true,
55
+ },
56
+ },
57
+ outcome: {
58
+ card: { home: HOME, away: AWAY, status: 'finished', resultKind: 'outcome', winnerSide: 'away', label: 'Round 3' },
59
+ },
60
+ tbd: {
61
+ card: { home: HOME, status: 'scheduled', label: 'Final', startTime: '11/21/2026 7:00 PM' },
62
+ },
63
+ compact: { card: { ...finished, size: 'compact' } },
64
+ expanded: { card: { ...finished, size: 'expanded' } },
65
+ wide: { card: { ...finished, size: 'wide' } },
66
+ hover: { card: { ...finished, interactive: true, force: 'hover' } },
67
+ 'focus-visible': { card: { ...finished, interactive: true, force: 'focus-visible' } },
68
+ },
69
+ widths: [280, 480, 720],
70
+ render: (props: Props) =>
71
+ drawing({
72
+ // Lib bug: et-match-score clips its 25px digit box to 24px (overflow: hidden at line-height 1.2), reported.
73
+ body: `<div class="t-frame">${matchCard(props.card)}</div>`,
74
+ styles: [matchStyles, frame].join('\n'),
75
+ }),
76
+ });
@@ -0,0 +1,22 @@
1
+ .menu-frame {
2
+ display: flex;
3
+ padding: 0.8rem;
4
+ }
5
+
6
+ .menu-frame .et-menu {
7
+ --et-menu-max-height: 100rem;
8
+ }
9
+
10
+ @layer components {
11
+ .et-menu .et-menu-selection-item:not(.et-menu-selection-item--has-icon) .et-menu-item-check,
12
+ .et-menu .et-menu-selection-item--has-icon:is([aria-checked='true'], [aria-checked='mixed']) .et-menu-item-check {
13
+ color: var(--et-theme-color-ink-solid);
14
+ }
15
+ }
16
+
17
+ @layer components {
18
+ .et-menu .et-menu-item[data-active]:focus-visible {
19
+ outline: 2px solid var(--et-theme-color-ink-solid);
20
+ outline-offset: -2px;
21
+ }
22
+ }
@@ -0,0 +1,91 @@
1
+ import { menu, type MenuMockRow, menuStyles } from '@ethlete/components/design/menu';
2
+ import { definePart, drawing, interactionRows } from '@design-system';
3
+ import edge from './menu.css?inline';
4
+
5
+ type ItemInteraction = 'hover' | 'active' | 'focus-visible';
6
+
7
+ type Props = {
8
+ rows: MenuMockRow[];
9
+ forced?: ItemInteraction;
10
+ };
11
+
12
+ const MARK = 'data-et-control="item"';
13
+
14
+ const force = (interaction?: ItemInteraction) =>
15
+ [MARK, interaction && `data-et-force="${interaction}"`].filter(Boolean).join(' ');
16
+
17
+ const row = (label: string, extra: Partial<Extract<MenuMockRow, { label: string }>> = {}) =>
18
+ ({ label, attributes: MARK, ...extra }) as MenuMockRow;
19
+
20
+ const FULL: MenuMockRow[] = [
21
+ { kind: 'label', label: 'Document' },
22
+ row('Rename', { shortcut: 'F2' }),
23
+ row('Duplicate', { shortcut: 'Ctrl D' }),
24
+ row('Move to', { submenu: true }),
25
+ row('Export as PDF', { disabled: true }),
26
+ { kind: 'separator' },
27
+ {
28
+ kind: 'checkbox-group',
29
+ label: 'Show',
30
+ items: [
31
+ { kind: 'checkbox', label: 'Comments', checked: true, attributes: MARK },
32
+ { kind: 'checkbox', label: 'Suggestions', attributes: MARK },
33
+ ],
34
+ },
35
+ { kind: 'separator' },
36
+ {
37
+ kind: 'radio-group',
38
+ label: 'Sort by',
39
+ items: [
40
+ { kind: 'radio', label: 'Name', checked: true, attributes: MARK },
41
+ { kind: 'radio', label: 'Date', attributes: MARK },
42
+ ],
43
+ },
44
+ { kind: 'separator' },
45
+ row('Delete', { destructive: true }),
46
+ ];
47
+
48
+ const withForced = (rows: MenuMockRow[], forced?: ItemInteraction): MenuMockRow[] =>
49
+ rows.map((entry, index) =>
50
+ index === 1 && 'label' in entry && entry.kind !== 'label'
51
+ ? ({ ...entry, active: !!forced, attributes: force(forced) } as MenuMockRow)
52
+ : entry,
53
+ );
54
+
55
+ const { states, grid } = interactionRows(
56
+ {
57
+ item: { rows: [row('Rename'), row('Duplicate', { shortcut: 'Ctrl D' }), row('Move to', { submenu: true })] },
58
+ checked: {
59
+ rows: [
60
+ { kind: 'checkbox', label: 'Suggestions', attributes: MARK },
61
+ { kind: 'checkbox', label: 'Comments', checked: true, attributes: MARK },
62
+ { kind: 'radio', label: 'Name', checked: true, attributes: MARK },
63
+ ],
64
+ },
65
+ } satisfies Record<string, Props>,
66
+ {
67
+ interactions: ['hover', 'active', 'focus-visible'],
68
+ force: (props: Props, interaction: ItemInteraction): Props => ({ ...props, forced: interaction }),
69
+ },
70
+ );
71
+
72
+ export default definePart({
73
+ note: 'Decided rules only',
74
+ madeBy: ['claude-opus-5-5'],
75
+ states: {
76
+ menu: { rows: FULL },
77
+ ...states,
78
+ disabled: { rows: [row('Rename'), row('Export as PDF', { disabled: true }), row('Duplicate')] },
79
+ 'submenu-open': { rows: [row('Rename'), row('Move to', { submenu: 'open', active: true }), row('Duplicate')] },
80
+ },
81
+ grid,
82
+ widths: [480],
83
+ controls: {
84
+ item: { kind: 'row', input: ['pointer', 'keyboard'], disabled: true },
85
+ },
86
+ render: ({ rows, forced }: Props) =>
87
+ drawing({
88
+ body: `<div class="menu-frame">${menu({ rows: withForced(rows, forced), color: 'brand' })}</div>`,
89
+ styles: [menuStyles, edge].join('\n'),
90
+ }),
91
+ });
@@ -0,0 +1,32 @@
1
+ .notification-frame {
2
+ display: flex;
3
+ flex-direction: column;
4
+ align-items: flex-end;
5
+ padding: 2.4rem 1.6rem;
6
+ background: var(--et-surface-background-solid);
7
+ color: var(--et-surface-color-solid);
8
+ }
9
+
10
+ @layer components {
11
+ .et-notification {
12
+ border-inline-start-color: var(--et-theme-color-ink-solid);
13
+ }
14
+
15
+ .et-notification .et-notification-icon {
16
+ color: var(--et-theme-color-ink-solid);
17
+ }
18
+
19
+ .et-notification .et-notification-spinner {
20
+ --et-spinner-color: var(--et-theme-color-ink-solid);
21
+ }
22
+
23
+ .et-notification .et-focus-ring {
24
+ --_et-focus-ring-color: var(--et-theme-color-ink-solid);
25
+ }
26
+ }
27
+
28
+ @layer components {
29
+ .et-notification-dismiss-btn:focus-visible {
30
+ opacity: 1;
31
+ }
32
+ }
@@ -0,0 +1,106 @@
1
+ import { notification, notificationStack, notificationStyles } from '@ethlete/components/design/notification';
2
+ import { definePart, drawing } from '@design-system';
3
+ import edge from './notification.css?inline';
4
+
5
+ type Interaction = 'hover' | 'active' | 'focus-visible';
6
+
7
+ type Status = 'success' | 'error' | 'info' | 'loading';
8
+
9
+ type Props = {
10
+ status: Status | 'stack';
11
+ close?: Interaction;
12
+ action?: Interaction;
13
+ secondary?: Interaction;
14
+ };
15
+
16
+ const PANE = 'data-et-surface-fill';
17
+
18
+ const mark = (control: string, interaction?: Interaction) =>
19
+ [`data-et-control="${control}" data-can-animate`, interaction && `data-et-force="${interaction}"`]
20
+ .filter(Boolean)
21
+ .join(' ');
22
+
23
+ const draw = (status: Status, { close, action, secondary }: Omit<Props, 'status'> = {}) => {
24
+ const controls = {
25
+ dismissAttributes: mark('close', close),
26
+ attributes: PANE,
27
+ };
28
+
29
+ switch (status) {
30
+ case 'success':
31
+ return notification({
32
+ status,
33
+ title: 'Kick-off moved',
34
+ message: 'Both teams and the referee get an email with the new time.',
35
+ action: { label: 'Undo', attributes: mark('action', action) },
36
+ ...controls,
37
+ });
38
+ case 'error':
39
+ return notification({
40
+ status,
41
+ color: 'danger',
42
+ title: 'Result not saved',
43
+ message: 'The connection dropped before the server answered.',
44
+ action: { label: 'Retry', attributes: mark('action', action) },
45
+ secondaryAction: { label: 'Details', attributes: mark('secondary', secondary) },
46
+ ...controls,
47
+ });
48
+ case 'info':
49
+ return notification({
50
+ status,
51
+ title: 'Round 4 is open',
52
+ message: 'Predictions close at kick-off of the first match.',
53
+ ...controls,
54
+ });
55
+ case 'loading':
56
+ return notification({
57
+ status,
58
+ title: 'Uploading 3 files',
59
+ message: 'You can keep working while this runs.',
60
+ ...controls,
61
+ });
62
+ }
63
+ };
64
+
65
+ const render = ({ status, ...interactions }: Props) =>
66
+ status === 'stack'
67
+ ? notificationStack((['loading', 'info', 'error', 'success'] as const).map((each) => draw(each)))
68
+ : draw(status, interactions);
69
+
70
+ export default definePart({
71
+ note: 'The SDK notification (et-notification), drawn by its mock from @ethlete/components/design: one notification per status with title, message, dismiss icon button and, where the status has them, a primary and a secondary text-button action; the four statuses in the stack column. The pane sits one surface level above the page, as the component forces elevation 1. Error takes the danger theme (the semantic error theme); success, info and loading take the theme around them, since the design product registers no success theme.',
72
+ madeBy: ['claude-opus-5-5'],
73
+ states: {
74
+ success: { status: 'success' },
75
+ error: { status: 'error' },
76
+ info: { status: 'info' },
77
+ loading: { status: 'loading' },
78
+ 'close-hover': { status: 'error', close: 'hover' },
79
+ 'close-focus-visible': { status: 'error', close: 'focus-visible' },
80
+ 'action-focus-visible': { status: 'error', action: 'focus-visible' },
81
+ 'secondary-focus-visible': { status: 'error', secondary: 'focus-visible' },
82
+ 'success-close-focus-visible': { status: 'success', close: 'focus-visible' },
83
+ 'success-action-focus-visible': { status: 'success', action: 'focus-visible' },
84
+ stack: { status: 'stack' },
85
+ },
86
+ widths: [480],
87
+ contrast: {
88
+ exceptions: [
89
+ {
90
+ selector: '.et-notification-message',
91
+ reason:
92
+ "Today the message is the muted surface colour at 0.65 opacity; its contrast is an open point, not this round's question.",
93
+ },
94
+ ],
95
+ },
96
+ controls: {
97
+ close: { kind: 'button', input: ['pointer', 'keyboard'] },
98
+ action: { kind: 'button', input: ['pointer', 'keyboard'] },
99
+ secondary: { kind: 'button', input: ['pointer', 'keyboard'] },
100
+ },
101
+ render: (props: Props) =>
102
+ drawing({
103
+ body: `<div class="notification-frame">${render(props)}</div>`,
104
+ styles: [notificationStyles, edge].join('\n'),
105
+ }),
106
+ });