mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-11 21:57:14 +03:00
Make cramped-padding rule asymmetric and proportional to font-size
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>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
092e4a9e4f
commit
3569085cea
@@ -1052,6 +1052,12 @@ function checkQuality(opts) {
|
||||
}
|
||||
|
||||
// --- Cramped padding --- (browser-only: needs rect to skip small badges/labels)
|
||||
// Vertical and horizontal thresholds are independent because line-height
|
||||
// already provides built-in vertical breathing room (the line box is taller
|
||||
// than the cap height), but horizontal has no equivalent. Both scale with
|
||||
// font-size — bigger text demands proportionally more padding.
|
||||
// vertical: max(4px, fontSize × 0.3)
|
||||
// horizontal: max(8px, fontSize × 0.5)
|
||||
if (rect && hasDirectText && textLen > 20 && rect.width > 100 && rect.height > 30) {
|
||||
const borders = {
|
||||
top: parseFloat(style.borderTopWidth) || 0,
|
||||
@@ -1062,16 +1068,22 @@ function checkQuality(opts) {
|
||||
const borderCount = Object.values(borders).filter(w => w > 0).length;
|
||||
const hasBg = style.backgroundColor && style.backgroundColor !== 'rgba(0, 0, 0, 0)';
|
||||
if (borderCount >= 2 || hasBg) {
|
||||
const paddings = [];
|
||||
if (hasBg || borders.top > 0) paddings.push(parseFloat(style.paddingTop) || 0);
|
||||
if (hasBg || borders.right > 0) paddings.push(parseFloat(style.paddingRight) || 0);
|
||||
if (hasBg || borders.bottom > 0) paddings.push(parseFloat(style.paddingBottom) || 0);
|
||||
if (hasBg || borders.left > 0) paddings.push(parseFloat(style.paddingLeft) || 0);
|
||||
if (paddings.length > 0) {
|
||||
const minPad = Math.min(...paddings);
|
||||
if (minPad < 8) {
|
||||
findings.push({ id: 'cramped-padding', snippet: `${minPad}px padding (need >=8px)` });
|
||||
}
|
||||
const vPads = [], hPads = [];
|
||||
if (hasBg || borders.top > 0) vPads.push(parseFloat(style.paddingTop) || 0);
|
||||
if (hasBg || borders.bottom > 0) vPads.push(parseFloat(style.paddingBottom) || 0);
|
||||
if (hasBg || borders.left > 0) hPads.push(parseFloat(style.paddingLeft) || 0);
|
||||
if (hasBg || borders.right > 0) hPads.push(parseFloat(style.paddingRight) || 0);
|
||||
|
||||
const vMin = vPads.length ? Math.min(...vPads) : Infinity;
|
||||
const hMin = hPads.length ? Math.min(...hPads) : Infinity;
|
||||
const vThresh = Math.max(4, fontSize * 0.3);
|
||||
const hThresh = Math.max(8, fontSize * 0.5);
|
||||
|
||||
// Emit at most one finding per element — pick whichever axis is worse.
|
||||
if (vMin < vThresh) {
|
||||
findings.push({ id: 'cramped-padding', snippet: `${vMin}px vertical padding (need ≥${vThresh.toFixed(1)}px for ${fontSize}px text)` });
|
||||
} else if (hMin < hThresh) {
|
||||
findings.push({ id: 'cramped-padding', snippet: `${hMin}px horizontal padding (need ≥${hThresh.toFixed(1)}px for ${fontSize}px text)` });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
-10
@@ -1047,6 +1047,12 @@ function checkQuality(opts) {
|
||||
}
|
||||
|
||||
// --- Cramped padding --- (browser-only: needs rect to skip small badges/labels)
|
||||
// Vertical and horizontal thresholds are independent because line-height
|
||||
// already provides built-in vertical breathing room (the line box is taller
|
||||
// than the cap height), but horizontal has no equivalent. Both scale with
|
||||
// font-size — bigger text demands proportionally more padding.
|
||||
// vertical: max(4px, fontSize × 0.3)
|
||||
// horizontal: max(8px, fontSize × 0.5)
|
||||
if (rect && hasDirectText && textLen > 20 && rect.width > 100 && rect.height > 30) {
|
||||
const borders = {
|
||||
top: parseFloat(style.borderTopWidth) || 0,
|
||||
@@ -1057,16 +1063,22 @@ function checkQuality(opts) {
|
||||
const borderCount = Object.values(borders).filter(w => w > 0).length;
|
||||
const hasBg = style.backgroundColor && style.backgroundColor !== 'rgba(0, 0, 0, 0)';
|
||||
if (borderCount >= 2 || hasBg) {
|
||||
const paddings = [];
|
||||
if (hasBg || borders.top > 0) paddings.push(parseFloat(style.paddingTop) || 0);
|
||||
if (hasBg || borders.right > 0) paddings.push(parseFloat(style.paddingRight) || 0);
|
||||
if (hasBg || borders.bottom > 0) paddings.push(parseFloat(style.paddingBottom) || 0);
|
||||
if (hasBg || borders.left > 0) paddings.push(parseFloat(style.paddingLeft) || 0);
|
||||
if (paddings.length > 0) {
|
||||
const minPad = Math.min(...paddings);
|
||||
if (minPad < 8) {
|
||||
findings.push({ id: 'cramped-padding', snippet: `${minPad}px padding (need >=8px)` });
|
||||
}
|
||||
const vPads = [], hPads = [];
|
||||
if (hasBg || borders.top > 0) vPads.push(parseFloat(style.paddingTop) || 0);
|
||||
if (hasBg || borders.bottom > 0) vPads.push(parseFloat(style.paddingBottom) || 0);
|
||||
if (hasBg || borders.left > 0) hPads.push(parseFloat(style.paddingLeft) || 0);
|
||||
if (hasBg || borders.right > 0) hPads.push(parseFloat(style.paddingRight) || 0);
|
||||
|
||||
const vMin = vPads.length ? Math.min(...vPads) : Infinity;
|
||||
const hMin = hPads.length ? Math.min(...hPads) : Infinity;
|
||||
const vThresh = Math.max(4, fontSize * 0.3);
|
||||
const hThresh = Math.max(8, fontSize * 0.5);
|
||||
|
||||
// Emit at most one finding per element — pick whichever axis is worse.
|
||||
if (vMin < vThresh) {
|
||||
findings.push({ id: 'cramped-padding', snippet: `${vMin}px vertical padding (need ≥${vThresh.toFixed(1)}px for ${fontSize}px text)` });
|
||||
} else if (hMin < hThresh) {
|
||||
findings.push({ id: 'cramped-padding', snippet: `${hMin}px horizontal padding (need ≥${hThresh.toFixed(1)}px for ${fontSize}px text)` });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,14 +74,22 @@ describe('detectUrl — browser-only fixtures', () => {
|
||||
// Everything else in the quality.html fixture runs in jsdom and is asserted
|
||||
// by tests/detect-antipatterns-fixtures.test.mjs.
|
||||
|
||||
it('cramped-padding: flag column triggers, small-pill case is currently a known false positive', async () => {
|
||||
it('cramped-padding: flag column triggers all 8 cramped cases, pass column adds none', async () => {
|
||||
const f = await detectUrl(`${BASE}/fixtures/antipatterns/cramped-padding.html`);
|
||||
const cramped = f.filter(r => r.antipattern === 'cramped-padding');
|
||||
// Flag column: 2 obvious cramped containers (4px and 2px padding).
|
||||
// Pass column: 1 finding from the .detection-cmd-style small pill —
|
||||
// currently a false positive that the user is deciding what to do with.
|
||||
// Total = 3. When the rule is relaxed for small inline pills, expect 2.
|
||||
assert.equal(cramped.length, 3, `expected 3 cramped-padding findings (2 flag + 1 disputed pill), got ${cramped.length}`);
|
||||
// Flag column has 8 cases that should fire under the asymmetric
|
||||
// proportional rule (vertical: max(4, fs×0.3), horizontal: max(8, fs×0.5)):
|
||||
// 1. 14px body / 4px all sides — V fail
|
||||
// 2. 14px body / 2px all sides — both fail
|
||||
// 3. 16px body / 4px all sides — both fail
|
||||
// 4. 14px body / 1px V / 16px H — V fail
|
||||
// 5. 14px body / 12px V / 4px H — H fail
|
||||
// 6. 24px heading / 8px all sides — H fail (improvement over old 8px floor)
|
||||
// 7. 32px hero / 6px V / 16px H — V fail
|
||||
// 8. 14px <pre> / 2px all sides — both fail
|
||||
// Pass column has 12 cases (small pills, standard cards, code blocks,
|
||||
// buttons, inputs, big text with proportional padding) — none should fire.
|
||||
assert.equal(cramped.length, 8, `expected 8 cramped-padding findings, got ${cramped.length}`);
|
||||
});
|
||||
|
||||
it('line-length: flag column triggers, pass column adds none', async () => {
|
||||
|
||||
+152
-91
@@ -5,96 +5,84 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Cramped Padding — Should Flag vs Should Pass</title>
|
||||
<style>
|
||||
/* Two-column fixture: left = should flag, right = should pass.
|
||||
Focused on the cramped-padding rule alone so we can think about
|
||||
its threshold and edge cases without other rules interfering. */
|
||||
body { font-family: system-ui, sans-serif; background: #fafafa; padding: 24px; margin: 0; color: #0f172a; }
|
||||
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; max-width: 1200px; margin: 0 auto; }
|
||||
/* 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: 11px; text-transform: uppercase; letter-spacing: 0.05em; margin: 24px 0 8px; color: #64748b; }
|
||||
.case { margin-bottom: 12px; }
|
||||
.case-label { display: block; font-size: 11px; color: #64748b; margin-bottom: 4px; }
|
||||
.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: clearly cramped ── */
|
||||
/* ── 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; }
|
||||
|
||||
/* 4px padding on a bordered container with body-length text */
|
||||
.cramped-border {
|
||||
border: 1px solid #d1d5db;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
/* ── 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; }
|
||||
|
||||
/* 2px padding on a colored container */
|
||||
.cramped-bg {
|
||||
background: #e5e7eb;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
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; }
|
||||
|
||||
/* Zero padding on a bordered container — text touches the border */
|
||||
.cramped-zero {
|
||||
border: 2px solid #3b82f6;
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
/* ── 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: comfortable padding ── */
|
||||
|
||||
.good-padding {
|
||||
border: 1px solid #d1d5db;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.good-padding-bg {
|
||||
background: #f1f5f9;
|
||||
padding: 14px 18px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Small inline command pill — exact replica of .detection-cmd on
|
||||
the impeccable.style homepage. The detector currently flags 6px
|
||||
vertical padding as "cramped", but visually this is a small
|
||||
inline badge where the generous 14px horizontal padding plus
|
||||
tight font-size makes 6px vertical look balanced. Under
|
||||
consideration: should the rule skip small inline pills, or
|
||||
relax for small font sizes? */
|
||||
.small-pill {
|
||||
display: inline-block;
|
||||
font-family: ui-monospace, SFMono-Regular, monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1.625; /* matches inherited body line-height on homepage */
|
||||
color: #0f172a;
|
||||
background: #f5f5f7;
|
||||
padding: 6px 14px;
|
||||
border-radius: 6px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.small-pill::before {
|
||||
content: '➜ ';
|
||||
color: #ec4899;
|
||||
}
|
||||
|
||||
/* Same pill at the 8px threshold — should pass cleanly */
|
||||
.small-pill-8 {
|
||||
/* ── 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: 8px 14px;
|
||||
padding: 6px 14px;
|
||||
border-radius: 6px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.small-pill-8::before {
|
||||
content: '➜ ';
|
||||
color: #ec4899;
|
||||
.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>
|
||||
@@ -106,18 +94,47 @@
|
||||
<div class="col" data-col="flag">
|
||||
<h2>Should flag</h2>
|
||||
|
||||
<h3>Bordered containers with too-small padding</h3>
|
||||
<h3>Cramped body in cards</h3>
|
||||
<div class="case">
|
||||
<span class="case-label">4px padding, bordered, body-length text</span>
|
||||
<div class="cramped-border">This text is crammed against the border with only 4px padding. It feels claustrophobic and hard to read.</div>
|
||||
<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">2px / 4px padding, colored background</span>
|
||||
<div class="cramped-bg">Cramped background padding makes the body text feel jammed against the edges of the colored container.</div>
|
||||
<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">Zero padding, bordered</span>
|
||||
<div class="cramped-zero">Zero padding on a bordered element. The text is literally touching the border.</div>
|
||||
<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>
|
||||
|
||||
@@ -127,24 +144,68 @@
|
||||
<div class="col" data-col="pass">
|
||||
<h2>Should pass</h2>
|
||||
|
||||
<h3>Comfortable container padding</h3>
|
||||
<h3>Small inline pills</h3>
|
||||
<div class="case">
|
||||
<span class="case-label">16px padding, bordered</span>
|
||||
<div class="good-padding">This container has 16px padding, giving the text room to breathe within its border.</div>
|
||||
<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">14px / 18px padding, colored background</span>
|
||||
<div class="good-padding-bg">Generous padding inside the colored container — text has plenty of room from the edge.</div>
|
||||
<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>Small inline pills (under consideration)</h3>
|
||||
<h3>Cards at current standards</h3>
|
||||
<div class="case">
|
||||
<span class="case-label">6px / 14px small pill (matches .detection-cmd on impeccable.style)</span>
|
||||
<code class="small-pill">npx impeccable detect src/</code>
|
||||
<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">8px / 14px small pill (clears the rule's current 8px floor)</span>
|
||||
<code class="small-pill-8">npx impeccable detect src/</code>
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user