base-ui icon indicating copy to clipboard operation
base-ui copied to clipboard

[tabs] Inconsistency between "selected", "highlighted" and "active" tab states

Open ciampo opened this issue 7 months ago • 3 comments

Bug report

Current behavior

I find that some of the variable names used in the Tabs component are confusing, especially about the difference between:

  • the selected tab
  • the tab that is the active item in the composite tablist widget

In particular:

  • when it's selected, a tab receives the aria-selected="true" and data-selected attributes
  • when it's the "active" composite item, a tab receives the data-highlighted attribute
    • the data-highlighted attribute is also added when keyboard focus is not on the tablist
  • consumers can use --active-tab-* CSS variables to style the indicator to follow the size and dimensions of the selected tab

The result is that different terms are used for overlapping concepts: selected, highlighted, active

Expected behavior

Establish a clear nomenclature for composite widgets and apply consistently — for example, selected and active. The result would be the following:

  • aria-selected="true" and data-selected attributes for selected tabs
  • data-active attribute for tabs when they are the active composite item
  • --selected-tab-* CSS variables to style the indicator

Two extra thoughts:

  • I guess the data-active attribute (currently data-highlighted) should not be added when the keyboard focus is not on the tablist?
  • Are data-* attributes needed if an equivalent aria-* attribute is already specified?

Reproducible example

N/A

Base UI version

1.0.0-beta.0

Which browser are you using?

Chrome

Which OS are you using?

Mac OS

Which assistive tech are you using (if applicable)?

N/A

Additional context

I assume that any changes should be applied consistently across all composite-based components.

ciampo avatar Jun 12 '25 12:06 ciampo

I think [data-highlighted] should only exist when hover is synchronized with focus (as in Select/Menu). Otherwise, since Composite components don't synchronize hover and focus, and since they use roving focus, the :focus pseudo-selector should be enough? Meaning Composite components shouldn't have an attribute to indicate the current "active item" to begin with

Are data-* attributes needed if an equivalent aria-* attribute is already specified?

I think it's better to use data attributes since aria attributes are more of an implementation detail and not a style target

atomiks avatar Jun 12 '25 15:06 atomiks

The data-highlighted attribute could still be helpful to abstract over instances that use roving tabinxed vs virtual focus (ie. focus stays on the parent composite item, and the aria-activedescendant⁠ attribute is used instead).

The aria-activedescendant⁠ attribute is also why I usually prefer to use the term active rather than highlighted — after all, Base UI doesn't highlight that item (the consumer is expected to do that).

Also, what do you think about renaming --active-tab-* CSS variables to --selected-tab-* ?

ciampo avatar Jun 14 '25 13:06 ciampo

(cc @colmtuite from a recent conversation) — I believe it could be beneficial to add the data-highlighted regardless of virtual/real focus — it basically allows consumers of Base UI not to worry about the specific details of how focus is implemented.

ciampo avatar Jun 24 '25 17:06 ciampo

This fix will be available in the next npm release of Base UI.

In the meantime, you can try it out on our Canary release channel:

npm i https://pkg.pr.new/@base-ui-components/react@3024

github-actions[bot] avatar Oct 29 '25 23:10 github-actions[bot]