srcdev-nuxt-components 9.6.19 → 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/ids-from-useid.md +3 -2
- package/.claude/skills/component-compliance-checklist.md +5 -0
- 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/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/index.md +12 -12
- package/.claude/skills/storybook-add-story.md +25 -0
- package/.claude/skills/testing-add-unit-test.md +26 -0
- 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/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/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/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/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/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
package/app/components/02.molecules/navigation/deep-expanding-menu/tests/DeepExpandingMenu.spec.ts
CHANGED
|
@@ -17,49 +17,62 @@ const defaultNavLinks: ResponsiveHeaderNavItem[] = [
|
|
|
17
17
|
{ name: "Contact", path: "/contact" },
|
|
18
18
|
];
|
|
19
19
|
|
|
20
|
+
const mounted: Awaited<ReturnType<typeof mountSuspended>>[] = [];
|
|
21
|
+
|
|
22
|
+
const mountMenu = async (options: { props?: Record<string, unknown>; attachTo?: HTMLElement } = {}) => {
|
|
23
|
+
const wrapper = await mountSuspended(DeepExpandingMenu, options);
|
|
24
|
+
mounted.push(wrapper);
|
|
25
|
+
return wrapper;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
mounted.splice(0).forEach((wrapper) => wrapper.unmount());
|
|
30
|
+
vi.restoreAllMocks();
|
|
31
|
+
});
|
|
32
|
+
|
|
20
33
|
describe("DeepExpandingMenu", () => {
|
|
21
34
|
it("mounts without error", async () => {
|
|
22
|
-
const wrapper = await
|
|
35
|
+
const wrapper = await mountMenu({ props: { navLinks: defaultNavLinks } });
|
|
23
36
|
expect(wrapper.vm).toBeTruthy();
|
|
24
37
|
});
|
|
25
38
|
|
|
26
39
|
it("renders correct HTML structure", async () => {
|
|
27
|
-
const wrapper = await
|
|
40
|
+
const wrapper = await mountMenu({ props: { navLinks: defaultNavLinks } });
|
|
28
41
|
expect(wrapper.html()).toMatchSnapshot();
|
|
29
42
|
});
|
|
30
43
|
|
|
31
44
|
it("renders a <nav> by default", async () => {
|
|
32
|
-
const wrapper = await
|
|
45
|
+
const wrapper = await mountMenu({ props: { navLinks: defaultNavLinks } });
|
|
33
46
|
expect(wrapper.element.tagName.toLowerCase()).toBe("nav");
|
|
34
47
|
});
|
|
35
48
|
|
|
36
49
|
it("renders the given tag", async () => {
|
|
37
|
-
const wrapper = await
|
|
50
|
+
const wrapper = await mountMenu({
|
|
38
51
|
props: { navLinks: defaultNavLinks, tag: "div" },
|
|
39
52
|
});
|
|
40
53
|
expect(wrapper.element.tagName.toLowerCase()).toBe("div");
|
|
41
54
|
});
|
|
42
55
|
|
|
43
56
|
it("renders a direct link for items with a path", async () => {
|
|
44
|
-
const wrapper = await
|
|
45
|
-
const links = wrapper.findAll(".
|
|
57
|
+
const wrapper = await mountMenu({ props: { navLinks: defaultNavLinks } });
|
|
58
|
+
const links = wrapper.findAll(".deep-expanding-menu-link");
|
|
46
59
|
expect(links.map((l) => l.text())).toEqual(["Home", "Contact"]);
|
|
47
60
|
});
|
|
48
61
|
|
|
49
62
|
it("renders a toggle group for items with childLinks", async () => {
|
|
50
|
-
const wrapper = await
|
|
51
|
-
expect(wrapper.find(".
|
|
63
|
+
const wrapper = await mountMenu({ props: { navLinks: defaultNavLinks } });
|
|
64
|
+
expect(wrapper.find(".deep-expanding-menu-group-toggle").text()).toContain("Services");
|
|
52
65
|
});
|
|
53
66
|
|
|
54
67
|
it("renders each child link inside the group panel", async () => {
|
|
55
|
-
const wrapper = await
|
|
56
|
-
const childLinks = wrapper.findAll(".
|
|
68
|
+
const wrapper = await mountMenu({ props: { navLinks: defaultNavLinks } });
|
|
69
|
+
const childLinks = wrapper.findAll(".deep-expanding-menu-group-link");
|
|
57
70
|
expect(childLinks.map((l) => l.text())).toEqual(["Haircuts", "Colouring"]);
|
|
58
71
|
});
|
|
59
72
|
|
|
60
73
|
it("renders the childLinksTitle heading", async () => {
|
|
61
|
-
const wrapper = await
|
|
62
|
-
expect(wrapper.find(".
|
|
74
|
+
const wrapper = await mountMenu({ props: { navLinks: defaultNavLinks } });
|
|
75
|
+
expect(wrapper.find(".deep-expanding-menu-group-heading").text()).toBe("Our services");
|
|
63
76
|
});
|
|
64
77
|
|
|
65
78
|
it("gives each group toggle a unique popovertarget", async () => {
|
|
@@ -67,21 +80,21 @@ describe("DeepExpandingMenu", () => {
|
|
|
67
80
|
{ name: "A", childLinksTitle: "A", childLinks: [{ name: "A1", path: "/a1" }] },
|
|
68
81
|
{ name: "B", childLinksTitle: "B", childLinks: [{ name: "B1", path: "/b1" }] },
|
|
69
82
|
];
|
|
70
|
-
const wrapper = await
|
|
71
|
-
const toggles = wrapper.findAll(".
|
|
83
|
+
const wrapper = await mountMenu({ props: { navLinks } });
|
|
84
|
+
const toggles = wrapper.findAll(".deep-expanding-menu-group-toggle");
|
|
72
85
|
const targets = toggles.map((t) => t.attributes("popovertarget"));
|
|
73
86
|
expect(new Set(targets).size).toBe(2);
|
|
74
87
|
});
|
|
75
88
|
|
|
76
89
|
it("applies styleClassPassthrough classes", async () => {
|
|
77
|
-
const wrapper = await
|
|
90
|
+
const wrapper = await mountMenu({
|
|
78
91
|
props: { navLinks: defaultNavLinks, styleClassPassthrough: ["custom-class"] },
|
|
79
92
|
});
|
|
80
93
|
expect(wrapper.classes()).toContain("custom-class");
|
|
81
94
|
});
|
|
82
95
|
|
|
83
96
|
it("resets classes when styleClassPassthrough prop changes", async () => {
|
|
84
|
-
const wrapper = await
|
|
97
|
+
const wrapper = await mountMenu({
|
|
85
98
|
props: { navLinks: defaultNavLinks, styleClassPassthrough: ["initial-class"] },
|
|
86
99
|
});
|
|
87
100
|
expect(wrapper.classes()).toContain("initial-class");
|
|
@@ -91,9 +104,60 @@ describe("DeepExpandingMenu", () => {
|
|
|
91
104
|
expect(wrapper.classes()).toContain("updated-class");
|
|
92
105
|
});
|
|
93
106
|
|
|
107
|
+
it("labels the root when ariaLabel is set, and leaves it unlabelled otherwise", async () => {
|
|
108
|
+
const unlabelled = await mountMenu({ props: { navLinks: defaultNavLinks } });
|
|
109
|
+
expect(unlabelled.attributes("aria-label")).toBeUndefined();
|
|
110
|
+
|
|
111
|
+
const labelled = await mountMenu({
|
|
112
|
+
props: { navLinks: defaultNavLinks, ariaLabel: "Main" },
|
|
113
|
+
});
|
|
114
|
+
expect(labelled.attributes("aria-label")).toBe("Main");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("gives the child link list a list role", async () => {
|
|
118
|
+
const wrapper = await mountMenu({ props: { navLinks: defaultNavLinks } });
|
|
119
|
+
expect(wrapper.find(".deep-expanding-menu-group-list").attributes("role")).toBe("list");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("omits the heading when childLinksTitle is missing or empty", async () => {
|
|
123
|
+
const navLinks: ResponsiveHeaderNavItem[] = [
|
|
124
|
+
{ name: "A", childLinks: [{ name: "A1", path: "/a1" }] },
|
|
125
|
+
{ name: "B", childLinksTitle: "", childLinks: [{ name: "B1", path: "/b1" }] },
|
|
126
|
+
];
|
|
127
|
+
const wrapper = await mountMenu({ props: { navLinks } });
|
|
128
|
+
expect(wrapper.find(".deep-expanding-menu-group-heading").exists()).toBe(false);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("omits the list when a group has no child links", async () => {
|
|
132
|
+
const navLinks: ResponsiveHeaderNavItem[] = [{ name: "Empty", childLinksTitle: "Empty", childLinks: [] }];
|
|
133
|
+
const wrapper = await mountMenu({ props: { navLinks } });
|
|
134
|
+
expect(wrapper.find(".deep-expanding-menu-group-list").exists()).toBe(false);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("keeps child links with duplicate names in step when the list is reordered", async () => {
|
|
138
|
+
const childLinks = [
|
|
139
|
+
{ name: "Same", path: "/one" },
|
|
140
|
+
{ name: "Same", path: "/two" },
|
|
141
|
+
{ name: "Other", path: "/three" },
|
|
142
|
+
];
|
|
143
|
+
const wrapper = await mountMenu({
|
|
144
|
+
props: { navLinks: [{ name: "Group", childLinksTitle: "Group", childLinks }] },
|
|
145
|
+
});
|
|
146
|
+
await wrapper.setProps({
|
|
147
|
+
navLinks: [{ name: "Group", childLinksTitle: "Group", childLinks: [childLinks[2]!, childLinks[0]!] }],
|
|
148
|
+
});
|
|
149
|
+
const links = wrapper.findAll(".deep-expanding-menu-group-link");
|
|
150
|
+
expect(links.map((l) => l.attributes("href"))).toEqual(["/three", "/one"]);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("hides the caret icon from assistive technology", async () => {
|
|
154
|
+
const wrapper = await mountMenu({ props: { navLinks: defaultNavLinks } });
|
|
155
|
+
expect(wrapper.find(".deep-expanding-menu-group-icon").attributes("aria-hidden")).toBe("true");
|
|
156
|
+
});
|
|
157
|
+
|
|
94
158
|
it("doesn't give the link panels a menu role", async () => {
|
|
95
|
-
const wrapper = await
|
|
96
|
-
expect(wrapper.find(".
|
|
159
|
+
const wrapper = await mountMenu({ props: { navLinks: defaultNavLinks } });
|
|
160
|
+
expect(wrapper.find(".deep-expanding-menu-group-panel").attributes("role")).toBeUndefined();
|
|
97
161
|
});
|
|
98
162
|
|
|
99
163
|
describe("open state", () => {
|
|
@@ -116,9 +180,9 @@ describe("DeepExpandingMenu", () => {
|
|
|
116
180
|
});
|
|
117
181
|
|
|
118
182
|
it("tracks the open group from toggle events, whichever order they arrive in", async () => {
|
|
119
|
-
const wrapper = await
|
|
120
|
-
const [first, second] = wrapper.findAll(".
|
|
121
|
-
const toggles = wrapper.findAll(".
|
|
183
|
+
const wrapper = await mountMenu({ props: { navLinks: twoGroups } });
|
|
184
|
+
const [first, second] = wrapper.findAll(".deep-expanding-menu-group-panel");
|
|
185
|
+
const toggles = wrapper.findAll(".deep-expanding-menu-group-toggle");
|
|
122
186
|
|
|
123
187
|
first!.element.dispatchEvent(toggleEvent("open"));
|
|
124
188
|
await nextTick();
|
|
@@ -142,9 +206,9 @@ describe("DeepExpandingMenu", () => {
|
|
|
142
206
|
});
|
|
143
207
|
|
|
144
208
|
it("opens, switches and closes groups from their toggles", async () => {
|
|
145
|
-
const wrapper = await
|
|
146
|
-
const toggles = wrapper.findAll(".
|
|
147
|
-
const panels = wrapper.findAll(".
|
|
209
|
+
const wrapper = await mountMenu({ props: { navLinks: twoGroups } });
|
|
210
|
+
const toggles = wrapper.findAll(".deep-expanding-menu-group-toggle");
|
|
211
|
+
const panels = wrapper.findAll(".deep-expanding-menu-group-panel");
|
|
148
212
|
|
|
149
213
|
await toggles[0]!.trigger("click");
|
|
150
214
|
expect(panels[0]!.classes()).toContain("deep-expanding-menu-panel-open");
|
|
@@ -160,14 +224,13 @@ describe("DeepExpandingMenu", () => {
|
|
|
160
224
|
});
|
|
161
225
|
|
|
162
226
|
it("closes the open group on Escape", async () => {
|
|
163
|
-
const wrapper = await
|
|
164
|
-
await wrapper.findAll(".
|
|
227
|
+
const wrapper = await mountMenu({ props: { navLinks: twoGroups }, attachTo: document.body });
|
|
228
|
+
await wrapper.findAll(".deep-expanding-menu-group-toggle")[0]!.trigger("click");
|
|
165
229
|
await nextTick();
|
|
166
230
|
|
|
167
231
|
document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape" }));
|
|
168
232
|
await nextTick();
|
|
169
233
|
expect(wrapper.find(".deep-expanding-menu-panel-open").exists()).toBe(false);
|
|
170
|
-
wrapper.unmount();
|
|
171
234
|
});
|
|
172
235
|
});
|
|
173
236
|
});
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`DeepExpandingMenu > renders correct HTML structure 1`] = `
|
|
4
4
|
"<nav class="deep-expanding-menu">
|
|
5
|
-
<div class="inner"><a href="/" class="
|
|
6
|
-
<div class="
|
|
7
|
-
<div id="popovertarget-v-0-0-1" class="
|
|
8
|
-
<h4 class="page-heading-4 mb-6">Our services</h4>
|
|
9
|
-
<ul class="
|
|
10
|
-
<li class="
|
|
11
|
-
<li class="
|
|
5
|
+
<div class="deep-expanding-menu-inner"><a href="/" class="deep-expanding-menu-link">Home</a>
|
|
6
|
+
<div class="deep-expanding-menu-group" style="--_anchor-name: --anchor-v-0-0-1;"><button type="button" popovertarget="popovertarget-v-0-0-1" class="deep-expanding-menu-group-toggle" aria-expanded="false"><span class="deep-expanding-menu-group-label">Services</span><span class="iconify i-bi:caret-down-fill deep-expanding-menu-group-icon" aria-hidden="true"></span></button>
|
|
7
|
+
<div id="popovertarget-v-0-0-1" class="deep-expanding-menu-group-panel" popover="">
|
|
8
|
+
<h4 class="deep-expanding-menu-group-heading page-heading-4 mb-6">Our services</h4>
|
|
9
|
+
<ul class="deep-expanding-menu-group-list" role="list">
|
|
10
|
+
<li class="deep-expanding-menu-group-item"><a href="/services/haircuts" class="deep-expanding-menu-group-link">Haircuts</a></li>
|
|
11
|
+
<li class="deep-expanding-menu-group-item"><a href="/services/colouring" class="deep-expanding-menu-group-link">Colouring</a></li>
|
|
12
12
|
</ul>
|
|
13
13
|
</div>
|
|
14
|
-
</div><a href="/contact" class="
|
|
14
|
+
</div><a href="/contact" class="deep-expanding-menu-link">Contact</a>
|
|
15
15
|
</div>
|
|
16
16
|
</nav>"
|
|
17
17
|
`;
|
package/app/components/02.molecules/navigation/deep-expanding-menu-classic/CONSUMER-STYLING.md
CHANGED
|
@@ -2,44 +2,72 @@
|
|
|
2
2
|
|
|
3
3
|
## Public token API
|
|
4
4
|
|
|
5
|
+
> Changed 2026-10-21: colour defaults now come from `--theme-*` tokens (were `--blue-10`, `white`,
|
|
6
|
+
> `black`, `--slate-10`), `--deep-expanding-menu-classic-panel-offset-top` defaults to
|
|
7
|
+
> `calc(100% + 1rem)` (was `4rem`, which overlapped a wrapped toggle label), the panel widths switch
|
|
8
|
+
> on the menu's own width instead of the viewport, and `--deep-expanding-menu-classic-gap` was
|
|
9
|
+
> removed (the root grid has one area, so it never did anything).
|
|
10
|
+
|
|
11
|
+
### Top-level row
|
|
12
|
+
|
|
5
13
|
| Token | Default | Controls |
|
|
6
14
|
|---|---|---|
|
|
7
|
-
| `--deep-expanding-menu-classic-gap` | `
|
|
8
|
-
| `--deep-expanding-menu-classic-
|
|
9
|
-
| `--deep-expanding-menu-classic-link-border-width` | `0.2rem` | Bottom border width on links and group toggles |
|
|
15
|
+
| `--deep-expanding-menu-classic-item-gap` | `2.4rem` | Gap between top-level items (row and column, the row wraps) |
|
|
16
|
+
| `--deep-expanding-menu-classic-link-border-width` | `0.2rem` | Bottom border width on links, group toggles and child links |
|
|
10
17
|
| `--deep-expanding-menu-classic-link-padding-block` | `0.8rem` | Vertical padding on links and group toggles |
|
|
11
|
-
| `--deep-expanding-menu-classic-link-border-colour-hover` | `var(--
|
|
18
|
+
| `--deep-expanding-menu-classic-link-border-colour-hover` | `var(--theme-border)` | Bottom border colour on hover/focus |
|
|
19
|
+
| `--deep-expanding-menu-classic-focus-outline-width` | `0.2rem` | Keyboard focus ring width on links and toggles |
|
|
20
|
+
| `--deep-expanding-menu-classic-focus-outline-colour` | `var(--theme-ring, currentcolor)` | Keyboard focus ring colour |
|
|
12
21
|
| `--deep-expanding-menu-classic-icon-size` | `1.2rem` | Caret icon size |
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
|
17
|
-
|
|
22
|
+
|
|
23
|
+
### Panel
|
|
24
|
+
|
|
25
|
+
| Token | Default | Controls |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| `--deep-expanding-menu-classic-panel-offset-top` | `calc(100% + 1rem)` | Panel offset from the top of its group |
|
|
28
|
+
| `--deep-expanding-menu-classic-panel-width` | `20rem` | Panel width while the menu is under `768px` wide |
|
|
29
|
+
| `--deep-expanding-menu-classic-panel-width-tablet` | `40rem` | Panel width once the menu is `768px` wide |
|
|
30
|
+
| `--deep-expanding-menu-classic-panel-width-desktop` | `60rem` | Panel width once the menu is `1024px` wide |
|
|
31
|
+
| `--deep-expanding-menu-classic-panel-text-colour` | `var(--theme-text)` | Panel text colour |
|
|
32
|
+
| `--deep-expanding-menu-classic-panel-background-colour` | `var(--theme-surface-subtle)` | Panel background |
|
|
18
33
|
| `--deep-expanding-menu-classic-panel-border-width` | `0.1rem` | Panel border width |
|
|
19
|
-
| `--deep-expanding-menu-classic-panel-border-colour` | `
|
|
34
|
+
| `--deep-expanding-menu-classic-panel-border-colour` | `var(--theme-border)` | Panel border colour |
|
|
20
35
|
| `--deep-expanding-menu-classic-panel-border-radius` | `1.2rem` | Panel corner radius |
|
|
21
36
|
| `--deep-expanding-menu-classic-panel-shadow` | `0 0 1rem rgba(0, 0, 0, 0.1)` | Panel box-shadow |
|
|
22
37
|
| `--deep-expanding-menu-classic-panel-padding` | `1.2rem` | Panel padding |
|
|
23
|
-
| `--deep-expanding-menu-classic-panel-heading-colour` | `var(--
|
|
24
|
-
| `--deep-expanding-menu-classic-panel-
|
|
25
|
-
| `--deep-expanding-menu-classic-
|
|
26
|
-
| `--deep-expanding-menu-classic-group-link-
|
|
38
|
+
| `--deep-expanding-menu-classic-panel-heading-colour` | `var(--theme-text)` | `childLinksTitle` heading colour |
|
|
39
|
+
| `--deep-expanding-menu-classic-panel-heading-line-clamp` | `none` | Lines of `childLinksTitle` before an ellipsis. `1` is single-line ellipsis, `none` shows everything |
|
|
40
|
+
| `--deep-expanding-menu-classic-panel-list-gap` | `1.2rem` | Gap between the panel's heading and list, and between child link grid items |
|
|
41
|
+
| `--deep-expanding-menu-classic-group-link-colour` | `var(--theme-text)` | Child link text colour |
|
|
42
|
+
| `--deep-expanding-menu-classic-group-link-border-colour-hover` | `var(--theme-text)` | Child link bottom border colour on hover/focus |
|
|
43
|
+
|
|
44
|
+
Each panel width is capped at the menu's own width (`min(<token>, 100cqi)`). Private tokens (not
|
|
45
|
+
public API): `--_icon-transform` (caret flip).
|
|
46
|
+
|
|
47
|
+
## State hooks
|
|
27
48
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
--deep-expanding-menu-classic-panel-border-colour: transparent;
|
|
32
|
-
--deep-expanding-menu-classic-group-link-colour: white;
|
|
33
|
-
}
|
|
34
|
-
```
|
|
49
|
+
| Hook | Meaning |
|
|
50
|
+
|---|---|
|
|
51
|
+
| `.deep-expanding-menu-classic-group[open]` | Group open (flips the caret) |
|
|
35
52
|
|
|
36
|
-
|
|
53
|
+
Inner elements: `.deep-expanding-menu-classic-inner` (the flex row),
|
|
54
|
+
`.deep-expanding-menu-classic-link` (direct link), `.deep-expanding-menu-classic-group` (the
|
|
55
|
+
`<details>`), `.deep-expanding-menu-classic-group-toggle` (the `<summary>`),
|
|
56
|
+
`.deep-expanding-menu-classic-group-label`, `.deep-expanding-menu-classic-group-icon`,
|
|
57
|
+
`.deep-expanding-menu-classic-group-panel`, `.deep-expanding-menu-classic-group-heading`,
|
|
58
|
+
`.deep-expanding-menu-classic-group-list`, `.deep-expanding-menu-classic-group-item`,
|
|
59
|
+
`.deep-expanding-menu-classic-group-link`.
|
|
37
60
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
61
|
+
> Changed 2026-10-21: these were `.inner`, `.navigation-link`, `.navigation-group`,
|
|
62
|
+
> `.navigation-group-toggle`, `.icon`, `.navigation-group-panel`, `.navigation-group-list`,
|
|
63
|
+
> `.navigation-group-item` and `.navigation-group-link`. The heading had no class of its own.
|
|
41
64
|
|
|
42
|
-
|
|
65
|
+
## Sizing model
|
|
66
|
+
|
|
67
|
+
The root is an inline-size container named `deep-expanding-menu-classic`, so it can't size itself
|
|
68
|
+
from its content: give it a width from its parent (it fills a block or grid cell by default). A
|
|
69
|
+
panel opens from its toggle's left edge, so a group near the menu's right edge can still overrun it
|
|
70
|
+
by up to the panel's width; `DeepExpandingMenu` flips its panel instead.
|
|
43
71
|
|
|
44
72
|
## Local overrides
|
|
45
73
|
|
|
@@ -49,3 +77,7 @@ Set the tokens above on an element you own (a page or section class, or a class
|
|
|
49
77
|
`<style scoped>`, tokens set on your element still work, but selectors that reach inside the component need
|
|
50
78
|
`:deep()`. Patterns and examples: `.claude/skills/component-local-style-override.md`.
|
|
51
79
|
|
|
80
|
+
## Class passthrough
|
|
81
|
+
|
|
82
|
+
`style-class-passthrough` adds classes to the root element (the `<nav>` by default). It's the
|
|
83
|
+
usual place to scope token overrides to one instance.
|
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<component
|
|
3
|
-
|
|
2
|
+
<component
|
|
3
|
+
:is="tag"
|
|
4
|
+
ref="rootRef"
|
|
5
|
+
class="deep-expanding-menu-classic"
|
|
6
|
+
:class="[elementClasses]"
|
|
7
|
+
:aria-label="ariaLabel"
|
|
8
|
+
@click="closeOtherGroups"
|
|
9
|
+
@keydown.esc="closeOnEscape"
|
|
10
|
+
>
|
|
11
|
+
<div class="deep-expanding-menu-classic-inner">
|
|
4
12
|
<template v-for="(link, key) in navLinks" :key="key">
|
|
5
|
-
<NuxtLink v-if="link.path" :to="link.path" class="
|
|
6
|
-
<details v-else
|
|
7
|
-
<summary class="
|
|
8
|
-
<span>{{ link.name }}</span>
|
|
9
|
-
<Icon name="bi:caret-down-fill" class="icon" />
|
|
13
|
+
<NuxtLink v-if="link.path" :to="link.path" class="deep-expanding-menu-classic-link">{{ link.name }}</NuxtLink>
|
|
14
|
+
<details v-else class="deep-expanding-menu-classic-group" :name="groupName">
|
|
15
|
+
<summary class="deep-expanding-menu-classic-group-toggle">
|
|
16
|
+
<span class="deep-expanding-menu-classic-group-label">{{ link.name }}</span>
|
|
17
|
+
<Icon name="bi:caret-down-fill" class="deep-expanding-menu-classic-group-icon" aria-hidden="true" />
|
|
10
18
|
</summary>
|
|
11
|
-
<div class="
|
|
12
|
-
<h4 class="page-heading-4 mb-6">
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
<div class="deep-expanding-menu-classic-group-panel">
|
|
20
|
+
<h4 v-if="link.childLinksTitle" class="deep-expanding-menu-classic-group-heading page-heading-4 mb-6">
|
|
21
|
+
{{ link.childLinksTitle }}
|
|
22
|
+
</h4>
|
|
23
|
+
<ul v-if="link.childLinks?.length" class="deep-expanding-menu-classic-group-list" role="list">
|
|
24
|
+
<li
|
|
25
|
+
v-for="(childLink, childIndex) in link.childLinks"
|
|
26
|
+
:key="`${childIndex}-${childLink.name}`"
|
|
27
|
+
class="deep-expanding-menu-classic-group-item"
|
|
28
|
+
>
|
|
29
|
+
<NuxtLink :to="childLink.path" class="deep-expanding-menu-classic-group-link">
|
|
30
|
+
{{ childLink.name }}
|
|
31
|
+
</NuxtLink>
|
|
16
32
|
</li>
|
|
17
33
|
</ul>
|
|
18
34
|
</div>
|
|
@@ -27,20 +43,48 @@ import { onClickOutside } from "@vueuse/core";
|
|
|
27
43
|
import type { ResponsiveHeaderNavItem } from "~/types/components";
|
|
28
44
|
|
|
29
45
|
interface Props {
|
|
30
|
-
tag?: "div" | "section" | "nav"
|
|
46
|
+
tag?: "div" | "section" | "nav";
|
|
31
47
|
navLinks?: ResponsiveHeaderNavItem[];
|
|
48
|
+
ariaLabel?: string;
|
|
32
49
|
styleClassPassthrough?: string | string[];
|
|
33
50
|
}
|
|
34
51
|
|
|
35
52
|
const props = withDefaults(defineProps<Props>(), {
|
|
36
53
|
tag: "nav",
|
|
37
54
|
navLinks: () => [],
|
|
55
|
+
ariaLabel: undefined,
|
|
38
56
|
styleClassPassthrough: () => [],
|
|
39
57
|
});
|
|
40
58
|
|
|
41
59
|
const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
|
|
42
60
|
|
|
43
|
-
|
|
61
|
+
// Per-instance so groups are exclusive within one menu but not across menus.
|
|
62
|
+
const groupName = `deep-expanding-menu-classic-${useId()}`;
|
|
63
|
+
|
|
64
|
+
const rootRef = ref<HTMLElement | null>(null);
|
|
65
|
+
|
|
66
|
+
const openGroups = () =>
|
|
67
|
+
Array.from(rootRef.value?.querySelectorAll<HTMLDetailsElement>("details[open]") ?? []);
|
|
68
|
+
|
|
69
|
+
const closeOtherGroups = (event: Event) => {
|
|
70
|
+
const target = event.target as Element | null;
|
|
71
|
+
const followedLink = !!target?.closest?.("a");
|
|
72
|
+
openGroups().forEach((group) => {
|
|
73
|
+
if (followedLink || !target || !group.contains(target)) group.open = false;
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const closeOnEscape = (event: KeyboardEvent) => {
|
|
78
|
+
const target = event.target as Node | null;
|
|
79
|
+
const group = openGroups().find((details) => target && details.contains(target));
|
|
80
|
+
if (!group) return;
|
|
81
|
+
group.open = false;
|
|
82
|
+
group.querySelector<HTMLElement>("summary")?.focus();
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
onClickOutside(rootRef, () => {
|
|
86
|
+
openGroups().forEach((group) => (group.open = false));
|
|
87
|
+
});
|
|
44
88
|
|
|
45
89
|
watch(
|
|
46
90
|
() => props.styleClassPassthrough,
|
|
@@ -48,36 +92,31 @@ watch(
|
|
|
48
92
|
resetElementClasses(props.styleClassPassthrough);
|
|
49
93
|
}
|
|
50
94
|
);
|
|
51
|
-
|
|
52
|
-
onMounted(() => {
|
|
53
|
-
navigationGroupRef.value?.forEach((element, index) => {
|
|
54
|
-
onClickOutside(element, () => {
|
|
55
|
-
navigationGroupRef.value?.[index]?.removeAttribute("open");
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
95
|
</script>
|
|
60
96
|
|
|
61
97
|
<style lang="css">
|
|
62
98
|
@layer components {
|
|
63
99
|
@layer popover-setup {
|
|
64
100
|
.deep-expanding-menu-classic {
|
|
65
|
-
container
|
|
101
|
+
container: deep-expanding-menu-classic / inline-size;
|
|
66
102
|
display: grid;
|
|
67
103
|
grid-template-areas: "element-stack";
|
|
68
104
|
align-items: center;
|
|
69
|
-
gap: var(--deep-expanding-menu-classic-gap, 1.2rem);
|
|
70
105
|
|
|
71
|
-
.inner {
|
|
106
|
+
.deep-expanding-menu-classic-inner {
|
|
72
107
|
grid-area: element-stack;
|
|
73
108
|
display: flex;
|
|
109
|
+
flex-wrap: wrap;
|
|
74
110
|
gap: var(--deep-expanding-menu-classic-item-gap, 2.4rem);
|
|
75
111
|
align-items: center;
|
|
112
|
+
min-inline-size: 0;
|
|
76
113
|
z-index: 1;
|
|
77
114
|
|
|
78
|
-
.
|
|
79
|
-
.
|
|
115
|
+
.deep-expanding-menu-classic-link,
|
|
116
|
+
.deep-expanding-menu-classic-group-toggle {
|
|
80
117
|
all: unset;
|
|
118
|
+
min-inline-size: 0;
|
|
119
|
+
overflow-wrap: anywhere;
|
|
81
120
|
border-bottom: var(--deep-expanding-menu-classic-link-border-width, 0.2rem) solid transparent;
|
|
82
121
|
padding-block: var(--deep-expanding-menu-classic-link-padding-block, 0.8rem);
|
|
83
122
|
|
|
@@ -87,18 +126,22 @@ onMounted(() => {
|
|
|
87
126
|
&:focus,
|
|
88
127
|
&:focus-visible {
|
|
89
128
|
cursor: pointer;
|
|
90
|
-
border-color: var(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
129
|
+
border-color: var(--deep-expanding-menu-classic-link-border-colour-hover, var(--theme-border));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
&:focus-visible {
|
|
133
|
+
outline: var(--deep-expanding-menu-classic-focus-outline-width, 0.2rem) solid
|
|
134
|
+
var(--deep-expanding-menu-classic-focus-outline-colour, var(--theme-ring, currentcolor));
|
|
135
|
+
outline-offset: 0.2rem;
|
|
94
136
|
}
|
|
95
137
|
}
|
|
96
138
|
|
|
97
|
-
.
|
|
139
|
+
.deep-expanding-menu-classic-group {
|
|
98
140
|
--_icon-transform: scaleY(1);
|
|
99
141
|
|
|
100
142
|
display: grid;
|
|
101
143
|
grid-template-areas: "details-stack";
|
|
144
|
+
min-inline-size: 0;
|
|
102
145
|
z-index: 1;
|
|
103
146
|
position: relative;
|
|
104
147
|
|
|
@@ -111,16 +154,21 @@ onMounted(() => {
|
|
|
111
154
|
--_icon-transform: scaleY(-1);
|
|
112
155
|
}
|
|
113
156
|
|
|
114
|
-
.
|
|
157
|
+
.deep-expanding-menu-classic-group-toggle {
|
|
115
158
|
grid-area: details-stack;
|
|
116
159
|
|
|
117
|
-
display: flex
|
|
160
|
+
display: flex;
|
|
118
161
|
align-items: center;
|
|
119
162
|
gap: 1.2rem;
|
|
120
163
|
list-style: none;
|
|
121
164
|
|
|
122
|
-
.
|
|
165
|
+
.deep-expanding-menu-classic-group-label {
|
|
166
|
+
min-inline-size: 0;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.deep-expanding-menu-classic-group-icon {
|
|
123
170
|
display: block;
|
|
171
|
+
flex-shrink: 0;
|
|
124
172
|
font-size: var(--deep-expanding-menu-classic-icon-size, 1.2rem);
|
|
125
173
|
|
|
126
174
|
transform: var(--_icon-transform);
|
|
@@ -128,51 +176,62 @@ onMounted(() => {
|
|
|
128
176
|
}
|
|
129
177
|
}
|
|
130
178
|
|
|
131
|
-
.
|
|
179
|
+
.deep-expanding-menu-classic-group-panel {
|
|
132
180
|
display: grid;
|
|
133
181
|
grid-area: details-stack;
|
|
134
182
|
z-index: 2;
|
|
135
183
|
position: absolute;
|
|
136
184
|
inset: auto;
|
|
137
|
-
top: var(--deep-expanding-menu-classic-panel-offset-top,
|
|
138
|
-
left:
|
|
185
|
+
top: var(--deep-expanding-menu-classic-panel-offset-top, calc(100% + 1rem));
|
|
186
|
+
left: 0;
|
|
139
187
|
gap: var(--deep-expanding-menu-classic-panel-list-gap, 1.2rem);
|
|
140
188
|
|
|
141
|
-
width: var(--deep-expanding-menu-classic-panel-width, 20rem);
|
|
189
|
+
width: min(var(--deep-expanding-menu-classic-panel-width, 20rem), 100cqi);
|
|
142
190
|
|
|
143
|
-
@
|
|
144
|
-
width: var(--deep-expanding-menu-classic-panel-width-tablet, 40rem);
|
|
191
|
+
@container deep-expanding-menu-classic (min-width: 768px) {
|
|
192
|
+
width: min(var(--deep-expanding-menu-classic-panel-width-tablet, 40rem), 100cqi);
|
|
145
193
|
}
|
|
146
194
|
|
|
147
|
-
@
|
|
148
|
-
width: var(--deep-expanding-menu-classic-panel-width-desktop, 60rem);
|
|
195
|
+
@container deep-expanding-menu-classic (min-width: 1024px) {
|
|
196
|
+
width: min(var(--deep-expanding-menu-classic-panel-width-desktop, 60rem), 100cqi);
|
|
149
197
|
}
|
|
150
198
|
|
|
151
|
-
|
|
199
|
+
color: var(--deep-expanding-menu-classic-panel-text-colour, var(--theme-text));
|
|
200
|
+
background-color: var(--deep-expanding-menu-classic-panel-background-colour, var(--theme-surface-subtle));
|
|
152
201
|
border: var(--deep-expanding-menu-classic-panel-border-width, 0.1rem) solid
|
|
153
|
-
var(--deep-expanding-menu-classic-panel-border-colour,
|
|
202
|
+
var(--deep-expanding-menu-classic-panel-border-colour, var(--theme-border));
|
|
154
203
|
border-radius: var(--deep-expanding-menu-classic-panel-border-radius, 1.2rem);
|
|
155
204
|
box-shadow: var(--deep-expanding-menu-classic-panel-shadow, 0 0 1rem rgba(0, 0, 0, 0.1));
|
|
156
205
|
padding: var(--deep-expanding-menu-classic-panel-padding, 1.2rem);
|
|
157
206
|
overflow: clip;
|
|
158
207
|
|
|
159
|
-
|
|
160
|
-
color: var(--deep-expanding-menu-classic-panel-heading-colour, var(--
|
|
208
|
+
.deep-expanding-menu-classic-group-heading {
|
|
209
|
+
color: var(--deep-expanding-menu-classic-panel-heading-colour, var(--theme-text));
|
|
210
|
+
overflow-wrap: anywhere;
|
|
211
|
+
display: -webkit-box;
|
|
212
|
+
-webkit-box-orient: vertical;
|
|
213
|
+
overflow: hidden;
|
|
214
|
+
-webkit-line-clamp: var(--deep-expanding-menu-classic-panel-heading-line-clamp, none);
|
|
215
|
+
line-clamp: var(--deep-expanding-menu-classic-panel-heading-line-clamp, none);
|
|
161
216
|
}
|
|
162
217
|
|
|
163
|
-
.
|
|
218
|
+
.deep-expanding-menu-classic-group-list {
|
|
164
219
|
display: grid;
|
|
165
|
-
grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
|
|
220
|
+
grid-template-columns: repeat(auto-fill, minmax(min(100%, 12rem), 1fr));
|
|
166
221
|
gap: var(--deep-expanding-menu-classic-panel-list-gap, 1.2rem);
|
|
222
|
+
list-style: none;
|
|
167
223
|
padding-inline-start: 0;
|
|
168
|
-
margin-block
|
|
224
|
+
margin-block: 0 0.8rem;
|
|
169
225
|
|
|
170
|
-
.
|
|
226
|
+
.deep-expanding-menu-classic-group-item {
|
|
171
227
|
display: block;
|
|
228
|
+
min-inline-size: 0;
|
|
172
229
|
|
|
173
|
-
a.
|
|
230
|
+
a.deep-expanding-menu-classic-group-link {
|
|
174
231
|
display: inline-block;
|
|
175
|
-
|
|
232
|
+
max-inline-size: 100%;
|
|
233
|
+
overflow-wrap: anywhere;
|
|
234
|
+
color: var(--deep-expanding-menu-classic-group-link-colour, var(--theme-text));
|
|
176
235
|
text-decoration: none;
|
|
177
236
|
padding-block: 0.8rem;
|
|
178
237
|
|
|
@@ -183,10 +242,7 @@ onMounted(() => {
|
|
|
183
242
|
&:hover,
|
|
184
243
|
&:focus-visible {
|
|
185
244
|
cursor: pointer;
|
|
186
|
-
border-color: var(
|
|
187
|
-
--deep-expanding-menu-classic-group-link-border-colour-hover,
|
|
188
|
-
var(--slate-10)
|
|
189
|
-
);
|
|
245
|
+
border-color: var(--deep-expanding-menu-classic-group-link-border-colour-hover, var(--theme-text));
|
|
190
246
|
}
|
|
191
247
|
}
|
|
192
248
|
}
|