Skip to content

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

Description

@jpenilla

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions