@ethlete/components 1.0.0-next.78 → 1.0.0-next.80

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 (270) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/design/accordion.ts +73 -0
  3. package/design/anchored-dialog.ts +92 -0
  4. package/design/avatar.ts +90 -0
  5. package/design/badge.ts +48 -0
  6. package/design/banner.ts +77 -0
  7. package/design/bracket.ts +457 -0
  8. package/design/breadcrumb.ts +145 -0
  9. package/design/button.ts +62 -1
  10. package/design/calendar.ts +306 -0
  11. package/design/card.ts +92 -0
  12. package/design/carousel.ts +240 -0
  13. package/design/chart.ts +512 -0
  14. package/design/checkbox.ts +275 -0
  15. package/design/chip.ts +64 -0
  16. package/design/config.json +8 -0
  17. package/design/control.ts +19 -0
  18. package/design/copy-button.ts +59 -0
  19. package/design/description-list.ts +41 -0
  20. package/design/dialog.ts +216 -0
  21. package/design/divider.ts +27 -0
  22. package/design/empty-state.ts +45 -0
  23. package/design/floating-action.ts +55 -0
  24. package/design/form-field.ts +3 -0
  25. package/design/grid.ts +148 -0
  26. package/design/input.ts +86 -0
  27. package/design/kbd.ts +19 -0
  28. package/design/loader.ts +152 -0
  29. package/design/masonry.ts +115 -0
  30. package/design/match.ts +131 -0
  31. package/design/menu.ts +147 -0
  32. package/design/notification.ts +133 -0
  33. package/design/otp-input.ts +107 -0
  34. package/design/pagination.ts +120 -0
  35. package/design/picture.ts +80 -0
  36. package/design/progress-steps.ts +79 -0
  37. package/design/query-error.ts +60 -0
  38. package/design/radio-group.ts +132 -0
  39. package/design/scheduler.ts +369 -0
  40. package/design/scrollable.ts +218 -0
  41. package/design/scrollbar.ts +47 -0
  42. package/design/sdk/assets/fallback.svg +1 -0
  43. package/design/sdk/assets/tall.svg +1 -0
  44. package/design/sdk/assets/wide.svg +1 -0
  45. package/design/sdk/components/accent-on-light/accent-on-light.css +35 -0
  46. package/design/sdk/components/accent-on-light/accent-on-light.ts +10 -0
  47. package/design/sdk/components/accent-on-light/shared/controls.ts +46 -0
  48. package/design/sdk/components/accordion/accordion.css +17 -0
  49. package/design/sdk/components/accordion/accordion.ts +68 -0
  50. package/design/sdk/components/anchored-dialog/anchored-dialog.css +63 -0
  51. package/design/sdk/components/anchored-dialog/anchored-dialog.ts +65 -0
  52. package/design/sdk/components/avatar/avatar.css +14 -0
  53. package/design/sdk/components/avatar/avatar.ts +79 -0
  54. package/design/sdk/components/badge/badge.css +13 -0
  55. package/design/sdk/components/badge/badge.ts +53 -0
  56. package/design/sdk/components/banner/banner.css +18 -0
  57. package/design/sdk/components/banner/banner.ts +88 -0
  58. package/design/sdk/components/bracket/bracket.css +59 -0
  59. package/design/sdk/components/bracket/bracket.ts +144 -0
  60. package/design/sdk/components/breadcrumb/breadcrumb.css +25 -0
  61. package/design/sdk/components/breadcrumb/breadcrumb.ts +82 -0
  62. package/design/sdk/components/button/button.css +41 -0
  63. package/design/sdk/components/button/button.ts +59 -7
  64. package/design/sdk/components/calendar/calendar.css +33 -0
  65. package/design/sdk/components/calendar/calendar.ts +97 -0
  66. package/design/sdk/components/card/card.css +19 -0
  67. package/design/sdk/components/card/card.ts +62 -0
  68. package/design/sdk/components/carousel/carousel.css +44 -0
  69. package/design/sdk/components/carousel/carousel.ts +75 -0
  70. package/design/sdk/components/chart/chart.css +56 -0
  71. package/design/sdk/components/chart/chart.ts +99 -0
  72. package/design/sdk/components/checkbox/checkbox.css +65 -0
  73. package/design/sdk/components/checkbox/checkbox.ts +180 -0
  74. package/design/sdk/components/chip/chip.css +18 -0
  75. package/design/sdk/components/chip/chip.ts +77 -0
  76. package/design/sdk/components/copy-button/copy-button.css +14 -0
  77. package/design/sdk/components/copy-button/copy-button.ts +60 -0
  78. package/design/sdk/components/description-list/description-list.css +7 -0
  79. package/design/sdk/components/description-list/description-list.ts +54 -0
  80. package/design/sdk/components/dialog/dialog.css +29 -0
  81. package/design/sdk/components/dialog/dialog.ts +79 -0
  82. package/design/sdk/components/divider/divider.css +26 -0
  83. package/design/sdk/components/divider/divider.ts +44 -0
  84. package/design/sdk/components/empty-state/empty-state.css +15 -0
  85. package/design/sdk/components/empty-state/empty-state.ts +57 -0
  86. package/design/sdk/components/floating-action/floating-action.css +51 -0
  87. package/design/sdk/components/floating-action/floating-action.ts +63 -0
  88. package/design/sdk/components/form-field/form-field.ts +23 -5
  89. package/design/sdk/components/grid/grid.css +17 -0
  90. package/design/sdk/components/grid/grid.ts +81 -0
  91. package/design/sdk/components/input/input.css +75 -0
  92. package/design/sdk/components/input/input.ts +80 -0
  93. package/design/sdk/components/kbd/kbd.css +25 -0
  94. package/design/sdk/components/kbd/kbd.ts +58 -0
  95. package/design/sdk/components/loader/loader.css +37 -0
  96. package/design/sdk/components/loader/loader.ts +69 -0
  97. package/design/sdk/components/masonry/masonry.css +7 -0
  98. package/design/sdk/components/masonry/masonry.ts +43 -0
  99. package/design/sdk/components/match/match.css +25 -0
  100. package/design/sdk/components/match/match.ts +77 -0
  101. package/design/sdk/components/menu/menu.css +22 -0
  102. package/design/sdk/components/menu/menu.ts +103 -0
  103. package/design/sdk/components/notification/notification.css +32 -0
  104. package/design/sdk/components/notification/notification.ts +107 -0
  105. package/design/sdk/components/otp-input/otp-input.css +35 -0
  106. package/design/sdk/components/otp-input/otp-input.ts +65 -0
  107. package/design/sdk/components/pagination/pagination.css +14 -0
  108. package/design/sdk/components/pagination/pagination.ts +76 -0
  109. package/design/sdk/components/picture/picture.css +37 -0
  110. package/design/sdk/components/picture/picture.ts +97 -0
  111. package/design/sdk/components/progress-steps/progress-steps.css +37 -0
  112. package/design/sdk/components/progress-steps/progress-steps.ts +92 -0
  113. package/design/sdk/components/query-error/query-error.css +33 -0
  114. package/design/sdk/components/query-error/query-error.ts +121 -0
  115. package/design/sdk/components/radio-group/radio-group.css +46 -0
  116. package/design/sdk/components/radio-group/radio-group.ts +167 -0
  117. package/design/sdk/components/scheduler/scheduler.css +55 -0
  118. package/design/sdk/components/scheduler/scheduler.ts +240 -0
  119. package/design/sdk/components/scrollable/scrollable.css +58 -0
  120. package/design/sdk/components/scrollable/scrollable.ts +133 -0
  121. package/design/sdk/components/scrollbar/scrollbar.css +78 -0
  122. package/design/sdk/components/scrollbar/scrollbar.ts +124 -0
  123. package/design/sdk/components/select/select.ts +1 -1
  124. package/design/sdk/components/select/shared/select-part.ts +25 -3
  125. package/design/sdk/components/select-panel/select-panel.css +3 -0
  126. package/design/sdk/components/select-panel/select-panel.ts +125 -0
  127. package/design/sdk/components/skeleton/skeleton.css +22 -0
  128. package/design/sdk/components/skeleton/skeleton.ts +51 -0
  129. package/design/sdk/components/slider/slider.css +52 -0
  130. package/design/sdk/components/slider/slider.ts +87 -0
  131. package/design/sdk/components/standings/standings.css +33 -0
  132. package/design/sdk/components/standings/standings.ts +131 -0
  133. package/design/sdk/components/stat-tile/stat-tile.css +15 -0
  134. package/design/sdk/components/stat-tile/stat-tile.ts +85 -0
  135. package/design/sdk/components/stream/stream.css +48 -0
  136. package/design/sdk/components/stream/stream.ts +43 -0
  137. package/design/sdk/components/switch/switch.css +37 -0
  138. package/design/sdk/components/switch/switch.ts +63 -0
  139. package/design/sdk/components/table/table.css +67 -0
  140. package/design/sdk/components/table/table.ts +161 -0
  141. package/design/sdk/components/tabs/tabs.css +13 -0
  142. package/design/sdk/components/tabs/tabs.ts +74 -0
  143. package/design/sdk/components/textarea/textarea.css +116 -0
  144. package/design/sdk/components/textarea/textarea.ts +65 -0
  145. package/design/sdk/components/timeline/timeline.css +30 -0
  146. package/design/sdk/components/timeline/timeline.ts +87 -0
  147. package/design/sdk/components/toolbar/toolbar.css +24 -0
  148. package/design/sdk/components/toolbar/toolbar.ts +88 -0
  149. package/design/sdk/components/tooltip/tooltip.css +15 -0
  150. package/design/sdk/components/tooltip/tooltip.ts +28 -0
  151. package/design/sdk/components/tree/selected-tint.css +15 -0
  152. package/design/sdk/components/tree/tree.ts +70 -0
  153. package/design/sdk/foundations/colors/colors.css +124 -4
  154. package/design/sdk/foundations/colors/colors.ts +1 -1
  155. package/design/sdk/foundations/colors/shared/contrast.ts +1 -1
  156. package/design/sdk/foundations/elevation/elevation.css +6 -0
  157. package/design/sdk/foundations/elevation/elevation.ts +11 -0
  158. package/design/sdk/foundations/elevation/shared/elevation/scene.css +101 -0
  159. package/design/sdk/foundations/elevation/shared/elevation/scene.ts +74 -0
  160. package/design/sdk/foundations/icons/icons.ts +119 -0
  161. package/design/sdk/pictures.json +1183 -0
  162. package/design/select.ts +5 -4
  163. package/design/skeleton.ts +67 -0
  164. package/design/slider.ts +155 -0
  165. package/design/standings.ts +161 -0
  166. package/design/stat-tile.ts +109 -0
  167. package/design/stream.ts +92 -0
  168. package/design/switch.ts +83 -0
  169. package/design/table.ts +302 -0
  170. package/design/tabs.ts +75 -0
  171. package/design/textarea.ts +94 -0
  172. package/design/timeline.ts +52 -0
  173. package/design/toolbar.ts +95 -0
  174. package/design/tooltip.ts +87 -0
  175. package/fesm2022/ethlete-components.mjs +1440 -1209
  176. package/fesm2022/ethlete-components.mjs.map +1 -1
  177. package/generators/generators.json +2 -0
  178. package/package.json +1 -1
  179. package/src/lib/accordion/accordion.component.css +2 -1
  180. package/src/lib/avatar/avatar.component.css +10 -0
  181. package/src/lib/badge/badge.component.css +2 -2
  182. package/src/lib/banner/banner.component.css +3 -1
  183. package/src/lib/breadcrumb/breadcrumb-outlet.component.css +5 -0
  184. package/src/lib/breadcrumb/breadcrumb.component.css +5 -1
  185. package/src/lib/button/button-properties-styles.component.css +6 -6
  186. package/src/lib/button/button.component.css +27 -4
  187. package/src/lib/button/button.types.ts +33 -0
  188. package/src/lib/button/icon-button.component.css +21 -22
  189. package/src/lib/button/split-button.component.css +5 -1
  190. package/src/lib/button/window-control-button.component.css +43 -3
  191. package/src/lib/calendar/calendar.component.css +15 -5
  192. package/src/lib/card/card.component.css +4 -0
  193. package/src/lib/carousel/carousel-autoplay-styles.component.css +1 -1
  194. package/src/lib/carousel/carousel.component.css +2 -2
  195. package/src/lib/chart/chart-axis.component.css +3 -3
  196. package/src/lib/chip/chip.component.css +12 -6
  197. package/src/lib/description-list/description-list.component.css +2 -1
  198. package/src/lib/empty-state/empty-state.component.css +4 -0
  199. package/src/lib/floating-action/floating-action-styles.component.css +27 -0
  200. package/src/lib/focus-ring/focus-ring-styles.component.css +4 -1
  201. package/src/lib/forms/checkbox/checkbox.component.css +31 -5
  202. package/src/lib/forms/color-input/color-input.component.css +3 -1
  203. package/src/lib/forms/color-input/color-picker-panel.component.css +6 -2
  204. package/src/lib/forms/date-time/date-input/date-input.component.css +1 -1
  205. package/src/lib/forms/date-time/date-time-input/date-time-input.component.css +1 -1
  206. package/src/lib/forms/date-time/duration-input/duration-input.component.css +1 -1
  207. package/src/lib/forms/date-time/range-input-shell-styles.component.css +1 -1
  208. package/src/lib/forms/date-time/time-input/time-input.component.css +1 -1
  209. package/src/lib/forms/description/description.component.css +7 -0
  210. package/src/lib/forms/dropzone/dropzone.component.css +26 -0
  211. package/src/lib/forms/form-field/form-field-control-suffix-styles.component.css +4 -2
  212. package/src/lib/forms/form-field/form-field-text-shell-styles.component.css +54 -5
  213. package/src/lib/forms/form-field/form-field-textarea-styles.component.css +62 -0
  214. package/src/lib/forms/form-field/form-field.component.css +6 -0
  215. package/src/lib/forms/form-field/headless/label.directive.css +1 -1
  216. package/src/lib/forms/input/input.component.css +6 -2
  217. package/src/lib/forms/input/number-input.component.css +2 -2
  218. package/src/lib/forms/input/password-input.component.css +4 -3
  219. package/src/lib/forms/otp-input/otp-input.component.css +23 -4
  220. package/src/lib/forms/phone-input/phone-input.component.css +4 -3
  221. package/src/lib/forms/rating/rating.component.css +2 -1
  222. package/src/lib/forms/rich-text-editor/rich-text-editor.component.css +1 -1
  223. package/src/lib/forms/selection-card-styles.component.css +3 -2
  224. package/src/lib/forms/selection-list/checkbox-group/checkbox-group-select-all.component.css +4 -2
  225. package/src/lib/forms/selection-list/checkbox-group/checkbox-option.component.css +4 -2
  226. package/src/lib/forms/selection-list/radio-group/radio.component.css +5 -2
  227. package/src/lib/forms/selection-list/segmented-button-group/segmented-button.component.css +2 -1
  228. package/src/lib/forms/slider/range-slider.component.css +98 -6
  229. package/src/lib/forms/slider/slider.component.css +96 -4
  230. package/src/lib/forms/switch/switch.component.css +45 -15
  231. package/src/lib/forms/tag-input/tag-input.component.css +2 -2
  232. package/src/lib/forms/textarea/textarea-autosize-styles.component.css +2 -3
  233. package/src/lib/forms/textarea/textarea.component.css +7 -2
  234. package/src/lib/grid/grid-item-toolbar.component.css +10 -0
  235. package/src/lib/grid/grid-item.component.css +6 -1
  236. package/src/lib/kbd/kbd.component.css +1 -1
  237. package/src/lib/loader/brand-loader/brand-loader.component.css +4 -1
  238. package/src/lib/loader/progress-bar/progress-bar.component.css +1 -1
  239. package/src/lib/loader/spinner/spinner-styles.component.css +1 -1
  240. package/src/lib/match/match-card.component.css +9 -3
  241. package/src/lib/match/match-score.component.css +4 -1
  242. package/src/lib/menu/menu-selection-item.component.css +1 -1
  243. package/src/lib/menu/menu.component.css +6 -1
  244. package/src/lib/notification/notification.component.css +3 -3
  245. package/src/lib/overlay/overlay-container.component.css +4 -0
  246. package/src/lib/pagination/pagination.component.css +4 -0
  247. package/src/lib/progress-steps/progress-step.component.css +4 -4
  248. package/src/lib/query-error/query-error.component.css +4 -0
  249. package/src/lib/scheduler/scheduler-appointment-styles.component.css +21 -5
  250. package/src/lib/scheduler/scheduler-month-view.component.css +4 -2
  251. package/src/lib/scheduler/scheduler-time-grid-view.component.css +8 -2
  252. package/src/lib/scrollable/headless/scrollable-navigation.component.css +1 -1
  253. package/src/lib/standings/standings-pick.component.css +1 -1
  254. package/src/lib/standings/standings.component.css +10 -10
  255. package/src/lib/stat-tile/stat-tile-sparkline.component.css +1 -1
  256. package/src/lib/stream/consent/stream-consent.component.css +99 -0
  257. package/src/lib/stream/error/stream-player-error.component.css +100 -0
  258. package/src/lib/stream/loading/stream-player-loading.component.css +16 -0
  259. package/src/lib/stream/pip/pip-slot-placeholder.component.css +68 -0
  260. package/src/lib/stream/stream-player-slot-styles.component.css +4 -0
  261. package/src/lib/table/table-resize-grip.component.css +2 -1
  262. package/src/lib/table/table-select-cell.component.css +45 -15
  263. package/src/lib/table/table.component.css +15 -5
  264. package/src/lib/tabs/tab-bar-styles.component.css +1 -1
  265. package/src/lib/tabs/tabs/tab-group.component.css +111 -0
  266. package/src/lib/time-picker/time-picker.component.css +2 -1
  267. package/src/lib/timeline/timeline-item.component.css +5 -1
  268. package/src/lib/toolbar/toolbar.component.css +4 -0
  269. package/src/lib/tooltip/tooltip.component.css +14 -0
  270. package/types/ethlete-components.d.ts +156 -128
@@ -1,17 +1,38 @@
1
- import { button, buttonStyles, ButtonMockOptions } from '@ethlete/components/design/button';
1
+ import {
2
+ button,
3
+ buttonStyles,
4
+ ButtonMockOptions,
5
+ iconButton,
6
+ IconButtonMockOptions,
7
+ iconButtonStyles,
8
+ } from '@ethlete/components/design/button';
9
+ import { iconMarkup } from '@ethlete/components/design/icon';
10
+ import { loaderStyles } from '@ethlete/components/design/loader';
11
+ import { SDK_ICONS } from '@ethlete/components/design/icon-set';
2
12
  import { definePart, drawing, forceInteraction, interactionRows } from '@design-system';
13
+ import hover from './button.css?inline';
3
14
 
4
15
  type ButtonInteraction = 'hover' | 'active' | 'focus-visible';
5
16
 
6
- type Props = ButtonMockOptions & { interaction?: ButtonInteraction };
17
+ type IconOnly = IconButtonMockOptions & { iconOnly: true };
18
+
19
+ type Props = (ButtonMockOptions | IconOnly) & { interaction?: ButtonInteraction };
7
20
 
8
21
  const control = ({ interaction, ...options }: Props) => {
9
- const markup = button(options).replace(/^<(button|a) /, '<$1 data-et-control="button" data-can-animate ');
22
+ const drawn = 'iconOnly' in options ? iconButton(options) : button(options);
23
+ const markup = drawn
24
+ .replace(/^<(button|a) /, '<$1 data-et-control="button" data-can-animate ')
25
+ .replace('<div class="et-button-loader"', '<div class="et-button-loader" data-et-skip="CLIPPED"');
10
26
 
11
27
  return interaction ? forceInteraction(markup, interaction) : markup;
12
28
  };
13
29
 
14
- export const { states, grid } = interactionRows<
30
+ const plus = iconMarkup(SDK_ICONS.find((each) => each.name === 'et-plus')!);
31
+ const SIZES = ['xs', 'sm', 'md', 'lg', 'xl'] as const;
32
+ const VARIANTS = ['filled', 'outline', 'tonal', 'transparent'] as const;
33
+ type Size = (typeof SIZES)[number];
34
+
35
+ const interactive = interactionRows<
15
36
  Props,
16
37
  'filled' | 'outline' | 'tonal' | 'transparent' | 'pressed' | 'danger' | 'small' | 'disabled',
17
38
  ButtonInteraction
@@ -29,11 +50,42 @@ export const { states, grid } = interactionRows<
29
50
  { interactions: ['hover', 'active', 'focus-visible'], force: (props, interaction) => ({ ...props, interaction }) },
30
51
  );
31
52
 
53
+ const iconOnly = interactionRows<Props, `icon-${(typeof VARIANTS)[number]}`, ButtonInteraction>(
54
+ Object.fromEntries(
55
+ VARIANTS.map((variant) => [`icon-${variant}`, { iconOnly: true, icon: plus, ariaLabel: 'Add', variant }]),
56
+ ) as Record<`icon-${(typeof VARIANTS)[number]}`, Props>,
57
+ { interactions: ['hover', 'active', 'focus-visible'], force: (props, interaction) => ({ ...props, interaction }) },
58
+ );
59
+
60
+ const sizeStates = Object.fromEntries(
61
+ SIZES.map((size) => [`size-${size}`, { label: 'Add', icon: plus, variant: 'filled', size }]),
62
+ ) as Record<`size-${Size}`, Props>;
63
+
64
+ export const states = { ...interactive.states, ...iconOnly.states, ...sizeStates };
65
+ export const grid = {
66
+ columns: interactive.grid.columns,
67
+ rows: {
68
+ ...interactive.grid.rows,
69
+ ...Object.fromEntries(VARIANTS.map((variant) => [`icon ${variant}`, iconOnly.grid.rows[`icon-${variant}`]])),
70
+ ...Object.fromEntries(SIZES.map((size) => [`size ${size}`, { rest: `size-${size}` as const }])),
71
+ },
72
+ };
73
+
32
74
  export default definePart({
33
- note: 'The SDK button, drawn by its mock from @ethlete/components/design.',
34
- madeBy: ['claude-opus-5-5'],
75
+ note: 'scale of the decided shape, Q182, lead merge',
76
+ madeBy: ['claude-opus-5-5', 'claude-sonnet-5-5'],
35
77
  states,
36
78
  grid,
37
79
  controls: { button: { kind: 'button', input: ['pointer', 'keyboard'], disabled: true } },
38
- render: (props: Props) => drawing({ body: control(props), styles: buttonStyles }),
80
+ render: (props: Props) =>
81
+ drawing({
82
+ body: control(props),
83
+ styles: [
84
+ 'iconOnly' in props ? iconButtonStyles : buttonStyles,
85
+ hover,
86
+ !('iconOnly' in props) && props.loading && loaderStyles,
87
+ ]
88
+ .filter(Boolean)
89
+ .join('\n'),
90
+ }),
39
91
  });
@@ -0,0 +1,33 @@
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-calendar .et-calendar-nav-button {
11
+ --_et-focus-ring-color: var(--et-theme-color-ink-solid);
12
+ }
13
+
14
+ .et-calendar .et-calendar-header-label:focus-visible,
15
+ .et-calendar .et-calendar-cell:focus-visible .et-calendar-cell-content {
16
+ outline-color: var(--et-theme-color-ink-solid);
17
+ }
18
+
19
+ .et-calendar .et-calendar-cell::before {
20
+ background: light-dark(
21
+ color-mix(in srgb, var(--et-theme-color-primary-solid) 32%, transparent),
22
+ color-mix(in srgb, var(--et-theme-color-primary-solid) 12%, transparent)
23
+ );
24
+ }
25
+
26
+ .et-calendar
27
+ .et-calendar-cell:where([data-selected], [data-band='start'], [data-band='end']):where(
28
+ :not([data-disabled], [data-today])
29
+ )
30
+ .et-calendar-cell-content {
31
+ box-shadow: inset 0 0 0 1px var(--et-theme-color-ink-solid);
32
+ }
33
+ }
@@ -0,0 +1,97 @@
1
+ import { calendar, calendarStyles, CalendarMockOptions } from '@ethlete/components/design/calendar';
2
+ import { definePart, drawing } from '@design-system';
3
+ import frame from './calendar.css?inline';
4
+
5
+ type Interaction = 'hover' | 'focus-visible';
6
+
7
+ type Props = {
8
+ view?: CalendarMockOptions['view'];
9
+ selected?: boolean;
10
+ range?: boolean;
11
+ day?: Interaction;
12
+ selectedDay?: Interaction;
13
+ rangeDay?: Interaction;
14
+ disabled?: boolean;
15
+ limits?: boolean;
16
+ weekNumbers?: boolean;
17
+ comparison?: boolean;
18
+ nav?: Interaction;
19
+ label?: Interaction;
20
+ compact?: boolean;
21
+ };
22
+
23
+ const TODAY = '2026-09-14';
24
+
25
+ const force = (interaction: Interaction | undefined, key: string) =>
26
+ interaction ? { [key]: `data-et-force="${interaction}"` } : {};
27
+
28
+ const render = (props: Props) => {
29
+ const view = props.view ?? 'month';
30
+ const coarseKey = view === 'year' ? '2026-03' : '2021';
31
+
32
+ return calendar({
33
+ view,
34
+ month: '2026-09',
35
+ today: TODAY,
36
+ value: props.selected
37
+ ? view === 'year'
38
+ ? '2026-05-20'
39
+ : view === 'multiYear'
40
+ ? '2024-05-20'
41
+ : '2026-09-17'
42
+ : undefined,
43
+ range: props.range
44
+ ? { start: '2026-09-09', end: '2026-09-16' }
45
+ : props.comparison
46
+ ? { start: '2026-09-15', end: '2026-09-18' }
47
+ : undefined,
48
+ comparison: props.comparison ? { start: '2026-09-07', end: '2026-09-11' } : undefined,
49
+ min: props.limits ? '2026-09-07' : undefined,
50
+ max: props.limits ? '2026-09-24' : undefined,
51
+ disabled: props.disabled ? ['2026-09-05', '2026-09-06', '2026-09-26', '2026-09-27'] : undefined,
52
+ weekNumbers: props.weekNumbers,
53
+ cellAttributes: {
54
+ ...force(props.day, view === 'month' ? '2026-09-22' : coarseKey),
55
+ ...force(props.selectedDay, '2026-09-17'),
56
+ ...force(props.rangeDay, '2026-09-09'),
57
+ },
58
+ nextAttributes: props.nav ? `data-et-force="${props.nav}"` : undefined,
59
+ labelAttributes: props.label ? `data-et-force="${props.label}"` : undefined,
60
+ attributes: props.compact ? 'style="--et-calendar-cell-size: 32px"' : undefined,
61
+ });
62
+ };
63
+
64
+ export default definePart({
65
+ note: 'Decided rules only',
66
+ madeBy: ['claude-opus-5-5'],
67
+ states: {
68
+ rest: {},
69
+ selected: { selected: true },
70
+ 'selected-hover': { selected: true, selectedDay: 'hover' },
71
+ 'selected-focus-visible': { selected: true, selectedDay: 'focus-visible' },
72
+ range: { range: true },
73
+ 'range-focus-visible': { range: true, rangeDay: 'focus-visible' },
74
+ 'day-hover': { day: 'hover' },
75
+ 'day-focus-visible': { day: 'focus-visible' },
76
+ disabled: { disabled: true },
77
+ limits: { limits: true, selected: true },
78
+ 'week-numbers': { weekNumbers: true, selected: true },
79
+ comparison: { comparison: true },
80
+ 'year-view': { view: 'year', selected: true },
81
+ 'year-view-hover': { view: 'year', selected: true, day: 'hover' },
82
+ 'year-view-focus-visible': { view: 'year', selected: true, day: 'focus-visible' },
83
+ 'multi-year-view': { view: 'multiYear', selected: true },
84
+ 'nav-hover': { nav: 'hover' },
85
+ 'nav-focus-visible': { nav: 'focus-visible' },
86
+ 'label-hover': { label: 'hover' },
87
+ 'label-focus-visible': { label: 'focus-visible' },
88
+ 'long-label': { compact: true, selected: true },
89
+ },
90
+ widths: [480],
91
+ frame: (body) => `<div class="t-frame">${body}</div>`,
92
+ render: (props: Props) =>
93
+ drawing({
94
+ body: render(props),
95
+ styles: [calendarStyles, frame].join('\n'),
96
+ }),
97
+ });
@@ -0,0 +1,19 @@
1
+ .card-frame {
2
+ padding: 2.4rem 1.6rem;
3
+ background: var(--et-surface-background-solid);
4
+ color: var(--et-surface-color-solid);
5
+ }
6
+
7
+ .card-frame .et-card {
8
+ max-inline-size: 32rem;
9
+ }
10
+
11
+ @layer components {
12
+ .et-card .et-focus-ring {
13
+ --_et-focus-ring-color: var(--et-theme-color-ink-solid);
14
+ }
15
+
16
+ .et-card .et-button[data-variant='filled'] {
17
+ --et-button-shadow: inset 0 0 0 1px var(--et-theme-color-ink-solid);
18
+ }
19
+ }
@@ -0,0 +1,62 @@
1
+ import { button } from '@ethlete/components/design/button';
2
+ import { card, cardContent, CardMockOptions, cardPlaceholderMedia, cardStyles } from '@ethlete/components/design/card';
3
+ import { definePart, drawing } from '@design-system';
4
+ import frame from './card.css?inline';
5
+
6
+ type Interaction = 'hover' | 'active' | 'focus-visible';
7
+
8
+ type Props = {
9
+ variant: NonNullable<CardMockOptions['variant']>;
10
+ form?: 'full' | 'media' | 'plain';
11
+ confirm?: Interaction;
12
+ cancel?: Interaction;
13
+ };
14
+
15
+ const mark = (control: string, interaction?: Interaction) =>
16
+ [`data-et-control="${control}" data-can-animate`, interaction && `data-et-force="${interaction}"`]
17
+ .filter(Boolean)
18
+ .join(' ');
19
+
20
+ const actions = ({ confirm, cancel }: Props) =>
21
+ `<div class="et-card-mock-actions">${[
22
+ button({ label: 'Cancel', variant: 'outline' }).replace(/^<button /, `<button ${mark('cancel', cancel)} `),
23
+ button({ label: 'Open', variant: 'filled' }).replace(/^<button /, `<button ${mark('confirm', confirm)} `),
24
+ ].join('')}</div>`;
25
+
26
+ const content = (props: Props) => {
27
+ if (props.form === 'plain') return cardContent({ title: 'Revenue', text: '$12,400 this month' });
28
+
29
+ return (
30
+ cardContent({
31
+ media: props.form === 'media' ? cardPlaceholderMedia : undefined,
32
+ title: 'Spring league',
33
+ subtitle: 'Starts 12 April',
34
+ text: 'Eight teams play two rounds. Sign-ups close one week before kick-off.',
35
+ }) + actions(props)
36
+ );
37
+ };
38
+
39
+ export default definePart({
40
+ note: 'Decided rules only',
41
+ madeBy: ['claude-opus-5-5'],
42
+ states: {
43
+ outlined: { variant: 'outlined' },
44
+ elevated: { variant: 'elevated' },
45
+ filled: { variant: 'filled' },
46
+ media: { variant: 'outlined', form: 'media' },
47
+ plain: { variant: 'outlined', form: 'plain' },
48
+ 'confirm-focus-visible': { variant: 'outlined', confirm: 'focus-visible' },
49
+ 'cancel-focus-visible': { variant: 'outlined', cancel: 'focus-visible' },
50
+ },
51
+ widths: [480],
52
+ controls: {
53
+ cancel: { kind: 'button', input: ['pointer', 'keyboard'] },
54
+ confirm: { kind: 'button', input: ['pointer', 'keyboard'] },
55
+ },
56
+ frame: (body) => `<div class="card-frame">${body}</div>`,
57
+ render: (props: Props) =>
58
+ drawing({
59
+ body: card({ variant: props.variant, content: content(props) }),
60
+ styles: [cardStyles, frame].join('\n'),
61
+ }),
62
+ });
@@ -0,0 +1,44 @@
1
+ .carousel-frame {
2
+ padding: 2.4rem;
3
+ background: var(--et-surface-background-solid);
4
+ color: var(--et-surface-color-solid);
5
+ font-size: 1.4rem;
6
+
7
+ .carousel-slide {
8
+ display: flex;
9
+ flex-direction: column;
10
+ justify-content: flex-end;
11
+ gap: 0.4rem;
12
+ box-sizing: border-box;
13
+ block-size: 100%;
14
+ min-block-size: 200px;
15
+ padding: 2.4rem;
16
+ border-radius: 12px;
17
+ background: color-mix(in srgb, var(--et-surface-color-solid) 14%, transparent);
18
+ color: var(--et-surface-color-solid);
19
+ }
20
+
21
+ .carousel-slide p {
22
+ margin: 0;
23
+ }
24
+
25
+ .carousel-slide-title {
26
+ font-size: 2rem;
27
+ font-weight: 600;
28
+ }
29
+
30
+ .carousel-slide-meta {
31
+ font-size: 1.2rem;
32
+ }
33
+ }
34
+
35
+ @layer components {
36
+ .et-carousel .et-focus-ring {
37
+ --_et-focus-ring-color: var(--et-theme-color-ink-solid);
38
+ }
39
+
40
+ .et-carousel .et-carousel-dot[data-active]::before,
41
+ .et-carousel .et-carousel-dot-progress-half::before {
42
+ background: light-dark(var(--et-theme-color-ink-solid), var(--et-theme-color-primary-solid));
43
+ }
44
+ }
@@ -0,0 +1,75 @@
1
+ import { carousel, carouselStyles, type CarouselMockOptions } from '@ethlete/components/design/carousel';
2
+ import { definePart, drawing } from '@design-system';
3
+ import frame from './carousel.css?inline';
4
+
5
+ type Interaction = 'hover' | 'active' | 'focus-visible';
6
+
7
+ type Props = Omit<CarouselMockOptions, 'slides'> & {
8
+ count?: number;
9
+ longCaption?: boolean;
10
+ previous?: Interaction;
11
+ next?: Interaction;
12
+ playToggle?: Interaction;
13
+ dot?: { index: number; interaction: Interaction };
14
+ };
15
+
16
+ const TITLES = ['Kick-off', 'First half', 'Half time', 'Second half', 'Full time'];
17
+ const LONG_CAPTION =
18
+ 'A long caption that wraps over several lines inside the slide, the way a match report teaser runs on past a single line of text.';
19
+
20
+ const force = (interaction: Interaction | undefined) => (interaction ? `data-et-force="${interaction}"` : undefined);
21
+
22
+ const slideContent = (index: number, count: number, longCaption: boolean) =>
23
+ `<div class="carousel-slide"><p class="carousel-slide-title">${index + 1}. ${TITLES[index % TITLES.length]}</p>` +
24
+ `<p>${longCaption && index === 0 ? LONG_CAPTION : 'A short line about the slide.'}</p>` +
25
+ `<p class="carousel-slide-meta">slide ${index + 1} of ${count}</p></div>`;
26
+
27
+ const render = ({ count = 5, longCaption = false, previous, next, playToggle, dot, ...options }: Props) =>
28
+ carousel({
29
+ ...options,
30
+ slides: Array.from({ length: count }, (_, index) => ({ content: slideContent(index, count, longCaption) })),
31
+ previousAttributes: force(previous),
32
+ nextAttributes: force(next),
33
+ playToggleAttributes: force(playToggle),
34
+ dotAttributes: dot ? { [dot.index]: `data-et-force="${dot.interaction}"` } : undefined,
35
+ trackAttributes: 'data-et-skip="CLIPPED"',
36
+ }).replaceAll(
37
+ 'class="et-carousel-dot-progress-half"',
38
+ 'data-et-skip="CLIPPED" class="et-carousel-dot-progress-half"',
39
+ );
40
+
41
+ export default definePart({
42
+ note: 'scale of the decided shape, Q182, lead merge',
43
+ madeBy: ['claude-opus-5-5'],
44
+ states: {
45
+ 'first-slide': {},
46
+ 'middle-slide': { active: 2 },
47
+ 'last-slide': { active: 4 },
48
+ 'no-loop-first': { loop: false },
49
+ 'no-loop-last': { loop: false, active: 4 },
50
+ 'next-hover': { active: 2, next: 'hover' },
51
+ 'next-active': { active: 2, next: 'active' },
52
+ 'next-focus-visible': { active: 2, next: 'focus-visible' },
53
+ 'dot-hover': { active: 2, dot: { index: 3, interaction: 'hover' } },
54
+ 'active-dot-hover': { active: 2, dot: { index: 2, interaction: 'hover' } },
55
+ 'dot-focus-visible': { active: 2, dot: { index: 3, interaction: 'focus-visible' } },
56
+ 'active-dot-focus-visible': { active: 2, dot: { index: 2, interaction: 'focus-visible' } },
57
+ 'autoplay-playing': { active: 1, autoplay: true },
58
+ 'autoplay-paused': { active: 1, autoplay: true, playing: false },
59
+ 'play-toggle-hover': { active: 1, autoplay: true, playToggle: 'hover' },
60
+ 'play-toggle-focus-visible': { active: 1, autoplay: true, playToggle: 'focus-visible' },
61
+ 'multiple-items': { itemSize: 'half', slideGap: 16, active: 1 },
62
+ 'item-size-third': { itemSize: 'third', slideGap: 16, active: 1 },
63
+ 'center-aligned': { itemSize: 'half', slideGap: 16, slideAlign: 'center', active: 2 },
64
+ 'no-controls': { active: 1, showControls: false },
65
+ 'long-caption': { longCaption: true },
66
+ 'single-slide': { count: 1 },
67
+ },
68
+ widths: [480],
69
+ frame: (body) => `<div class="carousel-frame">${body}</div>`,
70
+ render: (props: Props) =>
71
+ drawing({
72
+ body: render(props),
73
+ styles: [carouselStyles, frame].join('\n'),
74
+ }),
75
+ });
@@ -0,0 +1,56 @@
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-line-chart-series,
11
+ .et-line-chart-slice .et-line-chart-slice-point,
12
+ .et-chart-legend[data-mark='line'] .et-chart-legend-swatch,
13
+ .et-chart-tooltip .et-chart-tooltip-key,
14
+ .et-line-chart-tooltip .et-line-chart-tooltip-key {
15
+ --_et-chart-mark-accent: color-mix(
16
+ in oklab,
17
+ light-dark(var(--et-theme-color-ink-solid), var(--et-theme-color-primary-solid)) var(--_et-chart-accent-mix, 100%),
18
+ var(--et-surface-background-solid, transparent)
19
+ );
20
+ }
21
+
22
+ .et-line-chart-series {
23
+ --_et-line-chart-color: var(--_et-chart-mark-accent);
24
+ }
25
+
26
+ .et-line-chart-slice .et-line-chart-slice-point {
27
+ fill: var(--_et-chart-mark-accent);
28
+ }
29
+
30
+ .et-chart-legend[data-mark='line'] .et-chart-legend-swatch,
31
+ .et-chart-tooltip .et-chart-tooltip-key,
32
+ .et-line-chart-tooltip .et-line-chart-tooltip-key {
33
+ background: var(--_et-chart-mark-accent);
34
+ }
35
+
36
+ .et-bar-chart-bar .et-bar-chart-bar-mark,
37
+ .et-pie-chart-slice .et-pie-chart-slice-mark {
38
+ stroke: var(--et-theme-color-ink-solid);
39
+ stroke-width: 1px;
40
+ }
41
+
42
+ .et-chart-legend:not([data-mark='line']) .et-chart-legend-swatch,
43
+ .et-pie-chart-legend .et-pie-chart-legend-swatch {
44
+ box-shadow: inset 0 0 0 1px var(--et-theme-color-ink-solid);
45
+ }
46
+
47
+ .et-bar-chart-bar:focus-visible .et-bar-chart-bar-target,
48
+ .et-line-chart-slice:focus-visible .et-line-chart-focus-ring {
49
+ stroke: var(--et-theme-color-ink-solid);
50
+ }
51
+
52
+ .et-pie-chart-slice:focus-visible .et-pie-chart-slice-mark {
53
+ stroke: var(--et-theme-color-ink-solid);
54
+ stroke-width: 2px;
55
+ }
56
+ }
@@ -0,0 +1,99 @@
1
+ import { barChart, chartStyles, ChartMockMark, lineChart, pieChart } from '@ethlete/components/design/chart';
2
+ import { definePart, drawing } from '@design-system';
3
+ import frame from './chart.css?inline';
4
+
5
+ type Kind = 'bar' | 'line' | 'pie';
6
+
7
+ type Props = {
8
+ kind: Kind;
9
+ series?: boolean;
10
+ mark?: ChartMockMark;
11
+ empty?: boolean;
12
+ longLabel?: boolean;
13
+ points?: boolean;
14
+ donut?: boolean;
15
+ };
16
+
17
+ const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'];
18
+ const LONG_MONTHS = ['January', 'February', 'March', 'April', 'May', 'June'];
19
+ const DAYS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
20
+ const BAR_2026 = { label: '2026', values: [32, 48, 41, 67, 54, 72] };
21
+ const BAR_2025 = { label: '2025', values: [28, 35, 44, 51, 47, 58] };
22
+ const VISITS = { label: 'Visits', values: [42, 55, 49, 63, 71, 38, 30] };
23
+ const SIGNUPS = { label: 'Sign-ups', values: [18, 24, 21, 30, 34, 15, 12] };
24
+ const SOURCES = [
25
+ { label: 'Direct', value: 420 },
26
+ { label: 'Search', value: 280 },
27
+ { label: 'Social', value: 180 },
28
+ { label: 'Referral', value: 120 },
29
+ ];
30
+ const LONG_SOURCES = [
31
+ { label: 'Direct', value: 420 },
32
+ { label: 'Search engines and paid search campaigns', value: 280 },
33
+ { label: 'Social', value: 180 },
34
+ { label: 'Referral', value: 120 },
35
+ ];
36
+
37
+ const PLOT_WIDTH = 410;
38
+
39
+ const render = (props: Props) => {
40
+ if (props.kind === 'bar') {
41
+ return barChart({
42
+ plotWidth: PLOT_WIDTH,
43
+ categories: props.longLabel ? LONG_MONTHS.map((month) => `${month} 2026`) : MONTHS,
44
+ series: props.empty ? [{ label: '2026', values: [] }] : props.series ? [BAR_2025, BAR_2026] : [BAR_2026],
45
+ empty: 'No sales in this period',
46
+ mark: props.mark,
47
+ });
48
+ }
49
+
50
+ if (props.kind === 'line') {
51
+ return lineChart({
52
+ plotWidth: PLOT_WIDTH,
53
+ categories: DAYS,
54
+ series: props.series ? [VISITS, SIGNUPS] : [VISITS],
55
+ points: props.points,
56
+ mark: props.mark,
57
+ });
58
+ }
59
+
60
+ return pieChart({
61
+ data: props.empty ? SOURCES.map((source) => ({ ...source, value: 0 })) : props.longLabel ? LONG_SOURCES : SOURCES,
62
+ innerRadius: props.donut ? 0.6 : 0,
63
+ mark: props.mark,
64
+ });
65
+ };
66
+
67
+ export default definePart({
68
+ note: "The SDK charts (et-bar-chart, et-line-chart, et-pie-chart), first drawing, drawn by their mocks from @ethlete/components/design/chart with the real markup and CSS: bar, line and pie chart sheets plus the axis, grid, legend, chart tooltip and line chart tooltip sheets, and the et-tooltip pane for the open tooltip. Framed as a 480px page with 16px padding; bar and line plots 410px wide, 240px high (the default); pie 200px (the default), donut innerRadius 0.6 with its total. Single series draw in the accent; two or more in accent mix steps (100 / 40 %, pie 100 / 80 / 60 / 40 %). States: bar (Jan to Jun), bar-series (2025 and 2026, legend), bar-hover and bar-focus-visible (Apr), bar-tooltip (Mar 2025, hover with its tooltip), bar-empty (projected etBarChartEmpty text), bar-long-label (January 2026 ... June 2026: the auto label spacing thins to every second label); line, line-series (Visits and Sign-ups, legend), line-points, line-hover and line-focus-visible (Thu: crosshair, slice dots, focus box), line-tooltip (Wed, active slice with the multi-series tooltip); pie, donut, pie-hover and pie-focus-visible (Search), pie-tooltip (Direct), pie-empty (all zero: the empty ring), pie-long-label (a long legend label, ellipsed). Static snapshot: the bar grow, line reveal and slice fade are drawn at rest. The lib has no loading state. Numbers (light / dark), from shot pixels at scale 2, brand mint, a: mint marks (bars, line 1, dots, legend and tooltip keys) 1.33 / 13.50; 40 % series (bar 2026, line 2) 1.13 / 2.79; axis and legend text (muted) 7.81 / 6.94; crosshair (subtle) 4.95 / 4.99; hover and focus tint 1.07 / 1.08; focus rings: bar and line (2px, series colour / primary) 1.33 / 13.50, pie (2px, text colour) 17.93 / 17.18. Q98 numbers only: grid lines vs page 1.26 / 1.73 (as the table's edges). Decided rules that arise: Q88 (bar, line and pie focus rings), Q99a (on light the line strokes, slice dots, line legend swatches and tooltip keys take ink in their mix steps; bars, pie slices and the square legend swatches are mint fills and get a 1px ink edge). Series colours otherwise stay data colours: the mix steps are kept. Q101 does not arise: no filled button. An ink edge arises, so Q102 arises: under the brand theme the dark ink is the mint, so the edge is invisible on the full mint fill but shows as a bright outline around the 40 % series in dark (b), while c drops it there. The thinned first and last category labels sit inside the plot (lib fix 3c26c2204). Findings for later, not render refusals: the pie focus ring in b is the same ink as its new 1px edge, only 1px wider, so a focused slice reads close to rest (a used the text colour); d draws it as an outer ring instead. The pie tooltip opens over the legend. Later rounds, left out here: horizontal and stacked bars, negative values, area and stacked area, the time scale, sankey, per-series colour themes, the title and note slots, touch tap.",
69
+ madeBy: ['claude-opus-5-5'],
70
+ states: {
71
+ bar: { kind: 'bar' },
72
+ 'bar-series': { kind: 'bar', series: true },
73
+ 'bar-hover': { kind: 'bar', mark: { index: 3, force: 'hover' } },
74
+ 'bar-focus-visible': { kind: 'bar', mark: { index: 3, force: 'focus-visible' } },
75
+ 'bar-tooltip': { kind: 'bar', series: true, mark: { index: 4, force: 'hover', tooltip: true } },
76
+ 'bar-empty': { kind: 'bar', empty: true },
77
+ 'bar-long-label': { kind: 'bar', longLabel: true },
78
+ line: { kind: 'line' },
79
+ 'line-series': { kind: 'line', series: true },
80
+ 'line-points': { kind: 'line', points: true },
81
+ 'line-hover': { kind: 'line', series: true, mark: { index: 3, force: 'hover' } },
82
+ 'line-focus-visible': { kind: 'line', series: true, mark: { index: 3, force: 'focus-visible' } },
83
+ 'line-tooltip': { kind: 'line', series: true, mark: { index: 2, force: 'hover', tooltip: true } },
84
+ pie: { kind: 'pie' },
85
+ donut: { kind: 'pie', donut: true },
86
+ 'pie-hover': { kind: 'pie', mark: { index: 1, force: 'hover' } },
87
+ 'pie-focus-visible': { kind: 'pie', mark: { index: 1, force: 'focus-visible' } },
88
+ 'pie-tooltip': { kind: 'pie', mark: { index: 0, force: 'hover', tooltip: true } },
89
+ 'pie-empty': { kind: 'pie', empty: true },
90
+ 'pie-long-label': { kind: 'pie', longLabel: true },
91
+ },
92
+ widths: [480],
93
+ frame: (body) => `<div class="t-frame">${body}</div>`,
94
+ render: (props: Props) =>
95
+ drawing({
96
+ body: render(props),
97
+ styles: [chartStyles, frame].join('\n'),
98
+ }),
99
+ });
@@ -0,0 +1,65 @@
1
+ .t-frame {
2
+ box-sizing: border-box;
3
+ display: grid;
4
+ justify-items: start;
5
+ gap: 1.6rem;
6
+ padding: 1.6rem;
7
+ background: var(--et-surface-background-solid);
8
+ color: var(--et-surface-color-solid);
9
+ font-size: 1.4rem;
10
+ }
11
+
12
+ @layer components {
13
+ et-checkbox.et-focus-ring,
14
+ et-choice-field[data-error]
15
+ et-checkbox.et-checkbox:focus-visible:not([aria-checked='true']):not([aria-checked='mixed']) {
16
+ --_et-focus-ring-color: var(--et-theme-color-ink-solid);
17
+ }
18
+
19
+ et-checkbox:is([aria-checked='true'], [aria-checked='mixed']) .et-checkbox-box {
20
+ outline: 1px solid light-dark(var(--et-theme-color-ink-solid), transparent);
21
+ outline-offset: -1px;
22
+ }
23
+
24
+ et-choice-field[data-variant='card']
25
+ et-checkbox:focus-visible:not([aria-checked='true']):not([aria-checked='mixed'])
26
+ .et-checkbox-box {
27
+ border-color: light-dark(var(--et-theme-color-ink-solid), var(--et-theme-color-primary-solid));
28
+ }
29
+
30
+ et-choice-field
31
+ .et-selection-card:where([aria-checked='true'], :has(:is([aria-checked='true'], [aria-checked='mixed']))) {
32
+ border-color: light-dark(var(--et-theme-color-ink-solid), var(--et-theme-color-primary-solid));
33
+ }
34
+
35
+ et-choice-field .et-selection-card:where(:focus-visible, :has(:focus-visible)) {
36
+ border-color: light-dark(var(--et-theme-color-ink-solid), var(--et-theme-color-primary-solid));
37
+ outline-color: var(--et-theme-color-ink-solid);
38
+ }
39
+
40
+ et-checkbox-option.et-checkbox-option:focus-visible .et-checkbox-option-box,
41
+ .et-checkbox-group-select-all.et-checkbox-group-select-all:focus-visible .et-checkbox-group-select-all-box {
42
+ border-color: light-dark(var(--et-theme-color-ink-solid), var(--et-theme-color-primary-solid));
43
+ outline-color: var(--et-theme-color-ink-solid);
44
+ }
45
+
46
+ et-checkbox-option[aria-checked='true']:not(:focus-visible) .et-checkbox-option-box,
47
+ .et-checkbox-group-select-all:is([aria-checked='true'], [aria-checked='mixed']):not(:focus-visible)
48
+ .et-checkbox-group-select-all-box {
49
+ outline: 1px solid light-dark(var(--et-theme-color-ink-solid), transparent);
50
+ outline-offset: -1px;
51
+ }
52
+
53
+ @media (hover: hover) {
54
+ et-checkbox:is([aria-checked='true'], [aria-checked='mixed']):hover,
55
+ .et-color-interactive-container:hover et-checkbox:is([aria-checked='true'], [aria-checked='mixed']),
56
+ et-checkbox-option[aria-checked='true']:hover,
57
+ .et-checkbox-group-select-all:is([aria-checked='true'], [aria-checked='mixed']):hover {
58
+ --et-theme-color-primary-rgb: var(--et-color-primary-active);
59
+ }
60
+ }
61
+
62
+ .et-label-required-marker {
63
+ color: var(--et-theme-color-ink-solid);
64
+ }
65
+ }