facebook / facebook/astryx

Tab — hover shows a filled button/pill shape instead of a bottom bar

Open
#2,768 2 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
13k
Forks
1.1k
Avg merge
1d 15h
Merged PRs (30d)
690

Description

**Component:** `XDSTab`
**Type:** Bug — hover styling

### Description

Hovering an unselected `XDSTab` renders a **filled button/pill shape** behind the tab, rather than showing a **bottom bar** consistent with the selected-tab indicator.

In `packages/core/src/TabList/XDSTab.tsx`, hover is driven by a full-size background element (`hoverBg`), which fills the tab with an overlay color and a rounded radius:

```tsx
hoverBg: {
position: 'absolute',
inset: 0,
width: '100%',
borderRadius: radiusVars['--radius-element'], // ← rounded "button" shape
backgroundColor: {
default: 'transparent',
[stylex.when.ancestor(':hover', tabScope)]: {
'@media (hover: hover)': colorVars['--color-overlay-hover'], // ← filled background
},
},

},
```

This `hoverBgElement` is rendered for every tab and sized to the full tab (`hoverSizeStyles[size]`), so on hover it reads as a button/pill.

Meanwhile the bottom-bar `indicator` only shows when selected — unselected tabs get `indicatorUnselected` (`opacity: 0`, `backgroundColor: 'transparent'`), so hover never reveals the bar:

```tsx
indicatorSelected: { backgroundColor: colorVars['--color-icon-primary'], opacity: 1 },
indicatorUnselected: { backgroundColor: 'transparent', opacity: 0 },
```

### Proposed fix

Make hover use the **bottom-bar indicator** rather than a filled background:

- On hover of an unselected tab, show the `indicator` bar (e.g. a muted/secondary color, or reduced opacity) so the affordance matches the selected state — just a bottom bar, not a pill.
- Remove (or neutralize) the `hoverBg` filled-background + `--radius-element` treatment so hover no longer produces a button/pill shape. If a subtle background or text-color shift on hover is still desired, keep it minimal and avoid the rounded full-tab fill.
- Keep the selected indicator visually distinct from the hover indicator (e.g. selected = `--color-icon-primary` full opacity; hover = muted), and ensure it only applies under `@media (hover: hover)`.

End result: hovering a tab reveals a bottom bar consistent with the selected tab, not a button shape.

---
_Split out from the tracking issue #2631 (item 17 of 17)._

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.