mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-17 00:26:41 +03:00
detector: narrow the tab-strip stripe exemption to actual selection state
Tab-strip MEMBERSHIP no longer exempts chromatic top/bottom stripes — only a real selection marker does: aria-selected="true", aria-current (any non-false value), or an active/current/selected class hint. A stripe repeated on every tab in the group ([role=tab], .tabs items, aria-selected="false" tabs) is decoration and flags as side-tab; the selected tab's own underline — including the reserved-space transparent-border pattern — stays legal. Applied consistently across the element border path (isTabContextElement), the pseudo-element stripe scan, and the inset box-shadow stripe scan. Also replaces a stray NUL byte in the marquee scanner's dedupe key that made tools treat checks.mjs as binary. Browser bundle regenerated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
5e1925f9d2
commit
b6304913ef
@@ -1441,12 +1441,17 @@ function scanCssTextForPseudoStripe(content) {
|
||||
decls.get('height') || decls.get('block-size') || '', customProps));
|
||||
const verticalCandidate = widthPx != null && widthPx >= 3 && widthPx <= 12;
|
||||
// Horizontal variant (top/bottom stripe) carries extra exemptions:
|
||||
// link/button underline affordances, tab strips, selected states, and
|
||||
// state-conditional (:hover/:focus/...) affordances are not stripes.
|
||||
// link/button underline affordances, selected-state indicators
|
||||
// (aria-selected="true", aria-current, active/current/selected class
|
||||
// hints), and state-conditional (:hover/:focus/...) affordances are
|
||||
// not stripes. Tab-strip membership alone ([role=tab], .tabs, bare
|
||||
// [aria-selected]) is NOT exempt — a stripe on every tab in the
|
||||
// group is decoration; only the selected item's underline stays.
|
||||
const horizontalCandidate = heightPx != null && heightPx >= 3 && heightPx <= 12
|
||||
&& !/(?:^|[\s>+~,(])(?:a|button|summary|tr|td|th|table|li)(?![\w-])/i.test(selector)
|
||||
&& !/\[role=["']?tab|\[aria-selected/i.test(selector)
|
||||
&& !/(?:^|[\s._[-])(?:tabs?|tablist|tab-[\w-]*|btn[\w-]*|button[\w-]*|link[\w-]*)(?![\w])/i.test(selector)
|
||||
&& !/\[aria-selected\s*[*^$|~]?=\s*["']?true/i.test(selector)
|
||||
&& !/\[aria-current(?!\s*[*^$|~]?=\s*["']?false)/i.test(selector)
|
||||
&& !/(?:^|[\s._[-])(?:active|current|selected|btn[\w-]*|button[\w-]*|link[\w-]*)(?![\w])/i.test(selector)
|
||||
&& !/:(?:hover|focus|focus-visible|focus-within|active|checked)\b/i.test(selector);
|
||||
if (!verticalCandidate && !horizontalCandidate) continue;
|
||||
|
||||
@@ -1539,12 +1544,14 @@ function scanCssTextForInsetStripe(content) {
|
||||
let m;
|
||||
while ((m = ruleRe.exec(content)) !== null) {
|
||||
const selector = m[1].trim();
|
||||
// State/selection contexts: current-item markers, interaction states,
|
||||
// explicit tab semantics.
|
||||
// Selection-state contexts: current-item markers and interaction
|
||||
// states. Tab-strip membership alone ([role=tab], .tabs, bare
|
||||
// [aria-selected]) is NOT exempt — a stripe on every tab in the
|
||||
// group is decoration; only the selected item's indicator stays.
|
||||
if (/:(?:hover|focus|focus-visible|focus-within|active|checked|target)\b/i.test(selector)) continue;
|
||||
if (/\[aria-(?:current|selected)/i.test(selector)) continue;
|
||||
if (/\[role=["']?tab/i.test(selector)) continue;
|
||||
if (/(?:^|[\s._[-])(?:active|current|selected|tabs?)(?![\w])/i.test(selector)) continue;
|
||||
if (/\[aria-selected\s*[*^$|~]?=\s*["']?true/i.test(selector)) continue;
|
||||
if (/\[aria-current(?!\s*[*^$|~]?=\s*["']?false)/i.test(selector)) continue;
|
||||
if (/(?:^|[\s._[-])(?:active|current|selected)(?![\w])/i.test(selector)) continue;
|
||||
// Structural tags where a single-edge inset shadow is depth/quoting,
|
||||
// not an accent stripe.
|
||||
if (/(?:^|[\s>+~,(])(?:button|hr|tr|td|th|table|blockquote|pre|code)(?![\w-])/i.test(selector)) continue;
|
||||
@@ -1646,7 +1653,7 @@ function scanCssTextForMarquee(content) {
|
||||
const decls = parseCssDeclBlock(m[2]);
|
||||
for (const name of infiniteAnimationNames(decls)) {
|
||||
if (!marqueeKeyframes.has(name)) continue;
|
||||
const key = `${selector} | ||||