Skip to content

feat(action): add buttonType and menu properties to support menu patterns (WIP)#14237

Draft
ashetland wants to merge 14 commits intodevfrom
ashetland/11126-action-components-prototypes
Draft

feat(action): add buttonType and menu properties to support menu patterns (WIP)#14237
ashetland wants to merge 14 commits intodevfrom
ashetland/11126-action-components-prototypes

Conversation

@ashetland
Copy link
Copy Markdown
Contributor

@ashetland ashetland commented Apr 9, 2026

Related Issue: #11126

Summary

WIP prototyping of the following:

All final naming of props and slots TBD.

Action:

  • add button-type="menu" | "overflow" | "split" | "undefined" (default) prop to action to support these patterns
  • add menu-actions slot for these buttonTypes for configuration of menu button patterns
  • add menu-flip-placements, menu-open, and menu-placement props matching action-menu
  • add tooltip slot matching action-menu

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds initial support for menu-enabled calcite-action variants to prototype overflow/menu/split-button patterns that will later integrate with calcite-action-group overflow behavior (Issue #11126).

Changes:

  • Introduces button-type and open state to calcite-action, plus a new menu slot rendered via an internal calcite-popover.
  • Adds split/overflow/menu-specific rendering and styling (secondary split trigger, chevron, open/active visuals).
  • Updates Storybook stories and adds E2E coverage for the new variants and styling states.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/components/src/components/action/resources.ts Adds CSS class keys, menu slot constant, menu IDs, and icon constants used by new variants.
packages/components/src/components/action/action.tsx Implements buttonType, open, menu slot handling, split rendering, and popover-backed menu behavior.
packages/components/src/components/action/action.stories.ts Adds stories/examples for overflow/split/menu variants and open-state matrices.
packages/components/src/components/action/action.scss Adds styling for split button layout and menu/overflow open states and menu container styles.
packages/components/src/components/action/action.e2e.ts Adds E2E assertions for overflow text visibility, split hit targets, and open-state styling behavior.
packages/components/src/components/action/action.browser.e2e.tsx Extends default/reflect tests for the new buttonType and open props.
Comments suppressed due to low confidence (2)

packages/components/src/components/action/action.tsx:510

  • A menuId is generated and applied to the menu container, but neither the primary trigger nor the split secondary trigger associates itself to that menu via aria-controls/ariaControlsElements. For accessibility parity with calcite-action-menu (which sets aria-controls on its trigger), include the menu element in the trigger’s ariaControlsElements (when supportsMenu && hasSlottedMenu) and set aria-controls on the split secondary button as well.
    const internalControlsElements = indicator && indicatorRef.value ? [indicatorRef.value] : [];

    const ariaControlsElements = [
      ...(this.aria?.controlsElements ?? []),
      ...internalControlsElements,
    ];

packages/components/src/components/action/action.tsx:533

  • When dragHandle is true, the component renders a <span role="button"> but does not wire onClick (or key handlers) to handleClick()/toggleOpen(). This means buttonType="menu"|"overflow" triggers won’t open and type="submit"|"reset" behavior won’t run in the drag-handle rendering path. If drag handles should still be operable as actions, add the same click/keyboard handling used by the <button> path; otherwise consider guarding against menu/button types when dragHandle is enabled.
    if (this.dragHandle) {
      return (
        // Needs to be a span because of https://github.com/SortableJS/Sortable/issues/1486 & https://bugzilla.mozilla.org/show_bug.cgi?id=568313
        <span
          ariaBusy={loading}
          ariaControlsElements={ariaControlsElements}
          ariaDescribedByElements={this.aria?.describedByElements}
          ariaExpanded={this.getMenuTriggerAriaExpanded()}
          ariaHasPopup={this.getMenuTriggerAriaHasPopup()}
          ariaLabel={ariaLabel}
          ariaLabelledByElements={this.aria?.labelledByElements}
          ariaOwnsElements={this.aria?.ownsElements}
          ariaPressed={this.aria?.pressed}
          class={buttonClasses}
          id={buttonId}
          ref={ref}
          role="button"
          tabIndex={this.disabled ? undefined : 0}
        >
          {buttonContent}
        </span>
      );

Comment thread packages/components/src/components/action/action.tsx Outdated
Comment thread packages/components/src/components/action/action.tsx Outdated
Comment thread packages/components/src/components/action/action.tsx Outdated
Comment thread packages/components/src/components/action/action.tsx
Comment thread packages/components/src/components/action/action.tsx Outdated
Comment thread packages/components/src/components/action/action.tsx
@github-actions github-actions bot added the enhancement Issues tied to a new feature or request. label Apr 9, 2026
@ashetland ashetland requested a review from Copilot April 14, 2026 15:29
@ashetland ashetland changed the title feat(action): add buttonType property to support menus (WIP) feat(action): add buttonType and menu properties to support menu patterns (WIP) Apr 14, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Comment thread packages/components/src/components/action/action.tsx Outdated
Comment thread packages/components/src/components/action/action.tsx Outdated
Comment thread packages/components/src/components/action/action.tsx
Comment on lines +128 to +163
private toggleOpen = (value = !this.menuOpen): void => {
if (!this.supportsMenu || !this.hasSlottedMenu) {
return;
}

this.menuOpen = value;

// Emit event to close other action menus when opening
if (value) {
document.dispatchEvent(
new CustomEvent<{ menuElement: HTMLElement }>(ACTION_MENU_OPEN_EVENT, {
detail: { menuElement: this.el },
}),
);
}
};

private setPopoverEl = (el: Popover["el"]): void => {
if (!el) {
return;
}

el.open = this.menuOpen;
};

private handlePopoverOpen = (event: CustomEvent<void>): void => {
event.stopPropagation();
this.menuOpen = true;
this.menuButtonEl?.focus();
// Emit event to close other action menus when opening
document.dispatchEvent(
new CustomEvent<{ menuElement: HTMLElement }>(ACTION_MENU_OPEN_EVENT, {
detail: { menuElement: this.el },
}),
);
};
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Follow up on this after concept is proven. There could be a cleaner way to do this.

Comment thread packages/components/src/components/action/action.tsx Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Issues tied to a new feature or request.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants