feat: add semantic click events on child components (ListItem, MenuItem, Tab, etc.)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.8k
- Forks
- 285
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 59
Description
Problem
Several container components fire click/press events on behalf of their children (e.g., List fires item-click, Menu fires item-click), but the child elements themselves have no public click event. This means framework consumers (React, Angular, Vue) using wrappers like createReactComponent cannot attach onClick handlers directly on child elements — they must listen on the parent and match the clicked item from the event detail.
For example, React consumers expect to write:
<ListItemStandard onClick={() => handleClick()}>Product A</ListItemStandard>
But currently must write:
<List onItemClick={(e) => { if (e.detail.item === targetRef) handleClick(); }}>
<ListItemStandard>Product A</ListItemStandard>
</List>
Prior Art
This pattern has already been implemented for:
TableRow— fires ownclick+ Table keepsrow-click(#13303)TableRowActionBase— fires ownclick+ Table keepsrow-action-clickSideNavigationSelectableItemBase— fires ownclick+ SideNavigation keepsitem-clickButton,Link,Icon,CardHeader,Tag,Avatar— all suppress the native click and fire a semanticCustomEvent("click")covering mouse + keyboard
The pattern: intercept the native DOM click on the child via stopImmediatePropagation, fire a CustomEvent("click") via fireDecoratorEvent, then call the parent's handler for backward compatibility.
Candidates
High impact
| Child Component | Parent Component | Parent Event | Mechanism |
|---|---|---|---|
ListItemBase (all variants) |
List |
item-click |
Private _press event → List re-fires |
MenuItem |
Menu |
item-click |
Via inner List's item-click |
TreeItemBase / TreeItem |
Tree |
item-click |
Via inner List's item-click |
NotificationListItem |
NotificationList |
item-click |
Private _press → inner List → parent |
UserMenuItem |
UserMenu |
item-click |
Via inner List's item-click |
Note: ListItemBase is the foundation. Adding a semantic click there would cascade to MenuItem, TreeItem, NotificationListItem, and all other ListItem variants.
Medium impact
| Child Component | Parent Component | Parent Event | Mechanism |
|---|---|---|---|
Tab |
TabContainer |
tab-select |
Pure DOM delegation, no child event |
BreadcrumbsItem |
Breadcrumbs |
item-click |
Internal Link click, parent maps to item |
SegmentedButtonItem |
SegmentedButton |
selection-change |
Pure DOM delegation, no child event |
WizardTab |
Wizard |
step-change |
Private selection-change-requested |
Low impact
| Child Component | Parent Component | Parent Event |
|---|---|---|
ColorPaletteItem |
ColorPalette |
item-click |
Implementation approach
For each candidate:
- Declare
clickin the base classeventDetails(to preserve JSX type compatibility in the hierarchy) - Add
@eventStrict("click", { bubbles: true })on the concrete child class - Intercept the native click in the constructor (
this.addEventListener("click", ...)) — suppress viastopImmediatePropagation, firefireDecoratorEvent("click") - Keep the existing parent-level event (
item-click,tab-select, etc.) for backward compatibility
Suggested order
ListItemBase— highest impact, cascades to Menu, Tree, NotificationListTab— commonly requested by framework consumersBreadcrumbsItem/SegmentedButtonItem— smaller scope, straightforward
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with ListItemBase and compare the existing TableRow, TableRowActionBase, and SideNavigationSelectableItemBase patterns. Trace how List, Menu, and Tree currently propagate their parent events, then determine the candidate scope before changing child event declarations and handlers. Done means selected child components expose semantic click events while existing parent-level events remain compatible.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100