mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-19 17:46:36 +03:00
[codex] Improve detector false positive handling (#232)
* Improve detector false positive handling * Register docs integrity test * Fix clipped overflow decorative skip
This commit is contained in:
+61
-1
@@ -9,6 +9,26 @@
|
||||
.col { padding: 16px; }
|
||||
.box { position: relative; width: 200px; height: 120px; margin: 0 0 24px; padding: 16px; border: 1px solid #ddd; }
|
||||
.pop { position: absolute; top: 100%; left: 0; width: 220px; background: #222; color: #fff; padding: 8px; }
|
||||
.tip-negative { position: absolute; top: -34px; left: 16px; width: 160px; background: #222; color: #fff; padding: 8px; }
|
||||
.flyout { position: absolute; top: 28px; left: 100%; width: 180px; background: #222; color: #fff; padding: 8px; }
|
||||
.contained-badge { position: absolute; top: 10px; right: 10px; width: 36px; height: 24px; background: #e5f0ff; }
|
||||
.button-shine { position: absolute; inset: 0; background: linear-gradient(90deg, transparent, rgba(255,255,255,.6), transparent); }
|
||||
.crop-photo { position: absolute; inset: -18px; background: linear-gradient(135deg, #b7d7ff, #486aa3); }
|
||||
.inside-overlay { position: absolute; left: 12px; right: 12px; bottom: 12px; min-height: 28px; background: rgba(255,255,255,.86); }
|
||||
.pass-hidden-button { position: relative; overflow: hidden; width: 160px; height: 52px; border: 1px solid #ddd; background: #111; color: #fff; }
|
||||
.pass-carousel-viewport,
|
||||
.pass-fisheye-list,
|
||||
.pass-split-container {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 200px;
|
||||
height: 120px;
|
||||
margin: 0 0 24px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
.carousel-slide-next { position: absolute; top: 100%; left: 0; width: 100%; height: 100%; padding: 16px; background: #f5f5f5; }
|
||||
.fisheye-next-item { position: absolute; top: 100%; left: 0; width: 100%; padding: 8px; background: none; border: 0; text-align: left; }
|
||||
.split-after-panel { position: absolute; top: 0; left: 50%; width: 100%; height: 100%; background: #f5f5f5; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -23,9 +43,25 @@
|
||||
<button>Tooltip host</button>
|
||||
<span class="pop">Tooltip clipped by overflow clip</span>
|
||||
</div>
|
||||
<div class="box flag-overflow-negative" style="overflow: hidden">
|
||||
<button>Help</button>
|
||||
<span class="tip-negative">Tooltip clipped above the host</span>
|
||||
</div>
|
||||
<div class="box flag-overflow-right" style="overflow: hidden">
|
||||
<button>Actions</button>
|
||||
<div class="flyout">Flyout menu clipped to the right of the host</div>
|
||||
</div>
|
||||
<div class="box flag-shadow-utility" style="overflow: hidden">
|
||||
<button>More</button>
|
||||
<div class="pop bg-white shadow-lg">Dropdown with utility classes still gets clipped.</div>
|
||||
</div>
|
||||
<div class="box flag-overlay-surface" style="overflow: clip">
|
||||
<button>Dialog</button>
|
||||
<div class="pop modal-overlay">Overlay-style dialog content still needs to escape.</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- PASS column: no clipping, no positioned child, or a real scroll region -->
|
||||
<!-- PASS column: no clipping, no positioned child, real scroll region, or contained decorative positioning -->
|
||||
<section class="col pass">
|
||||
<div class="box pass-hidden-no-abs" style="overflow: hidden">
|
||||
<p style="position: static">Hidden container with only static content.</p>
|
||||
@@ -38,6 +74,30 @@
|
||||
<button>Scroll host</button>
|
||||
<span class="pop">A genuine scroll region is allowed to contain positioned children.</span>
|
||||
</div>
|
||||
<div class="box pass-contained-abs" style="overflow: hidden">
|
||||
<p>Positioned decoration remains inside the clipping box.</p>
|
||||
<span class="contained-badge" aria-hidden="true"></span>
|
||||
</div>
|
||||
<button type="button" class="pass-hidden-button pass-button-shine">
|
||||
Save
|
||||
<span class="button-shine" aria-hidden="true"></span>
|
||||
</button>
|
||||
<div class="box pass-crop-photo" style="overflow: hidden">
|
||||
<span class="crop-photo" aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class="box pass-contained-overlay" style="overflow: clip">
|
||||
<p>Mockup frame with a contained absolute overlay.</p>
|
||||
<span class="inside-overlay" aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class="pass-carousel-viewport" aria-roledescription="carousel">
|
||||
<div class="carousel-slide-next">A hidden next slide is clipped intentionally by the viewport.</div>
|
||||
</div>
|
||||
<div class="pass-fisheye-list">
|
||||
<button type="button" class="fisheye-next-item">Next command</button>
|
||||
</div>
|
||||
<div class="pass-split-container">
|
||||
<div class="split-after-panel">Before/after comparison panel clipped by the split frame.</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -66,6 +66,16 @@
|
||||
border-radius: 4px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.pass-inline-code-chip {
|
||||
display: inline-block;
|
||||
font-family: ui-monospace, SFMono-Regular, monospace;
|
||||
font-size: 12px;
|
||||
line-height: 2;
|
||||
padding: 0.3em 0.5em;
|
||||
background: #eef2f7;
|
||||
color: #0f172a;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* ── PASS: cards at current standards ── */
|
||||
.pass-card-min { padding: 8px; background: #f1f5f9; border-radius: 6px; font-size: 16px; line-height: 1.6; }
|
||||
@@ -157,6 +167,10 @@
|
||||
<span class="case-label">tag chip: 12px font, 4px / 10px padding</span>
|
||||
<span class="pass-chip">design system tag chip</span>
|
||||
</div>
|
||||
<div class="case">
|
||||
<span class="case-label">long inline code chip: compact inline code should not be treated like a padded card</span>
|
||||
<code class="pass-inline-code-chip">npx impeccable skills check</code>
|
||||
</div>
|
||||
|
||||
<h3>Cards at current standards</h3>
|
||||
<div class="case">
|
||||
|
||||
@@ -218,6 +218,83 @@
|
||||
height: 80px;
|
||||
background: linear-gradient(135deg, #cbd5e1, #94a3b8);
|
||||
}
|
||||
|
||||
/* ── PASS: parent has zero padding, but child margins create the visible inset ── */
|
||||
.pass-margin-inset {
|
||||
padding: 0;
|
||||
background: white;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.pass-margin-inset h4 { margin: 16px 18px 4px; font-size: 14px; color: #0f172a; }
|
||||
.pass-margin-inset p { margin: 0 18px 16px; font-size: 13px; color: #475569; }
|
||||
|
||||
/* ── PASS: an inner shell, not the parent, owns the inset spacing ── */
|
||||
.pass-inner-shell {
|
||||
padding: 0;
|
||||
background: white;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.pass-inner-shell .inner-shell {
|
||||
margin: 18px;
|
||||
}
|
||||
.pass-inner-shell h4 { margin: 0 0 4px; font-size: 14px; color: #0f172a; }
|
||||
.pass-inner-shell p { margin: 0; font-size: 13px; color: #475569; }
|
||||
|
||||
/* ── PASS: same background as parent, so the child draws no visible boundary ── */
|
||||
.pass-same-bg-parent {
|
||||
padding: 16px;
|
||||
background: #eef2f7;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.pass-same-bg-child {
|
||||
padding: 0;
|
||||
background: #eef2f7;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.pass-same-bg-child h4 { margin: 0; font-size: 14px; color: #0f172a; }
|
||||
.pass-same-bg-child p { margin: 4px 0 0; font-size: 13px; color: #475569; }
|
||||
|
||||
/* ── PASS: full-bleed marquee/surface, not a text card missing padding ── */
|
||||
.pass-marquee-shell {
|
||||
padding: 0;
|
||||
background: #172033;
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
}
|
||||
.pass-marquee-track {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
width: max-content;
|
||||
}
|
||||
.pass-marquee-card {
|
||||
width: 220px;
|
||||
padding: 14px;
|
||||
background: #23304a;
|
||||
border: 1px solid rgba(255, 255, 255, 0.16);
|
||||
}
|
||||
.pass-marquee-card p { margin: 0; font-size: 13px; }
|
||||
|
||||
/* ── PASS: outer scene owns background; inner text surface owns padding ── */
|
||||
.pass-inner-text-surface {
|
||||
padding: 0;
|
||||
background: #0f172a;
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
}
|
||||
.pass-inner-text-surface-window {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
min-height: 92px;
|
||||
padding: 14px;
|
||||
background: #111827;
|
||||
border: 1px solid rgba(255, 255, 255, 0.16);
|
||||
}
|
||||
.pass-inner-text-surface-window p { margin: 0; font-size: 13px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -346,6 +423,59 @@
|
||||
<div class="placeholder-img"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Child margins provide the inset</h3>
|
||||
<div class="case">
|
||||
<span class="case-label">card: parent padding 0, but text children have margins that create visible inset.</span>
|
||||
<div class="pass-margin-inset">
|
||||
<h4>Title inset by child margin</h4>
|
||||
<p>Body copy is not visually flush even though the parent has zero padding.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Inner shell provides the inset</h3>
|
||||
<div class="case">
|
||||
<span class="case-label">card: parent padding 0, but an inner shell is offset from every edge.</span>
|
||||
<div class="pass-inner-shell">
|
||||
<div class="inner-shell">
|
||||
<h4>Title inset by inner shell</h4>
|
||||
<p>The direct child creates the breathing room.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Same background as parent</h3>
|
||||
<div class="case">
|
||||
<span class="case-label">child padding 0, but it has the same background as the parent, so no child boundary is visible.</span>
|
||||
<div class="pass-same-bg-parent">
|
||||
<div class="pass-same-bg-child">
|
||||
<h4>Same-surface visual shell</h4>
|
||||
<p>The text belongs to the parent surface, not to a distinct zero-padding card.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Full-bleed marquee shell</h3>
|
||||
<div class="case">
|
||||
<span class="case-label">marquee shell clips animated cards intentionally; the cards, not the shell, own text padding.</span>
|
||||
<section class="pass-marquee-shell">
|
||||
<div class="pass-marquee-track">
|
||||
<article class="pass-marquee-card"><p>Quote card with its own comfortable padding.</p></article>
|
||||
<article class="pass-marquee-card"><p>Another moving card, also padded inside.</p></article>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<h3>Inner text surface</h3>
|
||||
<div class="case">
|
||||
<span class="case-label">outer shell has a scene background; the inner window owns the actual text padding.</span>
|
||||
<div class="pass-inner-text-surface">
|
||||
<div class="pass-inner-text-surface-window">
|
||||
<p>Build step running</p>
|
||||
<p>Detector output belongs to the mock window.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
|
||||
+6
@@ -27,6 +27,12 @@
|
||||
<div class="card pass-tight-shadow" style="border: 1px solid #e5e7eb; box-shadow: 0 1px 4px rgba(0,0,0,0.08)">
|
||||
Hairline border with a tight, purposeful shadow.
|
||||
</div>
|
||||
<div class="card pass-soft-border-wide-shadow" style="border: 1px solid rgba(148, 163, 184, 0.16); box-shadow: 0 18px 48px -16px rgba(15, 23, 42, 0.18)">
|
||||
A quiet low-contrast hairline with a broad but restrained ambient shadow.
|
||||
</div>
|
||||
<div class="card pass-oklch-soft-shadow" style="border: 1px solid oklch(78% 0 0 / 0.16); box-shadow: 0 16px 36px -12px oklch(2% 0.004 95 / 0.18)">
|
||||
OKLCH shadow hue values should not be mistaken for shadow blur.
|
||||
</div>
|
||||
<div class="stripes pass-plain-gradient" style="background: linear-gradient(180deg, #f3f4f6, #ffffff)"></div>
|
||||
<p class="pass-no-theater">We measured real outcomes for the people who use this every day.</p>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Oversized H1 browser fixture</title>
|
||||
<style>
|
||||
body { font-family: Georgia, serif; margin: 0; color: #1a1a1a; background: #fff; }
|
||||
main { display: grid; gap: 48px; padding: 32px; }
|
||||
h1 { margin: 0; line-height: 1.04; }
|
||||
.flag-dominating-h1 {
|
||||
max-width: 1040px;
|
||||
font-size: 104px;
|
||||
}
|
||||
.pass-contained-large-h1 {
|
||||
max-width: 1120px;
|
||||
font-size: 83px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1 class="flag-dominating-h1">A sweeping product headline that sprawls across the whole viewport and keeps going</h1>
|
||||
<h1 class="pass-contained-large-h1">The missing design vocabulary for agents.</h1>
|
||||
</main>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
+19
@@ -116,6 +116,17 @@
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.mock-terminal-title,
|
||||
.mock-terminal-meta,
|
||||
.mock-diff-line {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
color: #475569;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.mock-terminal-title { font-size: 11px; }
|
||||
.mock-terminal-meta { font-size: 10.8px; }
|
||||
.mock-diff-line { font-size: 11.84px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -220,6 +231,14 @@
|
||||
<h2 style="font-size: 18px; margin: 0 0 4px;">Second level</h2>
|
||||
<h3 style="font-size: 16px; margin: 0;">Third level</h3>
|
||||
</div>
|
||||
|
||||
<h3>Small mockup metadata</h3>
|
||||
<div class="case">
|
||||
<span class="case-label">terminal/diff metadata at tiny sizes</span>
|
||||
<span class="mock-terminal-title">/impeccable polish : scanning codebase</span>
|
||||
<div class="mock-terminal-meta">12 files inspected · 4 visual issues queued</div>
|
||||
<div class="mock-diff-line">+ Replace generic button label with action-specific copy</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/js/detect-antipatterns-browser.js"></script>
|
||||
|
||||
@@ -69,6 +69,54 @@
|
||||
.brand-system {
|
||||
min-height: 120px;
|
||||
}
|
||||
.card-grid,
|
||||
.command-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
margin: 0 0 24px;
|
||||
}
|
||||
.suite-card,
|
||||
.command-card {
|
||||
display: block;
|
||||
min-height: 120px;
|
||||
padding: 16px;
|
||||
border: 1px solid #d8cec0;
|
||||
background: #fff;
|
||||
text-align: left;
|
||||
}
|
||||
.taxonomy-label {
|
||||
display: block;
|
||||
margin: 0 0 8px;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
letter-spacing: 0.11em;
|
||||
text-transform: uppercase;
|
||||
color: #5b5046;
|
||||
}
|
||||
.suite-card h3,
|
||||
.command-card h3 {
|
||||
font-size: 24px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.command-carousel,
|
||||
.hidden-mockup {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
margin: 0 0 24px;
|
||||
}
|
||||
.command-spread,
|
||||
.mockup-hero {
|
||||
min-height: 120px;
|
||||
padding: 16px;
|
||||
border: 1px solid #d8cec0;
|
||||
background: #fff;
|
||||
}
|
||||
.command-spread h3,
|
||||
.mockup-hero h2 {
|
||||
font-size: 24px;
|
||||
line-height: 30px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -140,6 +188,75 @@
|
||||
<h2>"Intentional Brand Label"</h2>
|
||||
<p>Deliberate brand systems can opt out with an explicit marker.</p>
|
||||
</section>
|
||||
|
||||
<div class="card-grid" aria-label="Room cards">
|
||||
<article class="suite-card">
|
||||
<span class="taxonomy-label">Suite</span>
|
||||
<h3>"Garden Suite"</h3>
|
||||
<p>Repeated category labels inside cards are structured metadata, not page-section scaffolding.</p>
|
||||
</article>
|
||||
<article class="suite-card">
|
||||
<span class="taxonomy-label">Suite</span>
|
||||
<h3>"Sea Loft"</h3>
|
||||
<p>The label is useful because the user is scanning sibling cards.</p>
|
||||
</article>
|
||||
<article class="suite-card">
|
||||
<span class="taxonomy-label">Suite</span>
|
||||
<h3>"Cliff Suite"</h3>
|
||||
<p>Repeating it here does not create the generic section-kicker smell.</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div class="command-grid" aria-label="Command cards">
|
||||
<button type="button" class="command-card">
|
||||
<span class="taxonomy-label">Refine</span>
|
||||
<h3>"/impeccabletypeset"</h3>
|
||||
<p>Command category labels can repeat across many action cards.</p>
|
||||
</button>
|
||||
<button type="button" class="command-card">
|
||||
<span class="taxonomy-label">Refine</span>
|
||||
<h3>"/impeccablelayout"</h3>
|
||||
<p>The repeated taxonomy helps compare tools inside the same group.</p>
|
||||
</button>
|
||||
<button type="button" class="command-card">
|
||||
<span class="taxonomy-label">Refine</span>
|
||||
<h3>"/impeccablecolorize"</h3>
|
||||
<p>This is a card-grid label, not a page-level eyebrow before a section.</p>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="command-carousel" aria-label="Command carousel">
|
||||
<div class="command-spread" data-category="create">
|
||||
<span class="taxonomy-label">Create</span>
|
||||
<h3>"/impeccablecraft"</h3>
|
||||
<p>Carousel slides can repeat category labels as navigational taxonomy.</p>
|
||||
</div>
|
||||
<div class="command-spread" data-category="evaluate">
|
||||
<span class="taxonomy-label">Evaluate</span>
|
||||
<h3>"/impeccableaudit"</h3>
|
||||
<p>The slash command heading identifies an item, not a page section.</p>
|
||||
</div>
|
||||
<div class="command-spread" data-category="harden">
|
||||
<span class="taxonomy-label">Harden</span>
|
||||
<h3>"/impeccablepolish"</h3>
|
||||
<p>The label is a category chip for a selectable command slide.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hidden-mockup" aria-hidden="true">
|
||||
<div class="mockup-hero">
|
||||
<span class="taxonomy-label">Amalfi Coast</span>
|
||||
<h2>"Mockup Hero Variant One"</h2>
|
||||
</div>
|
||||
<div class="mockup-hero">
|
||||
<span class="taxonomy-label">Amalfi Coast</span>
|
||||
<h2>"Mockup Hero Variant Two"</h2>
|
||||
</div>
|
||||
<div class="mockup-hero">
|
||||
<span class="taxonomy-label">Amalfi Coast</span>
|
||||
<h2>"Mockup Hero Variant Three"</h2>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
+12
@@ -29,6 +29,15 @@
|
||||
white-space: nowrap;
|
||||
clip-path: inset(50%);
|
||||
}
|
||||
.hidden-slide {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.hidden-slide .pass-hidden-slide-overflow {
|
||||
display: block;
|
||||
width: 120px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -49,6 +58,9 @@
|
||||
<span class="pass-sr-only-legacy sr-only sr-only-legacy-clip">A legacy clipped screen-reader-only label with long text that should not be flagged.</span>
|
||||
<span class="pass-sr-only-tiny-hidden sr-only sr-only-tiny-hidden">A tiny overflow-hidden screen-reader-only label without a clip declaration should not be flagged.</span>
|
||||
<span class="pass-sr-only-clipped-wide sr-only-clipped-wide">A fully clipped label with a normal-sized box and overflowing text should not be flagged.</span>
|
||||
<div class="hidden-slide">
|
||||
<span class="pass-hidden-slide-overflow">An inactive carousel slide can contain long text that overflows while hidden.</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -150,6 +150,10 @@
|
||||
</svg>
|
||||
<p style="color: rgb(35, 31, 27);">Dark text over a light SVG underlay should pass.</p>
|
||||
</article>
|
||||
|
||||
<article class="image-card light-image" aria-hidden="true">
|
||||
<p style="color: rgb(255, 255, 255);">Hidden mockup text on a light image should not be sampled.</p>
|
||||
</article>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user