Files
pbakaus_impeccable/tests/fixtures/antipatterns/motion.html
T
Paul BakausandClaude Opus 4.6 8b93dfad5e Merge color/motion/glow/layout fixture pairs into side-by-side files
Each problem-space fixture is now a single file with two columns: left
for cases that should flag, right for cases that should not. Matches the
icon-tile-stack convention and makes browser-based visual review easier.
The pass column proves that no false positives leak from look-alike
patterns next to the real anti-patterns.

Merged (4 pairs → 4 files)
- color-should-{flag,pass}.html → color.html
- motion-should-{flag,pass}.html → motion.html
- glow-should-{flag,pass}.html → glow.html
- layout-should-{flag,pass}.html → layout.html

Left untouched
- should-{flag,pass}.html — used by the CLI smoke tests in
  detect-antipatterns.test.js, which need a known-clean fixture for the
  exit-code-0 path.
- typography-should-{flag,pass}.html — all three typography rules
  (overused-font, single-font, flat-type-hierarchy) are page-level and
  fundamentally can't share a page with their pass cases. Loading two
  font stacks suppresses single-font; varied sizes suppress flat-type-
  hierarchy. Documented in the test file.

Test calibration
- Hardcoded the jsdom finding counts (motion: 2 bounce + 2 layout-
  transition; glow: 1 dark-glow). Real browser sees more because
  jsdom doesn't fully apply class-based styles, but the pass-column
  count is reliably 0. Browser-verified all 4 fixtures show expected
  flag counts and zero pass-column false positives.

Fixture chrome fixes
- Sub-section labels (.col h3) now use #64748b instead of #94a3b8 so
  the fixture's own UI doesn't trigger low-contrast. glow.html got a
  CSS restructure into card-dark/card-light/card-medium variants so
  every text/background pairing meets WCAG AA. layout.html's "card
  with image" gradient changed from blue→purple to amber→rose so it
  doesn't trip ai-color-palette.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 23:31:29 -07:00

161 lines
7.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Motion Anti-Patterns — Should Flag vs Should Pass</title>
<style>
/* ─── Two-column fixture convention ─────────────────────────────
Left column = should flag. Right column = should pass.
Tests assert (a) every flag-column rule fires and (b) the total
finding count matches the number of flag cases (no false
positives leaking from the pass column).
──────────────────────────────────────────────────────────── */
body { font-family: system-ui, sans-serif; background: #f9fafb; padding: 24px; margin: 0; }
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; max-width: 1200px; margin: 0 auto; }
.col h2 { font-size: 14px; text-transform: uppercase; letter-spacing: 0.05em; margin: 0 0 16px; color: #475569; }
.col h3 { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; margin: 24px 0 8px; color: #64748b; }
.demo { padding: 14px 16px; background: white; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); margin-bottom: 10px; }
.demo h4 { font-weight: 600; font-size: 13px; margin: 0; }
.demo p { font-size: 12px; color: #6b7280; margin: 4px 0 0; }
/* ── FLAG: bounce / elastic easing ── */
@keyframes bounce-keyframe {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
.bounce-animation { animation: bounce-keyframe 1s infinite; }
.elastic-transition { transition: transform 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); }
/* ── FLAG: layout property transitions ── */
.width-transition { transition: width 0.3s ease; }
.height-transition { transition: height 0.4s ease-out; }
.padding-transition { transition: padding 0.2s linear; }
.margin-transition { transition: margin 0.3s ease-in; }
.max-height-transition { transition: max-height 0.5s ease; }
.multi-layout-transition { transition: width 0.3s ease, height 0.3s ease; }
.mixed-transition { transition: width 0.3s ease, opacity 0.3s ease; }
.transition-property-width { transition-property: width; transition-duration: 0.3s; }
/* ── PASS: good easing ── */
@keyframes fade-in-keyframe {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
.fade-in-good { animation: fade-in-keyframe 0.4s cubic-bezier(0.16, 1, 0.3, 1); }
.ease-out-quart { transition: transform 0.4s cubic-bezier(0.25, 1, 0.5, 1); }
.ease-out-expo { transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1); }
/* ── PASS: safe transitions ── */
.transform-transition { transition: transform 0.3s ease-out; }
.opacity-transition { transition: opacity 0.2s ease; }
.color-transition { transition: color 0.15s ease, background-color 0.15s ease; }
.shadow-transition { transition: box-shadow 0.2s ease; }
.all-transition { transition: all 0.3s ease; }
.multi-safe-transition { transition: transform 0.3s ease, opacity 0.3s ease, box-shadow 0.2s ease; }
</style>
</head>
<body>
<div class="grid">
<!-- ════════════════════════════════════════════════════════════
LEFT COLUMN: should flag
═══════════════════════════════════════════════════════════ -->
<div class="col" data-col="flag">
<h2>Should flag</h2>
<h3>Bounce / elastic easing</h3>
<div class="demo bounce-animation">
<h4>CSS bounce animation</h4>
<p>animation: bounce 1s infinite</p>
</div>
<div class="demo elastic-transition">
<h4>Elastic cubic-bezier</h4>
<p>cubic-bezier(0.68, -0.55, 0.265, 1.55)</p>
</div>
<h3>Layout property transitions</h3>
<div class="demo width-transition">
<h4>transition: width</h4>
<p>Animating width causes layout thrash.</p>
</div>
<div class="demo height-transition">
<h4>transition: height</h4>
<p>Animating height causes layout thrash.</p>
</div>
<div class="demo padding-transition">
<h4>transition: padding</h4>
<p>Animating padding causes layout thrash.</p>
</div>
<div class="demo margin-transition">
<h4>transition: margin</h4>
<p>Animating margin causes layout thrash.</p>
</div>
<div class="demo max-height-transition">
<h4>transition: max-height</h4>
<p>Use grid-template-rows instead.</p>
</div>
<div class="demo multi-layout-transition">
<h4>transition: width, height</h4>
<p>Multiple layout properties.</p>
</div>
<div class="demo mixed-transition">
<h4>transition: width, opacity</h4>
<p>Layout property mixed with OK property.</p>
</div>
<div class="demo transition-property-width">
<h4>transition-property: width</h4>
<p>Longhand form.</p>
</div>
</div>
<!-- ════════════════════════════════════════════════════════════
RIGHT COLUMN: should pass
═══════════════════════════════════════════════════════════ -->
<div class="col" data-col="pass">
<h2>Should pass</h2>
<h3>Good easing</h3>
<div class="demo fade-in-good">
<h4>Smooth fade in</h4>
<p>animation: fadeIn with exponential ease-out</p>
</div>
<div class="demo ease-out-quart">
<h4>Ease-out quart</h4>
<p>cubic-bezier(0.25, 1, 0.5, 1) — smooth deceleration</p>
</div>
<div class="demo ease-out-expo">
<h4>Ease-out expo</h4>
<p>cubic-bezier(0.16, 1, 0.3, 1) — natural feel</p>
</div>
<h3>Safe transitions (transform / opacity / color only)</h3>
<div class="demo transform-transition">
<h4>transition: transform</h4>
<p>Transform is GPU-accelerated and safe.</p>
</div>
<div class="demo opacity-transition">
<h4>transition: opacity</h4>
<p>Opacity is GPU-accelerated and safe.</p>
</div>
<div class="demo color-transition">
<h4>transition: color, background-color</h4>
<p>Color transitions are paint-only, no layout.</p>
</div>
<div class="demo shadow-transition">
<h4>transition: box-shadow</h4>
<p>Shadow transitions are paint-only.</p>
</div>
<div class="demo all-transition">
<h4>transition: all</h4>
<p>Too common to flag — usually paired with transform/opacity.</p>
</div>
<div class="demo multi-safe-transition">
<h4>transition: transform, opacity, box-shadow</h4>
<p>Multiple safe properties combined.</p>
</div>
</div>
</div>
<script src="/js/detect-antipatterns-browser.js"></script>
</body>
</html>