cloudflare / cloudflare/kumo

Tabs: indicator pop-in animation never runs — data-[rendered=false] styles are dead against Base UI 1.6

Open
#714 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
3.9k
Forks
177
Avg merge
1d 5h
Merged PRs (30d)
48

Description

## Summary

On initial mount, the Tabs indicator (both segmented pill and underline variants) appears instantly at full opacity. The intended pop-in — `scale-90 → scale-100` + `opacity-0 → opacity-1` over 200ms — never runs.

## Root cause

The indicator in `packages/kumo/src/components/tabs/tabs.tsx` is styled with:

```
data-[rendered=false]:scale-90 data-[rendered=false]:opacity-0
```

but Base UI's `TabsIndicator` (v1.6.0) never sets a `data-rendered` attribute, so these rules are dead CSS — the element is painted at full opacity/scale from its first frame.

For the record, Base UI does correctly avoid the 0×0 flash: it measures the active tab during render and keeps the element `hidden` until `isTabSelected && width > 0 && height > 0`. Only the pop animation is missing.

## Expected

Indicator pops in at the correct size/position (scale 0.9 → 1, opacity 0 → 1, ~200ms), as the dead classes suggest was intended — never animating its size from 0, never appearing instantly.

## Suggested approaches

1. Drive `data-rendered` from a small piece of state: start `false`, flip to `true` on a later frame after the first measurement (e.g. double `requestAnimationFrame` from a mount effect), guaranteeing one painted frame at the pre-pop state so the CSS transition actually runs.
2. Or drop the dead classes and use `@starting-style` + `transition-behavior: allow-discrete` (modern browsers only).

## Environment

- `@base-ui/react` ^1.6.0
- `main` @ 65db2e6

Contributor guide

Open the contributing guide

Research direction

Start in packages/kumo/src/components/tabs/tabs.tsx and trace how the Tabs indicator is rendered and styled against Base UI 1.6. Implement a reliable first-render trigger for the existing pop-in behavior, then verify that both segmented-pill and underline indicators transition from scale 0.9 and opacity 0 to their full state over about 200ms without a size flash or instant appearance.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.