@ethlete/components 1.0.0-next.78 → 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 (252) hide show
  1. package/CHANGELOG.md +113 -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 +4 -1
  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/grid.ts +148 -0
  24. package/design/input.ts +86 -0
  25. package/design/kbd.ts +19 -0
  26. package/design/loader.ts +152 -0
  27. package/design/masonry.ts +115 -0
  28. package/design/match.ts +131 -0
  29. package/design/menu.ts +143 -0
  30. package/design/notification.ts +129 -0
  31. package/design/otp-input.ts +107 -0
  32. package/design/pagination.ts +120 -0
  33. package/design/picture.ts +80 -0
  34. package/design/progress-steps.ts +79 -0
  35. package/design/query-error.ts +60 -0
  36. package/design/radio-group.ts +132 -0
  37. package/design/scheduler.ts +369 -0
  38. package/design/scrollable.ts +218 -0
  39. package/design/scrollbar.ts +47 -0
  40. package/design/sdk/assets/fallback.svg +1 -0
  41. package/design/sdk/assets/tall.svg +1 -0
  42. package/design/sdk/assets/wide.svg +1 -0
  43. package/design/sdk/components/accent-on-light/accent-on-light.css +35 -0
  44. package/design/sdk/components/accent-on-light/accent-on-light.ts +10 -0
  45. package/design/sdk/components/accent-on-light/shared/controls.ts +46 -0
  46. package/design/sdk/components/accordion/accordion.css +17 -0
  47. package/design/sdk/components/accordion/accordion.ts +64 -0
  48. package/design/sdk/components/avatar/avatar.css +14 -0
  49. package/design/sdk/components/avatar/avatar.ts +78 -0
  50. package/design/sdk/components/badge/badge.css +13 -0
  51. package/design/sdk/components/badge/badge.ts +52 -0
  52. package/design/sdk/components/banner/banner.css +18 -0
  53. package/design/sdk/components/banner/banner.ts +87 -0
  54. package/design/sdk/components/bracket/bracket.css +59 -0
  55. package/design/sdk/components/bracket/bracket.ts +143 -0
  56. package/design/sdk/components/breadcrumb/breadcrumb.css +25 -0
  57. package/design/sdk/components/breadcrumb/breadcrumb.ts +81 -0
  58. package/design/sdk/components/button/button.css +33 -0
  59. package/design/sdk/components/button/button.ts +50 -7
  60. package/design/sdk/components/calendar/calendar.css +33 -0
  61. package/design/sdk/components/calendar/calendar.ts +96 -0
  62. package/design/sdk/components/card/card.css +19 -0
  63. package/design/sdk/components/card/card.ts +61 -0
  64. package/design/sdk/components/carousel/carousel.css +44 -0
  65. package/design/sdk/components/carousel/carousel.ts +74 -0
  66. package/design/sdk/components/chart/chart.css +56 -0
  67. package/design/sdk/components/chart/chart.ts +98 -0
  68. package/design/sdk/components/chip/chip.css +18 -0
  69. package/design/sdk/components/chip/chip.ts +76 -0
  70. package/design/sdk/components/copy-button/copy-button.css +14 -0
  71. package/design/sdk/components/copy-button/copy-button.ts +59 -0
  72. package/design/sdk/components/description-list/description-list.css +7 -0
  73. package/design/sdk/components/description-list/description-list.ts +53 -0
  74. package/design/sdk/components/dialog/dialog.css +29 -0
  75. package/design/sdk/components/dialog/dialog.ts +78 -0
  76. package/design/sdk/components/divider/divider.css +26 -0
  77. package/design/sdk/components/divider/divider.ts +43 -0
  78. package/design/sdk/components/empty-state/empty-state.css +15 -0
  79. package/design/sdk/components/empty-state/empty-state.ts +56 -0
  80. package/design/sdk/components/floating-action/floating-action.css +51 -0
  81. package/design/sdk/components/floating-action/floating-action.ts +63 -0
  82. package/design/sdk/components/form-field/form-field.ts +23 -5
  83. package/design/sdk/components/grid/grid.css +17 -0
  84. package/design/sdk/components/grid/grid.ts +80 -0
  85. package/design/sdk/components/input/input.css +75 -0
  86. package/design/sdk/components/input/input.ts +79 -0
  87. package/design/sdk/components/kbd/kbd.css +25 -0
  88. package/design/sdk/components/kbd/kbd.ts +57 -0
  89. package/design/sdk/components/loader/loader.css +37 -0
  90. package/design/sdk/components/loader/loader.ts +68 -0
  91. package/design/sdk/components/masonry/masonry.css +7 -0
  92. package/design/sdk/components/masonry/masonry.ts +42 -0
  93. package/design/sdk/components/match/match.css +25 -0
  94. package/design/sdk/components/match/match.ts +76 -0
  95. package/design/sdk/components/menu/menu.css +22 -0
  96. package/design/sdk/components/menu/menu.ts +91 -0
  97. package/design/sdk/components/notification/notification.css +32 -0
  98. package/design/sdk/components/notification/notification.ts +106 -0
  99. package/design/sdk/components/otp-input/otp-input.css +35 -0
  100. package/design/sdk/components/otp-input/otp-input.ts +64 -0
  101. package/design/sdk/components/pagination/pagination.css +14 -0
  102. package/design/sdk/components/pagination/pagination.ts +75 -0
  103. package/design/sdk/components/picture/picture.css +37 -0
  104. package/design/sdk/components/picture/picture.ts +96 -0
  105. package/design/sdk/components/progress-steps/progress-steps.css +37 -0
  106. package/design/sdk/components/progress-steps/progress-steps.ts +91 -0
  107. package/design/sdk/components/query-error/query-error.css +33 -0
  108. package/design/sdk/components/query-error/query-error.ts +120 -0
  109. package/design/sdk/components/scheduler/scheduler.css +55 -0
  110. package/design/sdk/components/scheduler/scheduler.ts +239 -0
  111. package/design/sdk/components/scrollable/scrollable.css +58 -0
  112. package/design/sdk/components/scrollable/scrollable.ts +133 -0
  113. package/design/sdk/components/scrollbar/scrollbar.css +78 -0
  114. package/design/sdk/components/scrollbar/scrollbar.ts +123 -0
  115. package/design/sdk/components/select/select.ts +1 -1
  116. package/design/sdk/components/select/shared/select-part.ts +16 -1
  117. package/design/sdk/components/select-panel/select-panel.css +3 -0
  118. package/design/sdk/components/select-panel/select-panel.ts +124 -0
  119. package/design/sdk/components/skeleton/skeleton.css +22 -0
  120. package/design/sdk/components/skeleton/skeleton.ts +50 -0
  121. package/design/sdk/components/slider/slider.css +52 -0
  122. package/design/sdk/components/slider/slider.ts +86 -0
  123. package/design/sdk/components/standings/standings.css +33 -0
  124. package/design/sdk/components/standings/standings.ts +130 -0
  125. package/design/sdk/components/stat-tile/stat-tile.css +15 -0
  126. package/design/sdk/components/stat-tile/stat-tile.ts +84 -0
  127. package/design/sdk/components/stream/stream.css +48 -0
  128. package/design/sdk/components/stream/stream.ts +38 -0
  129. package/design/sdk/components/switch/switch.css +35 -0
  130. package/design/sdk/components/switch/switch.ts +63 -0
  131. package/design/sdk/components/table/table.css +67 -0
  132. package/design/sdk/components/table/table.ts +160 -0
  133. package/design/sdk/components/tabs/tabs.css +13 -0
  134. package/design/sdk/components/tabs/tabs.ts +74 -0
  135. package/design/sdk/components/textarea/textarea.css +116 -0
  136. package/design/sdk/components/textarea/textarea.ts +64 -0
  137. package/design/sdk/components/timeline/timeline.css +30 -0
  138. package/design/sdk/components/timeline/timeline.ts +87 -0
  139. package/design/sdk/components/toolbar/toolbar.css +24 -0
  140. package/design/sdk/components/toolbar/toolbar.ts +87 -0
  141. package/design/sdk/components/tooltip/tooltip.css +15 -0
  142. package/design/sdk/components/tooltip/tooltip.ts +28 -0
  143. package/design/sdk/components/tree/selected-tint.css +15 -0
  144. package/design/sdk/components/tree/tree.ts +70 -0
  145. package/design/sdk/foundations/colors/colors.css +108 -4
  146. package/design/sdk/foundations/elevation/elevation.css +6 -0
  147. package/design/sdk/foundations/elevation/elevation.ts +11 -0
  148. package/design/sdk/foundations/elevation/shared/elevation/scene.css +101 -0
  149. package/design/sdk/foundations/elevation/shared/elevation/scene.ts +74 -0
  150. package/design/sdk/foundations/icons/icons.ts +119 -0
  151. package/design/skeleton.ts +67 -0
  152. package/design/slider.ts +155 -0
  153. package/design/standings.ts +161 -0
  154. package/design/stat-tile.ts +109 -0
  155. package/design/stream.ts +92 -0
  156. package/design/switch.ts +83 -0
  157. package/design/table.ts +302 -0
  158. package/design/tabs.ts +75 -0
  159. package/design/textarea.ts +92 -0
  160. package/design/timeline.ts +52 -0
  161. package/design/toolbar.ts +95 -0
  162. package/design/tooltip.ts +87 -0
  163. package/fesm2022/ethlete-components.mjs +228 -187
  164. package/fesm2022/ethlete-components.mjs.map +1 -1
  165. package/package.json +1 -1
  166. package/src/lib/accordion/accordion.component.css +2 -1
  167. package/src/lib/avatar/avatar.component.css +10 -0
  168. package/src/lib/badge/badge.component.css +2 -2
  169. package/src/lib/banner/banner.component.css +3 -1
  170. package/src/lib/breadcrumb/breadcrumb-outlet.component.css +5 -0
  171. package/src/lib/breadcrumb/breadcrumb.component.css +5 -1
  172. package/src/lib/button/button.component.css +19 -0
  173. package/src/lib/button/icon-button.component.css +19 -20
  174. package/src/lib/button/split-button.component.css +5 -1
  175. package/src/lib/calendar/calendar.component.css +13 -3
  176. package/src/lib/card/card.component.css +4 -0
  177. package/src/lib/carousel/carousel-autoplay-styles.component.css +1 -1
  178. package/src/lib/carousel/carousel.component.css +2 -2
  179. package/src/lib/chart/chart-axis.component.css +3 -3
  180. package/src/lib/chip/chip.component.css +8 -2
  181. package/src/lib/description-list/description-list.component.css +2 -1
  182. package/src/lib/empty-state/empty-state.component.css +4 -0
  183. package/src/lib/floating-action/floating-action-styles.component.css +27 -0
  184. package/src/lib/focus-ring/focus-ring-styles.component.css +4 -1
  185. package/src/lib/forms/checkbox/checkbox.component.css +31 -5
  186. package/src/lib/forms/color-input/color-input.component.css +3 -1
  187. package/src/lib/forms/color-input/color-picker-panel.component.css +6 -2
  188. package/src/lib/forms/date-time/date-input/date-input.component.css +1 -1
  189. package/src/lib/forms/date-time/date-time-input/date-time-input.component.css +1 -1
  190. package/src/lib/forms/date-time/duration-input/duration-input.component.css +1 -1
  191. package/src/lib/forms/date-time/range-input-shell-styles.component.css +1 -1
  192. package/src/lib/forms/date-time/time-input/time-input.component.css +1 -1
  193. package/src/lib/forms/description/description.component.css +7 -0
  194. package/src/lib/forms/dropzone/dropzone.component.css +26 -0
  195. package/src/lib/forms/form-field/form-field-control-suffix-styles.component.css +4 -2
  196. package/src/lib/forms/form-field/form-field-text-shell-styles.component.css +54 -5
  197. package/src/lib/forms/form-field/form-field-textarea-styles.component.css +62 -0
  198. package/src/lib/forms/form-field/form-field.component.css +6 -0
  199. package/src/lib/forms/form-field/headless/label.directive.css +1 -1
  200. package/src/lib/forms/input/input.component.css +6 -2
  201. package/src/lib/forms/input/number-input.component.css +2 -2
  202. package/src/lib/forms/input/password-input.component.css +4 -3
  203. package/src/lib/forms/otp-input/otp-input.component.css +23 -4
  204. package/src/lib/forms/phone-input/phone-input.component.css +4 -3
  205. package/src/lib/forms/rating/rating.component.css +2 -1
  206. package/src/lib/forms/rich-text-editor/rich-text-editor.component.css +1 -1
  207. package/src/lib/forms/selection-card-styles.component.css +3 -2
  208. package/src/lib/forms/selection-list/checkbox-group/checkbox-group-select-all.component.css +4 -2
  209. package/src/lib/forms/selection-list/checkbox-group/checkbox-option.component.css +4 -2
  210. package/src/lib/forms/selection-list/radio-group/radio.component.css +5 -2
  211. package/src/lib/forms/selection-list/segmented-button-group/segmented-button.component.css +2 -1
  212. package/src/lib/forms/slider/range-slider.component.css +98 -6
  213. package/src/lib/forms/slider/slider.component.css +96 -4
  214. package/src/lib/forms/switch/switch.component.css +47 -4
  215. package/src/lib/forms/tag-input/tag-input.component.css +2 -2
  216. package/src/lib/forms/textarea/textarea-autosize-styles.component.css +2 -3
  217. package/src/lib/forms/textarea/textarea.component.css +7 -2
  218. package/src/lib/grid/grid-item-toolbar.component.css +10 -0
  219. package/src/lib/grid/grid-item.component.css +6 -1
  220. package/src/lib/loader/brand-loader/brand-loader.component.css +4 -1
  221. package/src/lib/loader/progress-bar/progress-bar.component.css +1 -1
  222. package/src/lib/loader/spinner/spinner-styles.component.css +1 -1
  223. package/src/lib/match/match-card.component.css +9 -3
  224. package/src/lib/match/match-score.component.css +4 -1
  225. package/src/lib/menu/menu-selection-item.component.css +1 -1
  226. package/src/lib/menu/menu.component.css +5 -0
  227. package/src/lib/overlay/overlay-container.component.css +4 -0
  228. package/src/lib/pagination/pagination.component.css +4 -0
  229. package/src/lib/progress-steps/progress-step.component.css +4 -4
  230. package/src/lib/query-error/query-error.component.css +4 -0
  231. package/src/lib/scheduler/scheduler-appointment-styles.component.css +21 -5
  232. package/src/lib/scheduler/scheduler-month-view.component.css +4 -2
  233. package/src/lib/scheduler/scheduler-time-grid-view.component.css +8 -2
  234. package/src/lib/scrollable/headless/scrollable-navigation.component.css +1 -1
  235. package/src/lib/standings/standings-pick.component.css +1 -1
  236. package/src/lib/standings/standings.component.css +10 -10
  237. package/src/lib/stat-tile/stat-tile-sparkline.component.css +1 -1
  238. package/src/lib/stream/consent/stream-consent.component.css +99 -0
  239. package/src/lib/stream/error/stream-player-error.component.css +100 -0
  240. package/src/lib/stream/loading/stream-player-loading.component.css +16 -0
  241. package/src/lib/stream/pip/pip-slot-placeholder.component.css +68 -0
  242. package/src/lib/stream/stream-player-slot-styles.component.css +4 -0
  243. package/src/lib/table/table-resize-grip.component.css +2 -1
  244. package/src/lib/table/table-select-cell.component.css +45 -15
  245. package/src/lib/table/table.component.css +15 -5
  246. package/src/lib/tabs/tab-bar-styles.component.css +1 -1
  247. package/src/lib/tabs/tabs/tab-group.component.css +111 -0
  248. package/src/lib/time-picker/time-picker.component.css +2 -1
  249. package/src/lib/timeline/timeline-item.component.css +5 -1
  250. package/src/lib/toolbar/toolbar.component.css +4 -0
  251. package/src/lib/tooltip/tooltip.component.css +14 -0
  252. package/types/ethlete-components.d.ts +11 -2
@@ -0,0 +1,64 @@
1
+ import { textareaField, type TextareaFieldMockOptions, textareaFieldStyles } from '@ethlete/components/design/textarea';
2
+ import { definePart, drawing } from '@design-system';
3
+ import frame from './textarea.css?inline';
4
+
5
+ type Props = { field: TextareaFieldMockOptions; scrolled?: boolean };
6
+
7
+ const message = (extra: Partial<TextareaFieldMockOptions> = {}): Props => ({
8
+ field: { id: 'message', label: 'Message', placeholder: 'Write something…', ...extra },
9
+ });
10
+
11
+ const VALUE = 'Hi Lena,\nthe venue moved to Hall B.\nKick-off stays at 18:00.';
12
+
13
+ const LONG =
14
+ 'Hi Lena,\nthe venue moved to Hall B, next to the north entrance.\nKick-off stays at 18:00, doors open at 17:15.\nPlease bring your team list and the signed waiver for every player.\nParking is free after 17:00 on the east lot.\nThe referee briefing starts at 17:30 in room 2.\nSee you there,\nJonas';
15
+
16
+ const INVALID = {
17
+ required: true,
18
+ value: 'Hi',
19
+ error: 'Write at least 20 characters.',
20
+ errorColor: 'danger',
21
+ } satisfies Partial<TextareaFieldMockOptions>;
22
+
23
+ export default definePart({
24
+ note: 'scale of the decided shape, Q182, lead merge',
25
+ madeBy: ['claude-opus-5-5'],
26
+ states: {
27
+ empty: message({ placeholder: undefined }),
28
+ placeholder: message(),
29
+ filled: message({ value: VALUE }),
30
+ hover: message({ force: 'hover' }),
31
+ 'hover-filled': message({ value: VALUE, force: 'hover' }),
32
+ focus: message({ focused: true, force: 'focus-visible' }),
33
+ 'focus-filled': message({ value: VALUE, focused: true, force: 'focus-visible' }),
34
+ 'focus-hover': message({ value: VALUE, focused: true, force: ['hover', 'focus-visible'] }),
35
+ hint: message({ hint: 'Visible to everyone on the team.' }),
36
+ description: message({ description: 'Shown above the event on the team page.' }),
37
+ required: message({ required: true, hint: 'Visible to everyone on the team.' }),
38
+ invalid: message(INVALID),
39
+ 'invalid-hover': message({ ...INVALID, force: 'hover' }),
40
+ 'invalid-focus': message({ ...INVALID, focused: true, force: 'focus-visible' }),
41
+ disabled: message({ disabled: true }),
42
+ 'disabled-filled': message({ value: VALUE, disabled: true }),
43
+ readonly: message({ value: VALUE, readonly: true }),
44
+ 'readonly-focus': message({ value: VALUE, readonly: true, focused: true, force: 'focus-visible' }),
45
+ 'long-autosize': message({ value: LONG }),
46
+ 'long-max-rows': message({ value: LONG, maxRows: 4 }),
47
+ 'long-max-rows-scrolled': { ...message({ value: LONG, maxRows: 4 }), scrolled: true },
48
+ 'manual-resize': message({ value: VALUE, autosize: false, rows: 4 }),
49
+ 'manual-resize-overflow': message({ value: LONG, autosize: false, rows: 4 }),
50
+ 'single-row': message({ rows: 1, placeholder: 'Add a note…' }),
51
+ mixed: message({ value: VALUE, mixed: true, mixedLabel: 'Mixed values' }),
52
+ 'no-label': message({ label: undefined, placeholder: 'Add a comment…' }),
53
+ 'size-sm': message({ value: VALUE, size: 'sm' }),
54
+ 'size-lg': message({ value: VALUE, size: 'lg' }),
55
+ },
56
+ widths: [320, 360, 640],
57
+ render: (props: Props) =>
58
+ drawing({
59
+ body: props.scrolled
60
+ ? `<div class="t-frame t-scrolled">${textareaField(props.field).replace('<div class="et-form-field-control-frame"', '$& data-et-skip="CLIPPED"')}</div>`
61
+ : `<div class="t-frame">${textareaField(props.field)}</div>`,
62
+ styles: [textareaFieldStyles, frame].join('\n'),
63
+ }),
64
+ });
@@ -0,0 +1,30 @@
1
+ .timeline-frame {
2
+ max-inline-size: 520px;
3
+ padding: 2.4rem 1.6rem;
4
+ background: var(--et-surface-background-solid);
5
+ color: var(--et-surface-color-solid);
6
+ font-size: 1.4rem;
7
+
8
+ .timeline-label,
9
+ .timeline-description {
10
+ margin: 0;
11
+ }
12
+
13
+ .timeline-description {
14
+ color: var(--et-surface-color-muted-solid);
15
+ font-size: 1.2rem;
16
+ }
17
+ }
18
+
19
+ .timeline-frame--compact .et-timeline {
20
+ --et-timeline-gap: 8px;
21
+ --et-timeline-rail-gap: 8px;
22
+ --et-timeline-marker-size: 14px;
23
+ --et-timeline-dot-size: 6px;
24
+ }
25
+
26
+ @layer components {
27
+ .timeline-frame .et-timeline-item {
28
+ --et-timeline-marker-color: light-dark(var(--et-theme-color-ink-solid), var(--et-theme-color-primary-solid));
29
+ }
30
+ }
@@ -0,0 +1,87 @@
1
+ import { SDK_ICONS } from '@ethlete/components/design/icon-set';
2
+ import { iconMarkup } from '@ethlete/components/design/icon';
3
+ import { timeline, timelineStyles, type TimelineMockItem } from '@ethlete/components/design/timeline';
4
+ import { definePart, drawing } from '@design-system';
5
+ import frame from './timeline.css?inline';
6
+
7
+ const icon = (name: string) => SDK_ICONS.find((each) => each.name === name)!;
8
+
9
+ type Props = {
10
+ markers?: boolean;
11
+ themedDots?: boolean;
12
+ time?: boolean;
13
+ compact?: boolean;
14
+ long?: boolean;
15
+ count?: number;
16
+ };
17
+
18
+ const EVENTS = [
19
+ {
20
+ time: '18:30',
21
+ label: 'Squad announced',
22
+ description: 'Both line-ups published 60 minutes before kickoff.',
23
+ icon: 'et-clock',
24
+ color: undefined,
25
+ },
26
+ {
27
+ time: "23'",
28
+ label: 'Goal by A. Rossi',
29
+ description: 'Assisted by M. Keller after a counter down the left.',
30
+ icon: 'et-circle-check',
31
+ color: 'warning',
32
+ },
33
+ {
34
+ time: "67'",
35
+ label: 'Second yellow for L. Turner',
36
+ description: 'Sent off; the home side plays the rest a player down.',
37
+ icon: 'et-triangle-exclamation',
38
+ color: 'danger',
39
+ },
40
+ {
41
+ time: "90+4'",
42
+ label: 'Fulltime - 2:1',
43
+ description: 'The visitors take all three points and go top of the table.',
44
+ icon: 'et-trophy',
45
+ color: 'brand',
46
+ },
47
+ ];
48
+
49
+ const LONG_LABEL = 'Match report filed by the referee with notes on both sendings-off and the crowd incident';
50
+ const LONG_DESCRIPTION =
51
+ 'league.example.com/matches/20261031_home_visitors_report_attachments_referee_statement_final.pdf';
52
+
53
+ const items = ({ markers, themedDots, time = true, compact, long, count = EVENTS.length }: Props) =>
54
+ EVENTS.slice(0, count).map((event, index): TimelineMockItem => {
55
+ const label = long && index === 1 ? LONG_LABEL : event.label;
56
+ const description = long && index === 1 ? LONG_DESCRIPTION : event.description;
57
+
58
+ return {
59
+ time: time ? event.time : undefined,
60
+ marker: markers ? iconMarkup(icon(event.icon)) : undefined,
61
+ color: markers || themedDots ? event.color : undefined,
62
+ content:
63
+ `<p class="timeline-label">${label}</p>` +
64
+ (compact ? '' : `<p class="timeline-description">${description}</p>`),
65
+ };
66
+ });
67
+
68
+ export default definePart({
69
+ note: 'Decided rules only',
70
+ madeBy: ['claude-opus-5-5'],
71
+ states: {
72
+ default: {},
73
+ 'with-markers': { markers: true },
74
+ 'themed-dots': { themedDots: true },
75
+ compact: { compact: true },
76
+ 'compact-markers': { compact: true, markers: true },
77
+ 'no-time': { time: false },
78
+ 'long-content': { long: true, markers: true },
79
+ single: { count: 1 },
80
+ },
81
+ widths: [480],
82
+ render: (props: Props) =>
83
+ drawing({
84
+ body: `<div class="timeline-frame${props.compact ? ' timeline-frame--compact' : ''}">${timeline({ items: items(props) })}</div>`,
85
+ styles: [timelineStyles, frame].join('\n'),
86
+ }),
87
+ });
@@ -0,0 +1,24 @@
1
+ .toolbar-frame {
2
+ display: flex;
3
+ align-items: flex-start;
4
+ padding: 2.4rem 1.6rem;
5
+ background: var(--et-surface-background-solid);
6
+ color: var(--et-surface-color-solid);
7
+
8
+ .et-toolbar {
9
+ --et-toolbar-background: var(--et-surface-background-solid);
10
+
11
+ inline-size: fit-content;
12
+ border: 1px solid var(--et-surface-border-solid);
13
+ }
14
+ }
15
+
16
+ @layer components {
17
+ .toolbar-frame .et-focus-ring {
18
+ --_et-focus-ring-color: var(--et-theme-color-ink-solid);
19
+ }
20
+
21
+ .toolbar-frame .et-icon-button[data-pressed='true'] {
22
+ box-shadow: inset 0 0 0 1px var(--et-theme-color-ink-solid);
23
+ }
24
+ }
@@ -0,0 +1,87 @@
1
+ import { toolbar, toolbarStyles, type ToolbarMockItem } from '@ethlete/components/design/toolbar';
2
+ import { SDK_ICONS } from '@ethlete/components/design/icon-set';
3
+ import { definePart, drawing } from '@design-system';
4
+ import frame from './toolbar.css?inline';
5
+
6
+ const icon = (name: string) => SDK_ICONS.find((each) => each.name === name)!;
7
+
8
+ type Interaction = 'hover' | 'active' | 'focus-visible';
9
+ type Control = 'bold' | 'italic' | 'underline' | 'bulleted' | 'numbered' | 'quote' | 'link';
10
+
11
+ type Props = {
12
+ orientation?: 'horizontal' | 'vertical';
13
+ /** The controls an interaction is forced on. */
14
+ forced?: Control[];
15
+ interaction?: Interaction;
16
+ italicDisabled?: boolean;
17
+ tabStop?: Control;
18
+ size?: 'xs' | 'md' | 'lg' | 'xl';
19
+ };
20
+
21
+ const BUTTONS: { control: Control; icon: (typeof SDK_ICONS)[number]; label: string; pressed?: boolean }[] = [
22
+ { control: 'bold', icon: icon('et-bold'), label: 'Bold', pressed: true },
23
+ { control: 'italic', icon: icon('et-italic'), label: 'Italic', pressed: false },
24
+ { control: 'underline', icon: icon('et-underline'), label: 'Underline', pressed: false },
25
+ { control: 'bulleted', icon: icon('et-list-bulleted'), label: 'Bulleted list', pressed: true },
26
+ { control: 'numbered', icon: icon('et-list-numbered'), label: 'Numbered list', pressed: false },
27
+ { control: 'quote', icon: icon('et-quote'), label: 'Quote', pressed: false },
28
+ { control: 'link', icon: icon('et-link'), label: 'Link' },
29
+ ];
30
+
31
+ const GROUP_ENDS: Control[] = ['underline', 'numbered'];
32
+
33
+ const items = ({ forced = [], interaction, italicDisabled }: Props) =>
34
+ BUTTONS.flatMap(({ control, icon, label, pressed }): ToolbarMockItem[] => {
35
+ const attributes = [
36
+ `data-et-control="${control}" data-can-animate`,
37
+ interaction && forced.includes(control) && `data-et-force="${interaction}"`,
38
+ ]
39
+ .filter(Boolean)
40
+ .join(' ');
41
+ const button: ToolbarMockItem = {
42
+ type: 'button',
43
+ icon,
44
+ label,
45
+ pressed,
46
+ disabled: control === 'italic' && italicDisabled,
47
+ attributes,
48
+ };
49
+
50
+ return GROUP_ENDS.includes(control) ? [button, { type: 'divider' }] : [button];
51
+ });
52
+
53
+ const render = (props: Props) => {
54
+ const list = items(props);
55
+ const tabStop = props.tabStop
56
+ ? list.findIndex((item) => item.type === 'button' && item.attributes?.includes(`"${props.tabStop}"`))
57
+ : undefined;
58
+
59
+ return toolbar({ items: list, orientation: props.orientation, size: props.size, tabStop });
60
+ };
61
+
62
+ export default definePart({
63
+ note: 'scale of the decided shape, Q182, lead merge',
64
+ madeBy: ['claude-opus-5-5'],
65
+ states: {
66
+ default: {},
67
+ hover: { interaction: 'hover', forced: ['bold', 'italic'] },
68
+ active: { interaction: 'active', forced: ['bold', 'italic'] },
69
+ 'focus-visible': { interaction: 'focus-visible', forced: ['bold'] },
70
+ 'focus-visible-unpressed': { interaction: 'focus-visible', forced: ['italic'], tabStop: 'italic' },
71
+ disabled: { italicDisabled: true },
72
+ vertical: { orientation: 'vertical' },
73
+ 'size-xs': { size: 'xs' },
74
+ 'size-md': { size: 'md' },
75
+ 'size-lg': { size: 'lg' },
76
+ 'size-xl': { size: 'xl' },
77
+ },
78
+ widths: [528],
79
+ controls: Object.fromEntries(
80
+ BUTTONS.map(({ control }) => [control, { kind: 'button', input: ['pointer', 'keyboard'] }]),
81
+ ),
82
+ render: (props: Props) =>
83
+ drawing({
84
+ body: `<div class="toolbar-frame">${render(props)}</div>`,
85
+ styles: [toolbarStyles, frame].join('\n'),
86
+ }),
87
+ });
@@ -0,0 +1,15 @@
1
+ .sdk-tooltip-stage {
2
+ display: inline-block;
3
+ padding: 16px;
4
+ }
5
+
6
+ @media (prefers-color-scheme: dark) {
7
+ .et-tooltip-panel {
8
+ --et-surface-ring-solid: color-mix(in srgb, var(--et-surface-color-solid) 24%, var(--et-surface-background-solid));
9
+ --et-overlay-arrow-border: var(--et-surface-ring-solid);
10
+ }
11
+
12
+ .et-tooltip {
13
+ --_et-floating-tip-border: var(--et-surface-ring-solid);
14
+ }
15
+ }
@@ -0,0 +1,28 @@
1
+ import { tooltip, type TooltipMockOptions, tooltipStyles } from '@ethlete/components/design/tooltip';
2
+ import { definePart, drawing } from '@design-system';
3
+ import edge from './tooltip.css?inline';
4
+
5
+ const SHORT = 'Copy link';
6
+ const LONG = 'Everyone with the link can view this board. Comments stay private to the members of the workspace.';
7
+ const TEMPLATE = '<p><strong>Shift + C</strong></p><p>Copies the link to this board. Anyone with it can view.</p>';
8
+
9
+ export default definePart<TooltipMockOptions>({
10
+ note: 'The SDK tooltip, drawn by its mock from @ethlete/components/design: the open pane with its arrow on the inherited surface. Short text, long text that wraps at the 34ch max width, template content, and each side the pane opens on, plus a -start and an -end placement with the arrow 20 px in. In the dark scheme the pane border and the arrow edge are a 1 px ring in --et-surface-ring-solid, 24 % --et-surface-color-solid over the fill, as in the foundations/elevation round. The token is defined here; the generator does not emit it yet.',
11
+ madeBy: ['claude-opus-5-5'],
12
+ states: {
13
+ short: { text: SHORT },
14
+ long: { text: LONG },
15
+ template: { content: TEMPLATE },
16
+ top: { text: SHORT, placement: 'top' },
17
+ right: { text: SHORT, placement: 'right' },
18
+ bottom: { text: SHORT, placement: 'bottom' },
19
+ left: { text: SHORT, placement: 'left' },
20
+ 'bottom-start': { text: 'Copy the link to this board', placement: 'bottom-start' },
21
+ 'top-end': { text: 'Copy the link to this board', placement: 'top-end' },
22
+ },
23
+ render: (options: TooltipMockOptions) =>
24
+ drawing({
25
+ body: `<div class="sdk-tooltip-stage">${tooltip(options)}</div>`,
26
+ styles: [tooltipStyles, edge].join('\n'),
27
+ }),
28
+ });
@@ -0,0 +1,15 @@
1
+ @layer components {
2
+ @container style(--et-surface-type: light) {
3
+ .et-tree:not(:where([aria-multiselectable])) .et-tree-node:where([data-selected]) {
4
+ background: color-mix(in srgb, var(--et-theme-color-primary-solid, gray) 32%, transparent);
5
+
6
+ &:not(:where([aria-disabled])):hover {
7
+ background: color-mix(in srgb, var(--et-theme-color-primary-solid, gray) 38%, transparent);
8
+ }
9
+
10
+ &:not(:where([aria-disabled])):active {
11
+ background: color-mix(in srgb, var(--et-theme-color-primary-solid, gray) 44%, transparent);
12
+ }
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,70 @@
1
+ import { tree, TreeMockItem, treeStyles } from '@ethlete/components/design/tree';
2
+ import { definePart, drawing, interactionRows } from '@design-system';
3
+ import selectedTint from './selected-tint.css?inline';
4
+
5
+ type RowInteraction = 'hover' | 'active' | 'focus-visible';
6
+
7
+ type Props = {
8
+ items: TreeMockItem[];
9
+ expanded?: string[];
10
+ value?: string;
11
+ active?: string;
12
+ forced?: { row: string; interaction: RowInteraction };
13
+ };
14
+
15
+ const FILES: TreeMockItem[] = [
16
+ {
17
+ label: 'src',
18
+ children: [
19
+ {
20
+ label: 'app',
21
+ children: [{ label: 'app.component.ts' }, { label: 'app.config.ts' }, { label: 'legacy.ts', disabled: true }],
22
+ },
23
+ { label: 'assets', children: [{ label: 'logo.svg' }] },
24
+ { label: 'main.ts' },
25
+ ],
26
+ },
27
+ { label: 'docs', children: [{ label: 'getting-started.md' }] },
28
+ { label: 'package.json' },
29
+ ];
30
+
31
+ const SHORT: TreeMockItem[] = [{ label: 'docs' }, { label: 'notes.md' }, { label: 'README.md' }];
32
+
33
+ const { states, grid } = interactionRows(
34
+ {
35
+ row: { items: SHORT },
36
+ selected: { items: SHORT, value: 'notes.md' },
37
+ } satisfies Record<string, Props>,
38
+ {
39
+ interactions: ['hover', 'active', 'focus-visible'],
40
+ force: (props: Props, interaction: RowInteraction): Props => ({
41
+ ...props,
42
+ active: 'notes.md',
43
+ forced: { row: 'notes.md', interaction },
44
+ }),
45
+ },
46
+ );
47
+
48
+ export default definePart({
49
+ note: 'The SDK tree, drawn by its mock from @ethlete/components/design. Rows keep a roving tab stop, so a focused row draws the real :focus-visible ring.',
50
+ madeBy: ['claude-opus-5-5'],
51
+ states: {
52
+ ...states,
53
+ collapsed: { items: FILES },
54
+ expanded: { items: FILES, expanded: ['src', 'src/app', 'docs'], value: 'src/app/app.config.ts' },
55
+ },
56
+ grid,
57
+ widths: [320],
58
+ controls: {
59
+ row: { kind: 'row', input: ['pointer', 'keyboard'], disabled: true },
60
+ },
61
+ render: ({ forced, ...props }: Props) =>
62
+ drawing({
63
+ body: tree({
64
+ ...props,
65
+ label: 'Files',
66
+ rowAttributes: forced && { [forced.row]: `data-et-force="${forced.interaction}"` },
67
+ }).replaceAll('role="treeitem"', 'data-et-control="row" role="treeitem"'),
68
+ styles: [treeStyles, selectedTint].join('\n'),
69
+ }),
70
+ });
@@ -51,7 +51,6 @@
51
51
  --et-surface-interaction-disabled: 180 180 180;
52
52
  }
53
53
 
54
- .et-surface--default-dark,
55
54
  .et-surface--dark-elevated {
56
55
  --et-surface-background: 38 38 38;
57
56
  --et-surface-color: 250 250 250;
@@ -385,16 +384,34 @@
385
384
 
386
385
  @layer base {
387
386
  @media (prefers-color-scheme: light) {
388
- :root {
387
+ :root,
388
+ .et-color--brand {
389
389
  --et-color-primary-ink: 4 120 87;
390
390
  --et-color-primary-ink-hover: 6 95 70;
391
391
  --et-color-primary-ink-focus: 6 95 70;
392
392
  --et-color-primary-ink-active: 6 78 59;
393
393
  --et-color-primary-ink-disabled: 130 200 170;
394
394
  }
395
+
396
+ .et-color--danger {
397
+ --et-color-primary-ink: 185 28 28;
398
+ --et-color-primary-ink-hover: 153 27 27;
399
+ --et-color-primary-ink-focus: 153 27 27;
400
+ --et-color-primary-ink-active: 127 29 29;
401
+ --et-color-primary-ink-disabled: 220 150 150;
402
+ }
403
+
404
+ .et-color--warning {
405
+ --et-color-primary-ink: 146 64 14;
406
+ --et-color-primary-ink-hover: 120 53 15;
407
+ --et-color-primary-ink-focus: 120 53 15;
408
+ --et-color-primary-ink-active: 69 26 3;
409
+ --et-color-primary-ink-disabled: 220 170 120;
410
+ }
395
411
  }
396
412
 
397
- :root.et-scheme--light {
413
+ :root.et-scheme--light,
414
+ :where(:root.et-scheme--light) .et-color--brand {
398
415
  --et-color-primary-ink: 4 120 87;
399
416
  --et-color-primary-ink-hover: 6 95 70;
400
417
  --et-color-primary-ink-focus: 6 95 70;
@@ -402,13 +419,100 @@
402
419
  --et-color-primary-ink-disabled: 130 200 170;
403
420
  }
404
421
 
405
- :root.et-scheme--dark {
422
+ :where(:root.et-scheme--light) .et-color--danger {
423
+ --et-color-primary-ink: 185 28 28;
424
+ --et-color-primary-ink-hover: 153 27 27;
425
+ --et-color-primary-ink-focus: 153 27 27;
426
+ --et-color-primary-ink-active: 127 29 29;
427
+ --et-color-primary-ink-disabled: 220 150 150;
428
+ }
429
+
430
+ :where(:root.et-scheme--light) .et-color--warning {
431
+ --et-color-primary-ink: 146 64 14;
432
+ --et-color-primary-ink-hover: 120 53 15;
433
+ --et-color-primary-ink-focus: 120 53 15;
434
+ --et-color-primary-ink-active: 69 26 3;
435
+ --et-color-primary-ink-disabled: 220 170 120;
436
+ }
437
+
438
+ :root.et-scheme--dark,
439
+ :where(:root.et-scheme--dark) .et-color--brand {
440
+ --et-color-primary-ink: 0 255 161;
441
+ --et-color-primary-ink-hover: 0 255 161;
442
+ --et-color-primary-ink-focus: 0 255 161;
443
+ --et-color-primary-ink-active: 0 255 161;
444
+ --et-color-primary-ink-disabled: 0 255 161;
445
+ }
446
+
447
+ :where(:root.et-scheme--dark) .et-color--danger {
448
+ --et-color-primary-ink: 248 113 113;
449
+ --et-color-primary-ink-hover: 252 165 165;
450
+ --et-color-primary-ink-focus: 252 165 165;
451
+ --et-color-primary-ink-active: 239 68 68;
452
+ --et-color-primary-ink-disabled: 153 75 75;
453
+ }
454
+
455
+ :where(:root.et-scheme--dark) .et-color--warning {
456
+ --et-color-primary-ink: 245 158 11;
457
+ --et-color-primary-ink-hover: 251 191 36;
458
+ --et-color-primary-ink-focus: 251 191 36;
459
+ --et-color-primary-ink-active: 217 119 6;
460
+ --et-color-primary-ink-disabled: 133 77 14;
461
+ }
462
+
463
+ .et-surface--light.et-color--brand,
464
+ .et-surface--light .et-color--brand {
465
+ --et-color-primary-ink: 4 120 87;
466
+ --et-color-primary-ink-hover: 6 95 70;
467
+ --et-color-primary-ink-focus: 6 95 70;
468
+ --et-color-primary-ink-active: 6 78 59;
469
+ --et-color-primary-ink-disabled: 130 200 170;
470
+ }
471
+
472
+ .et-surface--light.et-color--danger,
473
+ .et-surface--light .et-color--danger {
474
+ --et-color-primary-ink: 185 28 28;
475
+ --et-color-primary-ink-hover: 153 27 27;
476
+ --et-color-primary-ink-focus: 153 27 27;
477
+ --et-color-primary-ink-active: 127 29 29;
478
+ --et-color-primary-ink-disabled: 220 150 150;
479
+ }
480
+
481
+ .et-surface--light.et-color--warning,
482
+ .et-surface--light .et-color--warning {
483
+ --et-color-primary-ink: 146 64 14;
484
+ --et-color-primary-ink-hover: 120 53 15;
485
+ --et-color-primary-ink-focus: 120 53 15;
486
+ --et-color-primary-ink-active: 69 26 3;
487
+ --et-color-primary-ink-disabled: 220 170 120;
488
+ }
489
+
490
+ .et-surface--dark.et-color--brand,
491
+ .et-surface--dark .et-color--brand {
406
492
  --et-color-primary-ink: 0 255 161;
407
493
  --et-color-primary-ink-hover: 0 255 161;
408
494
  --et-color-primary-ink-focus: 0 255 161;
409
495
  --et-color-primary-ink-active: 0 255 161;
410
496
  --et-color-primary-ink-disabled: 0 255 161;
411
497
  }
498
+
499
+ .et-surface--dark.et-color--danger,
500
+ .et-surface--dark .et-color--danger {
501
+ --et-color-primary-ink: 248 113 113;
502
+ --et-color-primary-ink-hover: 252 165 165;
503
+ --et-color-primary-ink-focus: 252 165 165;
504
+ --et-color-primary-ink-active: 239 68 68;
505
+ --et-color-primary-ink-disabled: 153 75 75;
506
+ }
507
+
508
+ .et-surface--dark.et-color--warning,
509
+ .et-surface--dark .et-color--warning {
510
+ --et-color-primary-ink: 245 158 11;
511
+ --et-color-primary-ink-hover: 251 191 36;
512
+ --et-color-primary-ink-focus: 251 191 36;
513
+ --et-color-primary-ink-active: 217 119 6;
514
+ --et-color-primary-ink-disabled: 133 77 14;
515
+ }
412
516
  }
413
517
 
414
518
  @layer base {
@@ -0,0 +1,6 @@
1
+ @media (prefers-color-scheme: dark) {
2
+ .sdk-ring {
3
+ --et-surface-ring-solid: color-mix(in srgb, var(--et-surface-color-solid) 24%, var(--et-surface-background-solid));
4
+ --sdk-elevation-edge: var(--et-surface-ring-solid);
5
+ }
6
+ }
@@ -0,0 +1,11 @@
1
+ import { definePart } from '@design-system';
2
+ import { ELEVATION_STATES, elevationScene, type ElevationProps } from './shared/elevation/scene';
3
+ import edge from './elevation.css?inline';
4
+
5
+ export default definePart<ElevationProps>({
6
+ note: 'How the SDK lifts things off the base surface: a card, an elevated panel and an overlay pane (the select panel mock), side by side and as a pane over a panel. Fills come from the elevated surface tokens; no background colour differs from the product. In the dark scheme a 1 px ring in --et-surface-ring-solid (24 % --et-surface-color-solid over the fill) replaces the border colour. The token is defined here; the generator does not emit it yet.',
7
+ madeBy: ['claude-opus-5-5'],
8
+ states: ELEVATION_STATES,
9
+ render: (props: ElevationProps) =>
10
+ elevationScene(props, { card: 'sdk-ring', panel: 'sdk-ring', pane: 'sdk-ring' }, edge),
11
+ });