@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.
- package/CHANGELOG.md +139 -0
- package/design/accordion.ts +73 -0
- package/design/anchored-dialog.ts +92 -0
- package/design/avatar.ts +90 -0
- package/design/badge.ts +48 -0
- package/design/banner.ts +77 -0
- package/design/bracket.ts +457 -0
- package/design/breadcrumb.ts +145 -0
- package/design/button.ts +62 -1
- package/design/calendar.ts +306 -0
- package/design/card.ts +92 -0
- package/design/carousel.ts +240 -0
- package/design/chart.ts +512 -0
- package/design/checkbox.ts +275 -0
- package/design/chip.ts +64 -0
- package/design/config.json +8 -0
- package/design/control.ts +19 -0
- package/design/copy-button.ts +59 -0
- package/design/description-list.ts +41 -0
- package/design/dialog.ts +216 -0
- package/design/divider.ts +27 -0
- package/design/empty-state.ts +45 -0
- package/design/floating-action.ts +55 -0
- package/design/form-field.ts +3 -0
- package/design/grid.ts +148 -0
- package/design/input.ts +86 -0
- package/design/kbd.ts +19 -0
- package/design/loader.ts +152 -0
- package/design/masonry.ts +115 -0
- package/design/match.ts +131 -0
- package/design/menu.ts +147 -0
- package/design/notification.ts +133 -0
- package/design/otp-input.ts +107 -0
- package/design/pagination.ts +120 -0
- package/design/picture.ts +80 -0
- package/design/progress-steps.ts +79 -0
- package/design/query-error.ts +60 -0
- package/design/radio-group.ts +132 -0
- package/design/scheduler.ts +369 -0
- package/design/scrollable.ts +218 -0
- package/design/scrollbar.ts +47 -0
- package/design/sdk/assets/fallback.svg +1 -0
- package/design/sdk/assets/tall.svg +1 -0
- package/design/sdk/assets/wide.svg +1 -0
- package/design/sdk/components/accent-on-light/accent-on-light.css +35 -0
- package/design/sdk/components/accent-on-light/accent-on-light.ts +10 -0
- package/design/sdk/components/accent-on-light/shared/controls.ts +46 -0
- package/design/sdk/components/accordion/accordion.css +17 -0
- package/design/sdk/components/accordion/accordion.ts +68 -0
- package/design/sdk/components/anchored-dialog/anchored-dialog.css +63 -0
- package/design/sdk/components/anchored-dialog/anchored-dialog.ts +65 -0
- package/design/sdk/components/avatar/avatar.css +14 -0
- package/design/sdk/components/avatar/avatar.ts +79 -0
- package/design/sdk/components/badge/badge.css +13 -0
- package/design/sdk/components/badge/badge.ts +53 -0
- package/design/sdk/components/banner/banner.css +18 -0
- package/design/sdk/components/banner/banner.ts +88 -0
- package/design/sdk/components/bracket/bracket.css +59 -0
- package/design/sdk/components/bracket/bracket.ts +144 -0
- package/design/sdk/components/breadcrumb/breadcrumb.css +25 -0
- package/design/sdk/components/breadcrumb/breadcrumb.ts +82 -0
- package/design/sdk/components/button/button.css +41 -0
- package/design/sdk/components/button/button.ts +59 -7
- package/design/sdk/components/calendar/calendar.css +33 -0
- package/design/sdk/components/calendar/calendar.ts +97 -0
- package/design/sdk/components/card/card.css +19 -0
- package/design/sdk/components/card/card.ts +62 -0
- package/design/sdk/components/carousel/carousel.css +44 -0
- package/design/sdk/components/carousel/carousel.ts +75 -0
- package/design/sdk/components/chart/chart.css +56 -0
- package/design/sdk/components/chart/chart.ts +99 -0
- package/design/sdk/components/checkbox/checkbox.css +65 -0
- package/design/sdk/components/checkbox/checkbox.ts +180 -0
- package/design/sdk/components/chip/chip.css +18 -0
- package/design/sdk/components/chip/chip.ts +77 -0
- package/design/sdk/components/copy-button/copy-button.css +14 -0
- package/design/sdk/components/copy-button/copy-button.ts +60 -0
- package/design/sdk/components/description-list/description-list.css +7 -0
- package/design/sdk/components/description-list/description-list.ts +54 -0
- package/design/sdk/components/dialog/dialog.css +29 -0
- package/design/sdk/components/dialog/dialog.ts +79 -0
- package/design/sdk/components/divider/divider.css +26 -0
- package/design/sdk/components/divider/divider.ts +44 -0
- package/design/sdk/components/empty-state/empty-state.css +15 -0
- package/design/sdk/components/empty-state/empty-state.ts +57 -0
- package/design/sdk/components/floating-action/floating-action.css +51 -0
- package/design/sdk/components/floating-action/floating-action.ts +63 -0
- package/design/sdk/components/form-field/form-field.ts +23 -5
- package/design/sdk/components/grid/grid.css +17 -0
- package/design/sdk/components/grid/grid.ts +81 -0
- package/design/sdk/components/input/input.css +75 -0
- package/design/sdk/components/input/input.ts +80 -0
- package/design/sdk/components/kbd/kbd.css +25 -0
- package/design/sdk/components/kbd/kbd.ts +58 -0
- package/design/sdk/components/loader/loader.css +37 -0
- package/design/sdk/components/loader/loader.ts +69 -0
- package/design/sdk/components/masonry/masonry.css +7 -0
- package/design/sdk/components/masonry/masonry.ts +43 -0
- package/design/sdk/components/match/match.css +25 -0
- package/design/sdk/components/match/match.ts +77 -0
- package/design/sdk/components/menu/menu.css +22 -0
- package/design/sdk/components/menu/menu.ts +103 -0
- package/design/sdk/components/notification/notification.css +32 -0
- package/design/sdk/components/notification/notification.ts +107 -0
- package/design/sdk/components/otp-input/otp-input.css +35 -0
- package/design/sdk/components/otp-input/otp-input.ts +65 -0
- package/design/sdk/components/pagination/pagination.css +14 -0
- package/design/sdk/components/pagination/pagination.ts +76 -0
- package/design/sdk/components/picture/picture.css +37 -0
- package/design/sdk/components/picture/picture.ts +97 -0
- package/design/sdk/components/progress-steps/progress-steps.css +37 -0
- package/design/sdk/components/progress-steps/progress-steps.ts +92 -0
- package/design/sdk/components/query-error/query-error.css +33 -0
- package/design/sdk/components/query-error/query-error.ts +121 -0
- package/design/sdk/components/radio-group/radio-group.css +46 -0
- package/design/sdk/components/radio-group/radio-group.ts +167 -0
- package/design/sdk/components/scheduler/scheduler.css +55 -0
- package/design/sdk/components/scheduler/scheduler.ts +240 -0
- package/design/sdk/components/scrollable/scrollable.css +58 -0
- package/design/sdk/components/scrollable/scrollable.ts +133 -0
- package/design/sdk/components/scrollbar/scrollbar.css +78 -0
- package/design/sdk/components/scrollbar/scrollbar.ts +124 -0
- package/design/sdk/components/select/select.ts +1 -1
- package/design/sdk/components/select/shared/select-part.ts +25 -3
- package/design/sdk/components/select-panel/select-panel.css +3 -0
- package/design/sdk/components/select-panel/select-panel.ts +125 -0
- package/design/sdk/components/skeleton/skeleton.css +22 -0
- package/design/sdk/components/skeleton/skeleton.ts +51 -0
- package/design/sdk/components/slider/slider.css +52 -0
- package/design/sdk/components/slider/slider.ts +87 -0
- package/design/sdk/components/standings/standings.css +33 -0
- package/design/sdk/components/standings/standings.ts +131 -0
- package/design/sdk/components/stat-tile/stat-tile.css +15 -0
- package/design/sdk/components/stat-tile/stat-tile.ts +85 -0
- package/design/sdk/components/stream/stream.css +48 -0
- package/design/sdk/components/stream/stream.ts +43 -0
- package/design/sdk/components/switch/switch.css +37 -0
- package/design/sdk/components/switch/switch.ts +63 -0
- package/design/sdk/components/table/table.css +67 -0
- package/design/sdk/components/table/table.ts +161 -0
- package/design/sdk/components/tabs/tabs.css +13 -0
- package/design/sdk/components/tabs/tabs.ts +74 -0
- package/design/sdk/components/textarea/textarea.css +116 -0
- package/design/sdk/components/textarea/textarea.ts +65 -0
- package/design/sdk/components/timeline/timeline.css +30 -0
- package/design/sdk/components/timeline/timeline.ts +87 -0
- package/design/sdk/components/toolbar/toolbar.css +24 -0
- package/design/sdk/components/toolbar/toolbar.ts +88 -0
- package/design/sdk/components/tooltip/tooltip.css +15 -0
- package/design/sdk/components/tooltip/tooltip.ts +28 -0
- package/design/sdk/components/tree/selected-tint.css +15 -0
- package/design/sdk/components/tree/tree.ts +70 -0
- package/design/sdk/foundations/colors/colors.css +124 -4
- package/design/sdk/foundations/colors/colors.ts +1 -1
- package/design/sdk/foundations/colors/shared/contrast.ts +1 -1
- package/design/sdk/foundations/elevation/elevation.css +6 -0
- package/design/sdk/foundations/elevation/elevation.ts +11 -0
- package/design/sdk/foundations/elevation/shared/elevation/scene.css +101 -0
- package/design/sdk/foundations/elevation/shared/elevation/scene.ts +74 -0
- package/design/sdk/foundations/icons/icons.ts +119 -0
- package/design/sdk/pictures.json +1183 -0
- package/design/select.ts +5 -4
- package/design/skeleton.ts +67 -0
- package/design/slider.ts +155 -0
- package/design/standings.ts +161 -0
- package/design/stat-tile.ts +109 -0
- package/design/stream.ts +92 -0
- package/design/switch.ts +83 -0
- package/design/table.ts +302 -0
- package/design/tabs.ts +75 -0
- package/design/textarea.ts +94 -0
- package/design/timeline.ts +52 -0
- package/design/toolbar.ts +95 -0
- package/design/tooltip.ts +87 -0
- package/fesm2022/ethlete-components.mjs +1440 -1209
- package/fesm2022/ethlete-components.mjs.map +1 -1
- package/generators/generators.json +2 -0
- package/package.json +1 -1
- package/src/lib/accordion/accordion.component.css +2 -1
- package/src/lib/avatar/avatar.component.css +10 -0
- package/src/lib/badge/badge.component.css +2 -2
- package/src/lib/banner/banner.component.css +3 -1
- package/src/lib/breadcrumb/breadcrumb-outlet.component.css +5 -0
- package/src/lib/breadcrumb/breadcrumb.component.css +5 -1
- package/src/lib/button/button-properties-styles.component.css +6 -6
- package/src/lib/button/button.component.css +27 -4
- package/src/lib/button/button.types.ts +33 -0
- package/src/lib/button/icon-button.component.css +21 -22
- package/src/lib/button/split-button.component.css +5 -1
- package/src/lib/button/window-control-button.component.css +43 -3
- package/src/lib/calendar/calendar.component.css +15 -5
- package/src/lib/card/card.component.css +4 -0
- package/src/lib/carousel/carousel-autoplay-styles.component.css +1 -1
- package/src/lib/carousel/carousel.component.css +2 -2
- package/src/lib/chart/chart-axis.component.css +3 -3
- package/src/lib/chip/chip.component.css +12 -6
- package/src/lib/description-list/description-list.component.css +2 -1
- package/src/lib/empty-state/empty-state.component.css +4 -0
- package/src/lib/floating-action/floating-action-styles.component.css +27 -0
- package/src/lib/focus-ring/focus-ring-styles.component.css +4 -1
- package/src/lib/forms/checkbox/checkbox.component.css +31 -5
- package/src/lib/forms/color-input/color-input.component.css +3 -1
- package/src/lib/forms/color-input/color-picker-panel.component.css +6 -2
- package/src/lib/forms/date-time/date-input/date-input.component.css +1 -1
- package/src/lib/forms/date-time/date-time-input/date-time-input.component.css +1 -1
- package/src/lib/forms/date-time/duration-input/duration-input.component.css +1 -1
- package/src/lib/forms/date-time/range-input-shell-styles.component.css +1 -1
- package/src/lib/forms/date-time/time-input/time-input.component.css +1 -1
- package/src/lib/forms/description/description.component.css +7 -0
- package/src/lib/forms/dropzone/dropzone.component.css +26 -0
- package/src/lib/forms/form-field/form-field-control-suffix-styles.component.css +4 -2
- package/src/lib/forms/form-field/form-field-text-shell-styles.component.css +54 -5
- package/src/lib/forms/form-field/form-field-textarea-styles.component.css +62 -0
- package/src/lib/forms/form-field/form-field.component.css +6 -0
- package/src/lib/forms/form-field/headless/label.directive.css +1 -1
- package/src/lib/forms/input/input.component.css +6 -2
- package/src/lib/forms/input/number-input.component.css +2 -2
- package/src/lib/forms/input/password-input.component.css +4 -3
- package/src/lib/forms/otp-input/otp-input.component.css +23 -4
- package/src/lib/forms/phone-input/phone-input.component.css +4 -3
- package/src/lib/forms/rating/rating.component.css +2 -1
- package/src/lib/forms/rich-text-editor/rich-text-editor.component.css +1 -1
- package/src/lib/forms/selection-card-styles.component.css +3 -2
- package/src/lib/forms/selection-list/checkbox-group/checkbox-group-select-all.component.css +4 -2
- package/src/lib/forms/selection-list/checkbox-group/checkbox-option.component.css +4 -2
- package/src/lib/forms/selection-list/radio-group/radio.component.css +5 -2
- package/src/lib/forms/selection-list/segmented-button-group/segmented-button.component.css +2 -1
- package/src/lib/forms/slider/range-slider.component.css +98 -6
- package/src/lib/forms/slider/slider.component.css +96 -4
- package/src/lib/forms/switch/switch.component.css +45 -15
- package/src/lib/forms/tag-input/tag-input.component.css +2 -2
- package/src/lib/forms/textarea/textarea-autosize-styles.component.css +2 -3
- package/src/lib/forms/textarea/textarea.component.css +7 -2
- package/src/lib/grid/grid-item-toolbar.component.css +10 -0
- package/src/lib/grid/grid-item.component.css +6 -1
- package/src/lib/kbd/kbd.component.css +1 -1
- package/src/lib/loader/brand-loader/brand-loader.component.css +4 -1
- package/src/lib/loader/progress-bar/progress-bar.component.css +1 -1
- package/src/lib/loader/spinner/spinner-styles.component.css +1 -1
- package/src/lib/match/match-card.component.css +9 -3
- package/src/lib/match/match-score.component.css +4 -1
- package/src/lib/menu/menu-selection-item.component.css +1 -1
- package/src/lib/menu/menu.component.css +6 -1
- package/src/lib/notification/notification.component.css +3 -3
- package/src/lib/overlay/overlay-container.component.css +4 -0
- package/src/lib/pagination/pagination.component.css +4 -0
- package/src/lib/progress-steps/progress-step.component.css +4 -4
- package/src/lib/query-error/query-error.component.css +4 -0
- package/src/lib/scheduler/scheduler-appointment-styles.component.css +21 -5
- package/src/lib/scheduler/scheduler-month-view.component.css +4 -2
- package/src/lib/scheduler/scheduler-time-grid-view.component.css +8 -2
- package/src/lib/scrollable/headless/scrollable-navigation.component.css +1 -1
- package/src/lib/standings/standings-pick.component.css +1 -1
- package/src/lib/standings/standings.component.css +10 -10
- package/src/lib/stat-tile/stat-tile-sparkline.component.css +1 -1
- package/src/lib/stream/consent/stream-consent.component.css +99 -0
- package/src/lib/stream/error/stream-player-error.component.css +100 -0
- package/src/lib/stream/loading/stream-player-loading.component.css +16 -0
- package/src/lib/stream/pip/pip-slot-placeholder.component.css +68 -0
- package/src/lib/stream/stream-player-slot-styles.component.css +4 -0
- package/src/lib/table/table-resize-grip.component.css +2 -1
- package/src/lib/table/table-select-cell.component.css +45 -15
- package/src/lib/table/table.component.css +15 -5
- package/src/lib/tabs/tab-bar-styles.component.css +1 -1
- package/src/lib/tabs/tabs/tab-group.component.css +111 -0
- package/src/lib/time-picker/time-picker.component.css +2 -1
- package/src/lib/timeline/timeline-item.component.css +5 -1
- package/src/lib/toolbar/toolbar.component.css +4 -0
- package/src/lib/tooltip/tooltip.component.css +14 -0
- package/types/ethlete-components.d.ts +156 -128
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { iconMarkup } from '@ethlete/components/design/icon';
|
|
2
|
+
import { SDK_ICONS } from '@ethlete/components/design/icon-set';
|
|
3
|
+
import { tabs, type TabsMockOptions, tabsStyles } from '@ethlete/components/design/tabs';
|
|
4
|
+
import { definePart, drawing, interactionRows } from '@design-system';
|
|
5
|
+
import edge from './tabs.css?inline';
|
|
6
|
+
|
|
7
|
+
type TriggerInteraction = 'hover' | 'active' | 'focus-visible';
|
|
8
|
+
|
|
9
|
+
type Props = TabsMockOptions & { forced?: { tab: number; interaction: TriggerInteraction } };
|
|
10
|
+
|
|
11
|
+
const TABS = [{ label: 'Overview' }, { label: 'Activity' }, { label: 'Settings' }];
|
|
12
|
+
const WITH_DISABLED = [...TABS, { label: 'Billing', disabled: true }];
|
|
13
|
+
|
|
14
|
+
const icon = (name: string) =>
|
|
15
|
+
iconMarkup(
|
|
16
|
+
SDK_ICONS.find((each) => each.name === name)!,
|
|
17
|
+
'et-tab-group__trigger-icon',
|
|
18
|
+
);
|
|
19
|
+
const WITH_ICONS = [
|
|
20
|
+
{ label: `${icon('et-grid-2x2')}Overview` },
|
|
21
|
+
{ label: `${icon('et-clock')}Activity` },
|
|
22
|
+
{ label: `${icon('et-pencil')}Settings` },
|
|
23
|
+
];
|
|
24
|
+
const ICON_ONLY = [
|
|
25
|
+
{ label: icon('et-grid-2x2'), name: 'Overview' },
|
|
26
|
+
{ label: icon('et-clock'), name: 'Activity' },
|
|
27
|
+
{ label: icon('et-pencil'), name: 'Settings' },
|
|
28
|
+
];
|
|
29
|
+
const ICON_ONLY_LABELS = Object.fromEntries(ICON_ONLY.map(({ name }, index) => [index, `aria-label="${name}"`]));
|
|
30
|
+
|
|
31
|
+
const { states, grid } = interactionRows(
|
|
32
|
+
{
|
|
33
|
+
tab: { tabs: TABS, selected: 0 },
|
|
34
|
+
selected: { tabs: TABS, selected: 1 },
|
|
35
|
+
} satisfies Record<string, Props>,
|
|
36
|
+
{
|
|
37
|
+
interactions: ['hover', 'active', 'focus-visible'],
|
|
38
|
+
force: (props: Props, interaction: TriggerInteraction): Props => ({ ...props, forced: { tab: 1, interaction } }),
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
export default definePart({
|
|
43
|
+
note: 'The SDK tab group, drawn by its mock from @ethlete/components/design: the bar with its triggers, the underline of the selected tab and the baseline, in every size, both variants and both orientations.',
|
|
44
|
+
madeBy: ['claude-opus-5-5'],
|
|
45
|
+
states: {
|
|
46
|
+
...states,
|
|
47
|
+
disabled: { tabs: WITH_DISABLED, selected: 0 },
|
|
48
|
+
sm: { tabs: TABS, size: 'sm' },
|
|
49
|
+
lg: { tabs: TABS, size: 'lg' },
|
|
50
|
+
primary: { tabs: TABS, variant: 'primary' },
|
|
51
|
+
icons: { tabs: WITH_ICONS },
|
|
52
|
+
'primary-icons': { tabs: WITH_ICONS, variant: 'primary' },
|
|
53
|
+
'icon-only': { tabs: ICON_ONLY, triggerAttributes: ICON_ONLY_LABELS },
|
|
54
|
+
'primary-icon-only': { tabs: ICON_ONLY, triggerAttributes: ICON_ONLY_LABELS, variant: 'primary' },
|
|
55
|
+
'no-divider': { tabs: TABS, divider: false },
|
|
56
|
+
vertical: { tabs: TABS, orientation: 'vertical' },
|
|
57
|
+
panel: { tabs: TABS, panel: '<p>Three open tasks, two of them due this week.</p>' },
|
|
58
|
+
},
|
|
59
|
+
grid,
|
|
60
|
+
widths: [480],
|
|
61
|
+
controls: {
|
|
62
|
+
tab: { kind: 'button', input: ['pointer', 'keyboard'], disabled: true },
|
|
63
|
+
},
|
|
64
|
+
render: ({ forced, ...props }: Props) =>
|
|
65
|
+
drawing({
|
|
66
|
+
body: tabs({
|
|
67
|
+
...props,
|
|
68
|
+
triggerAttributes: forced
|
|
69
|
+
? { ...props.triggerAttributes, [forced.tab]: `data-et-force="${forced.interaction}"` }
|
|
70
|
+
: props.triggerAttributes,
|
|
71
|
+
}).replaceAll('role="tab"', 'data-et-control="tab" role="tab"'),
|
|
72
|
+
styles: [tabsStyles, edge].join('\n'),
|
|
73
|
+
}),
|
|
74
|
+
});
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
.t-frame {
|
|
2
|
+
box-sizing: border-box;
|
|
3
|
+
display: grid;
|
|
4
|
+
gap: 1.6rem;
|
|
5
|
+
padding: 1.6rem;
|
|
6
|
+
background: var(--et-surface-background-solid);
|
|
7
|
+
color: var(--et-surface-color-solid);
|
|
8
|
+
font-size: 1.4rem;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@layer components {
|
|
12
|
+
et-form-field[data-text-shell] {
|
|
13
|
+
--_t-focus-frame: var(--et-surface-color-solid);
|
|
14
|
+
--_et-form-field-frame-border: var(--et-surface-interaction-solid);
|
|
15
|
+
--_et-form-field-frame-border-hover: color-mix(
|
|
16
|
+
in srgb,
|
|
17
|
+
var(--et-surface-interaction-solid) 75%,
|
|
18
|
+
var(--et-surface-color-solid)
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
et-form-field[data-text-shell][data-error] {
|
|
23
|
+
--_t-focus-frame: var(--et-theme-color-ink-solid);
|
|
24
|
+
--_et-form-field-frame-border: var(--et-theme-color-primary-solid);
|
|
25
|
+
--_et-form-field-frame-border-hover: light-dark(
|
|
26
|
+
rgb(var(--et-color-primary-hover, var(--et-color-primary))),
|
|
27
|
+
rgb(
|
|
28
|
+
var(
|
|
29
|
+
--et-color-primary-ink-active,
|
|
30
|
+
var(
|
|
31
|
+
--et-color-primary-ink-focus,
|
|
32
|
+
var(
|
|
33
|
+
--et-color-primary-ink-hover,
|
|
34
|
+
var(
|
|
35
|
+
--et-color-primary-ink,
|
|
36
|
+
var(
|
|
37
|
+
--et-color-primary-active,
|
|
38
|
+
var(--et-color-primary-focus, var(--et-color-primary-hover, var(--et-color-primary)))
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
et-form-field[data-text-shell]:is([data-focused], :has(:focus-visible)):not([data-readonly])
|
|
49
|
+
.et-form-field-control-frame {
|
|
50
|
+
border-color: var(--_t-focus-frame);
|
|
51
|
+
box-shadow: inset 0 0 0 var(--et-form-field-control-border-width) var(--_t-focus-frame);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
et-form-field[data-text-shell][data-readonly] .et-form-field-control-frame {
|
|
55
|
+
border-style: dashed;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
et-form-field[data-text-shell][data-readonly]:is([data-focused], :has(:focus-visible)) .et-form-field-control-frame {
|
|
59
|
+
outline: calc(2 * var(--et-form-field-control-border-width)) dashed var(--_t-focus-frame);
|
|
60
|
+
outline-offset: calc(-2 * var(--et-form-field-control-border-width));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
et-textarea .et-textarea-native::placeholder {
|
|
64
|
+
color: color-mix(in srgb, currentColor 60%, transparent);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
et-form-field et-label .et-label-required-marker {
|
|
68
|
+
color: var(--et-theme-color-ink-solid);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@layer components {
|
|
73
|
+
et-form-field[data-text-shell][data-control-type='textarea'][data-appearance='box']:not(
|
|
74
|
+
[data-label-mode='floating-inside']
|
|
75
|
+
) {
|
|
76
|
+
--_t-line: calc(var(--et-form-field-control-font-size) * var(--et-form-field-control-line-height));
|
|
77
|
+
--_t-pad: max(
|
|
78
|
+
var(--et-form-field-control-padding-block),
|
|
79
|
+
(
|
|
80
|
+
var(--et-form-field-control-min-height) - var(--et-form-field-control-font-size) *
|
|
81
|
+
var(--et-form-field-control-line-height) - 2 * var(--et-form-field-control-border-width)
|
|
82
|
+
) /
|
|
83
|
+
2
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
.et-form-field-control-frame {
|
|
87
|
+
padding-block: 0;
|
|
88
|
+
padding-inline-end: 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.et-textarea-native {
|
|
92
|
+
box-sizing: border-box;
|
|
93
|
+
padding-block: var(--_t-pad);
|
|
94
|
+
padding-inline-end: var(--et-form-field-control-padding-inline);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
textarea[data-et-textarea-autosize] {
|
|
98
|
+
min-block-size: calc(var(--et-textarea-min-rows, 1) * 1lh + 2 * var(--_t-pad));
|
|
99
|
+
max-block-size: calc(var(--et-textarea-max-block-size, 1000lh) + 2 * var(--_t-pad));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
&[data-label-mode='inline'] .et-form-field-label-area--inline {
|
|
103
|
+
margin-block: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.t-scrolled & .et-form-field-control-slot {
|
|
107
|
+
overflow: clip;
|
|
108
|
+
max-block-size: calc(4 * var(--_t-line) + 2 * var(--_t-pad));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.t-scrolled & textarea[data-et-textarea-autosize] {
|
|
112
|
+
max-block-size: none;
|
|
113
|
+
translate: 0 calc(-2.5 * var(--_t-line) - var(--_t-pad));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
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', 'claude-sonnet-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
|
+
frame: (body, props) => `<div class="t-frame ${props.scrolled ? 't-scrolled' : ''}">${body}</div>`,
|
|
58
|
+
render: (props: Props) =>
|
|
59
|
+
drawing({
|
|
60
|
+
body: props.scrolled
|
|
61
|
+
? textareaField(props.field).replace('<div class="et-form-field-control-frame"', '$& data-et-skip="CLIPPED"')
|
|
62
|
+
: textareaField(props.field),
|
|
63
|
+
styles: [textareaFieldStyles, frame].join('\n'),
|
|
64
|
+
}),
|
|
65
|
+
});
|
|
@@ -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', 'claude-sonnet-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,88 @@
|
|
|
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
|
+
frame: (body) => `<div class="toolbar-frame">${body}</div>`,
|
|
83
|
+
render: (props: Props) =>
|
|
84
|
+
drawing({
|
|
85
|
+
body: render(props),
|
|
86
|
+
styles: [toolbarStyles, frame].join('\n'),
|
|
87
|
+
}),
|
|
88
|
+
});
|
|
@@ -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
|
+
});
|