diff --git a/docs/assets/styles/docs.css b/docs/assets/styles/docs.css
index 2ccb7e4b9..f9d62bdfc 100644
--- a/docs/assets/styles/docs.css
+++ b/docs/assets/styles/docs.css
@@ -237,6 +237,7 @@ kbd {
border: solid 1px var(--sl-color-neutral-200);
box-shadow: inset 0 1px 0 0 var(--sl-color-neutral-0), inset 0 -1px 0 0 var(--sl-color-neutral-200);
font-family: var(--sl-font-mono);
+ font-size: 0.9125em;
border-radius: var(--docs-border-radius);
color: var(--sl-color-neutral-800);
padding: 0.125em 0.4em;
diff --git a/docs/pages/resources/changelog.md b/docs/pages/resources/changelog.md
index 3698347b4..a8d2a327c 100644
--- a/docs/pages/resources/changelog.md
+++ b/docs/pages/resources/changelog.md
@@ -12,6 +12,10 @@ Components with the Experimental bad
New versions of Shoelace are released as-needed and generally occur when a critical mass of changes have accumulated. At any time, you can see what's coming in the next release by visiting [next.shoelace.style](https://next.shoelace.style).
+## Next
+
+- Fixed a bug in `` where pressing [[Up]] or [[Down]] when focused on the trigger wouldn't focus the first/last menu items [#1472]
+
## 2.6.0
- Added JSDoc comments to React Wrappers for better documentation when hovering a component. [#1450]
diff --git a/src/components/dropdown/dropdown.component.ts b/src/components/dropdown/dropdown.component.ts
index 9d99d402e..76ab4feb8 100644
--- a/src/components/dropdown/dropdown.component.ts
+++ b/src/components/dropdown/dropdown.component.ts
@@ -213,7 +213,7 @@ export default class SlDropdown extends ShoelaceElement {
}
}
- handleTriggerKeyDown(event: KeyboardEvent) {
+ async handleTriggerKeyDown(event: KeyboardEvent) {
// When spacebar/enter is pressed, show the panel but don't focus on the menu. This let's the user press the same
// key again to hide the menu in case they don't want to make a selection.
if ([' ', 'Enter'].includes(event.key)) {
@@ -238,6 +238,9 @@ export default class SlDropdown extends ShoelaceElement {
// Show the menu if it's not already open
if (!this.open) {
this.show();
+
+ // Wait for the dropdown to open before focusing, but not the animation
+ await this.updateComplete;
}
if (menuItems.length > 0) {
diff --git a/src/components/dropdown/dropdown.test.ts b/src/components/dropdown/dropdown.test.ts
index 36f4d6725..1140ede3c 100644
--- a/src/components/dropdown/dropdown.test.ts
+++ b/src/components/dropdown/dropdown.test.ts
@@ -162,7 +162,7 @@ describe('', () => {
expect(el.open).to.be.true;
});
- it('should open on arrow navigation', async () => {
+ it('should open on arrow down navigation', async () => {
const el = await fixture(html`
Toggle
@@ -173,12 +173,35 @@ describe('', () => {
`);
const trigger = el.querySelector('sl-button')!;
+ const firstMenuItem = el.querySelectorAll('sl-menu-item')[0];
trigger.focus();
await sendKeys({ press: 'ArrowDown' });
await el.updateComplete;
expect(el.open).to.be.true;
+ expect(document.activeElement).to.equal(firstMenuItem);
+ });
+
+ it('should open on arrow up navigation', async () => {
+ const el = await fixture(html`
+
+ Toggle
+
+ Item 1
+ Item 2
+
+
+ `);
+ const trigger = el.querySelector('sl-button')!;
+ const secondMenuItem = el.querySelectorAll('sl-menu-item')[1];
+
+ trigger.focus();
+ await sendKeys({ press: 'ArrowUp' });
+ await el.updateComplete;
+
+ expect(el.open).to.be.true;
+ expect(document.activeElement).to.equal(secondMenuItem);
});
it('should navigate to first focusable item on arrow navigation', async () => {