Skip to content

fix(registry): make the tabs active label follow the sliding indicator - #3437

Open
rajanpanth wants to merge 1 commit into
heygen-com:mainfrom
rajanpanth:fix/tabs-active-label-follows-indicator
Open

fix(registry): make the tabs active label follow the sliding indicator#3437
rajanpanth wants to merge 1 commit into
heygen-com:mainfrom
rajanpanth:fix/tabs-active-label-follows-indicator

Conversation

@rajanpanth

Copy link
Copy Markdown

Fixes #3266

Problem

The component pinned its active colour to a fixed tab:

.hf-transition-tabs-slide-indicator button:nth-of-type(2) {
  color: #fff;
}

The pill starts under the first tab, so before the slide "Plan" was gray on the dark pill and "Debug" was white on the light track. The two only agreed once the pill arrived at "Debug".

The inactive gray #71717a also measured 4.40:1 against the #f4f4f5 track, just under the 4.5:1 AA requirement.

Fix

The pill now carries a clipped copy of the label row:

<span class="indicator"
  ><span class="indicator-labels" aria-hidden="true"
    ><button tabindex="-1">Plan</button>...</span
  ></span
><button>Plan</button>...

.indicator gets overflow: hidden, and the copy counters the pill's own translate:

transform: translateX(calc(var(--hf-tab-x) * var(--hf-tab-step, 1) * -1));

That keeps the copy aligned with the buttons underneath at every frame, so the white text is exactly the part of the row the pill covers. It crosses over mid-slide instead of being pinned to one tab, and it is driven by the same --hf-tab-x the timeline already animates, so it stays deterministic under seek. The documented timeline recipe is unchanged.

Inactive gray is now #6b6b73, 4.80:1.

One consequence worth flagging

.indicator needed z-index: 2 to sit above the z-index: 1 buttons, because its transform makes it a stacking context and the label copy cannot otherwise paint above the row. The copy has to live inside .indicator since that is the element the timeline sets --hf-tab-x on, and inheritance only goes downward.

So the pill's box-shadow now paints over the track rather than behind the labels. I think this reads correctly, a raised pill casting onto what is below it, but it is a visual change beyond the reported bug and easy to revert if you would rather not have it. The alternative I considered was animating left instead of transform, which keeps the old layering exactly but trades a composited property for a layout one.

Verification

Measured in the browser against the demo, at several points of the slide:

--hf-tab-x pill position white label copy-to-row drift
0px tab 1 Plan 0.00px
43px mid-slide Plan + Debug, split at the pill edge 0.00px
86px tab 2 Debug 0.00px

elementFromPoint at each label centre confirms the pill's subtree is topmost exactly where the pill sits and the gray row elsewhere.

Contrast computed with the WCAG relative-luminance formula: #71717a 4.397:1, #6b6b73 4.805:1, white on the #18181b pill 17.72:1.

The labels variable rebuilds both rows, checked with four labels: 4 row buttons, 4 copies, 0.00px drift, copies at tabIndex -1. The copy is aria-hidden and pointer-events: none so it adds nothing to the accessibility tree or the tab order.

node scripts/lint-registry-items.mjs passes at 372 items, 0 errors. Both demo.html and the installable snippet carry the same change, including the demo's duplicated head style block.

The component pinned its active colour to the second button with
button:nth-of-type(2), while the pill starts under the first. Before
the slide, Plan sat gray on the dark pill and Debug sat white on the
light track, and the two only agreed once the pill reached Debug.

The pill now carries a clipped copy of the label row. Countering the
pill's own translate keeps that copy aligned with the buttons
underneath at every frame, so the white text is exactly the part of the
row the pill covers and it crosses over as the pill moves, driven by
the same --hf-tab-x the timeline already animates.

The inactive gray also failed WCAG AA at 4.40:1 against the track.
#6b6b73 measures 4.80:1.

Fixes heygen-com#3266
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tabs Slide Indicator shows the wrong active label before sliding

1 participant