mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-16 08:06:24 +03:00
The old rule used a fixed 8px floor on minPad, which produced false positives on small inline pills (like the homepage's .detection-cmd at 6px vertical / 14px horizontal on 13px font) and false negatives on large text (a 24px heading with 8px padding all around passed the floor but is genuinely too tight for the text size). The new rule uses two independent axis thresholds that scale with font-size: vertical: max(4px, fontSize × 0.3) horizontal: max(8px, fontSize × 0.5) The asymmetry reflects typographic reality: line-height already provides built-in vertical breathing room (the line box is taller than the cap height), so vertical padding can be tighter than horizontal. Both thresholds scale with font-size — bigger text demands proportionally more padding. Behavior changes - Small inline pills with line-height-aware padding now pass (.detection-cmd: V 6 ≥ 4, H 14 ≥ 8). The homepage CSS is unchanged. - Cramped large text now flags (24px heading with 8px padding fails H 8 < 12). The old rule missed this entirely. - All original 8px-floor flag cases still flag — 4px on 14px text is still 4 < 4.2 vertical, 2px is still cramped, etc. - Snippet now indicates which axis failed and the specific threshold for the font-size: "6px vertical padding (need ≥4.8px for 16px text)" instead of the old "6px padding (need >=8px)". Fixture - tests/fixtures/antipatterns/cramped-padding.html is a new comprehensive side-by-side fixture with 8 flag cases and 12 pass cases spanning small pills, cards, code blocks, interactive elements, and big text. Replaces the prior 3-case version. Test - tests/detect-antipatterns-browser.test.mjs asserts exactly 8 cramped-padding findings with detailed comments listing each expected case and which axis fails. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
215 lines
11 KiB
HTML
215 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Cramped Padding — Should Flag vs Should Pass</title>
|
|
<style>
|
|
/* Comprehensive fixture for the cramped-padding rule.
|
|
Both columns include a wide variety of cases so we can verify the
|
|
rule scales sensibly with font-size and treats the two axes
|
|
independently (vertical can be tighter because line-height already
|
|
provides built-in breathing room; horizontal has no equivalent). */
|
|
body { font-family: system-ui, sans-serif; background: #fafafa; padding: 24px; margin: 0; color: #0f172a; line-height: 1.5; }
|
|
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; max-width: 1400px; 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: 12px; text-transform: uppercase; letter-spacing: 0.05em; margin: 28px 0 10px; color: #64748b; }
|
|
.case { margin-bottom: 14px; padding: 14px 16px; background: white; border: 1px solid #e2e8f0; border-radius: 10px; }
|
|
.case-label { display: block; font-size: 12px; color: #64748b; margin-bottom: 8px; font-style: italic; }
|
|
|
|
/* ── FLAG: cramped body in cards ── */
|
|
.flag-card-4 { padding: 4px; border: 1px solid #d1d5db; border-radius: 6px; font-size: 14px; }
|
|
.flag-card-2 { padding: 2px; background: #f1f5f9; border-radius: 6px; font-size: 14px; }
|
|
.flag-card-bg4 { padding: 4px; background: #fef3c7; border-radius: 6px; font-size: 16px; }
|
|
|
|
/* ── FLAG: asymmetric cramping ── */
|
|
.flag-asym-v { padding: 1px 16px; background: #f1f5f9; border-radius: 6px; font-size: 14px; }
|
|
.flag-asym-h { padding: 12px 4px; background: #f1f5f9; border-radius: 6px; font-size: 14px; }
|
|
|
|
/* ── FLAG: cramped large text (currently MISSED by the 8px floor) ── */
|
|
.flag-heading-tight { padding: 8px; background: #f1f5f9; border-radius: 6px; font-size: 24px; font-weight: 600; line-height: 1.2; }
|
|
.flag-hero-tight { padding: 6px 16px; background: #f1f5f9; border-radius: 6px; font-size: 32px; font-weight: 700; line-height: 1.2; }
|
|
|
|
/* ── FLAG: cramped multi-line code block ── */
|
|
.flag-pre-tight { padding: 2px; background: #1e293b; color: #e2e8f0; border-radius: 6px; font-family: ui-monospace, monospace; font-size: 14px; line-height: 1.5; }
|
|
|
|
/* ── PASS: small inline pills (the .detection-cmd category) ── */
|
|
.pass-cmd {
|
|
display: inline-block;
|
|
font-family: ui-monospace, SFMono-Regular, monospace;
|
|
font-size: 13px;
|
|
line-height: 1.625;
|
|
color: #0f172a;
|
|
background: #f5f5f7;
|
|
padding: 6px 14px;
|
|
border-radius: 6px;
|
|
white-space: nowrap;
|
|
}
|
|
.pass-cmd::before { content: '➜ '; color: #ec4899; }
|
|
.pass-badge {
|
|
display: inline-block;
|
|
font-size: 11px;
|
|
line-height: 1.6;
|
|
padding: 4px 8px;
|
|
background: #dbeafe;
|
|
color: #1e40af;
|
|
border-radius: 999px;
|
|
font-weight: 600;
|
|
}
|
|
.pass-chip {
|
|
display: inline-block;
|
|
font-size: 12px;
|
|
line-height: 1.6;
|
|
padding: 4px 10px;
|
|
background: #fef3c7;
|
|
color: #92400e;
|
|
border-radius: 4px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* ── PASS: cards at current standards ── */
|
|
.pass-card-min { padding: 8px; background: #f1f5f9; border-radius: 6px; font-size: 16px; line-height: 1.6; }
|
|
.pass-card-good { padding: 16px; background: #f1f5f9; border-radius: 8px; font-size: 14px; line-height: 1.6; }
|
|
.pass-card-large { padding: 12px; background: #f1f5f9; border-radius: 8px; font-size: 18px; line-height: 1.6; }
|
|
|
|
/* ── PASS: comfortable code blocks ── */
|
|
.pass-pre-min { padding: 8px; background: #1e293b; color: #e2e8f0; border-radius: 6px; font-family: ui-monospace, monospace; font-size: 14px; line-height: 1.5; }
|
|
.pass-pre-good { padding: 12px; background: #1e293b; color: #e2e8f0; border-radius: 6px; font-family: ui-monospace, monospace; font-size: 14px; line-height: 1.5; }
|
|
|
|
/* ── PASS: interactive elements ── */
|
|
.pass-button-std { padding: 8px 16px; background: #3b82f6; color: white; border: 0; border-radius: 6px; font-size: 14px; cursor: pointer; }
|
|
.pass-input-std { padding: 8px 12px; border: 1px solid #cbd5e1; border-radius: 4px; font-size: 16px; width: 100%; box-sizing: border-box; }
|
|
|
|
/* ── PASS: big text with proportional padding ── */
|
|
.pass-heading-good { padding: 16px; background: #f1f5f9; border-radius: 8px; font-size: 24px; font-weight: 600; line-height: 1.2; }
|
|
.pass-hero-good { padding: 20px 32px; background: #f1f5f9; border-radius: 8px; font-size: 32px; font-weight: 700; line-height: 1.2; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="grid">
|
|
|
|
<!-- ════════════════════════════════════════════════════════════
|
|
LEFT COLUMN: should flag
|
|
═══════════════════════════════════════════════════════════ -->
|
|
<div class="col" data-col="flag">
|
|
<h2>Should flag</h2>
|
|
|
|
<h3>Cramped body in cards</h3>
|
|
<div class="case">
|
|
<span class="case-label">14px body, 4px padding all sides</span>
|
|
<div class="flag-card-4">This text is crammed against the border with only 4px padding. It feels claustrophobic and hard to read because the eye has nowhere to rest.</div>
|
|
</div>
|
|
<div class="case">
|
|
<span class="case-label">14px body, 2px padding all sides</span>
|
|
<div class="flag-card-2">Two pixels of padding is essentially nothing — body text needs room to breathe inside its container, especially across multiple lines.</div>
|
|
</div>
|
|
<div class="case">
|
|
<span class="case-label">16px body, 4px padding, background only</span>
|
|
<div class="flag-card-bg4">A colored background containment with only 4px padding around 16px body text. The colored edge feels like it's pressing in.</div>
|
|
</div>
|
|
|
|
<h3>Asymmetric cramping</h3>
|
|
<div class="case">
|
|
<span class="case-label">1px vertical / 16px horizontal, 14px body</span>
|
|
<div class="flag-asym-v">Generous horizontal padding doesn't save you when the vertical padding is just one pixel. Lines stack on top of each other against the container edge.</div>
|
|
</div>
|
|
<div class="case">
|
|
<span class="case-label">12px vertical / 4px horizontal, 14px body</span>
|
|
<div class="flag-asym-h">Comfortable vertical padding can't fix horizontal text running right up against the side edges. Words feel like they're falling off the container.</div>
|
|
</div>
|
|
|
|
<h3>Currently missed: cramped large text</h3>
|
|
<div class="case">
|
|
<span class="case-label">24px heading, 8px padding (passes the 8px floor but is too tight for the text size)</span>
|
|
<div class="flag-heading-tight">Tight Heading Container Label</div>
|
|
</div>
|
|
<div class="case">
|
|
<span class="case-label">32px hero, 6px vertical / 16px horizontal padding</span>
|
|
<div class="flag-hero-tight">Hero Section With Tight Vertical Padding</div>
|
|
</div>
|
|
|
|
<h3>Cramped multi-line code block</h3>
|
|
<div class="case">
|
|
<span class="case-label"><pre>, 2px padding, 14px monospace</span>
|
|
<pre class="flag-pre-tight">function example() {
|
|
const value = "cramped";
|
|
return value;
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ════════════════════════════════════════════════════════════
|
|
RIGHT COLUMN: should pass
|
|
═══════════════════════════════════════════════════════════ -->
|
|
<div class="col" data-col="pass">
|
|
<h2>Should pass</h2>
|
|
|
|
<h3>Small inline pills</h3>
|
|
<div class="case">
|
|
<span class="case-label">.detection-cmd replica: 13px font, 6px / 14px padding (the homepage case)</span>
|
|
<code class="pass-cmd">npx impeccable detect src/</code>
|
|
</div>
|
|
<div class="case">
|
|
<span class="case-label">small badge: 11px font, 4px / 8px padding</span>
|
|
<span class="pass-badge">FEATURED ITEM BADGE</span>
|
|
</div>
|
|
<div class="case">
|
|
<span class="case-label">tag chip: 12px font, 4px / 10px padding</span>
|
|
<span class="pass-chip">design system tag chip</span>
|
|
</div>
|
|
|
|
<h3>Cards at current standards</h3>
|
|
<div class="case">
|
|
<span class="case-label">16px body, 8px padding (the original 8px floor)</span>
|
|
<div class="pass-card-min">Standard card with 8px padding around 16px body text. Comfortable and within current conventions.</div>
|
|
</div>
|
|
<div class="case">
|
|
<span class="case-label">14px body, 16px padding (generous)</span>
|
|
<div class="pass-card-good">Generous 16px padding around 14px body text. The eye has plenty of room from the container edge.</div>
|
|
</div>
|
|
<div class="case">
|
|
<span class="case-label">18px body, 12px padding (proportional)</span>
|
|
<div class="pass-card-large">Larger body text gets proportionally more padding. 12px around 18px text feels balanced.</div>
|
|
</div>
|
|
|
|
<h3>Comfortable code blocks</h3>
|
|
<div class="case">
|
|
<span class="case-label">multi-line <pre>, 8px padding, 14px font</span>
|
|
<pre class="pass-pre-min">function example() {
|
|
const value = "ok";
|
|
return value;
|
|
}</pre>
|
|
</div>
|
|
<div class="case">
|
|
<span class="case-label">multi-line <pre>, 12px padding, 14px font</span>
|
|
<pre class="pass-pre-good">function example() {
|
|
const value = "comfortable";
|
|
return value;
|
|
}</pre>
|
|
</div>
|
|
|
|
<h3>Interactive elements</h3>
|
|
<div class="case">
|
|
<span class="case-label">button: 14px font, 8px / 16px padding</span>
|
|
<button class="pass-button-std">Standard sized button</button>
|
|
</div>
|
|
<div class="case">
|
|
<span class="case-label">form input: 16px font, 8px / 12px padding</span>
|
|
<input type="text" class="pass-input-std" value="Standard input with adequate padding">
|
|
</div>
|
|
|
|
<h3>Big text with proportional padding</h3>
|
|
<div class="case">
|
|
<span class="case-label">24px heading, 16px padding</span>
|
|
<div class="pass-heading-good">Heading With Room To Breathe</div>
|
|
</div>
|
|
<div class="case">
|
|
<span class="case-label">32px hero, 20px / 32px padding</span>
|
|
<div class="pass-hero-good">Hero With Big Padding</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script src="/js/detect-antipatterns-browser.js"></script>
|
|
</body>
|
|
</html>
|