@aceshooting/lyra-ui 2.0.0 → 2.1.0
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/README.md +87 -14
- package/custom-elements.json +11555 -5539
- package/dist/components/app-rail/app-rail-item.d.ts +30 -0
- package/dist/components/app-rail/app-rail-item.js +68 -0
- package/dist/components/app-rail/app-rail-item.styles.d.ts +1 -0
- package/dist/components/app-rail/app-rail-item.styles.js +65 -0
- package/dist/components/app-rail/app-rail.d.ts +21 -24
- package/dist/components/app-rail/app-rail.js +68 -132
- package/dist/components/app-rail/app-rail.styles.js +5 -2
- package/dist/components/attachment-chip/attachment-chip.d.ts +38 -11
- package/dist/components/attachment-chip/attachment-chip.js +73 -29
- package/dist/components/attachment-trigger/attachment-trigger.d.ts +13 -0
- package/dist/components/attachment-trigger/attachment-trigger.js +13 -1
- package/dist/components/attachment-trigger/attachment-trigger.styles.js +28 -6
- package/dist/components/chart/bar-chart.js +2 -18
- package/dist/components/chart/box-plot.d.ts +25 -1
- package/dist/components/chart/box-plot.js +136 -6
- package/dist/components/chart/box-plot.styles.js +13 -0
- package/dist/components/chart/bubble-chart.js +2 -18
- package/dist/components/chart/chart.d.ts +54 -10
- package/dist/components/chart/chart.js +182 -39
- package/dist/components/chart/doughnut-chart.js +2 -18
- package/dist/components/chart/histogram-bin.d.ts +5 -2
- package/dist/components/chart/histogram-bin.js +12 -4
- package/dist/components/chart/histogram.js +8 -16
- package/dist/components/chart/line-chart.js +2 -18
- package/dist/components/chart/lite-chart.d.ts +80 -3
- package/dist/components/chart/lite-chart.js +250 -53
- package/dist/components/chart/pie-chart.js +2 -18
- package/dist/components/chart/polar-area-chart.js +2 -18
- package/dist/components/chart/radar-chart.js +2 -18
- package/dist/components/chart/scatter-chart.js +2 -18
- package/dist/components/chat-composer/chat-composer.d.ts +42 -1
- package/dist/components/chat-composer/chat-composer.js +84 -3
- package/dist/components/chat-composer/chat-composer.styles.js +11 -1
- package/dist/components/chat-message/chat-message.d.ts +32 -4
- package/dist/components/chat-message/chat-message.js +57 -17
- package/dist/components/checkbox/checkbox.d.ts +66 -8
- package/dist/components/checkbox/checkbox.js +173 -50
- package/dist/components/checkbox/checkbox.styles.js +9 -2
- package/dist/components/chip/chip-group.js +8 -2
- package/dist/components/chip/chip.js +9 -2
- package/dist/components/citation-badge/citation-badge.js +21 -3
- package/dist/components/code-block/code-block.d.ts +38 -0
- package/dist/components/code-block/code-block.js +72 -7
- package/dist/components/code-block/code-loader.d.ts +44 -1
- package/dist/components/code-block/code-loader.js +63 -0
- package/dist/components/combobox/combobox.d.ts +46 -5
- package/dist/components/combobox/combobox.js +175 -35
- package/dist/components/combobox/combobox.styles.js +3 -3
- package/dist/components/context-meter/context-meter.js +17 -8
- package/dist/components/context-meter/context-meter.styles.js +0 -6
- package/dist/components/conversation-item/conversation-item.d.ts +13 -16
- package/dist/components/conversation-item/conversation-item.js +29 -20
- package/dist/components/date-picker/calendar-core.d.ts +24 -0
- package/dist/components/date-picker/calendar-core.js +51 -4
- package/dist/components/date-picker/date-input.d.ts +77 -10
- package/dist/components/date-picker/date-input.js +278 -73
- package/dist/components/date-picker/date-picker.d.ts +28 -4
- package/dist/components/date-picker/date-picker.js +95 -37
- package/dist/components/dialog/confirm.js +3 -6
- package/dist/components/dialog/dialog.d.ts +75 -31
- package/dist/components/dialog/dialog.js +147 -131
- package/dist/components/dialog/dialog.styles.js +46 -2
- package/dist/components/dock-panel/dock-panel.d.ts +8 -0
- package/dist/components/dock-panel/dock-panel.js +15 -1
- package/dist/components/dock-panel/dock-panel.styles.js +15 -1
- package/dist/components/document-preview/document-preview.d.ts +15 -7
- package/dist/components/document-preview/document-preview.js +29 -13
- package/dist/components/empty/empty.d.ts +1 -2
- package/dist/components/empty/empty.js +18 -12
- package/dist/components/empty/empty.styles.js +0 -3
- package/dist/components/export-button/export-button.d.ts +12 -0
- package/dist/components/export-button/export-button.js +33 -5
- package/dist/components/export-button/export-button.styles.js +5 -1
- package/dist/components/file-input/accept.js +2 -0
- package/dist/components/file-input/file-input.d.ts +10 -1
- package/dist/components/file-input/file-input.js +36 -5
- package/dist/components/flag/flag.d.ts +1 -1
- package/dist/components/flag/flag.js +15 -1
- package/dist/components/flag/flag.styles.js +1 -1
- package/dist/components/flag/language-map.d.ts +4 -1
- package/dist/components/flag/language-map.js +6 -3
- package/dist/components/gauge/gauge.d.ts +10 -1
- package/dist/components/gauge/gauge.js +28 -9
- package/dist/components/generation-status/generation-status.d.ts +13 -5
- package/dist/components/generation-status/generation-status.js +59 -5
- package/dist/components/graph/graph.d.ts +37 -3
- package/dist/components/graph/graph.js +132 -20
- package/dist/components/heatmap/calendar-grid.d.ts +15 -6
- package/dist/components/heatmap/calendar-grid.js +17 -6
- package/dist/components/heatmap/heatmap-scale.d.ts +5 -1
- package/dist/components/heatmap/heatmap-scale.js +8 -2
- package/dist/components/heatmap/heatmap.d.ts +166 -25
- package/dist/components/heatmap/heatmap.js +372 -89
- package/dist/components/json-viewer/json-viewer.d.ts +22 -5
- package/dist/components/json-viewer/json-viewer.js +115 -37
- package/dist/components/json-viewer/json-viewer.styles.js +2 -1
- package/dist/components/kbd/kbd.js +24 -7
- package/dist/components/live-region/live-region.d.ts +10 -1
- package/dist/components/live-region/live-region.js +42 -6
- package/dist/components/map/map.d.ts +24 -1
- package/dist/components/map/map.js +89 -24
- package/dist/components/markdown/markdown-loader.d.ts +24 -0
- package/dist/components/markdown/markdown-loader.js +35 -1
- package/dist/components/markdown/markdown.d.ts +46 -8
- package/dist/components/markdown/markdown.js +136 -31
- package/dist/components/markdown/markdown.styles.js +7 -1
- package/dist/components/media-card/media-card.d.ts +25 -17
- package/dist/components/media-card/media-card.js +43 -65
- package/dist/components/mention-popover/mention-popover.d.ts +4 -1
- package/dist/components/mention-popover/mention-popover.js +23 -5
- package/dist/components/menu/menu-item.d.ts +32 -3
- package/dist/components/menu/menu-item.js +94 -7
- package/dist/components/menu/menu-item.styles.js +8 -0
- package/dist/components/menu/menu.d.ts +25 -1
- package/dist/components/menu/menu.js +99 -3
- package/dist/components/menu/menu.styles.js +3 -2
- package/dist/components/model-select/model-select.d.ts +48 -3
- package/dist/components/model-select/model-select.js +120 -22
- package/dist/components/model-select/model-select.styles.js +17 -3
- package/dist/components/model-settings-panel/model-settings-panel.d.ts +25 -1
- package/dist/components/model-settings-panel/model-settings-panel.js +65 -1
- package/dist/components/playback/playback.d.ts +6 -2
- package/dist/components/playback/playback.js +72 -29
- package/dist/components/playback/playback.styles.js +6 -1
- package/dist/components/responsive-panel/responsive-panel.d.ts +29 -16
- package/dist/components/responsive-panel/responsive-panel.js +130 -132
- package/dist/components/responsive-panel/responsive-panel.styles.js +1 -1
- package/dist/components/result-card/result-card.d.ts +8 -2
- package/dist/components/result-card/result-card.js +9 -3
- package/dist/components/result-card/result-card.styles.js +0 -1
- package/dist/components/select/select.d.ts +59 -20
- package/dist/components/select/select.js +125 -43
- package/dist/components/skeleton/skeleton.d.ts +3 -0
- package/dist/components/skeleton/skeleton.js +7 -1
- package/dist/components/skeleton/skeleton.styles.js +5 -4
- package/dist/components/slider/slider.d.ts +57 -5
- package/dist/components/slider/slider.js +195 -80
- package/dist/components/source-card/source-card.d.ts +17 -5
- package/dist/components/source-card/source-card.js +55 -8
- package/dist/components/source-card/source-card.styles.js +1 -1
- package/dist/components/source-list/source-list.js +9 -1
- package/dist/components/sparkline/sparkline.js +34 -10
- package/dist/components/split/split.d.ts +141 -14
- package/dist/components/split/split.js +357 -52
- package/dist/components/split/split.styles.js +18 -1
- package/dist/components/stat/stat.d.ts +10 -4
- package/dist/components/stat/stat.js +46 -11
- package/dist/components/stream-status/stream-status.d.ts +27 -11
- package/dist/components/stream-status/stream-status.js +95 -13
- package/dist/components/streaming-text/streaming-text.d.ts +9 -3
- package/dist/components/streaming-text/streaming-text.js +25 -10
- package/dist/components/streaming-text/streaming-text.styles.js +3 -2
- package/dist/components/switch/switch.d.ts +52 -7
- package/dist/components/switch/switch.js +111 -40
- package/dist/components/switch/switch.styles.js +1 -1
- package/dist/components/table/table.d.ts +18 -3
- package/dist/components/table/table.js +88 -20
- package/dist/components/tabs/tabs.d.ts +23 -0
- package/dist/components/tabs/tabs.js +76 -12
- package/dist/components/tabs/tabs.styles.js +11 -0
- package/dist/components/thinking-panel/thinking-panel.d.ts +3 -1
- package/dist/components/thinking-panel/thinking-panel.js +34 -9
- package/dist/components/thinking-panel/thinking-panel.styles.js +6 -0
- package/dist/components/time-range/time-range.d.ts +59 -2
- package/dist/components/time-range/time-range.js +163 -67
- package/dist/components/toast/toast-item.d.ts +12 -3
- package/dist/components/toast/toast-item.js +90 -53
- package/dist/components/toast/toast-item.styles.js +59 -28
- package/dist/components/toast/toast.js +17 -5
- package/dist/components/toast/toaster.js +10 -1
- package/dist/components/tool-approval-dialog/tool-approval-dialog.d.ts +11 -10
- package/dist/components/tool-approval-dialog/tool-approval-dialog.js +50 -124
- package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.js +1 -1
- package/dist/components/tool-call-chip/tool-call-chip.d.ts +18 -2
- package/dist/components/tool-call-chip/tool-call-chip.js +86 -25
- package/dist/components/tool-param-form/tool-param-form.d.ts +89 -28
- package/dist/components/tool-param-form/tool-param-form.js +350 -106
- package/dist/components/tool-result-dialog/tool-result-dialog.d.ts +27 -7
- package/dist/components/tool-result-dialog/tool-result-dialog.js +80 -115
- package/dist/components/tool-result-dialog/tool-result-dialog.styles.js +1 -1
- package/dist/components/tool-result-view/registry.d.ts +0 -8
- package/dist/components/tool-result-view/registry.js +7 -2
- package/dist/components/tool-result-view/tool-result-view.d.ts +6 -3
- package/dist/components/tool-result-view/tool-result-view.js +18 -4
- package/dist/components/tool-select-dialog/tool-select-dialog.d.ts +11 -11
- package/dist/components/tool-select-dialog/tool-select-dialog.js +44 -133
- package/dist/components/tool-select-dialog/tool-select-dialog.styles.js +13 -4
- package/dist/components/tree/tree-node.d.ts +4 -1
- package/dist/components/tree/tree-node.js +4 -1
- package/dist/components/tree/tree.d.ts +17 -8
- package/dist/components/tree/tree.js +21 -20
- package/dist/components/typing-indicator/typing-indicator.d.ts +12 -2
- package/dist/components/typing-indicator/typing-indicator.js +16 -4
- package/dist/components/typing-indicator/typing-indicator.styles.js +2 -2
- package/dist/components/virtual-list/virtual-list.d.ts +56 -19
- package/dist/components/virtual-list/virtual-list.js +184 -38
- package/dist/components/virtual-list/virtual-list.styles.js +12 -0
- package/dist/components/widget/widget.d.ts +5 -4
- package/dist/components/widget/widget.js +54 -120
- package/dist/components/widget/widget.styles.js +8 -2
- package/dist/components/word-cloud/word-cloud-layout.d.ts +7 -0
- package/dist/components/word-cloud/word-cloud-layout.js +20 -6
- package/dist/components/word-cloud/word-cloud.d.ts +22 -2
- package/dist/components/word-cloud/word-cloud.js +45 -6
- package/dist/components/word-cloud/word-cloud.styles.js +13 -1
- package/dist/internal/anchored-validity.d.ts +1 -0
- package/dist/internal/anchored-validity.js +86 -0
- package/dist/internal/form-associated.d.ts +7 -0
- package/dist/internal/form-associated.js +43 -4
- package/dist/internal/numbers.d.ts +12 -0
- package/dist/internal/numbers.js +26 -0
- package/dist/internal/overlay-manager.d.ts +51 -0
- package/dist/internal/overlay-manager.js +523 -0
- package/dist/internal/positioner.js +27 -3
- package/dist/internal/safe-url.d.ts +12 -0
- package/dist/internal/safe-url.js +41 -0
- package/dist/internal/tokens.styles.js +17 -11
- package/dist/lyra.d.ts +5 -2
- package/dist/lyra.js +3 -1
- package/llms-full.txt +970 -426
- package/llms.txt +5 -4
- package/package.json +19 -2
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type TemplateResult } from 'lit';
|
|
2
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
3
|
+
/**
|
|
4
|
+
* `<lyra-app-rail-item>` — an explicit icon/label navigation item for
|
|
5
|
+
* `<lyra-app-rail>`. The rail sets its `icon-only` attribute as the viewport
|
|
6
|
+
* changes, keeping the label available to assistive technology while removing
|
|
7
|
+
* it from the visual layout.
|
|
8
|
+
*
|
|
9
|
+
* @customElement lyra-app-rail-item
|
|
10
|
+
* @slot - The visible navigation label.
|
|
11
|
+
* @slot icon - The leading icon.
|
|
12
|
+
* @csspart base - The link or button receiving focus and activation.
|
|
13
|
+
* @csspart icon - The icon wrapper.
|
|
14
|
+
* @csspart label - The label wrapper; visually clipped in icon-only mode.
|
|
15
|
+
*/
|
|
16
|
+
export declare class LyraAppRailItem extends LyraElement {
|
|
17
|
+
static styles: import("lit").CSSResultGroup[];
|
|
18
|
+
/** Optional destination. Without `href`, the item renders as a button. */
|
|
19
|
+
href: string;
|
|
20
|
+
/** Optional link target. */
|
|
21
|
+
target: string;
|
|
22
|
+
/** Prevents activation while retaining the item in the rail. */
|
|
23
|
+
disabled: boolean;
|
|
24
|
+
render(): TemplateResult;
|
|
25
|
+
}
|
|
26
|
+
declare global {
|
|
27
|
+
interface HTMLElementTagNameMap {
|
|
28
|
+
'lyra-app-rail-item': LyraAppRailItem;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { html, nothing } from 'lit';
|
|
8
|
+
import { property } from 'lit/decorators.js';
|
|
9
|
+
import { LyraElement } from '../../internal/lyra-element.js';
|
|
10
|
+
import { defineElement } from '../../internal/prefix.js';
|
|
11
|
+
import { styles } from './app-rail-item.styles.js';
|
|
12
|
+
/**
|
|
13
|
+
* `<lyra-app-rail-item>` — an explicit icon/label navigation item for
|
|
14
|
+
* `<lyra-app-rail>`. The rail sets its `icon-only` attribute as the viewport
|
|
15
|
+
* changes, keeping the label available to assistive technology while removing
|
|
16
|
+
* it from the visual layout.
|
|
17
|
+
*
|
|
18
|
+
* @customElement lyra-app-rail-item
|
|
19
|
+
* @slot - The visible navigation label.
|
|
20
|
+
* @slot icon - The leading icon.
|
|
21
|
+
* @csspart base - The link or button receiving focus and activation.
|
|
22
|
+
* @csspart icon - The icon wrapper.
|
|
23
|
+
* @csspart label - The label wrapper; visually clipped in icon-only mode.
|
|
24
|
+
*/
|
|
25
|
+
export class LyraAppRailItem extends LyraElement {
|
|
26
|
+
constructor() {
|
|
27
|
+
super(...arguments);
|
|
28
|
+
/** Optional destination. Without `href`, the item renders as a button. */
|
|
29
|
+
this.href = '';
|
|
30
|
+
/** Optional link target. */
|
|
31
|
+
this.target = '';
|
|
32
|
+
/** Prevents activation while retaining the item in the rail. */
|
|
33
|
+
this.disabled = false;
|
|
34
|
+
}
|
|
35
|
+
static { this.styles = [LyraElement.styles, styles]; }
|
|
36
|
+
render() {
|
|
37
|
+
const label = this.getAttribute('aria-label');
|
|
38
|
+
const content = html `
|
|
39
|
+
<span part="icon" aria-hidden=${label ? 'true' : nothing}><slot name="icon"></slot></span>
|
|
40
|
+
<span part="label"><slot></slot></span>
|
|
41
|
+
`;
|
|
42
|
+
if (this.href && !this.disabled) {
|
|
43
|
+
return html `<a
|
|
44
|
+
part="base"
|
|
45
|
+
href=${this.href}
|
|
46
|
+
target=${this.target || nothing}
|
|
47
|
+
aria-label=${label || nothing}
|
|
48
|
+
>${content}</a>`;
|
|
49
|
+
}
|
|
50
|
+
return html `<button
|
|
51
|
+
part="base"
|
|
52
|
+
type="button"
|
|
53
|
+
?disabled=${this.disabled}
|
|
54
|
+
aria-disabled=${this.disabled ? 'true' : nothing}
|
|
55
|
+
aria-label=${label || nothing}
|
|
56
|
+
>${content}</button>`;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
__decorate([
|
|
60
|
+
property()
|
|
61
|
+
], LyraAppRailItem.prototype, "href", void 0);
|
|
62
|
+
__decorate([
|
|
63
|
+
property()
|
|
64
|
+
], LyraAppRailItem.prototype, "target", void 0);
|
|
65
|
+
__decorate([
|
|
66
|
+
property({ type: Boolean, reflect: true })
|
|
67
|
+
], LyraAppRailItem.prototype, "disabled", void 0);
|
|
68
|
+
defineElement('app-rail-item', LyraAppRailItem);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import("lit").CSSResult;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: block;
|
|
5
|
+
inline-size: 100%;
|
|
6
|
+
}
|
|
7
|
+
[part='base'] {
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: flex-start;
|
|
11
|
+
gap: var(--lyra-space-s);
|
|
12
|
+
inline-size: 100%;
|
|
13
|
+
min-block-size: var(--lyra-icon-button-size);
|
|
14
|
+
padding: var(--lyra-space-s);
|
|
15
|
+
border: 0;
|
|
16
|
+
border-radius: var(--lyra-radius);
|
|
17
|
+
background: transparent;
|
|
18
|
+
color: var(--lyra-color-text);
|
|
19
|
+
font: inherit;
|
|
20
|
+
text-align: start;
|
|
21
|
+
text-decoration: none;
|
|
22
|
+
cursor: pointer;
|
|
23
|
+
}
|
|
24
|
+
[part='base']:hover {
|
|
25
|
+
background: var(--lyra-color-brand-quiet);
|
|
26
|
+
color: var(--lyra-color-brand);
|
|
27
|
+
}
|
|
28
|
+
[part='base']:focus-visible {
|
|
29
|
+
outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
|
|
30
|
+
outline-offset: var(--lyra-focus-ring-offset);
|
|
31
|
+
}
|
|
32
|
+
[part='base'][aria-disabled='true'] {
|
|
33
|
+
opacity: var(--lyra-opacity-disabled);
|
|
34
|
+
cursor: not-allowed;
|
|
35
|
+
}
|
|
36
|
+
[part='icon'] {
|
|
37
|
+
display: inline-flex;
|
|
38
|
+
flex: 0 0 auto;
|
|
39
|
+
align-items: center;
|
|
40
|
+
justify-content: center;
|
|
41
|
+
inline-size: var(--lyra-icon-button-size);
|
|
42
|
+
min-inline-size: var(--lyra-icon-button-size);
|
|
43
|
+
}
|
|
44
|
+
[part='label'] {
|
|
45
|
+
min-inline-size: 0;
|
|
46
|
+
overflow: hidden;
|
|
47
|
+
text-overflow: ellipsis;
|
|
48
|
+
white-space: nowrap;
|
|
49
|
+
}
|
|
50
|
+
:host([icon-only]) [part='label'] {
|
|
51
|
+
position: absolute;
|
|
52
|
+
inline-size: 1px;
|
|
53
|
+
block-size: 1px;
|
|
54
|
+
padding: 0;
|
|
55
|
+
margin: -1px;
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
clip: rect(0, 0, 0, 0);
|
|
58
|
+
white-space: nowrap;
|
|
59
|
+
border: 0;
|
|
60
|
+
}
|
|
61
|
+
:host([icon-only]) [part='base'] {
|
|
62
|
+
justify-content: center;
|
|
63
|
+
padding-inline: 0;
|
|
64
|
+
}
|
|
65
|
+
`;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type TemplateResult, type PropertyValues } from 'lit';
|
|
2
2
|
import { LyraElement } from '../../internal/lyra-element.js';
|
|
3
|
+
import './app-rail-item.js';
|
|
3
4
|
/** The rail's effective presentation -- see the class doc for what each renders. */
|
|
4
5
|
export type AppRailMode = 'full' | 'icon-only' | 'mobile';
|
|
5
6
|
/** What can be *assigned* to `mode` -- `'auto'` is a write-only sentinel; see the `mode` accessor doc. */
|
|
@@ -31,12 +32,10 @@ export declare function computeAppRailMode(iconOnlyMatches: boolean, mobileMatch
|
|
|
31
32
|
* width the way a native OS shell's navigation does, not however much
|
|
32
33
|
* horizontal space a particular layout happens to give it.
|
|
33
34
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* shadow template
|
|
38
|
-
* overlay-shaped component in this library duplicates that pattern locally
|
|
39
|
-
* instead of composing the previous one. `[part="base"]` (the inline
|
|
35
|
+
* The `'mobile'` state participates in the library's shared overlay stack,
|
|
36
|
+
* which supplies focus trapping, Escape/backdrop dismissal, inerting, and
|
|
37
|
+
* focus restoration without nesting a `<lyra-dialog>` in this component's
|
|
38
|
+
* shadow template. `[part="base"]` (the inline
|
|
40
39
|
* `'full'`/`'icon-only'` presentation) and `[part="panel"]` (the mobile
|
|
41
40
|
* overlay) are the *same* element promoted in place across modes (mirrors
|
|
42
41
|
* `<lyra-widget>`'s fullscreen mode) — never both at once, and never two
|
|
@@ -49,15 +48,11 @@ export declare function computeAppRailMode(iconOnlyMatches: boolean, mobileMatch
|
|
|
49
48
|
* on a generic element can be swapped for `role="dialog"` freely.
|
|
50
49
|
*
|
|
51
50
|
* @customElement lyra-app-rail
|
|
52
|
-
* @slot - Nav items
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* overlay is open, clicking anywhere inside this slot closes it (see
|
|
58
|
-
* `onNavItemClick`) — every slotted item is assumed to be a navigation
|
|
59
|
-
* trigger, not necessarily a real link, so this fires on any click rather
|
|
60
|
-
* than trying to detect one.
|
|
51
|
+
* @slot - Nav items. Use `<lyra-app-rail-item>` for the explicit icon/label
|
|
52
|
+
* contract that automatically hides labels in `'icon-only'` mode. Generic
|
|
53
|
+
* links and buttons remain supported, but their compact presentation is the
|
|
54
|
+
* consumer's responsibility. While the mobile overlay is open, clicking
|
|
55
|
+
* anywhere inside this slot closes it.
|
|
61
56
|
* @slot header - Logo/brand content, shown above the nav items in every mode.
|
|
62
57
|
* @slot footer - A trailing user/settings trigger, shown below the nav items.
|
|
63
58
|
* @event lyra-mode-change - The effective mode changed, whether from a
|
|
@@ -80,13 +75,13 @@ export declare function computeAppRailMode(iconOnlyMatches: boolean, mobileMatch
|
|
|
80
75
|
* for why it's the same element as `base`, never both at once.
|
|
81
76
|
*
|
|
82
77
|
* @example
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* hidden text, or a `title` — since this component only lays out whatever is
|
|
86
|
-
* slotted and has no way to inspect or fix up a consumer's own markup:
|
|
78
|
+
* Use the item contract so the visible label collapses while its accessible
|
|
79
|
+
* name remains available:
|
|
87
80
|
* ```html
|
|
88
81
|
* <lyra-app-rail>
|
|
89
|
-
* <
|
|
82
|
+
* <lyra-app-rail-item href="/inbox" aria-label="Inbox">
|
|
83
|
+
* <svg slot="icon" aria-hidden="true">...</svg>Inbox
|
|
84
|
+
* </lyra-app-rail-item>
|
|
90
85
|
* </lyra-app-rail>
|
|
91
86
|
* ```
|
|
92
87
|
*/
|
|
@@ -126,8 +121,10 @@ export declare class LyraAppRail extends LyraElement {
|
|
|
126
121
|
private overlayActive;
|
|
127
122
|
private justOpened;
|
|
128
123
|
private releaseScrollLock?;
|
|
129
|
-
private
|
|
124
|
+
private overlayHandle?;
|
|
125
|
+
private explicitTrigger?;
|
|
130
126
|
private readonly navId;
|
|
127
|
+
private syncSlottedItems;
|
|
131
128
|
/**
|
|
132
129
|
* The rail's current effective presentation. Always one of the three real
|
|
133
130
|
* modes — never `'auto'` — reflecting either the live breakpoint match or,
|
|
@@ -147,6 +144,8 @@ export declare class LyraAppRail extends LyraElement {
|
|
|
147
144
|
protected updated(): void;
|
|
148
145
|
connectedCallback(): void;
|
|
149
146
|
disconnectedCallback(): void;
|
|
147
|
+
private activateMobileOverlay;
|
|
148
|
+
private deactivateMobileOverlay;
|
|
150
149
|
private setupMediaQueries;
|
|
151
150
|
private teardownMediaQueries;
|
|
152
151
|
private onIconOnlyChange;
|
|
@@ -159,9 +158,7 @@ export declare class LyraAppRail extends LyraElement {
|
|
|
159
158
|
private onNavItemClick;
|
|
160
159
|
private onHeaderSlotChange;
|
|
161
160
|
private onFooterSlotChange;
|
|
162
|
-
private
|
|
163
|
-
private getFocusableElements;
|
|
164
|
-
private getActiveElement;
|
|
161
|
+
private onNavSlotChange;
|
|
165
162
|
render(): TemplateResult;
|
|
166
163
|
}
|
|
167
164
|
declare global {
|
|
@@ -7,42 +7,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { html, nothing, svg } from 'lit';
|
|
8
8
|
import { property, state } from 'lit/decorators.js';
|
|
9
9
|
import { LyraElement } from '../../internal/lyra-element.js';
|
|
10
|
+
import { activateOverlay } from '../../internal/overlay-manager.js';
|
|
10
11
|
import { defineElement } from '../../internal/prefix.js';
|
|
11
12
|
import { lockScroll } from '../../internal/scroll-lock.js';
|
|
12
13
|
import { nextId } from '../../internal/a11y.js';
|
|
13
14
|
import { closeIcon } from '../../internal/icons.js';
|
|
14
15
|
import { styles } from './app-rail.styles.js';
|
|
15
|
-
|
|
16
|
-
// Shadow-piercing so a slotted custom element's real focusable target (e.g.
|
|
17
|
-
// an <input> inside its own shadow root) is found even though the host tag
|
|
18
|
-
// itself doesn't match FOCUSABLE_SELECTOR. Deliberately duplicated from
|
|
19
|
-
// lyra-dialog's identical helper rather than imported/shared -- this
|
|
20
|
-
// component is its own standalone overlay for the mobile state and must not
|
|
21
|
-
// depend on lyra-dialog (see this file's class doc).
|
|
22
|
-
function collectFocusable(el) {
|
|
23
|
-
const result = [];
|
|
24
|
-
if (el.matches(FOCUSABLE_SELECTOR)) {
|
|
25
|
-
result.push(el);
|
|
26
|
-
}
|
|
27
|
-
if (el instanceof HTMLSlotElement) {
|
|
28
|
-
for (const assigned of el.assignedElements({ flatten: true })) {
|
|
29
|
-
result.push(...collectFocusable(assigned));
|
|
30
|
-
}
|
|
31
|
-
return result;
|
|
32
|
-
}
|
|
33
|
-
const container = el.shadowRoot ?? el;
|
|
34
|
-
for (const child of Array.from(container.children)) {
|
|
35
|
-
result.push(...collectFocusable(child));
|
|
36
|
-
}
|
|
37
|
-
return result;
|
|
38
|
-
}
|
|
39
|
-
/** Whether `el` is actually laid out/paintable -- `checkVisibility()` (falling
|
|
40
|
-
* back to `getClientRects().length` where unsupported) correctly follows
|
|
41
|
-
* flattened-tree/slot assignment, unlike `offsetParent`. Mirrors
|
|
42
|
-
* lyra-dialog's/lyra-widget's identical helper. */
|
|
43
|
-
function isRendered(el) {
|
|
44
|
-
return el.checkVisibility ? el.checkVisibility() : el.getClientRects().length > 0;
|
|
45
|
-
}
|
|
16
|
+
import './app-rail-item.js';
|
|
46
17
|
// icons.ts has no hamburger/menu glyph and this component must not modify
|
|
47
18
|
// that shared module -- inlined here instead, matching its 24x24
|
|
48
19
|
// viewBox/stroke-width/currentColor convention so it reads as part of the
|
|
@@ -94,12 +65,10 @@ export function computeAppRailMode(iconOnlyMatches, mobileMatches) {
|
|
|
94
65
|
* width the way a native OS shell's navigation does, not however much
|
|
95
66
|
* horizontal space a particular layout happens to give it.
|
|
96
67
|
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* shadow template
|
|
101
|
-
* overlay-shaped component in this library duplicates that pattern locally
|
|
102
|
-
* instead of composing the previous one. `[part="base"]` (the inline
|
|
68
|
+
* The `'mobile'` state participates in the library's shared overlay stack,
|
|
69
|
+
* which supplies focus trapping, Escape/backdrop dismissal, inerting, and
|
|
70
|
+
* focus restoration without nesting a `<lyra-dialog>` in this component's
|
|
71
|
+
* shadow template. `[part="base"]` (the inline
|
|
103
72
|
* `'full'`/`'icon-only'` presentation) and `[part="panel"]` (the mobile
|
|
104
73
|
* overlay) are the *same* element promoted in place across modes (mirrors
|
|
105
74
|
* `<lyra-widget>`'s fullscreen mode) — never both at once, and never two
|
|
@@ -112,15 +81,11 @@ export function computeAppRailMode(iconOnlyMatches, mobileMatches) {
|
|
|
112
81
|
* on a generic element can be swapped for `role="dialog"` freely.
|
|
113
82
|
*
|
|
114
83
|
* @customElement lyra-app-rail
|
|
115
|
-
* @slot - Nav items
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* overlay is open, clicking anywhere inside this slot closes it (see
|
|
121
|
-
* `onNavItemClick`) — every slotted item is assumed to be a navigation
|
|
122
|
-
* trigger, not necessarily a real link, so this fires on any click rather
|
|
123
|
-
* than trying to detect one.
|
|
84
|
+
* @slot - Nav items. Use `<lyra-app-rail-item>` for the explicit icon/label
|
|
85
|
+
* contract that automatically hides labels in `'icon-only'` mode. Generic
|
|
86
|
+
* links and buttons remain supported, but their compact presentation is the
|
|
87
|
+
* consumer's responsibility. While the mobile overlay is open, clicking
|
|
88
|
+
* anywhere inside this slot closes it.
|
|
124
89
|
* @slot header - Logo/brand content, shown above the nav items in every mode.
|
|
125
90
|
* @slot footer - A trailing user/settings trigger, shown below the nav items.
|
|
126
91
|
* @event lyra-mode-change - The effective mode changed, whether from a
|
|
@@ -143,13 +108,13 @@ export function computeAppRailMode(iconOnlyMatches, mobileMatches) {
|
|
|
143
108
|
* for why it's the same element as `base`, never both at once.
|
|
144
109
|
*
|
|
145
110
|
* @example
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* hidden text, or a `title` — since this component only lays out whatever is
|
|
149
|
-
* slotted and has no way to inspect or fix up a consumer's own markup:
|
|
111
|
+
* Use the item contract so the visible label collapses while its accessible
|
|
112
|
+
* name remains available:
|
|
150
113
|
* ```html
|
|
151
114
|
* <lyra-app-rail>
|
|
152
|
-
* <
|
|
115
|
+
* <lyra-app-rail-item href="/inbox" aria-label="Inbox">
|
|
116
|
+
* <svg slot="icon" aria-hidden="true">...</svg>Inbox
|
|
117
|
+
* </lyra-app-rail-item>
|
|
153
118
|
* </lyra-app-rail>
|
|
154
119
|
* ```
|
|
155
120
|
*/
|
|
@@ -204,11 +169,12 @@ export class LyraAppRail extends LyraElement {
|
|
|
204
169
|
this.applyComputedMode();
|
|
205
170
|
};
|
|
206
171
|
this.onToggleClick = (e) => {
|
|
207
|
-
this.
|
|
172
|
+
if (!this.open)
|
|
173
|
+
this.explicitTrigger = e.currentTarget;
|
|
208
174
|
this.setOpen(!this.open);
|
|
209
175
|
};
|
|
210
176
|
this.onBackdropClick = () => {
|
|
211
|
-
this.
|
|
177
|
+
this.overlayHandle?.dismissBackdrop();
|
|
212
178
|
};
|
|
213
179
|
// See the default-slot @slot doc -- any click inside the nav items while
|
|
214
180
|
// the overlay is open closes it, without trying to distinguish a real
|
|
@@ -223,32 +189,8 @@ export class LyraAppRail extends LyraElement {
|
|
|
223
189
|
this.onFooterSlotChange = (e) => {
|
|
224
190
|
this.hasFooterSlot = e.target.assignedElements({ flatten: true }).length > 0;
|
|
225
191
|
};
|
|
226
|
-
this.
|
|
227
|
-
|
|
228
|
-
return;
|
|
229
|
-
if (e.key === 'Escape') {
|
|
230
|
-
e.preventDefault();
|
|
231
|
-
this.setOpen(false);
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
if (e.key !== 'Tab')
|
|
235
|
-
return;
|
|
236
|
-
const focusable = this.getFocusableElements();
|
|
237
|
-
if (focusable.length === 0) {
|
|
238
|
-
e.preventDefault();
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
const first = focusable[0];
|
|
242
|
-
const last = focusable[focusable.length - 1];
|
|
243
|
-
const active = this.getActiveElement();
|
|
244
|
-
if (e.shiftKey && active === first) {
|
|
245
|
-
e.preventDefault();
|
|
246
|
-
last.focus();
|
|
247
|
-
}
|
|
248
|
-
else if (!e.shiftKey && active === last) {
|
|
249
|
-
e.preventDefault();
|
|
250
|
-
first.focus();
|
|
251
|
-
}
|
|
192
|
+
this.onNavSlotChange = () => {
|
|
193
|
+
this.syncSlottedItems();
|
|
252
194
|
};
|
|
253
195
|
}
|
|
254
196
|
static { this.styles = [LyraElement.styles, styles]; }
|
|
@@ -262,6 +204,14 @@ export class LyraAppRail extends LyraElement {
|
|
|
262
204
|
static { this.properties = {
|
|
263
205
|
mode: { reflect: true, noAccessor: true },
|
|
264
206
|
}; }
|
|
207
|
+
syncSlottedItems() {
|
|
208
|
+
const slot = this.shadowRoot?.querySelector('[part="nav"] > slot');
|
|
209
|
+
for (const item of slot?.assignedElements({ flatten: true }) ?? []) {
|
|
210
|
+
if (item.localName === 'lyra-app-rail-item') {
|
|
211
|
+
item.toggleAttribute('icon-only', this._mode === 'icon-only');
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
265
215
|
/**
|
|
266
216
|
* The rail's current effective presentation. Always one of the three real
|
|
267
217
|
* modes — never `'auto'` — reflecting either the live breakpoint match or,
|
|
@@ -306,13 +256,10 @@ export class LyraAppRail extends LyraElement {
|
|
|
306
256
|
this.overlayActive = next;
|
|
307
257
|
if (next) {
|
|
308
258
|
this.justOpened = true;
|
|
309
|
-
this.
|
|
310
|
-
document.addEventListener('keydown', this.onDocKeyDown);
|
|
259
|
+
this.activateMobileOverlay();
|
|
311
260
|
}
|
|
312
261
|
else {
|
|
313
|
-
this.
|
|
314
|
-
this.releaseScrollLock = undefined;
|
|
315
|
-
document.removeEventListener('keydown', this.onDocKeyDown);
|
|
262
|
+
this.deactivateMobileOverlay();
|
|
316
263
|
}
|
|
317
264
|
}
|
|
318
265
|
}
|
|
@@ -322,15 +269,10 @@ export class LyraAppRail extends LyraElement {
|
|
|
322
269
|
// rely on them -- mirrors lyra-dialog's/lyra-widget's identical ordering
|
|
323
270
|
// rationale.
|
|
324
271
|
updated() {
|
|
272
|
+
this.syncSlottedItems();
|
|
325
273
|
if (this.justOpened) {
|
|
326
274
|
this.justOpened = false;
|
|
327
|
-
|
|
328
|
-
if (first) {
|
|
329
|
-
first.focus();
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
this.shadowRoot?.querySelector('[part="panel"]')?.focus();
|
|
333
|
-
}
|
|
275
|
+
this.overlayHandle?.focusInitial();
|
|
334
276
|
}
|
|
335
277
|
}
|
|
336
278
|
connectedCallback() {
|
|
@@ -339,11 +281,18 @@ export class LyraAppRail extends LyraElement {
|
|
|
339
281
|
// A reconnect (e.g. a drag-and-drop reparent keeping this same element
|
|
340
282
|
// instance) fires disconnectedCallback then connectedCallback
|
|
341
283
|
// synchronously with no update in between, so willUpdate never reruns to
|
|
342
|
-
// notice the overlay is still active -- restore
|
|
343
|
-
//
|
|
344
|
-
if (this.hasUpdated && this.
|
|
345
|
-
this.
|
|
346
|
-
|
|
284
|
+
// notice the overlay is still active -- restore its shared registration
|
|
285
|
+
// and scroll lock.
|
|
286
|
+
if (this.hasUpdated && this._mode === 'mobile' && this.open) {
|
|
287
|
+
if (this.overlayHandle?.isActive()) {
|
|
288
|
+
this.overlayHandle.resume();
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
this.activateMobileOverlay();
|
|
292
|
+
}
|
|
293
|
+
if (!this.releaseScrollLock)
|
|
294
|
+
this.releaseScrollLock = lockScroll(this.ownerDocument);
|
|
295
|
+
queueMicrotask(() => this.overlayHandle?.focusInitial());
|
|
347
296
|
}
|
|
348
297
|
}
|
|
349
298
|
disconnectedCallback() {
|
|
@@ -351,13 +300,31 @@ export class LyraAppRail extends LyraElement {
|
|
|
351
300
|
this.teardownMediaQueries();
|
|
352
301
|
this.releaseScrollLock?.();
|
|
353
302
|
this.releaseScrollLock = undefined;
|
|
354
|
-
|
|
303
|
+
this.overlayHandle?.suspend();
|
|
304
|
+
}
|
|
305
|
+
activateMobileOverlay() {
|
|
306
|
+
this.releaseScrollLock ??= lockScroll(this.ownerDocument);
|
|
307
|
+
this.overlayHandle = activateOverlay({
|
|
308
|
+
host: this,
|
|
309
|
+
panel: () => this.shadowRoot?.querySelector('[part="panel"]') ?? null,
|
|
310
|
+
onEscape: () => this.setOpen(false),
|
|
311
|
+
onBackdrop: () => this.setOpen(false),
|
|
312
|
+
restoreFocusTo: this.explicitTrigger,
|
|
313
|
+
});
|
|
314
|
+
this.explicitTrigger = undefined;
|
|
315
|
+
}
|
|
316
|
+
deactivateMobileOverlay() {
|
|
317
|
+
this.releaseScrollLock?.();
|
|
318
|
+
this.releaseScrollLock = undefined;
|
|
319
|
+
this.overlayHandle?.deactivate();
|
|
320
|
+
this.overlayHandle = undefined;
|
|
355
321
|
}
|
|
356
322
|
setupMediaQueries() {
|
|
357
|
-
|
|
323
|
+
const view = this.ownerDocument.defaultView;
|
|
324
|
+
if (!view?.matchMedia)
|
|
358
325
|
return;
|
|
359
|
-
this.mqIconOnly =
|
|
360
|
-
this.mqMobile =
|
|
326
|
+
this.mqIconOnly = view.matchMedia(`(max-width: ${this.iconOnlyBreakpoint})`);
|
|
327
|
+
this.mqMobile = view.matchMedia(`(max-width: ${this.mobileBreakpoint})`);
|
|
361
328
|
this.mqIconOnly.addEventListener('change', this.onIconOnlyChange);
|
|
362
329
|
this.mqMobile.addEventListener('change', this.onMobileChange);
|
|
363
330
|
this.iconOnlyMatches = this.mqIconOnly.matches;
|
|
@@ -394,37 +361,6 @@ export class LyraAppRail extends LyraElement {
|
|
|
394
361
|
return;
|
|
395
362
|
this.open = next;
|
|
396
363
|
this.emit('lyra-toggle', { open: next });
|
|
397
|
-
if (!next)
|
|
398
|
-
this.lastTrigger?.focus();
|
|
399
|
-
}
|
|
400
|
-
// Bounds Tab/Shift+Tab to the panel while the overlay is open. Order
|
|
401
|
-
// follows the header slot, then the nav (default) slot, then the footer
|
|
402
|
-
// slot -- the same order the flattened tree already tabs through. The
|
|
403
|
-
// toggle button itself is deliberately excluded, same as a dialog trigger
|
|
404
|
-
// living outside its own trap.
|
|
405
|
-
getFocusableElements() {
|
|
406
|
-
const root = this.shadowRoot;
|
|
407
|
-
if (!root)
|
|
408
|
-
return [];
|
|
409
|
-
const fromSlot = (selector) => {
|
|
410
|
-
const slot = root.querySelector(selector);
|
|
411
|
-
return slot ? slot.assignedElements({ flatten: true }).flatMap(collectFocusable) : [];
|
|
412
|
-
};
|
|
413
|
-
return [
|
|
414
|
-
...fromSlot('slot[name="header"]'),
|
|
415
|
-
...fromSlot('slot:not([name])'),
|
|
416
|
-
...fromSlot('slot[name="footer"]'),
|
|
417
|
-
].filter(isRendered);
|
|
418
|
-
}
|
|
419
|
-
getActiveElement() {
|
|
420
|
-
let active = document.activeElement;
|
|
421
|
-
while (active) {
|
|
422
|
-
const inner = active.shadowRoot?.activeElement ?? null;
|
|
423
|
-
if (!inner)
|
|
424
|
-
break;
|
|
425
|
-
active = inner;
|
|
426
|
-
}
|
|
427
|
-
return active;
|
|
428
364
|
}
|
|
429
365
|
render() {
|
|
430
366
|
const mobile = this._mode === 'mobile';
|
|
@@ -453,7 +389,7 @@ export class LyraAppRail extends LyraElement {
|
|
|
453
389
|
<slot name="header" @slotchange=${this.onHeaderSlotChange}></slot>
|
|
454
390
|
</div>
|
|
455
391
|
<div part="nav">
|
|
456
|
-
<slot @click=${this.onNavItemClick}></slot>
|
|
392
|
+
<slot @slotchange=${this.onNavSlotChange} @click=${this.onNavItemClick}></slot>
|
|
457
393
|
</div>
|
|
458
394
|
<div part="footer" ?hidden=${!this.hasFooterSlot}>
|
|
459
395
|
<slot name="footer" @slotchange=${this.onFooterSlotChange}></slot>
|
|
@@ -39,7 +39,7 @@ export const styles = css `
|
|
|
39
39
|
[part='backdrop'] {
|
|
40
40
|
position: fixed;
|
|
41
41
|
inset: 0;
|
|
42
|
-
z-index:
|
|
42
|
+
z-index: var(--lyra-overlay-stack-index, 1000);
|
|
43
43
|
background: var(--lyra-app-rail-overlay-color);
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -68,7 +68,7 @@ export const styles = css `
|
|
|
68
68
|
position: fixed;
|
|
69
69
|
inset-block: 0;
|
|
70
70
|
inset-inline-start: 0;
|
|
71
|
-
z-index: 1000;
|
|
71
|
+
z-index: calc(var(--lyra-overlay-stack-index, 1000) + 1);
|
|
72
72
|
display: flex;
|
|
73
73
|
flex-direction: column;
|
|
74
74
|
inline-size: min(var(--lyra-app-rail-mobile-width), 85vw);
|
|
@@ -115,6 +115,9 @@ export const styles = css `
|
|
|
115
115
|
:host([mode='icon-only']) [part='nav'] {
|
|
116
116
|
align-items: center;
|
|
117
117
|
}
|
|
118
|
+
:host([mode='icon-only']) ::slotted(lyra-app-rail-item) {
|
|
119
|
+
max-inline-size: var(--lyra-app-rail-icon-width);
|
|
120
|
+
}
|
|
118
121
|
|
|
119
122
|
@media (prefers-reduced-motion: reduce) {
|
|
120
123
|
[part='base'],
|