mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-11 21:57:14 +03:00
* Add a platform axis (web / ios / android / adaptive) to the skill Orthogonal to register: register decides whether design IS or SERVES the product; platform decides the delivery target and which native conventions apply. Set `## Platform` in PRODUCT.md; a missing field defaults to `web`, so legacy projects are unaffected. - extractPlatform() in skill/scripts/context.mjs (mirrors extractRegister); the CLI appends a NEXT STEP directive to read the native reference(s). `adaptive` (Flutter / RN / KMP shipping both iOS and Android) loads both ios.md and android.md. - New reference/ios.md (Apple HIG distilled) and reference/android.md (Material 3 distilled); reference/web.md is a thin pointer. The native refs frame register's role as narrow: platform conformance is the bar, brand lives in the expressive layer the platform gives you, never by breaking the rails. - Setup step 5 loads the native reference(s) when platform is native. Live mode and the detect CLI stay web-only, gated off ios/android/adaptive. - init asks platform right after register; adapt/audit/animate/layout carry short platform divergence notes; all secondary spots thread `adaptive`. - a11y stays in audit.md (loading it at design time makes output timid), so the native refs carry no Accessibility section; audit.md's Platform section owns native a11y. - Tests: extractPlatform unit coverage + skill-behavior scenario 10 (PRODUCT.md platform ios -> agent loads ios.md). Source-first: only skill/, scripts/, tests/, CLAUDE.md, NOTICE.md, the changelog and version are committed; the sync workflow regenerates the provider trees and ./plugin on merge. ios.md / android.md are distilled from the MIT-licensed ehmo/platform-design-skills; attribution in NOTICE.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Address review: gate web tools on native platforms, drop version churn Maintainer-review fixes applied with AI assistance (Claude Code), on top of the rebased platform-axis commit: - Design hook (post-edit and Cursor pre-edit) now resolves the project platform via loadContext + extractPlatform and skips its web rule scan for ios / android / adaptive projects, so React Native / Flutter code never draws web-shaped findings (new hook-lib resolveProjectPlatform / isNativePlatform helpers, covered by unit and subprocess tests). - context.mjs CLI warns on an unrecognized ## Platform value (e.g. a toolchain name like `flutter`) instead of silently defaulting to web; extractRegister / extractPlatform now share extractSectionValue. - Removed reference/web.md: nothing loaded it; CLAUDE.md carries the "web has no extra rulebook" explanation. - init.md: skip live-mode config (Step 6) for native platforms; note the per-app PRODUCT.md pattern for repos shipping web + native. - android.md: Material-everywhere apps that also ship on iPhone still owe iOS OS guarantees (safe areas, Reduce Motion, edge-swipe back). - ios.md: reworded a design-time line that framed Dynamic Type as an accessibility check (a11y stays owned by audit.md). - Renumbered the new skill-behavior scenario to 14 after main's 10-13; updated CLAUDE.md scenario list; added android + unrecognized-value CLI test cases. - No version or changelog changes: versioning happens at release time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Tighten platform reference prose Editorial pass on the platform-axis text, applied with AI assistance (Claude Code) under maintainer direction: - ios.md / android.md rewritten to house style: single-line paragraphs (no hard wraps), one-sentence scope intro, deduplicated intro/slop-test, register-compression down to two sentences. In-file attribution paragraphs removed (NOTICE.md owns attribution); "read on top of the register reference" cruft removed (SKILL step 5 and the context.mjs directive already say it). Bans sections dropped: they restated the rules above them; the two additive items (tab-bar overload, hover-dependent affordances) folded into rules. ~40% smaller each. - Sub-command Platform sections (adapt, audit, animate, layout), SKILL step 5, init.md platform prose, and the context.mjs directive trimmed the same way. Build (prose validators, counts) and both test runners green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Treat an empty PRODUCT.md section as absent, not the next heading Copilot review catch: extractSectionValue read the next `## ...` heading as the section value when a field was left empty, which made the CLI warn "value `## Product Purpose` is not recognized". Stop at the next heading and return null instead. Regression tests for extractPlatform, extractRegister, and the CLI warning path. Applied with AI assistance (Claude Code) under maintainer direction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Only read a token list of both native targets as adaptive Bugbot catch: after the exact platform tokens failed, any Platform line containing the words ios and android was classified adaptive, so negated or explanatory prose ("web only, not ios or android") silently loaded both native refs and skipped the hook, with no warning. The combo parse now accepts only list separators and the two platform words; anything else falls through to the CLI's unrecognized-value WARNING. Regression tests added. Applied with AI assistance (Claude Code) under maintainer direction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Paul Bakaus <paul.bakaus@gmail.com>
166 lines
8.8 KiB
Markdown
166 lines
8.8 KiB
Markdown
Space is the most underused design tool. Find the layout's actual problem (monotone spacing, weak hierarchy, identical card grids) and fix the structure, not the surface.
|
||
|
||
---
|
||
|
||
## Register
|
||
|
||
Brand: asymmetric compositions, fluid spacing with `clamp()`, intentional grid-breaking for emphasis. Rhythm through contrast: tight groupings paired with generous separations.
|
||
|
||
Product: predictable grids, consistent densities, familiar navigation patterns. Responsive behavior is structural (collapse sidebar, responsive table), not fluid typography. Consistency IS an affordance.
|
||
|
||
## Platform
|
||
|
||
Native (`ios` / `android` / `adaptive`): structure follows platform navigation (iOS tab bar / navigation stack; Android navigation bar / rail / drawer), safe-area / window insets, and spec touch targets (44 pt iOS, 48 dp Android). See [ios.md](ios.md) and [android.md](android.md); `adaptive` lays out per OS.
|
||
|
||
---
|
||
|
||
## Assess Current Layout
|
||
|
||
Analyze what's weak about the current spatial design:
|
||
|
||
1. **Spacing**:
|
||
- Is spacing consistent or arbitrary? (Random padding/margin values)
|
||
- Is all spacing the same? (Equal padding everywhere = no rhythm)
|
||
- Are related elements grouped tightly, with generous space between groups?
|
||
|
||
2. **Visual hierarchy**:
|
||
- Apply the squint test: blur your (metaphorical) eyes. Can you still identify the most important element, second most important, and clear groupings?
|
||
- Is hierarchy achieved effectively? (Space and weight alone can be enough; is the current approach working?)
|
||
- Does whitespace guide the eye to what matters?
|
||
|
||
3. **Grid & structure**:
|
||
- Is there a clear underlying structure, or does the layout feel random?
|
||
- Are identical card grids used everywhere? (Icon + heading + text, repeated endlessly)
|
||
|
||
4. **Rhythm & variety**:
|
||
- Does the layout have visual rhythm? (Alternating tight/generous spacing)
|
||
- Is every section structured the same way? (Monotonous repetition)
|
||
- Are there intentional moments of surprise or emphasis?
|
||
|
||
5. **Density**:
|
||
- Is the layout too cramped? (Not enough breathing room)
|
||
- Is the layout too sparse? (Excessive whitespace without purpose)
|
||
- Does density match the content type? (Data-dense UIs need tighter spacing; marketing pages need more air)
|
||
|
||
**CRITICAL**: Layout problems are often the root cause of interfaces feeling "off" even when colors and fonts are fine. Space is a design material; use it with intention.
|
||
|
||
## Plan Layout Improvements
|
||
|
||
Create a systematic plan:
|
||
|
||
- **Spacing system**: Use a consistent scale (a framework's built-in scale like Tailwind's, rem-based tokens, or a custom system). The specific values matter less than consistency.
|
||
- **Hierarchy strategy**: How will space communicate importance?
|
||
- **Layout approach**: What structure fits the content? Flex for 1D, Grid for 2D, named areas for complex page layouts.
|
||
- **Rhythm**: Where should spacing be tight vs generous?
|
||
|
||
## Improve Layout Systematically
|
||
|
||
### Establish a Spacing System
|
||
|
||
- Use a consistent spacing scale (framework scales like Tailwind, rem-based tokens, or a custom scale all work). What matters is that values come from a defined set, not arbitrary numbers.
|
||
- Prefer a 4pt base scale (4, 8, 12, 16, 24, 32, 48, 64, 96px) over 8pt; 8pt is too coarse and you'll frequently need 12px between 8 and 16.
|
||
- Name tokens semantically if using custom properties: `--space-xs` through `--space-xl`, not `--spacing-8`
|
||
- Use `gap` for sibling spacing instead of margins; eliminates margin collapse hacks
|
||
- Apply `clamp()` for fluid spacing that breathes on larger screens
|
||
|
||
### Create Visual Rhythm
|
||
|
||
- **Tight grouping** for related elements (8-12px between siblings)
|
||
- **Generous separation** between distinct sections (48-96px)
|
||
- **Varied spacing** within sections (not every row needs the same gap)
|
||
- **Asymmetric compositions**: a deliberate choice when the content invites it (not a default to chase).
|
||
|
||
### Choose the Right Layout Tool
|
||
|
||
- **Use Flexbox for 1D layouts**: Rows of items, nav bars, button groups, card contents, most component internals.
|
||
- **Use Grid for 2D layouts**: Page-level structure, dashboards, data-dense interfaces, anything where rows AND columns need coordinated control.
|
||
- Use named grid areas (`grid-template-areas`) for complex page layouts; redefine at breakpoints.
|
||
- Use **container queries** for components, viewport queries for page layouts. A card in a narrow sidebar can stay compact while the same card in a main content area expands automatically:
|
||
|
||
```css
|
||
.card-container { container-type: inline-size; }
|
||
.card { display: grid; gap: var(--space-md); }
|
||
@container (min-width: 400px) {
|
||
.card { grid-template-columns: 120px 1fr; }
|
||
}
|
||
```
|
||
|
||
### Break Card Grid Monotony
|
||
|
||
- Don't default to card grids for everything; spacing and alignment create visual grouping naturally
|
||
- Use cards only when content is truly distinct and actionable. Never nest cards inside cards
|
||
- Vary card sizes, span columns, or mix cards with non-card content to break repetition
|
||
|
||
### Strengthen Visual Hierarchy
|
||
|
||
- Use the fewest dimensions needed for clear hierarchy. Space alone can be enough; generous whitespace around an element draws the eye. Some of the most polished designs achieve rhythm with just space and weight. Add color or size contrast only when simpler means aren't sufficient.
|
||
- The best hierarchy combines 2–3 dimensions at once. A heading that's larger, bolder, AND has more space above it reads as primary without trying:
|
||
|
||
| Tool | Strong Hierarchy | Weak Hierarchy |
|
||
|------|------------------|----------------|
|
||
| **Size** | 3:1 ratio or more | <2:1 ratio |
|
||
| **Weight** | Bold vs Regular | Medium vs Regular |
|
||
| **Color** | High contrast | Similar tones |
|
||
| **Position** | Top/left (primary) | Bottom/right |
|
||
| **Space** | Surrounded by white space | Crowded |
|
||
|
||
- Be aware of reading flow: in LTR languages, the eye naturally scans top-left to bottom-right, but primary action placement depends on context (e.g., bottom-right in dialogs, top in navigation).
|
||
- Create clear content groupings through proximity and separation.
|
||
|
||
### Manage Depth & Elevation
|
||
|
||
- Build a consistent shadow scale (sm → md → lg → xl); shadows should be subtle
|
||
- Use elevation to reinforce hierarchy, not as decoration
|
||
|
||
### Optical Adjustments
|
||
|
||
- If an icon looks visually off-center despite being geometrically centered, nudge it. But only if you're confident it actually looks wrong. Don't adjust speculatively.
|
||
- Text at `margin-left: 0` looks slightly indented because of letterform whitespace; a negative margin (`-0.05em`) optically aligns it. Geometrically centered glyphs often look off-center (play icons need to shift right, arrows shift toward their direction).
|
||
- Touch targets must be 44×44px minimum even when the visual element is smaller. Expand the hit area with padding or a pseudo-element:
|
||
|
||
```css
|
||
.icon-button { width: 24px; height: 24px; position: relative; }
|
||
.icon-button::before {
|
||
content: ''; position: absolute; inset: -10px;
|
||
}
|
||
```
|
||
|
||
**NEVER**:
|
||
- Use arbitrary spacing values outside your scale
|
||
- Make all spacing equal (variety creates hierarchy)
|
||
- Wrap everything in cards (not everything needs a container)
|
||
- Nest cards inside cards (use spacing and dividers for hierarchy within)
|
||
- Use identical card grids everywhere (icon + heading + text, repeated)
|
||
- Default to the hero metric layout (big number, small label, stats, gradient) as a template. If showing real user data, a prominent metric can work, but it should display actual data, not decorative numbers.
|
||
|
||
## Verify Layout Improvements
|
||
|
||
- **Squint test**: Can you identify primary, secondary, and groupings with blurred vision?
|
||
- **Rhythm**: Does the page have a satisfying beat of tight and generous spacing?
|
||
- **Hierarchy**: Is the most important content obvious within 2 seconds?
|
||
- **Breathing room**: Does the layout feel comfortable, not cramped or wasteful?
|
||
- **Consistency**: Is the spacing system applied uniformly?
|
||
- **Responsiveness**: Does the layout adapt gracefully across screen sizes?
|
||
|
||
When the rhythm and hierarchy land, hand off to `{{command_prefix}}impeccable polish` for the final pass.
|
||
|
||
## Live-mode signature params
|
||
|
||
Each variant MUST declare a `density` param. Drive all spacing tokens in the variant's scoped CSS through `calc(var(--p-density, 1) * <base>)`: paddings, gaps, column widths. Users slide from airy to packed and see layout re-breathe with no regeneration.
|
||
|
||
```json
|
||
{"id":"density","kind":"range","min":0.6,"max":1.4,"step":0.05,"default":1,"label":"Density"}
|
||
```
|
||
|
||
For variants whose topology genuinely changes (stacked vs. side-by-side, grid vs. bento), use a `steps` param whose scoped CSS branches via `:scope[data-p-structure="X"]`. One structure param + one density param is a powerful combo; resist adding a third.
|
||
|
||
```json
|
||
{"id":"structure","kind":"steps","default":"grid","label":"Structure","options":[
|
||
{"value":"stacked","label":"Stacked"},
|
||
{"value":"grid","label":"Grid"},
|
||
{"value":"bento","label":"Bento"}
|
||
]}
|
||
```
|
||
|
||
See `reference/live.md` for the full params contract.
|