Skip to content

Commit 1f53476

Browse files
committed
fix(navigation): ensure dropdown can be rendered in a semantically correct way
1 parent 44920b4 commit 1f53476

File tree

4 files changed

+37
-23
lines changed

4 files changed

+37
-23
lines changed

.changeset/new-bees-grab.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@stackoverflow/stacks-svelte": patch
3+
---
4+
5+
Navigation: ensure dropdown items can be rendered in a semantically correct way

packages/stacks-svelte/src/components/Navigation/Navigation.stories.svelte

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
text: "Settings",
6969
icon: IconSettings,
7070
iconSelected: IconSettingsFill,
71-
dropdown: true,
7271
},
7372
];
7473
@@ -194,7 +193,6 @@
194193
icon={item.icon}
195194
iconSelected={item.iconSelected}
196195
text={item.text}
197-
dropdown={item.dropdown}
198196
selected={horizontal === item.text}
199197
onclick={() => (horizontal = item.text)}
200198
/>
@@ -260,19 +258,23 @@
260258
<Story name="Dropdown" asChild>
261259
<Navigation class="hs1" label="Dropdown">
262260
{#each ["Label 1", "Label 2", "Label 3"] as label (label)}
263-
<Popover id={`dropdown-${label}`} placement="bottom-start">
264-
<PopoverReference>
265-
<NavigationItem
266-
text={label}
267-
selected={base === label}
268-
onclick={() => (base = label)}
269-
dropdown
270-
/>
271-
</PopoverReference>
272-
<PopoverContent>
273-
<p>Content here</p>
274-
</PopoverContent>
275-
</Popover>
261+
<NavigationItem
262+
id={`dropdown-reference-${label}`}
263+
text={label}
264+
selected={base === label}
265+
onclick={() => (base = label)}
266+
>
267+
{#snippet dropdown()}
268+
<Popover id={`dropdown-${label}`} placement="bottom-start">
269+
<PopoverReference
270+
elementId={`dropdown-reference-${label}`}
271+
/>
272+
<PopoverContent>
273+
<p>Content here</p>
274+
</PopoverContent>
275+
</Popover>
276+
{/snippet}
277+
</NavigationItem>
276278
{/each}
277279
</Navigation>
278280
</Story>

packages/stacks-svelte/src/components/Navigation/Navigation.test.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expect } from "@open-wc/testing";
2-
import { render, screen } from "@testing-library/svelte";
2+
import { render, screen, within } from "@testing-library/svelte";
33
import userEvent from "@testing-library/user-event";
44
import { createRawSnippet } from "svelte";
55
import sinon from "sinon";
@@ -192,7 +192,10 @@ describe("Navigation", () => {
192192
text: "Settings",
193193
icon: IconSettings,
194194
iconSelected: IconSettingsFill,
195-
dropdown: true,
195+
dropdown: createRawSnippet(() => ({
196+
render: () =>
197+
`<div>popover component goes in here</div>`,
198+
})),
196199
},
197200
},
198201
]),
@@ -213,6 +216,9 @@ describe("Navigation", () => {
213216
expect(contentButton).not.to.have.class("s-navigation--item__dropdown");
214217
expect(topicsButton).not.to.have.class("s-navigation--item__dropdown");
215218
expect(settingsButton).to.have.class("s-navigation--item__dropdown");
219+
220+
expect(within(list).getByText("popover component goes in here")).to
221+
.exist;
216222
});
217223

218224
it("should render navigation with title sections separating groups", () => {

packages/stacks-svelte/src/components/Navigation/NavigationItem.svelte

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@
2525
* Indicates if the navigation item is selected
2626
*/
2727
selected?: boolean;
28-
/**
29-
* Indicates if the navigation item is a dropdown. Use in horizontal navigations.
30-
*/
31-
dropdown?: boolean;
3228
/**
3329
* The icon source to display before the navigation item text
3430
*/
@@ -49,6 +45,10 @@
4945
* If true, applies a slide animation to the navigation item.
5046
*/
5147
animate?: boolean;
48+
/**
49+
* Optional snippet for the dropdown content. Use in horizontal navigations.
50+
*/
51+
dropdown?: Snippet;
5252
/**
5353
* Optional content rendered at the end of the navigation item.
5454
*/
@@ -58,12 +58,12 @@
5858
text,
5959
href = undefined,
6060
selected = false,
61-
dropdown = false,
6261
icon = undefined,
6362
iconSelected = undefined,
6463
avatar = undefined,
6564
class: className = "",
6665
animate = false,
66+
dropdown,
6767
trailing,
6868
...restProps
6969
}: Props = $props();
@@ -85,7 +85,7 @@
8585
}
8686
return classes;
8787
};
88-
const classes = $derived(getClasses(className, selected, dropdown));
88+
const classes = $derived(getClasses(className, selected, !!dropdown));
8989
9090
const maybeslide = (node: Element) => (animate ? slide(node) : {});
9191
</script>
@@ -113,4 +113,5 @@
113113
{@render trailing?.()}
114114
</div>
115115
</svelte:element>
116+
{@render dropdown?.()}
116117
</li>

0 commit comments

Comments
 (0)