srcdev-nuxt-components 9.6.18 → 9.6.20
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/.claude/rules/consumer/css-relative-colour-calc.md +15 -0
- package/.claude/rules/consumer/ids-from-useid.md +3 -2
- package/.claude/rules/consumer/vue-dynamic-arg-no-spaces.md +16 -0
- package/.claude/skills/component-compliance-checklist.md +11 -1
- package/.claude/skills/component-dynamic-slots.md +2 -2
- package/.claude/skills/component-naming.md +1 -1
- package/.claude/skills/components/accordion-chat.md +99 -0
- package/.claude/skills/components/accordion-group.md +98 -0
- package/.claude/skills/components/action-menu.md +11 -5
- package/.claude/skills/components/auto-grid.md +3 -1
- package/.claude/skills/components/capture-qr-code.md +9 -5
- package/.claude/skills/components/carousel-flip.md +41 -30
- package/.claude/skills/components/column-flow-grid.md +2 -0
- package/.claude/skills/components/dashboard-quad-grid.md +7 -2
- package/.claude/skills/components/dashboard-stats-grid.md +4 -0
- package/.claude/skills/components/decode-qr-code.md +7 -2
- package/.claude/skills/components/deep-expanding-menu-classic.md +31 -30
- package/.claude/skills/components/deep-expanding-menu.md +22 -21
- package/.claude/skills/components/expanding-panel-classic.md +9 -7
- package/.claude/skills/components/expanding-panel.md +9 -8
- package/.claude/skills/components/grid-stack.md +2 -0
- package/.claude/skills/components/layout-grid-by-cols.md +2 -0
- package/.claude/skills/components/masonry-grid.md +9 -1
- package/.claude/skills/components/page-row.md +3 -0
- package/.claude/skills/components/samaritan-prompt.md +24 -8
- package/.claude/skills/components/site-header.md +16 -2
- package/.claude/skills/components/sparkle-effect.md +79 -0
- package/.claude/skills/index.md +16 -14
- package/.claude/skills/storybook-add-story.md +33 -0
- package/.claude/skills/testing-add-unit-test.md +26 -0
- package/.claude/skills/using-component-skills.md +1 -1
- package/.vscode/srcdev-component-accordion-chat.code-snippets +42 -0
- package/.vscode/srcdev-component-accordion-group.code-snippets +38 -0
- package/.vscode/srcdev-component-action-menu.code-snippets +3 -3
- package/.vscode/srcdev-component-capture-decode-qr-code.code-snippets +11 -2
- package/.vscode/srcdev-component-carousel-flip.code-snippets +22 -4
- package/.vscode/srcdev-component-deep-expanding-menu-classic.code-snippets +32 -2
- package/.vscode/srcdev-component-deep-expanding-menu.code-snippets +31 -1
- package/.vscode/srcdev-component-samaritan-prompt.code-snippets +5 -4
- package/.vscode/srcdev-component-site-header.code-snippets +13 -1
- package/.vscode/srcdev-component-sparkle-effect.code-snippets +33 -0
- package/app/components/01.atoms/animations/sparkle-effect/CONSUMER-STYLING.md +75 -0
- package/app/components/01.atoms/animations/sparkle-effect/SparkleEffect.vue +213 -0
- package/app/components/01.atoms/animations/sparkle-effect/stories/SparkleEffect.stories.ts +303 -0
- package/app/components/01.atoms/animations/sparkle-effect/tests/SparkleEffect.spec.ts +150 -0
- package/app/components/01.atoms/content-wrappers/docs-pages/ContentDocs.vue +1 -1
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/CONSUMER-STYLING.md +12 -2
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/DashboardQuadGrid.vue +19 -17
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/stories/DashboardQuadGrid.stories.ts +42 -0
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/tests/DashboardQuadGrid.spec.ts +31 -44
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/CONSUMER-STYLING.md +13 -1
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/DashboardStatsGrid.vue +40 -31
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/stories/DashboardStatsGrid.stories.ts +47 -0
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/tests/DashboardStatsGrid.spec.ts +51 -53
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/CONSUMER-STYLING.md +3 -0
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/LayoutGridByCols.vue +4 -0
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/stories/LayoutGridByCols.stories.ts +47 -2
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/LayoutGridByCols.spec.ts +36 -23
- package/app/components/01.atoms/grids/auto-grid/AutoGrid.vue +7 -3
- package/app/components/01.atoms/grids/auto-grid/CONSUMER-STYLING.md +1 -1
- package/app/components/01.atoms/grids/auto-grid/stories/AutoGrid.stories.ts +46 -1
- package/app/components/01.atoms/grids/auto-grid/tests/AutoGrid.spec.ts +40 -27
- package/app/components/01.atoms/grids/auto-grid/tests/__snapshots__/AutoGrid.spec.ts.snap +1 -1
- package/app/components/01.atoms/grids/column-flow-grid/CONSUMER-STYLING.md +9 -0
- package/app/components/01.atoms/grids/column-flow-grid/ColumnFlowGrid.vue +3 -2
- package/app/components/01.atoms/grids/column-flow-grid/stories/ColumnFlowGrid.stories.ts +46 -0
- package/app/components/01.atoms/grids/column-flow-grid/tests/ColumnFlowGrid.spec.ts +24 -11
- package/app/components/01.atoms/grids/grid-stack/CONSUMER-STYLING.md +3 -0
- package/app/components/01.atoms/grids/grid-stack/GridStack.vue +2 -0
- package/app/components/01.atoms/grids/grid-stack/stories/GridStack.stories.ts +41 -0
- package/app/components/01.atoms/grids/grid-stack/tests/GridStack.spec.ts +26 -13
- package/app/components/01.atoms/grids/masonry-grid/CONSUMER-STYLING.md +15 -0
- package/app/components/01.atoms/grids/masonry-grid/MasonryGrid.vue +51 -31
- package/app/components/01.atoms/grids/masonry-grid/stories/MasonryGrid.stories.ts +48 -0
- package/app/components/01.atoms/grids/masonry-grid/tests/MasonryGrid.spec.ts +84 -29
- package/app/components/01.atoms/page-row/CONSUMER-STYLING.md +6 -1
- package/app/components/01.atoms/page-row/PageRow.vue +16 -15
- package/app/components/01.atoms/page-row/stories/PageRow.stories.ts +23 -0
- package/app/components/01.atoms/page-row/tests/PageRow.spec.ts +6 -5
- package/app/components/02.molecules/action-menu/ActionMenu.vue +6 -2
- package/app/components/02.molecules/action-menu/ActionMenuItem.vue +6 -3
- package/app/components/02.molecules/action-menu/CONSUMER-STYLING.md +11 -4
- package/app/components/02.molecules/action-menu/stories/ActionMenu.stories.ts +130 -18
- package/app/components/02.molecules/expandable/accordion-chat/AccordionChat.vue +227 -0
- package/app/components/02.molecules/expandable/accordion-chat/CONSUMER-STYLING.md +150 -0
- package/app/components/02.molecules/expandable/accordion-chat/stories/AccordionChat.stories.ts +347 -0
- package/app/components/02.molecules/expandable/accordion-chat/tests/AccordionChat.spec.ts +205 -0
- package/app/components/02.molecules/expandable/accordion-chat/tests/__snapshots__/AccordionChat.spec.ts.snap +40 -0
- package/app/components/02.molecules/expandable/{accordian/AccordianCore.vue → accordion-group/AccordionGroup.vue} +32 -20
- package/app/components/02.molecules/expandable/accordion-group/CONSUMER-STYLING.md +66 -0
- package/app/components/02.molecules/expandable/accordion-group/stories/AccordionGroup.stories.ts +238 -0
- package/app/components/02.molecules/expandable/accordion-group/tests/AccordionGroup.spec.ts +172 -0
- package/app/components/02.molecules/expandable/accordion-group/tests/__snapshots__/AccordionGroup.spec.ts.snap +45 -0
- package/app/components/02.molecules/expandable/expanding-panel/CONSUMER-STYLING.md +1 -0
- package/app/components/02.molecules/expandable/expanding-panel/ExpandingPanel.vue +11 -6
- package/app/components/02.molecules/expandable/expanding-panel/stories/ExpandingPanel.stories.ts +82 -1
- package/app/components/02.molecules/expandable/expanding-panel/tests/ExpandingPanel.spec.ts +24 -30
- package/app/components/02.molecules/expandable/expanding-panel/tests/__snapshots__/ExpandingPanel.spec.ts.snap +8 -8
- package/app/components/02.molecules/expandable/expanding-panel-classic/CONSUMER-STYLING.md +1 -0
- package/app/components/02.molecules/expandable/expanding-panel-classic/ExpandingPanelClassic.vue +10 -5
- package/app/components/02.molecules/expandable/expanding-panel-classic/stories/ExpandingPanelClassic.stories.ts +83 -1
- package/app/components/02.molecules/expandable/expanding-panel-classic/tests/ExpandingPanelClassic.spec.ts +24 -30
- package/app/components/02.molecules/expandable/expanding-panel-classic/tests/__snapshots__/ExpandingPanelClassic.spec.ts.snap +8 -8
- package/app/components/02.molecules/navigation/deep-expanding-menu/CONSUMER-STYLING.md +63 -44
- package/app/components/02.molecules/navigation/deep-expanding-menu/DeepExpandingMenu.vue +74 -37
- package/app/components/02.molecules/navigation/deep-expanding-menu/stories/DeepExpandingMenu.stories.ts +139 -19
- package/app/components/02.molecules/navigation/deep-expanding-menu/tests/DeepExpandingMenu.spec.ts +90 -27
- package/app/components/02.molecules/navigation/deep-expanding-menu/tests/__snapshots__/DeepExpandingMenu.spec.ts.snap +8 -8
- package/app/components/02.molecules/navigation/deep-expanding-menu-classic/CONSUMER-STYLING.md +58 -26
- package/app/components/02.molecules/navigation/deep-expanding-menu-classic/DeepExpandingMenuClassic.vue +113 -57
- package/app/components/02.molecules/navigation/deep-expanding-menu-classic/stories/DeepExpandingMenuClassic.stories.ts +139 -19
- package/app/components/02.molecules/navigation/deep-expanding-menu-classic/tests/DeepExpandingMenuClassic.spec.ts +140 -22
- package/app/components/02.molecules/navigation/deep-expanding-menu-classic/tests/__snapshots__/DeepExpandingMenuClassic.spec.ts.snap +9 -9
- package/app/components/02.molecules/qr-code/CONSUMER-STYLING.md +22 -7
- package/app/components/02.molecules/qr-code/CaptureQrCode.vue +63 -71
- package/app/components/02.molecules/qr-code/DecodeQrCode.vue +47 -10
- package/app/components/02.molecules/qr-code/stories/CaptureQrCode.stories.ts +114 -26
- package/app/components/02.molecules/qr-code/stories/DecodeQrCode.stories.ts +115 -24
- package/app/components/02.molecules/qr-code/tests/CaptureQrCode.spec.ts +124 -51
- package/app/components/02.molecules/qr-code/tests/DecodeQrCode.spec.ts +74 -25
- package/app/components/02.molecules/samaritan-prompt/CONSUMER-STYLING.md +22 -10
- package/app/components/02.molecules/samaritan-prompt/SamaritanPrompt.vue +30 -12
- package/app/components/02.molecules/samaritan-prompt/SamaritanPromptMixed.vue +34 -10
- package/app/components/02.molecules/samaritan-prompt/stories/SamaritanPrompt.stories.ts +55 -4
- package/app/components/02.molecules/samaritan-prompt/stories/SamaritanPromptMixed.stories.ts +67 -7
- package/app/components/02.molecules/samaritan-prompt/tests/SamaritanPrompt.spec.ts +113 -29
- package/app/components/02.molecules/samaritan-prompt/tests/SamaritanPromptMixed.spec.ts +92 -45
- package/app/components/03.organisms/image-galleries/carousel-flip/CONSUMER-STYLING.md +82 -29
- package/app/components/03.organisms/image-galleries/carousel-flip/CarouselFlip.vue +176 -113
- package/app/components/03.organisms/image-galleries/carousel-flip/stories/CarouselFlip.stories.ts +153 -23
- package/app/components/03.organisms/image-galleries/carousel-flip/tests/CarouselFlip.spec.ts +119 -63
- package/app/components/03.organisms/responsive-header/tests/__snapshots__/NavigationItems.spec.ts.snap +2 -2
- package/app/components/03.organisms/responsive-header/tests/__snapshots__/ResponsiveHeader.spec.ts.snap +2 -2
- package/app/components/03.organisms/services/service-detail/tests/ServiceDetail.spec.ts +8 -8
- package/app/components/03.organisms/services/service-detail/tests/__snapshots__/ServiceDetail.spec.ts.snap +4 -4
- package/app/components/03.organisms/site-header/CONSUMER-STYLING.md +41 -23
- package/app/components/03.organisms/site-header/SiteHeader.vue +16 -21
- package/app/components/03.organisms/site-header/stories/SiteHeader.stories.ts +138 -0
- package/app/components/03.organisms/site-header/tests/SiteHeader.spec.ts +53 -26
- package/app/components/03.organisms/site-header/tests/__snapshots__/SiteHeader.spec.ts.snap +2 -2
- package/app/types/components/qr-code.d.ts +12 -0
- package/app/utils/graphemes.ts +8 -0
- package/package.json +1 -1
- package/.claude/skills/components/accordian-core.md +0 -180
- package/.vscode/srcdev-component-accordian-core.code-snippets +0 -74
- package/app/components/01.atoms/animations/entry/.nuxt/app.config.mjs +0 -21
- package/app/components/01.atoms/animations/entry/.nuxt/components.d.ts +0 -66
- package/app/components/01.atoms/animations/entry/.nuxt/imports.d.ts +0 -30
- package/app/components/01.atoms/animations/entry/.nuxt/manifest/meta/test.json +0 -1
- package/app/components/01.atoms/animations/entry/.nuxt/types/app.config.d.ts +0 -35
- package/app/components/01.atoms/animations/entry/.nuxt/types/build.d.ts +0 -23
- package/app/components/01.atoms/animations/entry/.nuxt/types/builder-env.d.ts +0 -1
- package/app/components/01.atoms/animations/entry/.nuxt/types/components.d.ts +0 -71
- package/app/components/01.atoms/animations/entry/.nuxt/types/imports.d.ts +0 -386
- package/app/components/01.atoms/animations/entry/.nuxt/types/middleware.d.ts +0 -11
- package/app/components/01.atoms/animations/entry/.nuxt/types/modules.d.ts +0 -79
- package/app/components/01.atoms/animations/entry/.nuxt/types/nitro-layouts.d.ts +0 -17
- package/app/components/01.atoms/animations/entry/.nuxt/types/nitro-nuxt.d.ts +0 -64
- package/app/components/01.atoms/animations/entry/.nuxt/types/plugins.d.ts +0 -29
- package/app/components/01.atoms/animations/entry/.nuxt/types/runtime-config.d.ts +0 -32
- package/app/components/01.atoms/animations/entry/.nuxt/types/shared-imports.d.ts +0 -10
- package/app/components/01.atoms/animations/entry/.nuxt/types/vue-shim.d.ts +0 -0
- package/app/components/01.atoms/animations/entry/.nuxtrc +0 -1
- package/app/components/01.atoms/animations/entry/node_modules/.cache/nuxt/chrome-workspace.json +0 -1
- package/app/components/01.atoms/animations/entry/node_modules/.cache/vite/client/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
- package/app/components/02.molecules/expandable/accordian/CONSUMER-STYLING.md +0 -100
- package/app/components/02.molecules/expandable/accordian/stories/AccordianCore.stories.ts +0 -272
- package/app/components/02.molecules/expandable/accordian/tests/AccordianCore.spec.ts +0 -257
- package/app/components/02.molecules/expandable/accordian/tests/__snapshots__/AccordianCore.spec.ts.snap +0 -95
- package/app/components/03.organisms/responsive-header/tests/.nuxt/app.config.mjs +0 -21
- package/app/components/03.organisms/responsive-header/tests/.nuxt/components.d.ts +0 -66
- package/app/components/03.organisms/responsive-header/tests/.nuxt/imports.d.ts +0 -30
- package/app/components/03.organisms/responsive-header/tests/.nuxt/manifest/meta/test.json +0 -1
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/app.config.d.ts +0 -35
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/build.d.ts +0 -23
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/builder-env.d.ts +0 -1
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/components.d.ts +0 -71
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/imports.d.ts +0 -386
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/middleware.d.ts +0 -11
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/modules.d.ts +0 -79
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/nitro-layouts.d.ts +0 -17
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/nitro-nuxt.d.ts +0 -64
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/plugins.d.ts +0 -29
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/runtime-config.d.ts +0 -32
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/shared-imports.d.ts +0 -10
- package/app/components/03.organisms/responsive-header/tests/.nuxt/types/vue-shim.d.ts +0 -0
- package/app/components/03.organisms/responsive-header/tests/node_modules/.cache/nuxt/chrome-workspace.json +0 -1
|
@@ -66,7 +66,7 @@ watch(
|
|
|
66
66
|
box-sizing: border-box;
|
|
67
67
|
cursor: pointer;
|
|
68
68
|
display: grid;
|
|
69
|
-
grid-template-columns: auto 1fr auto;
|
|
69
|
+
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
70
70
|
align-items: center;
|
|
71
71
|
|
|
72
72
|
width: 100%;
|
|
@@ -105,9 +105,12 @@ watch(
|
|
|
105
105
|
|
|
106
106
|
.action-menu-item-label {
|
|
107
107
|
grid-column: 2;
|
|
108
|
-
|
|
108
|
+
display: -webkit-box;
|
|
109
|
+
-webkit-box-orient: vertical;
|
|
109
110
|
overflow: hidden;
|
|
110
|
-
|
|
111
|
+
overflow-wrap: anywhere;
|
|
112
|
+
-webkit-line-clamp: var(--action-menu-item-label-line-clamp, none);
|
|
113
|
+
line-clamp: var(--action-menu-item-label-line-clamp, none);
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
.action-menu-item-arrow {
|
|
@@ -29,6 +29,7 @@ All `--action-menu-*` tokens are the stable override surface. Action menus repea
|
|
|
29
29
|
| `--action-menu-popover-border` | `0.1rem solid var(--slate-03)` | Menu panel border shorthand |
|
|
30
30
|
| `--action-menu-popover-border-radius` | `0.8rem` | Menu panel corner rounding |
|
|
31
31
|
| `--action-menu-popover-min-width` | `20rem` | Minimum menu width |
|
|
32
|
+
| `--action-menu-popover-max-width` | `min(32rem, calc(100vw - 3.2rem))` | Maximum menu width; longer labels wrap |
|
|
32
33
|
| `--action-menu-popover-shadow` | `0 0.4rem 1.6rem rgba(0, 0, 0, 0.1)` | Menu panel drop shadow |
|
|
33
34
|
| `--action-menu-popover-transition-duration` | `200ms` | Open/close fade duration |
|
|
34
35
|
| `--action-menu-popover-z-index` | `999999` | Stacking order in browsers without CSS anchor positioning (see Positioning). Ignored where the popover renders in the top layer |
|
|
@@ -45,7 +46,13 @@ All `--action-menu-*` tokens are the stable override surface. Action menus repea
|
|
|
45
46
|
| `--action-menu-item-gap` | `1.2rem` | Space between icon, label and arrow |
|
|
46
47
|
| `--action-menu-item-padding-inline` | `1.6rem` | Row horizontal padding |
|
|
47
48
|
| `--action-menu-item-padding-block` | `1.2rem` | Row vertical padding |
|
|
49
|
+
| `--action-menu-item-label-line-clamp` | `none` | Caps the label at this many lines with an ellipsis (`1` is single-line ellipsis, `none` shows it all) |
|
|
48
50
|
|
|
51
|
+
> Changed 2026-10-20: labels used to stay on one line and widen the menu without limit, so a long
|
|
52
|
+
> label pushed it past a phone screen. The menu now stops at `--action-menu-popover-max-width` and
|
|
53
|
+
> labels wrap; set `--action-menu-item-label-line-clamp: 1` for the old single-line look with an
|
|
54
|
+
> ellipsis. `--action-menu-popover-max-width` and `--action-menu-item-label-line-clamp` are new.
|
|
55
|
+
>
|
|
49
56
|
> Changed 2026-09-27: item `light-dark()` defaults replaced by their light values (older iPad
|
|
50
57
|
> Safari lacks `light-dark()`), matching the already-light panel. Icon sizes are applied as
|
|
51
58
|
> `font-size`; the old `width`/`height` on the trigger and arrow icons was silently overridden by
|
|
@@ -79,8 +86,8 @@ Inner classes: `.action-menu-trigger`, `.action-menu-trigger-icon`, `.action-men
|
|
|
79
86
|
## Positioning
|
|
80
87
|
|
|
81
88
|
The menu uses the Popover API plus CSS anchor positioning: it opens below the trigger,
|
|
82
|
-
right-aligned, and flips above near the bottom of the viewport
|
|
83
|
-
flip-block`).
|
|
89
|
+
right-aligned, and flips above near the bottom of the viewport and to open rightwards near the left
|
|
90
|
+
edge (`position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline`).
|
|
84
91
|
|
|
85
92
|
Fallbacks, via the shared `useAnchoredPopover` composable:
|
|
86
93
|
|
|
@@ -148,5 +155,5 @@ doesn't rely on it for its defaults.
|
|
|
148
155
|
## Notes
|
|
149
156
|
|
|
150
157
|
- Negative `--action-menu-block-distance` values make the menu overlap the trigger.
|
|
151
|
-
- `--action-menu-popover-min-width` is a floor
|
|
152
|
-
|
|
158
|
+
- `--action-menu-popover-min-width` is a floor and `--action-menu-popover-max-width` a ceiling;
|
|
159
|
+
between them the menu sizes to its longest label, and labels wrap at the ceiling.
|
|
@@ -2,11 +2,14 @@ import { computed, ref } from "vue";
|
|
|
2
2
|
import type { Meta, StoryObj } from "@nuxtjs/storybook";
|
|
3
3
|
import ActionMenu from "../ActionMenu.vue";
|
|
4
4
|
import ActionMenuItem from "../ActionMenuItem.vue";
|
|
5
|
+
import CanvasSwitcher from "../../../01.atoms/canvas-switcher/CanvasSwitcher.vue";
|
|
6
|
+
import type { MediaCanvas } from "~/types/components";
|
|
5
7
|
|
|
6
8
|
// ─── Meta ─────────────────────────────────────────────────────────────────────
|
|
7
9
|
|
|
8
10
|
interface StoryArgs {
|
|
9
11
|
itemCount?: number;
|
|
12
|
+
labelLineClamp?: string;
|
|
10
13
|
label?: string;
|
|
11
14
|
triggerIcon?: string;
|
|
12
15
|
styleClassPassthrough?: string | string[];
|
|
@@ -17,8 +20,8 @@ const meta: Meta<StoryArgs> = {
|
|
|
17
20
|
component: ActionMenu,
|
|
18
21
|
argTypes: {
|
|
19
22
|
itemCount: {
|
|
20
|
-
control: { type: "number", min: 0, max:
|
|
21
|
-
description: "Number of items to show (
|
|
23
|
+
control: { type: "number", min: 0, max: 5, step: 1 },
|
|
24
|
+
description: "**Story control, not a prop.** Number of items to show (0 to 5, the size of this data set).",
|
|
22
25
|
table: { category: "Content" },
|
|
23
26
|
},
|
|
24
27
|
label: {
|
|
@@ -31,6 +34,13 @@ const meta: Meta<StoryArgs> = {
|
|
|
31
34
|
description: "Icon name for the trigger button",
|
|
32
35
|
table: { category: "Appearance" },
|
|
33
36
|
},
|
|
37
|
+
labelLineClamp: {
|
|
38
|
+
control: { type: "select" },
|
|
39
|
+
options: ["none", "1", "2", "3"],
|
|
40
|
+
description:
|
|
41
|
+
"**Story control, not a prop.** Sets `--action-menu-item-label-line-clamp`. In your CSS: `.my-page { --action-menu-item-label-line-clamp: 1; }`",
|
|
42
|
+
table: { category: "CSS tokens (story only, set in your CSS)" },
|
|
43
|
+
},
|
|
34
44
|
styleClassPassthrough: {
|
|
35
45
|
table: { disable: true },
|
|
36
46
|
},
|
|
@@ -38,6 +48,7 @@ const meta: Meta<StoryArgs> = {
|
|
|
38
48
|
args: {
|
|
39
49
|
itemCount: 5,
|
|
40
50
|
label: "Open actions menu",
|
|
51
|
+
labelLineClamp: "none",
|
|
41
52
|
triggerIcon: "lucide:ellipsis",
|
|
42
53
|
},
|
|
43
54
|
parameters: {
|
|
@@ -67,6 +78,17 @@ const actionItems = [
|
|
|
67
78
|
{ label: "Delete", icon: "lucide:trash-2", href: undefined },
|
|
68
79
|
] as const;
|
|
69
80
|
|
|
81
|
+
function useStorySetup(args: StoryArgs) {
|
|
82
|
+
const componentArgs = computed(() => {
|
|
83
|
+
const { itemCount: _itemCount, labelLineClamp: _labelLineClamp, ...rest } = args;
|
|
84
|
+
return rest;
|
|
85
|
+
});
|
|
86
|
+
const tokenStyle = computed(() => ({
|
|
87
|
+
"--action-menu-item-label-line-clamp": args.labelLineClamp || undefined,
|
|
88
|
+
}));
|
|
89
|
+
return { args, componentArgs, tokenStyle };
|
|
90
|
+
}
|
|
91
|
+
|
|
70
92
|
// ─── Stories ──────────────────────────────────────────────────────────────────
|
|
71
93
|
|
|
72
94
|
/**
|
|
@@ -81,13 +103,7 @@ export const Default: Story = {
|
|
|
81
103
|
render: (args) => ({
|
|
82
104
|
components: { ActionMenu, ActionMenuItem },
|
|
83
105
|
setup() {
|
|
84
|
-
|
|
85
|
-
// these computeds rather than destructuring it into local variables at setup-time, which
|
|
86
|
-
// would snapshot the values once and stop reflecting later Controls-panel changes.
|
|
87
|
-
const componentArgs = computed(() => {
|
|
88
|
-
const { itemCount, ...rest } = args;
|
|
89
|
-
return rest;
|
|
90
|
-
});
|
|
106
|
+
const { componentArgs, tokenStyle } = useStorySetup(args);
|
|
91
107
|
const lastAction = ref<string | null>(null);
|
|
92
108
|
const items = computed(() =>
|
|
93
109
|
actionItems.slice(0, args.itemCount ?? 5).map((item, i) => ({
|
|
@@ -95,11 +111,11 @@ export const Default: Story = {
|
|
|
95
111
|
slotName: `item-${i}`,
|
|
96
112
|
}))
|
|
97
113
|
);
|
|
98
|
-
return { componentArgs, items, lastAction };
|
|
114
|
+
return { componentArgs, tokenStyle, items, lastAction };
|
|
99
115
|
},
|
|
100
116
|
template: `
|
|
101
117
|
<div style="padding: 4rem 8rem; display: flex; flex-direction: column; align-items: flex-end; gap: 2rem;">
|
|
102
|
-
<ActionMenu v-bind="componentArgs">
|
|
118
|
+
<ActionMenu v-bind="componentArgs" :style="tokenStyle">
|
|
103
119
|
<template v-for="item in items" :key="item.slotName" #[item.slotName]>
|
|
104
120
|
<ActionMenuItem :label="item.label" @click="lastAction = item.label">
|
|
105
121
|
<template #icon>
|
|
@@ -128,11 +144,11 @@ export const MixedItems: Story = {
|
|
|
128
144
|
render: (args) => ({
|
|
129
145
|
components: { ActionMenu, ActionMenuItem },
|
|
130
146
|
setup() {
|
|
131
|
-
return
|
|
147
|
+
return useStorySetup(args);
|
|
132
148
|
},
|
|
133
149
|
template: `
|
|
134
150
|
<div style="padding: 4rem 8rem; display: flex; justify-content: flex-end;">
|
|
135
|
-
<ActionMenu v-bind="
|
|
151
|
+
<ActionMenu v-bind="componentArgs" :style="tokenStyle">
|
|
136
152
|
<template #item-0>
|
|
137
153
|
<ActionMenuItem label="Edit record" @click="() => {}">
|
|
138
154
|
<template #icon><Icon name="lucide:pencil" /></template>
|
|
@@ -168,11 +184,11 @@ export const NoIcons: Story = {
|
|
|
168
184
|
render: (args) => ({
|
|
169
185
|
components: { ActionMenu, ActionMenuItem },
|
|
170
186
|
setup() {
|
|
171
|
-
return
|
|
187
|
+
return useStorySetup(args);
|
|
172
188
|
},
|
|
173
189
|
template: `
|
|
174
190
|
<div style="padding: 4rem 8rem; display: flex; justify-content: flex-end;">
|
|
175
|
-
<ActionMenu v-bind="
|
|
191
|
+
<ActionMenu v-bind="componentArgs" :style="tokenStyle">
|
|
176
192
|
<template #item-0>
|
|
177
193
|
<ActionMenuItem label="Approve" @click="() => {}" />
|
|
178
194
|
</template>
|
|
@@ -206,7 +222,7 @@ export const InContext: Story = {
|
|
|
206
222
|
{ name: "Sam Patel", email: "sam@example.com", role: "Editor" },
|
|
207
223
|
{ name: "Jordan Clarke", email: "jordan@example.com", role: "Viewer" },
|
|
208
224
|
];
|
|
209
|
-
return { args, users };
|
|
225
|
+
return { ...useStorySetup(args), users };
|
|
210
226
|
},
|
|
211
227
|
template: `
|
|
212
228
|
<div style="padding: 4rem; max-width: 56rem; margin: 0 auto;">
|
|
@@ -234,7 +250,7 @@ export const InContext: Story = {
|
|
|
234
250
|
flex-shrink: 0;
|
|
235
251
|
"
|
|
236
252
|
>
|
|
237
|
-
{{ user.name[0] }}
|
|
253
|
+
{{ Array.from(user.name)[0] }}
|
|
238
254
|
</div>
|
|
239
255
|
<div style="flex: 1; min-width: 0;">
|
|
240
256
|
<p style="margin: 0; font-size: 1.4rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
|
|
@@ -245,7 +261,7 @@ export const InContext: Story = {
|
|
|
245
261
|
</p>
|
|
246
262
|
</div>
|
|
247
263
|
<span style="font-size: 1.2rem; opacity: 0.5; white-space: nowrap;">{{ user.role }}</span>
|
|
248
|
-
<ActionMenu v-bind="
|
|
264
|
+
<ActionMenu v-bind="componentArgs" :style="tokenStyle">
|
|
249
265
|
<template #item-0>
|
|
250
266
|
<ActionMenuItem label="Edit user" @click="() => {}">
|
|
251
267
|
<template #icon><Icon name="lucide:pencil" /></template>
|
|
@@ -337,3 +353,99 @@ export const ItemCoreStandalone: Story = {
|
|
|
337
353
|
`,
|
|
338
354
|
}),
|
|
339
355
|
};
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Stress test: hostile labels and item counts, with triggers at both inline edges.
|
|
359
|
+
*/
|
|
360
|
+
export const StressTest: Story = {
|
|
361
|
+
name: "Stress Test (Worst-Case Data)",
|
|
362
|
+
args: {
|
|
363
|
+
label: "Aktionen für diesen Eintrag öffnen",
|
|
364
|
+
},
|
|
365
|
+
render: (args) => ({
|
|
366
|
+
components: { ActionMenu, ActionMenuItem },
|
|
367
|
+
setup() {
|
|
368
|
+
const hostileLabels = [
|
|
369
|
+
"Donaudampfschifffahrtselektrizitätenhauptbetriebswerkbauunterbeamtengesellschaft",
|
|
370
|
+
"https://example.com/" + "a-very-long-path-segment-without-spaces".repeat(3),
|
|
371
|
+
"Diesen Eintrag dauerhaft löschen, einschließlich aller zugehörigen Anhänge und Kommentare",
|
|
372
|
+
"🎉 Celebrate",
|
|
373
|
+
"<b>Not bold</b>",
|
|
374
|
+
"حذف هذا السجل نهائيا",
|
|
375
|
+
"A",
|
|
376
|
+
];
|
|
377
|
+
const manyItems = Array.from({ length: 12 }, (_, i) => `Action ${i + 1}`);
|
|
378
|
+
return { ...useStorySetup(args), hostileLabels, manyItems };
|
|
379
|
+
},
|
|
380
|
+
template: `
|
|
381
|
+
<div style="padding: 2.4rem 1.6rem; display: grid; gap: 4rem;">
|
|
382
|
+
<div style="display: flex; justify-content: space-between; align-items: center; gap: 1.6rem;">
|
|
383
|
+
<ActionMenu v-bind="componentArgs" :style="tokenStyle">
|
|
384
|
+
<template v-for="(text, i) in hostileLabels" :key="i" #[\`item-\${i}\`]>
|
|
385
|
+
<ActionMenuItem :label="text" @click="() => {}">
|
|
386
|
+
<template #icon><Icon name="lucide:pencil" /></template>
|
|
387
|
+
</ActionMenuItem>
|
|
388
|
+
</template>
|
|
389
|
+
</ActionMenu>
|
|
390
|
+
<span>Hostile labels: left-edge trigger and right-edge trigger</span>
|
|
391
|
+
<ActionMenu v-bind="componentArgs" :style="tokenStyle">
|
|
392
|
+
<template v-for="(text, i) in hostileLabels" :key="i" #[\`item-\${i}\`]>
|
|
393
|
+
<ActionMenuItem :label="text" href="https://example.com"></ActionMenuItem>
|
|
394
|
+
</template>
|
|
395
|
+
</ActionMenu>
|
|
396
|
+
</div>
|
|
397
|
+
|
|
398
|
+
<div style="display: flex; justify-content: space-between; align-items: center; gap: 1.6rem;">
|
|
399
|
+
<span>Twelve items</span>
|
|
400
|
+
<ActionMenu v-bind="componentArgs" :style="tokenStyle">
|
|
401
|
+
<template v-for="(text, i) in manyItems" :key="i" #[\`item-\${i}\`]>
|
|
402
|
+
<ActionMenuItem :label="text" @click="() => {}"></ActionMenuItem>
|
|
403
|
+
</template>
|
|
404
|
+
</ActionMenu>
|
|
405
|
+
</div>
|
|
406
|
+
|
|
407
|
+
<div style="display: flex; justify-content: space-between; align-items: center; gap: 1.6rem;">
|
|
408
|
+
<span>One item</span>
|
|
409
|
+
<ActionMenu v-bind="componentArgs" :style="tokenStyle">
|
|
410
|
+
<template #item-0><ActionMenuItem label="Only action" @click="() => {}"></ActionMenuItem></template>
|
|
411
|
+
</ActionMenu>
|
|
412
|
+
</div>
|
|
413
|
+
|
|
414
|
+
<div style="display: flex; justify-content: space-between; align-items: center; gap: 1.6rem;">
|
|
415
|
+
<span>No items (opens an empty panel, nothing focusable)</span>
|
|
416
|
+
<ActionMenu v-bind="componentArgs" :style="tokenStyle"></ActionMenu>
|
|
417
|
+
</div>
|
|
418
|
+
</div>
|
|
419
|
+
`,
|
|
420
|
+
}),
|
|
421
|
+
decorators: [
|
|
422
|
+
(story, context) => ({
|
|
423
|
+
components: { story, CanvasSwitcher },
|
|
424
|
+
setup() {
|
|
425
|
+
const canvasName = ref<MediaCanvas>(context.parameters.initialCanvas ?? "mobileCanvas");
|
|
426
|
+
return { canvasName };
|
|
427
|
+
},
|
|
428
|
+
template: `
|
|
429
|
+
<div style="padding: 1.2rem 1.6rem; border-block-end: 1px solid currentColor;">
|
|
430
|
+
<CanvasSwitcher v-model:canvas-name="canvasName" />
|
|
431
|
+
</div>
|
|
432
|
+
<div :class="canvasName" style="margin-inline: auto; outline: 1px dashed currentColor;">
|
|
433
|
+
<story />
|
|
434
|
+
</div>
|
|
435
|
+
`,
|
|
436
|
+
}),
|
|
437
|
+
],
|
|
438
|
+
parameters: {
|
|
439
|
+
initialCanvas: "mobileCanvas",
|
|
440
|
+
docs: {
|
|
441
|
+
story: { inline: false, height: "640px" },
|
|
442
|
+
description: {
|
|
443
|
+
story:
|
|
444
|
+
"Open each menu at every canvas width. Long unbroken words and URLs should wrap inside the menu, which never grows past " +
|
|
445
|
+
"`--action-menu-popover-max-width` (32rem, or the viewport less 3.2rem). The left-edge menu should flip to open rightwards " +
|
|
446
|
+
"rather than off-screen (CSS anchor positioning browsers). Emoji and HTML-like text render as text, the Arabic label wraps like the rest, " +
|
|
447
|
+
"twelve items stay keyboard-navigable, and the empty menu opens without errors. Try the line-clamp control to cap labels at 1 to 3 lines.",
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
},
|
|
451
|
+
};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="accordion-chat" :class="elementClasses">
|
|
3
|
+
<ExpandingPanelClassic
|
|
4
|
+
v-for="index in panelIndexes()"
|
|
5
|
+
:key="index"
|
|
6
|
+
:name
|
|
7
|
+
:animation-duration="animationDuration"
|
|
8
|
+
:style-class-passthrough="['accordion-chat-item']"
|
|
9
|
+
>
|
|
10
|
+
<template #summary>
|
|
11
|
+
<slot :name="`item-${index}-summary`"></slot>
|
|
12
|
+
</template>
|
|
13
|
+
<template #icon>
|
|
14
|
+
<slot :name="`item-${index}-icon`">
|
|
15
|
+
<span class="accordion-chat-icon" aria-hidden="true">
|
|
16
|
+
<Icon name="lucide:plus" class="accordion-chat-icon-glyph" />
|
|
17
|
+
</span>
|
|
18
|
+
</slot>
|
|
19
|
+
</template>
|
|
20
|
+
<template #content>
|
|
21
|
+
<div v-if="slots[`item-${index}-content`]" class="accordion-chat-answer">
|
|
22
|
+
<span v-if="hasAvatar(index)" class="accordion-chat-avatar" aria-hidden="true">
|
|
23
|
+
<slot :name="`item-${index}-avatar`">
|
|
24
|
+
<slot name="avatar">{{ avatarInitials }}</slot>
|
|
25
|
+
</slot>
|
|
26
|
+
</span>
|
|
27
|
+
<div class="accordion-chat-bubble">
|
|
28
|
+
<slot :name="`item-${index}-content`"></slot>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</template>
|
|
32
|
+
</ExpandingPanelClassic>
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script setup lang="ts">
|
|
37
|
+
import ExpandingPanelClassic from "../expanding-panel-classic/ExpandingPanelClassic.vue";
|
|
38
|
+
|
|
39
|
+
interface Props {
|
|
40
|
+
name?: string;
|
|
41
|
+
animationDuration?: number;
|
|
42
|
+
avatarLabel?: string;
|
|
43
|
+
showAvatar?: boolean;
|
|
44
|
+
styleClassPassthrough?: string | string[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
48
|
+
name: undefined,
|
|
49
|
+
animationDuration: 300,
|
|
50
|
+
avatarLabel: "",
|
|
51
|
+
showAvatar: true,
|
|
52
|
+
styleClassPassthrough: () => [],
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const slots = useSlots();
|
|
56
|
+
const SUMMARY_SLOT = /^item-(\d+)-summary$/;
|
|
57
|
+
|
|
58
|
+
const panelIndexes = () =>
|
|
59
|
+
Object.keys(slots)
|
|
60
|
+
.map((slotName) => SUMMARY_SLOT.exec(slotName)?.[1])
|
|
61
|
+
.filter((index): index is string => index !== undefined)
|
|
62
|
+
.map(Number)
|
|
63
|
+
.sort((a, b) => a - b);
|
|
64
|
+
|
|
65
|
+
const toGraphemes = (text: string) =>
|
|
66
|
+
typeof Intl.Segmenter === "function"
|
|
67
|
+
? Array.from(new Intl.Segmenter(undefined, { granularity: "grapheme" }).segment(text), ({ segment }) => segment)
|
|
68
|
+
: Array.from(text);
|
|
69
|
+
|
|
70
|
+
const avatarInitials = computed(() => toGraphemes(props.avatarLabel.trim()).slice(0, 2).join(""));
|
|
71
|
+
|
|
72
|
+
const hasAvatar = (index: number) =>
|
|
73
|
+
props.showAvatar && Boolean(slots[`item-${index}-avatar`] || slots.avatar || avatarInitials.value);
|
|
74
|
+
|
|
75
|
+
const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
|
|
76
|
+
|
|
77
|
+
watch(
|
|
78
|
+
() => props.styleClassPassthrough,
|
|
79
|
+
() => {
|
|
80
|
+
resetElementClasses(props.styleClassPassthrough);
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
</script>
|
|
84
|
+
|
|
85
|
+
<style lang="css">
|
|
86
|
+
@layer components {
|
|
87
|
+
.accordion-chat {
|
|
88
|
+
--_accordion-chat-radius: var(--accordion-chat-radius, 2rem);
|
|
89
|
+
--_accordion-chat-tail-radius: var(--accordion-chat-tail-radius, 0.6rem);
|
|
90
|
+
--_accordion-chat-bubble-max-width: var(--accordion-chat-bubble-max-width, 82%);
|
|
91
|
+
--_accordion-chat-duration: var(--accordion-chat-transition-duration, 200ms);
|
|
92
|
+
|
|
93
|
+
display: grid;
|
|
94
|
+
gap: var(--accordion-chat-gap, 1.4rem);
|
|
95
|
+
|
|
96
|
+
.accordion-chat-item.expanding-panel-classic {
|
|
97
|
+
--expanding-panel-classic-icon-size: var(--accordion-chat-icon-size, 2.2rem);
|
|
98
|
+
--expanding-panel-classic-summary-gap: var(--accordion-chat-question-icon-gap, 1.4rem);
|
|
99
|
+
|
|
100
|
+
.expanding-panel-classic-summary {
|
|
101
|
+
inline-size: fit-content;
|
|
102
|
+
max-inline-size: var(--_accordion-chat-bubble-max-width);
|
|
103
|
+
margin-inline-start: auto;
|
|
104
|
+
padding-block: var(--accordion-chat-question-padding-block, 1.3rem);
|
|
105
|
+
padding-inline: var(--accordion-chat-question-padding-inline, 2rem 1.8rem);
|
|
106
|
+
border: var(--accordion-chat-question-border-width, 0.1rem) solid
|
|
107
|
+
var(--accordion-chat-question-border, transparent);
|
|
108
|
+
border-radius: var(--_accordion-chat-radius);
|
|
109
|
+
border-end-end-radius: var(--_accordion-chat-tail-radius);
|
|
110
|
+
background-color: var(--accordion-chat-question-surface, var(--theme-surface-subtle));
|
|
111
|
+
color: var(--accordion-chat-question-colour, var(--theme-text));
|
|
112
|
+
font-family: var(--accordion-chat-question-font-family, inherit);
|
|
113
|
+
font-size: var(--accordion-chat-question-font-size, 1.6rem);
|
|
114
|
+
font-weight: var(--accordion-chat-question-font-weight, 600);
|
|
115
|
+
line-height: var(--accordion-chat-question-line-height, 1.3);
|
|
116
|
+
transition:
|
|
117
|
+
background-color var(--_accordion-chat-duration),
|
|
118
|
+
color var(--_accordion-chat-duration),
|
|
119
|
+
border-color var(--_accordion-chat-duration);
|
|
120
|
+
|
|
121
|
+
&:focus-visible {
|
|
122
|
+
outline: var(--accordion-chat-focus-ring-width, 0.2rem) solid
|
|
123
|
+
var(--accordion-chat-focus-ring-colour, var(--theme-border-focus));
|
|
124
|
+
outline-offset: 0.2rem;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.expanding-panel-classic-details[open] & {
|
|
128
|
+
border-color: var(--accordion-chat-question-border-open, var(--accordion-chat-question-border, transparent));
|
|
129
|
+
background-color: var(--accordion-chat-question-surface-open, var(--theme-surface-inverted));
|
|
130
|
+
color: var(--accordion-chat-question-colour-open, var(--theme-text-inverted));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.accordion-chat-icon {
|
|
134
|
+
display: grid;
|
|
135
|
+
place-items: center;
|
|
136
|
+
inline-size: 100%;
|
|
137
|
+
aspect-ratio: 1;
|
|
138
|
+
border-radius: 50%;
|
|
139
|
+
background-color: var(--accordion-chat-icon-surface, rgb(0 0 0 / 0.07));
|
|
140
|
+
|
|
141
|
+
.expanding-panel-classic-details[open] & {
|
|
142
|
+
background-color: var(--accordion-chat-icon-surface-open, rgb(255 255 255 / 0.16));
|
|
143
|
+
rotate: 45deg;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
147
|
+
transition:
|
|
148
|
+
background-color var(--_accordion-chat-duration),
|
|
149
|
+
rotate calc(var(--_accordion-chat-duration) * 1.25);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.accordion-chat-icon-glyph {
|
|
153
|
+
display: block;
|
|
154
|
+
font-size: var(--accordion-chat-icon-glyph-size, 1.4rem);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.accordion-chat-answer {
|
|
161
|
+
display: flex;
|
|
162
|
+
align-items: flex-end;
|
|
163
|
+
gap: var(--accordion-chat-avatar-gap, 1rem);
|
|
164
|
+
padding-block-start: var(--accordion-chat-answer-gap, 1rem);
|
|
165
|
+
|
|
166
|
+
.accordion-chat-avatar {
|
|
167
|
+
flex: none;
|
|
168
|
+
display: grid;
|
|
169
|
+
place-items: center;
|
|
170
|
+
inline-size: var(--accordion-chat-avatar-size, 3rem);
|
|
171
|
+
aspect-ratio: 1;
|
|
172
|
+
overflow: hidden;
|
|
173
|
+
border-radius: 50%;
|
|
174
|
+
background-color: var(--accordion-chat-avatar-surface, var(--theme-surface-inverted));
|
|
175
|
+
color: var(--accordion-chat-avatar-colour, var(--theme-text-inverted));
|
|
176
|
+
font-family: var(--accordion-chat-avatar-font-family, inherit);
|
|
177
|
+
font-size: var(--accordion-chat-avatar-font-size, 1.2rem);
|
|
178
|
+
font-weight: var(--accordion-chat-avatar-font-weight, 600);
|
|
179
|
+
line-height: 1;
|
|
180
|
+
white-space: nowrap;
|
|
181
|
+
|
|
182
|
+
& :where(img, svg) {
|
|
183
|
+
inline-size: 100%;
|
|
184
|
+
block-size: 100%;
|
|
185
|
+
object-fit: cover;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.accordion-chat-bubble {
|
|
190
|
+
min-inline-size: 0;
|
|
191
|
+
max-inline-size: var(--_accordion-chat-bubble-max-width);
|
|
192
|
+
padding-block: var(--accordion-chat-answer-padding-block, 1.4rem);
|
|
193
|
+
padding-inline: var(--accordion-chat-answer-padding-inline, 1.8rem);
|
|
194
|
+
border: var(--accordion-chat-answer-border-width, 0.1rem) solid
|
|
195
|
+
var(--accordion-chat-answer-border, var(--theme-surface-subtle));
|
|
196
|
+
border-radius: var(--_accordion-chat-radius);
|
|
197
|
+
border-end-start-radius: var(--_accordion-chat-tail-radius);
|
|
198
|
+
background-color: var(--accordion-chat-answer-surface, var(--theme-text-inverted));
|
|
199
|
+
color: var(--accordion-chat-answer-colour, var(--theme-text));
|
|
200
|
+
font-family: var(--accordion-chat-answer-font-family, inherit);
|
|
201
|
+
font-size: var(--accordion-chat-answer-font-size, 1.55rem);
|
|
202
|
+
font-weight: var(--accordion-chat-answer-font-weight, 400);
|
|
203
|
+
line-height: var(--accordion-chat-answer-line-height, 1.6);
|
|
204
|
+
|
|
205
|
+
& :where(img, video) {
|
|
206
|
+
max-inline-size: 100%;
|
|
207
|
+
block-size: auto;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
211
|
+
.expanding-panel-classic-details[open] + .expanding-panel-classic-content & {
|
|
212
|
+
animation: accordion-chat-answer-in var(--accordion-chat-entrance-duration, 260ms) ease-out both;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
@keyframes accordion-chat-answer-in {
|
|
220
|
+
from {
|
|
221
|
+
opacity: 0;
|
|
222
|
+
translate: 0 0.6rem;
|
|
223
|
+
scale: 0.98;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
</style>
|