@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
|
@@ -1,17 +1,38 @@
|
|
|
1
|
-
import {
|
|
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
|
|
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
|
|
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
|
-
|
|
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: '
|
|
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) =>
|
|
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
|
+
}
|