@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.
- package/CHANGELOG.md +113 -0
- package/design/accordion.ts +73 -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 +49 -0
- 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 +4 -1
- package/design/control.ts +19 -0
- package/design/copy-button.ts +59 -0
- package/design/description-list.ts +41 -0
- package/design/dialog.ts +214 -0
- package/design/divider.ts +27 -0
- package/design/empty-state.ts +45 -0
- package/design/floating-action.ts +55 -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 +143 -0
- package/design/notification.ts +129 -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 +64 -0
- package/design/sdk/components/avatar/avatar.css +14 -0
- package/design/sdk/components/avatar/avatar.ts +78 -0
- package/design/sdk/components/badge/badge.css +13 -0
- package/design/sdk/components/badge/badge.ts +52 -0
- package/design/sdk/components/banner/banner.css +18 -0
- package/design/sdk/components/banner/banner.ts +87 -0
- package/design/sdk/components/bracket/bracket.css +59 -0
- package/design/sdk/components/bracket/bracket.ts +143 -0
- package/design/sdk/components/breadcrumb/breadcrumb.css +25 -0
- package/design/sdk/components/breadcrumb/breadcrumb.ts +81 -0
- package/design/sdk/components/button/button.css +33 -0
- package/design/sdk/components/button/button.ts +50 -7
- package/design/sdk/components/calendar/calendar.css +33 -0
- package/design/sdk/components/calendar/calendar.ts +96 -0
- package/design/sdk/components/card/card.css +19 -0
- package/design/sdk/components/card/card.ts +61 -0
- package/design/sdk/components/carousel/carousel.css +44 -0
- package/design/sdk/components/carousel/carousel.ts +74 -0
- package/design/sdk/components/chart/chart.css +56 -0
- package/design/sdk/components/chart/chart.ts +98 -0
- package/design/sdk/components/chip/chip.css +18 -0
- package/design/sdk/components/chip/chip.ts +76 -0
- package/design/sdk/components/copy-button/copy-button.css +14 -0
- package/design/sdk/components/copy-button/copy-button.ts +59 -0
- package/design/sdk/components/description-list/description-list.css +7 -0
- package/design/sdk/components/description-list/description-list.ts +53 -0
- package/design/sdk/components/dialog/dialog.css +29 -0
- package/design/sdk/components/dialog/dialog.ts +78 -0
- package/design/sdk/components/divider/divider.css +26 -0
- package/design/sdk/components/divider/divider.ts +43 -0
- package/design/sdk/components/empty-state/empty-state.css +15 -0
- package/design/sdk/components/empty-state/empty-state.ts +56 -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 +80 -0
- package/design/sdk/components/input/input.css +75 -0
- package/design/sdk/components/input/input.ts +79 -0
- package/design/sdk/components/kbd/kbd.css +25 -0
- package/design/sdk/components/kbd/kbd.ts +57 -0
- package/design/sdk/components/loader/loader.css +37 -0
- package/design/sdk/components/loader/loader.ts +68 -0
- package/design/sdk/components/masonry/masonry.css +7 -0
- package/design/sdk/components/masonry/masonry.ts +42 -0
- package/design/sdk/components/match/match.css +25 -0
- package/design/sdk/components/match/match.ts +76 -0
- package/design/sdk/components/menu/menu.css +22 -0
- package/design/sdk/components/menu/menu.ts +91 -0
- package/design/sdk/components/notification/notification.css +32 -0
- package/design/sdk/components/notification/notification.ts +106 -0
- package/design/sdk/components/otp-input/otp-input.css +35 -0
- package/design/sdk/components/otp-input/otp-input.ts +64 -0
- package/design/sdk/components/pagination/pagination.css +14 -0
- package/design/sdk/components/pagination/pagination.ts +75 -0
- package/design/sdk/components/picture/picture.css +37 -0
- package/design/sdk/components/picture/picture.ts +96 -0
- package/design/sdk/components/progress-steps/progress-steps.css +37 -0
- package/design/sdk/components/progress-steps/progress-steps.ts +91 -0
- package/design/sdk/components/query-error/query-error.css +33 -0
- package/design/sdk/components/query-error/query-error.ts +120 -0
- package/design/sdk/components/scheduler/scheduler.css +55 -0
- package/design/sdk/components/scheduler/scheduler.ts +239 -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 +123 -0
- package/design/sdk/components/select/select.ts +1 -1
- package/design/sdk/components/select/shared/select-part.ts +16 -1
- package/design/sdk/components/select-panel/select-panel.css +3 -0
- package/design/sdk/components/select-panel/select-panel.ts +124 -0
- package/design/sdk/components/skeleton/skeleton.css +22 -0
- package/design/sdk/components/skeleton/skeleton.ts +50 -0
- package/design/sdk/components/slider/slider.css +52 -0
- package/design/sdk/components/slider/slider.ts +86 -0
- package/design/sdk/components/standings/standings.css +33 -0
- package/design/sdk/components/standings/standings.ts +130 -0
- package/design/sdk/components/stat-tile/stat-tile.css +15 -0
- package/design/sdk/components/stat-tile/stat-tile.ts +84 -0
- package/design/sdk/components/stream/stream.css +48 -0
- package/design/sdk/components/stream/stream.ts +38 -0
- package/design/sdk/components/switch/switch.css +35 -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 +160 -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 +64 -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 +87 -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 +108 -4
- 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/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 +92 -0
- package/design/timeline.ts +52 -0
- package/design/toolbar.ts +95 -0
- package/design/tooltip.ts +87 -0
- package/fesm2022/ethlete-components.mjs +228 -187
- package/fesm2022/ethlete-components.mjs.map +1 -1
- 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.component.css +19 -0
- package/src/lib/button/icon-button.component.css +19 -20
- package/src/lib/button/split-button.component.css +5 -1
- package/src/lib/calendar/calendar.component.css +13 -3
- 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 +8 -2
- 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 +47 -4
- 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/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 +5 -0
- 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 +11 -2
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { otpInput, type OtpInputMockOptions, otpInputStyles } from '@ethlete/components/design/otp-input';
|
|
2
|
+
import { definePart, drawing } from '@design-system';
|
|
3
|
+
import frame from './otp-input.css?inline';
|
|
4
|
+
|
|
5
|
+
type Props = { field: OtpInputMockOptions };
|
|
6
|
+
|
|
7
|
+
const code = (extra: Partial<OtpInputMockOptions> = {}): Props => ({
|
|
8
|
+
field: { id: 'code', label: 'Verification code', ...extra },
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const pin = (extra: Partial<OtpInputMockOptions> = {}): Props => ({
|
|
12
|
+
field: { id: 'pin', label: 'PIN', length: 4, masked: true, ...extra },
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const INVALID = {
|
|
16
|
+
required: true,
|
|
17
|
+
error: 'Enter the code from the SMS.',
|
|
18
|
+
errorColor: 'danger',
|
|
19
|
+
} satisfies Partial<OtpInputMockOptions>;
|
|
20
|
+
|
|
21
|
+
export default definePart({
|
|
22
|
+
note: 'The SDK otp input (et-otp-input), first drawing, drawn by the mock from @ethlete/components/design/otp-input with the real markup and CSS: et-label with the required marker, the segment row, the invisible native input over it, et-form-support with hint and error; the brand theme, danger as the error theme. The field has no :focus or :hover CSS of its own: focus is the data-caret segment (a 1px border plus a 1px inset outline in primary, and a blinking 2px caret bar in an empty one), which the mock draws with focused. Fixtures are fictional: Verification code, 6 digits 482193, hint We sent it to +49 151 0000 0000., required with error Enter the code from the SMS.; a 4-digit masked PIN. Framed as a page with 16px padding at 320, 360 and 640. States: empty, partial, filled, hover, focus-empty, focus-partial, focus-filled, hint, required, invalid, invalid-partial, invalid-focus, disabled, disabled-filled, readonly, readonly-focus, pin-partial and pin-focus. Numbers (light / dark), from shot pixels at scale 2 at 360, brand mint, a: segment 44px outer (border-box, fixed in 00072d935), gap 8px, row 304px, digits 19.8px; empty and filled segment border (surface border) vs page 1.26 / 1.73, the only edge of a segment; caret segment edge and caret bar (primary) 1.33 / 13.50; required marker (brand primary) 1.33 / 13.50; invalid border (danger) 4.83 / 3.71; label (muted) 7.81 / 6.94; disabled digits 2.55 / 3.72 (opacity 0.4, exempt). Decided rules that arise: Q88 (focus in ink: the caret segment edge and the caret bar take ink, the invalid one the danger ink) and Q99a (a mint mark on light takes ink: the required marker light-dark(ink, primary)). Hover follows the text field (form-field-text-shell: the frame border to surface-interaction-hover, the error frame to ink, none when readonly or disabled), on the host since the host is the click target (otp.activate()). The filled segment edge in c is my proposal, not a decided rule (Q103). Findings for later, lib bugs apart: (L1) a 6-digit field needed 304px and never shrank; at 320 with 16px page padding it overflowed by 16px (drawn at 320). Now fixed: the segments shrink, 41.3px at 320, and the render at 640 is unchanged. (L2) a readonly field showed the focus caret segment and, when not full, the blinking caret bar, though nothing can be typed (readonly-focus). Now fixed: no caret when readonly. Design: (1) WCAG 1.4.11: the segment border 1.26 / 1.73 is the only edge of an empty segment, as with the checkbox box and the radio circle. Not drawn. (2) A filled segment looks like an empty one apart from its digit; c answers it. (3) The error border is the full danger primary, while the text field draws its error frame at 50 % danger; kept, it passes 3:1. (4) Hover (10.37 / 13.07) outshines the focus edge (5.48 / 13.50) in b and c, as it does on the text field. (5) The masked dot is a 19.8px bullet, about 5px wide. (6) The error marker 3.71 in dark, exempted as in checkbox r1. Later rounds, left out here: data-warning (no CSS of its own), a coloured field, alphanumeric codes, other lengths and segment sizes via the custom properties, RTL and the pop-in animation.',
|
|
23
|
+
madeBy: ['claude-opus-5-5'],
|
|
24
|
+
states: {
|
|
25
|
+
empty: code(),
|
|
26
|
+
partial: code({ value: '482' }),
|
|
27
|
+
filled: code({ value: '482193' }),
|
|
28
|
+
hover: code({ value: '482', force: 'hover' }),
|
|
29
|
+
'focus-empty': code({ focused: true }),
|
|
30
|
+
'focus-partial': code({ value: '482', focused: true }),
|
|
31
|
+
'focus-filled': code({ value: '482193', focused: true }),
|
|
32
|
+
hint: code({ hint: 'We sent it to +49 151 0000 0000.' }),
|
|
33
|
+
required: code({ required: true, hint: 'We sent it to +49 151 0000 0000.' }),
|
|
34
|
+
invalid: code(INVALID),
|
|
35
|
+
'invalid-partial': code({ ...INVALID, value: '48' }),
|
|
36
|
+
'invalid-focus': code({ ...INVALID, value: '48', focused: true }),
|
|
37
|
+
disabled: code({ disabled: true }),
|
|
38
|
+
'disabled-filled': code({ value: '482193', disabled: true }),
|
|
39
|
+
readonly: code({ value: '482193', readonly: true }),
|
|
40
|
+
'readonly-focus': code({ value: '482', readonly: true, focused: true }),
|
|
41
|
+
'pin-partial': pin({ value: '73' }),
|
|
42
|
+
'pin-focus': pin({ value: '73', focused: true }),
|
|
43
|
+
},
|
|
44
|
+
contrast: {
|
|
45
|
+
exceptions: [
|
|
46
|
+
{
|
|
47
|
+
selector: 'et-otp-input:has(.et-otp-input-native:disabled) .et-otp-input-segment-char',
|
|
48
|
+
reason:
|
|
49
|
+
'A disabled field is exempt under WCAG 1.4.3 (inactive component): opacity 0.4 draws the digits 2.55:1 / 3.72:1.',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
selector: 'et-otp-input[data-error] .et-label-required-marker',
|
|
53
|
+
reason:
|
|
54
|
+
'The required marker takes the error theme primary: 3.71:1 in dark, under 4.5:1. An open point (checkbox r1 finding 3), not a decided rule.',
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
widths: [320, 360, 640],
|
|
59
|
+
render: (props: Props) =>
|
|
60
|
+
drawing({
|
|
61
|
+
body: `<div class="t-frame">${otpInput(props.field)}</div>`,
|
|
62
|
+
styles: [otpInputStyles, frame].join('\n'),
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
.pagination-frame {
|
|
2
|
+
display: flex;
|
|
3
|
+
padding: 0.8rem;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
@layer components {
|
|
7
|
+
.et-pagination-host .et-pagination-button {
|
|
8
|
+
--_et-focus-ring-color: var(--et-theme-color-ink-solid);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.et-pagination-host .et-pagination-button[aria-current='page'] {
|
|
12
|
+
--et-button-shadow: inset 0 0 0 1px var(--et-theme-color-ink-solid);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {
|
|
2
|
+
pagination,
|
|
3
|
+
type PaginationMockItem,
|
|
4
|
+
type PaginationMockOptions,
|
|
5
|
+
paginationStyles,
|
|
6
|
+
} from '@ethlete/components/design/pagination';
|
|
7
|
+
import { definePart, drawing, interactionRows } from '@design-system';
|
|
8
|
+
import edge from './pagination.css?inline';
|
|
9
|
+
|
|
10
|
+
type ItemInteraction = 'hover' | 'active' | 'focus-visible';
|
|
11
|
+
|
|
12
|
+
type Props = Omit<PaginationMockOptions, 'items'> & {
|
|
13
|
+
page: number;
|
|
14
|
+
pages: (number | null)[];
|
|
15
|
+
total: number;
|
|
16
|
+
target?: number;
|
|
17
|
+
forced?: ItemInteraction;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const MARK = 'data-et-control="item" data-can-animate';
|
|
21
|
+
|
|
22
|
+
const items = ({ page, pages, total, target, forced }: Props): PaginationMockItem[] => {
|
|
23
|
+
const attributes = (entry: number) => (forced && entry === target ? `${MARK} data-et-force="${forced}"` : MARK);
|
|
24
|
+
|
|
25
|
+
return [
|
|
26
|
+
{ type: 'first', page: 1, disabled: page === 1, attributes: MARK },
|
|
27
|
+
{ type: 'previous', page: page - 1, disabled: page === 1, attributes: MARK },
|
|
28
|
+
...pages.map((entry): PaginationMockItem =>
|
|
29
|
+
entry === null
|
|
30
|
+
? { type: 'ellipsis' }
|
|
31
|
+
: { type: 'page', page: entry, current: entry === page, attributes: attributes(entry) },
|
|
32
|
+
),
|
|
33
|
+
{ type: 'next', page: page + 1, disabled: page === total, attributes: MARK },
|
|
34
|
+
{ type: 'last', page: total, disabled: page === total, attributes: MARK },
|
|
35
|
+
];
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const MIDDLE: Props = { page: 10, total: 20, pages: [1, null, 9, 10, 11, null, 20] };
|
|
39
|
+
|
|
40
|
+
const { states, grid } = interactionRows(
|
|
41
|
+
{
|
|
42
|
+
page: { ...MIDDLE, target: 11 },
|
|
43
|
+
current: { ...MIDDLE, target: 10 },
|
|
44
|
+
} satisfies Record<string, Props>,
|
|
45
|
+
{
|
|
46
|
+
interactions: ['hover', 'active', 'focus-visible'],
|
|
47
|
+
force: (props: Props, interaction: ItemInteraction): Props => ({ ...props, forced: interaction }),
|
|
48
|
+
},
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
export default definePart({
|
|
52
|
+
note: 'Decided rules only',
|
|
53
|
+
madeBy: ['claude-opus-5-5'],
|
|
54
|
+
states: {
|
|
55
|
+
first: { page: 1, total: 20, pages: [1, 2, 3, 4, 5, null, 20] },
|
|
56
|
+
middle: MIDDLE,
|
|
57
|
+
last: { page: 20, total: 20, pages: [1, null, 16, 17, 18, 19, 20] },
|
|
58
|
+
few: { page: 2, total: 5, pages: [1, 2, 3, 4, 5] },
|
|
59
|
+
...states,
|
|
60
|
+
range: { ...MIDDLE, range: 'Showing 91–100 of 200' },
|
|
61
|
+
sm: { ...MIDDLE, size: 'sm' },
|
|
62
|
+
links: { ...MIDDLE, renderAs: 'links' },
|
|
63
|
+
compact: { ...MIDDLE, compactStatus: '10 / 20' },
|
|
64
|
+
},
|
|
65
|
+
grid,
|
|
66
|
+
widths: [480],
|
|
67
|
+
controls: {
|
|
68
|
+
item: { kind: 'button', input: ['pointer', 'keyboard'], disabled: true },
|
|
69
|
+
},
|
|
70
|
+
render: (props: Props) =>
|
|
71
|
+
drawing({
|
|
72
|
+
body: `<div class="pagination-frame">${pagination({ ...props, items: items(props) })}</div>`,
|
|
73
|
+
styles: [paginationStyles, edge].join('\n'),
|
|
74
|
+
}),
|
|
75
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
.picture-frame {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: 0.8rem;
|
|
5
|
+
max-inline-size: 520px;
|
|
6
|
+
padding: 2.4rem 1.6rem;
|
|
7
|
+
background: var(--et-surface-background-solid);
|
|
8
|
+
color: var(--et-surface-color-solid);
|
|
9
|
+
font-size: 1.4rem;
|
|
10
|
+
|
|
11
|
+
.picture-error {
|
|
12
|
+
margin: 0;
|
|
13
|
+
color: var(--et-surface-color-muted-solid);
|
|
14
|
+
font-size: 1.2rem;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.picture-fit-grid {
|
|
18
|
+
display: grid;
|
|
19
|
+
grid-template-columns: repeat(2, 180px);
|
|
20
|
+
gap: 1.6rem;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.picture-fit-cell {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
gap: 0.4rem;
|
|
27
|
+
margin: 0;
|
|
28
|
+
font-size: 1.2rem;
|
|
29
|
+
color: var(--et-surface-color-muted-solid);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.picture-fit-cell .et-picture {
|
|
33
|
+
inline-size: 180px;
|
|
34
|
+
block-size: 120px;
|
|
35
|
+
outline: 1px dashed var(--et-surface-border-solid);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { picture, pictureStyles, type PictureMockOptions } from '@ethlete/components/design/picture';
|
|
2
|
+
import { skeletonItem, skeletonStyles } from '@ethlete/components/design/skeleton';
|
|
3
|
+
import { definePart, drawing } from '@design-system';
|
|
4
|
+
import fallback from '@assets/fallback.svg?raw';
|
|
5
|
+
import tall from '@assets/tall.svg?raw';
|
|
6
|
+
import wide from '@assets/wide.svg?raw';
|
|
7
|
+
import frame from './picture.css?inline';
|
|
8
|
+
|
|
9
|
+
const svgUrl = (markup: string) => `data:image/svg+xml;utf8,${encodeURIComponent(markup.trim())}`;
|
|
10
|
+
|
|
11
|
+
type Fit = NonNullable<PictureMockOptions['fit']>;
|
|
12
|
+
|
|
13
|
+
type Props = {
|
|
14
|
+
ratio?: string;
|
|
15
|
+
caption?: 'short' | 'long' | 'none';
|
|
16
|
+
intrinsic?: boolean;
|
|
17
|
+
loading?: boolean;
|
|
18
|
+
error?: 'slot' | 'bare';
|
|
19
|
+
fit?: boolean;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const WIDE = svgUrl(wide);
|
|
23
|
+
const TALL = svgUrl(tall);
|
|
24
|
+
const FALLBACK = svgUrl(fallback);
|
|
25
|
+
const BROKEN = 'data:image/png;base64,this-is-not-an-image';
|
|
26
|
+
|
|
27
|
+
const CAPTIONS = {
|
|
28
|
+
short: 'A crop that follows the viewport.',
|
|
29
|
+
long: 'Fulltime at the home ground: the visitors celebrate in front of the away end after the late winner, while the stewards hold the line and the floodlights come on over the north stand.',
|
|
30
|
+
none: undefined,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const FITS: Fit[] = ['contain', 'cover', 'fill', 'none', 'scale-down'];
|
|
34
|
+
|
|
35
|
+
const body = ({ ratio = '16 / 9', caption = 'short', intrinsic, loading, error, fit }: Props) => {
|
|
36
|
+
if (fit) {
|
|
37
|
+
const cells = FITS.map(
|
|
38
|
+
(mode) =>
|
|
39
|
+
`<figure class="picture-fit-cell">${picture({ src: FALLBACK, alt: `fit ${mode}`, fit: mode })}<span>${mode}</span></figure>`,
|
|
40
|
+
).join('');
|
|
41
|
+
|
|
42
|
+
return `<div class="picture-fit-grid">${cells}</div>`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (loading) {
|
|
46
|
+
return picture({
|
|
47
|
+
alt: 'An image whose URL arrives after the page',
|
|
48
|
+
aspectRatio: '16 / 9',
|
|
49
|
+
state: 'loading',
|
|
50
|
+
placeholder: skeletonItem({ shape: 'rect', style: 'block-size: 100%; inline-size: 100%' }),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (error) {
|
|
55
|
+
return picture({
|
|
56
|
+
src: BROKEN,
|
|
57
|
+
alt: 'An image that fails to load',
|
|
58
|
+
aspectRatio: '16 / 9',
|
|
59
|
+
state: 'error',
|
|
60
|
+
error: error === 'slot' ? '<p class="picture-error">This image is unavailable.</p>' : undefined,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return picture({
|
|
65
|
+
sources: intrinsic ? undefined : [{ srcset: WIDE, media: '(min-width: 700px)' }, { srcset: TALL }],
|
|
66
|
+
src: FALLBACK,
|
|
67
|
+
alt: 'A coloured block labelled with its aspect ratio',
|
|
68
|
+
aspectRatio: ratio === 'none' ? undefined : ratio,
|
|
69
|
+
width: intrinsic ? 800 : undefined,
|
|
70
|
+
height: intrinsic ? 450 : undefined,
|
|
71
|
+
figcaption: CAPTIONS[caption],
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export default definePart({
|
|
76
|
+
note: "Today's look",
|
|
77
|
+
madeBy: ['claude-opus-5-5'],
|
|
78
|
+
states: {
|
|
79
|
+
default: {},
|
|
80
|
+
'ratio-4-3': { ratio: '4 / 3' },
|
|
81
|
+
'no-ratio': { ratio: 'none' },
|
|
82
|
+
'width-height': { intrinsic: true },
|
|
83
|
+
'no-caption': { caption: 'none' },
|
|
84
|
+
'long-caption': { caption: 'long' },
|
|
85
|
+
fit: { fit: true },
|
|
86
|
+
loading: { loading: true },
|
|
87
|
+
'error-slot': { error: 'slot' },
|
|
88
|
+
'error-bare': { error: 'bare' },
|
|
89
|
+
},
|
|
90
|
+
widths: [480],
|
|
91
|
+
render: (props: Props) =>
|
|
92
|
+
drawing({
|
|
93
|
+
body: `<div class="picture-frame">${body(props)}</div>`,
|
|
94
|
+
styles: [skeletonStyles, pictureStyles, frame].join('\n'),
|
|
95
|
+
}),
|
|
96
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
.progress-steps-frame {
|
|
2
|
+
padding: 2.4rem 1.6rem;
|
|
3
|
+
background: var(--et-surface-background-solid);
|
|
4
|
+
color: var(--et-surface-color-solid);
|
|
5
|
+
font-size: 1.4rem;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
@layer components {
|
|
9
|
+
.et-progress-step {
|
|
10
|
+
--_et-focus-ring-color: var(--et-theme-color-ink-solid);
|
|
11
|
+
|
|
12
|
+
&:is(
|
|
13
|
+
[data-state='current'],
|
|
14
|
+
[data-state='complete'],
|
|
15
|
+
[data-state='success'],
|
|
16
|
+
[data-state='warning'],
|
|
17
|
+
[data-state='error']
|
|
18
|
+
)
|
|
19
|
+
.et-progress-step-marker {
|
|
20
|
+
border-color: var(--et-theme-color-ink-solid);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&:is([data-state='complete'], [data-state='success'], [data-state='warning'], [data-state='error']):not(
|
|
24
|
+
:last-child
|
|
25
|
+
)::after {
|
|
26
|
+
background: var(--et-theme-color-ink-solid);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&:is(a, button) {
|
|
30
|
+
@media (hover: hover) {
|
|
31
|
+
&:hover .et-progress-step-marker {
|
|
32
|
+
border-color: var(--et-theme-color-ink-solid);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { progressSteps, ProgressStepMockStep, progressStepsStyles } from '@ethlete/components/design/progress-steps';
|
|
2
|
+
import { definePart, drawing } from '@design-system';
|
|
3
|
+
import frame from './progress-steps.css?inline';
|
|
4
|
+
|
|
5
|
+
type Interaction = 'hover' | 'active' | 'focus-visible';
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
set?: 'checkout' | 'outcomes' | 'described' | 'vertical' | 'links';
|
|
9
|
+
complete?: Interaction;
|
|
10
|
+
upcoming?: Interaction;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const mark = (control: string, interaction?: Interaction) =>
|
|
14
|
+
[`data-et-control="${control}"`, interaction && `data-et-force="${interaction}"`].filter(Boolean).join(' ');
|
|
15
|
+
|
|
16
|
+
const checkout: ProgressStepMockStep[] = [
|
|
17
|
+
{ label: 'Account', state: 'complete' },
|
|
18
|
+
{ label: 'Shipping', state: 'current' },
|
|
19
|
+
{ label: 'Payment' },
|
|
20
|
+
{ label: 'Review' },
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const outcomes: ProgressStepMockStep[] = [
|
|
24
|
+
{ label: 'Upload', state: 'success' },
|
|
25
|
+
{ label: 'Validate', state: 'warning', color: 'warning' },
|
|
26
|
+
{ label: 'Import', state: 'error', color: 'danger' },
|
|
27
|
+
{ label: 'Publish' },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const described: ProgressStepMockStep[] = [
|
|
31
|
+
{ label: 'Team', state: 'complete', description: '18 players' },
|
|
32
|
+
{ label: 'Squad', state: 'error', color: 'danger', description: '2 missing' },
|
|
33
|
+
{ label: 'Kit', state: 'current', description: 'Home colours' },
|
|
34
|
+
{ label: 'Submit', description: 'By Friday' },
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const vertical: ProgressStepMockStep[] = [
|
|
38
|
+
{ label: 'Registration received', state: 'complete', description: 'Mon, 12 Oct' },
|
|
39
|
+
{ label: 'Documents checked', state: 'warning', color: 'warning', description: 'Photo is blurry' },
|
|
40
|
+
{ label: 'Payment', state: 'current', description: 'Waiting for the transfer' },
|
|
41
|
+
{ label: 'Licence issued' },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const links = (props: Props): ProgressStepMockStep[] => [
|
|
45
|
+
{ label: 'Account', state: 'complete', as: 'a', attributes: mark('complete', props.complete) },
|
|
46
|
+
{ label: 'Shipping', state: 'current', as: 'a' },
|
|
47
|
+
{ label: 'Payment', as: 'a', attributes: mark('upcoming', props.upcoming) },
|
|
48
|
+
{ label: 'Review', as: 'a' },
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const steps = (props: Props) => {
|
|
52
|
+
switch (props.set) {
|
|
53
|
+
case 'outcomes':
|
|
54
|
+
return progressSteps({ steps: outcomes });
|
|
55
|
+
case 'described':
|
|
56
|
+
return progressSteps({ steps: described });
|
|
57
|
+
case 'vertical':
|
|
58
|
+
return progressSteps({ steps: vertical, orientation: 'vertical' });
|
|
59
|
+
case 'links':
|
|
60
|
+
return progressSteps({ steps: links(props) });
|
|
61
|
+
default:
|
|
62
|
+
return progressSteps({ steps: checkout });
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default definePart({
|
|
67
|
+
note: 'Decided rules only',
|
|
68
|
+
madeBy: ['claude-opus-5-5'],
|
|
69
|
+
states: {
|
|
70
|
+
default: {},
|
|
71
|
+
outcomes: { set: 'outcomes' },
|
|
72
|
+
described: { set: 'described' },
|
|
73
|
+
vertical: { set: 'vertical' },
|
|
74
|
+
links: { set: 'links' },
|
|
75
|
+
'upcoming-hover': { set: 'links', upcoming: 'hover' },
|
|
76
|
+
'upcoming-active': { set: 'links', upcoming: 'active' },
|
|
77
|
+
'upcoming-focus-visible': { set: 'links', upcoming: 'focus-visible' },
|
|
78
|
+
'complete-hover': { set: 'links', complete: 'hover' },
|
|
79
|
+
'complete-focus-visible': { set: 'links', complete: 'focus-visible' },
|
|
80
|
+
},
|
|
81
|
+
widths: [480],
|
|
82
|
+
controls: {
|
|
83
|
+
complete: { kind: 'button', input: ['pointer', 'keyboard'] },
|
|
84
|
+
upcoming: { kind: 'button', input: ['pointer', 'keyboard'] },
|
|
85
|
+
},
|
|
86
|
+
render: (props: Props) =>
|
|
87
|
+
drawing({
|
|
88
|
+
body: `<div class="progress-steps-frame">${steps(props)}</div>`,
|
|
89
|
+
styles: [progressStepsStyles, frame].join('\n'),
|
|
90
|
+
}),
|
|
91
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
.query-error-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
|
+
.query-error-support {
|
|
9
|
+
color: inherit;
|
|
10
|
+
font-size: 1.2rem;
|
|
11
|
+
text-decoration: underline;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@layer components {
|
|
16
|
+
.et-banner {
|
|
17
|
+
border-color: var(--et-theme-color-ink-solid);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.et-button {
|
|
21
|
+
--_et-focus-ring-color: var(--et-theme-color-ink-solid);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.et-button:where([data-variant='filled']) {
|
|
25
|
+
--et-button-shadow: inset 0 0 0 1px var(--et-theme-color-ink-solid);
|
|
26
|
+
|
|
27
|
+
@media (hover: hover) {
|
|
28
|
+
&:hover {
|
|
29
|
+
--et-theme-color-primary-rgb: var(--et-color-primary-active);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { button } from '@ethlete/components/design/button';
|
|
2
|
+
import { queryError, queryErrorStyles } from '@ethlete/components/design/query-error';
|
|
3
|
+
import { definePart, drawing } from '@design-system';
|
|
4
|
+
import frame from './query-error.css?inline';
|
|
5
|
+
|
|
6
|
+
type Interaction = 'hover' | 'active' | 'focus-visible';
|
|
7
|
+
|
|
8
|
+
type Shape = 'message' | 'violations' | 'classValidator' | 'retryable' | 'empty' | 'echoesTitle' | 'network' | 'long';
|
|
9
|
+
|
|
10
|
+
type Props = {
|
|
11
|
+
shape: Shape;
|
|
12
|
+
alwaysAllowRetry?: boolean;
|
|
13
|
+
slots?: boolean;
|
|
14
|
+
color?: string;
|
|
15
|
+
retry?: Interaction;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const SHAPES: Record<Shape, { status: number; title: string; messages: string[]; canRetry: boolean }> = {
|
|
19
|
+
message: { status: 403, title: 'Forbidden', messages: ['You do not have access to this team.'], canRetry: false },
|
|
20
|
+
violations: {
|
|
21
|
+
status: 422,
|
|
22
|
+
title: 'Unprocessable entity',
|
|
23
|
+
messages: ['A name is required.', 'The email address is not valid.', 'The start date must be before the end date.'],
|
|
24
|
+
canRetry: false,
|
|
25
|
+
},
|
|
26
|
+
classValidator: {
|
|
27
|
+
status: 400,
|
|
28
|
+
title: 'Bad request',
|
|
29
|
+
messages: ['name should not be empty', 'email must be an email'],
|
|
30
|
+
canRetry: false,
|
|
31
|
+
},
|
|
32
|
+
retryable: {
|
|
33
|
+
status: 503,
|
|
34
|
+
title: 'Service unavailable',
|
|
35
|
+
messages: ['The service is briefly unavailable.'],
|
|
36
|
+
canRetry: true,
|
|
37
|
+
},
|
|
38
|
+
empty: {
|
|
39
|
+
status: 500,
|
|
40
|
+
title: 'Internal server error',
|
|
41
|
+
messages: ['Something went wrong on our end. Please try again later. (Code: 500)'],
|
|
42
|
+
canRetry: false,
|
|
43
|
+
},
|
|
44
|
+
echoesTitle: {
|
|
45
|
+
status: 404,
|
|
46
|
+
title: 'Not found',
|
|
47
|
+
messages: ['The requested resource was not found. (Code: 404)'],
|
|
48
|
+
canRetry: false,
|
|
49
|
+
},
|
|
50
|
+
network: {
|
|
51
|
+
status: 0,
|
|
52
|
+
title: 'Something went wrong',
|
|
53
|
+
messages: ['Something went wrong. Check your internet connection and try again later. (Code: 0)'],
|
|
54
|
+
canRetry: true,
|
|
55
|
+
},
|
|
56
|
+
long: {
|
|
57
|
+
status: 409,
|
|
58
|
+
title: 'Conflict',
|
|
59
|
+
messages: [
|
|
60
|
+
'The fixture for matchday 14 was moved by another organiser while you were editing it, so your changes to the kick-off time, the venue and the referee assignment could not be saved. Reload the fixture and quote request league.example.com/fixtures/2026_matchday_14_home_visitors_edit_request_8f3a9c2e7b1d',
|
|
61
|
+
],
|
|
62
|
+
canRetry: false,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const mark = (control: string, interaction?: Interaction) =>
|
|
67
|
+
[`data-et-control="${control}" data-can-animate`, interaction && `data-et-force="${interaction}"`]
|
|
68
|
+
.filter(Boolean)
|
|
69
|
+
.join(' ');
|
|
70
|
+
|
|
71
|
+
const slotActions = (interaction?: Interaction) =>
|
|
72
|
+
button({ label: 'Try again', size: 'sm' }).replace('<button ', `<button ${mark('retry', interaction)} `) +
|
|
73
|
+
'<a class="query-error-support" href="#">Contact support</a>';
|
|
74
|
+
|
|
75
|
+
const render = ({ shape, alwaysAllowRetry, slots, color = 'danger', retry }: Props) => {
|
|
76
|
+
const { status, title, messages, canRetry } = SHAPES[shape];
|
|
77
|
+
|
|
78
|
+
return queryError({
|
|
79
|
+
status,
|
|
80
|
+
title: slots && status === 403 ? 'This team is private' : title,
|
|
81
|
+
messages,
|
|
82
|
+
color,
|
|
83
|
+
retry: !slots && (canRetry || alwaysAllowRetry) ? 'Retry' : undefined,
|
|
84
|
+
retryAttributes: mark('retry', retry),
|
|
85
|
+
actions: slots ? slotActions(retry) : undefined,
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export default definePart({
|
|
90
|
+
note: 'Decided rules only',
|
|
91
|
+
madeBy: ['claude-opus-5-5'],
|
|
92
|
+
states: {
|
|
93
|
+
message: { shape: 'message' },
|
|
94
|
+
violations: { shape: 'violations' },
|
|
95
|
+
'class-validator': { shape: 'classValidator' },
|
|
96
|
+
retryable: { shape: 'retryable' },
|
|
97
|
+
'empty-body': { shape: 'empty' },
|
|
98
|
+
'echoes-title': { shape: 'echoesTitle' },
|
|
99
|
+
network: { shape: 'network' },
|
|
100
|
+
'always-allow-retry': { shape: 'echoesTitle', alwaysAllowRetry: true },
|
|
101
|
+
'long-message': { shape: 'long' },
|
|
102
|
+
'custom-slots': { shape: 'message', slots: true },
|
|
103
|
+
'retry-hover': { shape: 'retryable', retry: 'hover' },
|
|
104
|
+
'retry-active': { shape: 'retryable', retry: 'active' },
|
|
105
|
+
'retry-focus-visible': { shape: 'retryable', retry: 'focus-visible' },
|
|
106
|
+
'slot-retry-focus-visible': { shape: 'message', slots: true, retry: 'focus-visible' },
|
|
107
|
+
'brand-color': { shape: 'retryable', color: 'brand' },
|
|
108
|
+
'brand-retry-hover': { shape: 'retryable', color: 'brand', retry: 'hover' },
|
|
109
|
+
'brand-retry-focus-visible': { shape: 'retryable', color: 'brand', retry: 'focus-visible' },
|
|
110
|
+
},
|
|
111
|
+
widths: [480],
|
|
112
|
+
controls: {
|
|
113
|
+
retry: { kind: 'button', input: ['pointer', 'keyboard'] },
|
|
114
|
+
},
|
|
115
|
+
render: (props: Props) =>
|
|
116
|
+
drawing({
|
|
117
|
+
body: `<div class="query-error-frame">${render(props)}</div>`,
|
|
118
|
+
styles: [queryErrorStyles, frame].join('\n'),
|
|
119
|
+
}),
|
|
120
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
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-button,
|
|
11
|
+
.et-icon-button {
|
|
12
|
+
--_et-focus-ring-color: var(--et-theme-color-ink-solid);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.et-button:where([data-variant='filled']) {
|
|
16
|
+
--et-button-shadow: inset 0 0 0 1px var(--et-theme-color-ink-solid);
|
|
17
|
+
|
|
18
|
+
@media (hover: hover) {
|
|
19
|
+
&:hover {
|
|
20
|
+
--et-theme-color-primary-rgb: var(--et-color-primary-active);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.et-segmented-button,
|
|
26
|
+
.et-scheduler-time-grid-slot,
|
|
27
|
+
.et-scheduler-time-grid-all-day-cell,
|
|
28
|
+
.et-scheduler-month-view-cell,
|
|
29
|
+
.et-scheduler-appointment,
|
|
30
|
+
.et-scheduler-time-grid-block,
|
|
31
|
+
.et-scheduler-month-view-overflow-trigger {
|
|
32
|
+
&:focus-visible {
|
|
33
|
+
outline-color: var(--et-theme-color-ink-solid);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
:is(.et-scheduler-appointment, .et-scheduler-time-grid-block):not([data-selected]) .et-scheduler-appointment-dot {
|
|
38
|
+
background: light-dark(var(--et-theme-color-ink-solid), var(--et-theme-color-primary-solid));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.et-scheduler-time-grid-now {
|
|
42
|
+
border-block-start-color: light-dark(var(--et-theme-color-ink-solid), var(--et-theme-color-primary-solid));
|
|
43
|
+
|
|
44
|
+
&::before {
|
|
45
|
+
background: light-dark(var(--et-theme-color-ink-solid), var(--et-theme-color-primary-solid));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.et-scheduler-time-grid-header-day[data-today] .et-scheduler-time-grid-header-date,
|
|
50
|
+
.et-scheduler-month-view-cell[data-today] .et-scheduler-month-view-cell-date,
|
|
51
|
+
.et-scheduler-agenda-view-day-header[data-today] .et-scheduler-agenda-view-day-date,
|
|
52
|
+
:is(.et-scheduler-appointment, .et-scheduler-time-grid-block)[data-selected] {
|
|
53
|
+
box-shadow: inset 0 0 0 1px var(--et-theme-color-ink-solid);
|
|
54
|
+
}
|
|
55
|
+
}
|