Skip to content

Conversation

@iuliauta
Copy link
Contributor

Description

Issue

Menu items (<sp-menu-item>) in <sp-action-menu> were not registering click events on iPad devices, while the same items wrapped in <sp-menu-group> worked correctly. This issue was reported in GitHub Issue #5706.

Symptoms

  • On iPad (and other tablets):
    • Direct menu items inside <sp-action-menu> don't fire click events
    • pointerdown and pointerup events fire correctly
    • Works fine when menu items are wrapped in <sp-menu-group>
  • On desktop and mobile phones:
    • Everything works as expected

Root cause

The issue stemmed from an incorrect device detection strategy that didn't properly account for tablet devices with touch input.

Technical details

  1. Device detection query

    // Old IS_MOBILE definition
    const IS_MOBILE =
        '(max-width: 743px) and (hover: none) and (pointer: coarse)';

    This query only matched devices with:

    • Screen width ≤ 743px AND
    • Touch input (hover: none, pointer: coarse)

    iPad devices don't match because their screen width is typically 768px-1024px.

  2. The shouldSupportDragAndSelect flag

    In packages/picker/src/InteractionController.ts, the code set:

    this.host.optionsMenu.shouldSupportDragAndSelect =
        !this.host.isMobile.matches;

    Since iPad didn't match IS_MOBILE, shouldSupportDragAndSelect was set to true.

  3. Event handling conflict

    In packages/menu/src/Menu.ts:

    private handlePointerup(event: Event): void {
        this.handleTouchEnd();
    
        if (!this.shouldSupportDragAndSelect) {
            return; // Selection handled by click event
        }
        this.pointerUpTarget = event.target;
        this.handlePointerBasedSelection(event);
    }
    
    private handleClick(event: Event): void {
        if (this.pointerUpTarget === event.target) {
            this.pointerUpTarget = null;
            return; // EARLY RETURN - Click is ignored!
        }
        this.handlePointerBasedSelection(event);
    }

    When shouldSupportDragAndSelect = true:

    • handlePointerup processes the selection and sets pointerUpTarget
    • handleClick sees that pointerUpTarget === event.target and returns early
    • The click event is never processed!
  4. Why menu-group worked

    When menu items are wrapped in <sp-menu-group>, the additional DOM wrapper causes the event.target in the click handler to sometimes differ from the pointerUpTarget set in the pointerup handler, allowing the click to proceed.

Solution

We introduced a new IS_TOUCH_DEVICE media query that detects any device with touch input, regardless of screen size:

export const IS_TOUCH_DEVICE = '(hover: none) and (pointer: coarse)';

This query matches:

  • Mobile phones (screen width ≤ 743px)
  • Tablets like iPad (screen width 744px-1366px)
  • Any other device with touch input

The PickerBase class now includes an isTouchDevice property:

public isTouchDevice = new MatchMediaController(this, IS_TOUCH_DEVICE);

The menu's shouldSupportDragAndSelect property is set directly in the template when the menu is rendered:

protected get renderMenu(): TemplateResult {
    const menu = html`
        <sp-menu
            ...
            .shouldSupportDragAndSelect=${!this.isTouchDevice.matches}
            ...
        >
            <slot></slot>
        </sp-menu>
    `;
    ...
}

This ensures that on all touch devices (including iPads), the menu uses click events instead of the drag-and-select pattern, preventing the event handling conflict.

Motivation and context

Related issue(s)

Screenshots (if appropriate)


Author's checklist

  • I have read the CONTRIBUTING and PULL_REQUESTS documents.
  • I have reviewed at the Accessibility Practices for this feature, see: Aria Practices
  • I have added automated tests to cover my changes.
  • I have included a well-written changeset if my change needs to be published.
  • I have included updated documentation if my change required it.

Reviewer's checklist

  • Includes a Github Issue with appropriate flag or Jira ticket number without a link
  • Includes thoughtfully written changeset if changes suggested include patch, minor, or major features
  • Automated tests cover all use cases and follow best practices for writing
  • Validated on all supported browsers
  • All VRTs are approved before the author can update Golden Hash

Manual review test cases

Device review

  • Did it pass in Desktop?
  • Did it pass in (emulated) Mobile?
  • Did it pass in (emulated) iPad?

@changeset-bot
Copy link

changeset-bot bot commented Nov 19, 2025

🦋 Changeset detected

Latest commit: dd2df56

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 78 packages
Name Type
@spectrum-web-components/picker Patch
@spectrum-web-components/reactive-controllers Patch
@spectrum-web-components/action-menu Patch
@spectrum-web-components/bundle Patch
@spectrum-web-components/accordion Patch
@spectrum-web-components/action-group Patch
@spectrum-web-components/button Patch
@spectrum-web-components/coachmark Patch
@spectrum-web-components/color-area Patch
@spectrum-web-components/color-slider Patch
@spectrum-web-components/color-wheel Patch
@spectrum-web-components/combobox Patch
@spectrum-web-components/contextual-help Patch
@spectrum-web-components/field-label Patch
@spectrum-web-components/icon Patch
@spectrum-web-components/menu Patch
@spectrum-web-components/meter Patch
@spectrum-web-components/number-field Patch
@spectrum-web-components/overlay Patch
@spectrum-web-components/progress-bar Patch
@spectrum-web-components/radio Patch
@spectrum-web-components/sidenav Patch
@spectrum-web-components/slider Patch
@spectrum-web-components/swatch Patch
@spectrum-web-components/tabs Patch
@spectrum-web-components/tags Patch
@spectrum-web-components/tooltip Patch
@spectrum-web-components/tray Patch
@spectrum-web-components/grid Patch
@spectrum-web-components/breadcrumbs Patch
@spectrum-web-components/action-bar Patch
@spectrum-web-components/action-button Patch
@spectrum-web-components/alert-banner Patch
@spectrum-web-components/alert-dialog Patch
@spectrum-web-components/button-group Patch
@spectrum-web-components/dialog Patch
@spectrum-web-components/infield-button Patch
@spectrum-web-components/picker-button Patch
@spectrum-web-components/search Patch
@spectrum-web-components/toast Patch
@spectrum-web-components/checkbox Patch
@spectrum-web-components/icons-ui Patch
@spectrum-web-components/icons-workflow Patch
@spectrum-web-components/table Patch
@spectrum-web-components/textfield Patch
@spectrum-web-components/popover Patch
@spectrum-web-components/truncated Patch
@spectrum-web-components/top-nav Patch
@spectrum-web-components/card Patch
@spectrum-web-components/switch Patch
@spectrum-web-components/help-text Patch
@spectrum-web-components/color-field Patch
@spectrum-web-components/field-group Patch
@spectrum-web-components/asset Patch
@spectrum-web-components/avatar Patch
@spectrum-web-components/badge Patch
@spectrum-web-components/clear-button Patch
@spectrum-web-components/close-button Patch
@spectrum-web-components/color-handle Patch
@spectrum-web-components/color-loupe Patch
@spectrum-web-components/divider Patch
@spectrum-web-components/dropzone Patch
@spectrum-web-components/icons Patch
@spectrum-web-components/iconset Patch
@spectrum-web-components/illustrated-message Patch
@spectrum-web-components/link Patch
@spectrum-web-components/modal Patch
@spectrum-web-components/progress-circle Patch
@spectrum-web-components/split-view Patch
@spectrum-web-components/status-light Patch
@spectrum-web-components/thumbnail Patch
@spectrum-web-components/underlay Patch
@spectrum-web-components/base Patch
@spectrum-web-components/opacity-checkerboard Patch
@spectrum-web-components/shared Patch
@spectrum-web-components/styles Patch
@spectrum-web-components/theme Patch
@spectrum-web-components/eslint-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@iuliauta iuliauta self-assigned this Nov 19, 2025
@iuliauta iuliauta added the Status: WIP PR is a work in progress or draft label Nov 19, 2025
@iuliauta iuliauta force-pushed the iuta/menu-item-ipad-click branch from 3ece1a2 to 7523d6a Compare November 19, 2025 14:18
@github-actions
Copy link
Contributor

github-actions bot commented Nov 19, 2025

📚 Branch Preview Links

🔍 First Generation Visual Regression Test Results

When a visual regression test fails (or has previously failed while working on this branch), its results can be found in the following URLs:

Deployed to Azure Blob Storage: pr-5901

If the changes are expected, update the current_golden_images_cache hash in the circleci config to accept the new images. Instructions are included in that file.
If the changes are unexpected, you can investigate the cause of the differences and update the code accordingly.

@iuliauta iuliauta marked this pull request as ready for review November 19, 2025 19:41
@iuliauta iuliauta requested a review from a team as a code owner November 19, 2025 19:41
@iuliauta iuliauta added Status: Ready for review PR ready for review or re-review. Component: Picker and removed Status: WIP PR is a work in progress or draft labels Nov 19, 2025
@caseyisonit caseyisonit added the Contribution PRs from contributors label Nov 19, 2025
@Rajdeepc Rajdeepc mentioned this pull request Nov 20, 2025
15 tasks
expect(el.optionsMenu.shouldSupportDragAndSelect).to.be.true;
});

it('dispatches change event when menu item is clicked on touch device', async () => {
Copy link
Collaborator

@marissahuysentruyt marissahuysentruyt Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this test fail for you occasionally? Or could it be me?

Screenshot 2025-11-20 at 5 59 35 PM

Could we maybe need an await nextFrame();? Could the menu.click() event not be propogating correctly since we're sort of "faking" a touch device here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Component: Picker Contribution PRs from contributors Status: Ready for review PR ready for review or re-review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Menu items in action menus do not dispatch click events on tablets

5 participants