SideNavItem: support independent trailing actions without nested controls
- Dominant language
- TypeScript
- Stars
- 13.1k
- Forks
- 1.1k
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 669
Description
## Problem
`SideNavItem.endContent?: ReactNode` is rendered inside the item's interactive `NavItemElement` on current main. If a consumer puts an independent action there (for example a More-menu button), the result is nested interactive markup such as ``.
The existing split-action path avoids nesting when a collapsible item also has a primary `href` or `onClick`, but it only separates the primary action from the disclosure toggle. It does not provide a seam for an arbitrary trailing action on a collapsible row whose primary row action is disclosure itself.
## Consumer case
Maka's project row needs two independently operable controls:
1. the project row toggles its child sessions;
2. a visually trailing More menu exposes project actions.
Minimal shape:
```tsx
}
>
{sessions}
```
This reproduces the nested-control problem tracked in [Maka #2360](https://github.com/Maka-Agent/maka-agent/issues/2360). The consumer-side fix is [Maka PR #2951](https://github.com/Maka-Agent/maka-agent/pull/2951).
## Cost of the consumer workaround
Maka now renders the menu as an absolutely positioned sibling outside `SideNavItem`, reserves a non-interactive placeholder in `endContent`, mirrors SideNav spacing/disclosure geometry in CSS, bridges hover/pressed paint back to the navigation button, and orders the external action before the SideNav root so keyboard focus stays adjacent to the child subtree.
That is valid and accessible, but it is coupled to private layout details (padding, gap, disclosure size) and cannot produce the ideal visual/DOM order without an upstream component seam.
## Requested capability
Please provide a supported way for a `SideNavItem` to expose an independent trailing action while keeping the row's visible surface and child disclosure behavior intact. The exact API could be an action slot, a ClickableContainer/interactive-ref composition, or an extension of the split-action path.
Acceptance properties:
- the row/disclosure target and trailing action are sibling interactive controls, never nested;
- focus order keeps both row controls adjacent and before the child group;
- Enter/Space on the row toggles disclosure, while the trailing action activates only itself;
- hover, pressed, and focus-visible treatment remains visually unified;
- layout uses SideNav-owned sizing/RTL rules rather than consumer offsets;
- both rows with children and empty rows are supported;
- `endContent` is documented as display-only if it remains inside the interactive target.
Related foundation: #3704.
Contributor guide
Research direction
Start at the SideNavItem implementation, focusing on endContent and the existing split-action path; compare the consumer shape from Maka #2360 and PR #2951. The work is done when a supported trailing action produces sibling controls with adjacent focus order, correct keyboard behavior, unified states, SideNav-owned layout, and coverage for rows with and without children.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- accessibility, design, frontend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100