Skip to content

fix(button): handles modifier keys correctly #5543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/witty-streets-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@spectrum-web-components/button': patch
---

** Fixed** -

- ✅ Regular click on action button with href opens exactly one tab
- ✅ Command + Click continues to open exactly one tab
- ✅ Ctrl + Click continues to open exactly one tab
5 changes: 5 additions & 0 deletions packages/button/src/ButtonBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ export class ButtonBase extends ObserveSlotText(LikeAnchor(Focusable), '', [
private shouldProxyClick(event?: MouseEvent): boolean {
let handled = false;

// If this is a link (has href), let the browser handle it naturally
if (this.href && this.href.length > 0) {
return false; // Don't interfere with browser's link handling
}

// Don't proxy clicks with modifier keys (Command/Meta, Ctrl, Shift, Alt)
if (
event &&
Expand Down
14 changes: 9 additions & 5 deletions packages/button/test/button.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ describe('Button', () => {
expect(el.hasAttribute('static-color')).to.be.false;
});
});
it('handles modifier key clicks correctly', async () => {
it('handles modifier key clicks correctly for buttons with href', async () => {
const el = await fixture<Button>(html`
<sp-button href="#test">Button with href</sp-button>
`);
Expand All @@ -839,7 +839,7 @@ describe('Button', () => {
) as HTMLAnchorElement;
expect(anchorElement).to.not.be.undefined;

// Set up spies instead of counters
// Set up spies to track events
const buttonClickSpy = spy();
const anchorClickSpy = spy();

Expand All @@ -852,7 +852,7 @@ describe('Button', () => {
// Track button clicks with spy
el.addEventListener('click', buttonClickSpy);

// Test normal click - should proxy to anchor
// Test normal click - should NOT proxy to anchor when href is present
const normalClick = new MouseEvent('click', {
bubbles: true,
cancelable: true,
Expand All @@ -865,9 +865,13 @@ describe('Button', () => {
await elementUpdated(el);

expect(
anchorClickSpy.called,
'Normal click should be proxied to the anchor'
buttonClickSpy.called,
'Normal click should be received by the button'
).to.be.true;
expect(
anchorClickSpy.called,
'Normal click should NOT be proxied to the anchor when href is present'
).to.be.false;

buttonClickSpy.resetHistory();
anchorClickSpy.resetHistory();
Expand Down
Loading