/ordinary-interfaces

180 interface rules that carry a number.

An agent skill for building and auditing UI. Every rule states a value, cites where that value came from, and says where it stops applying.

Ordinary is the goal, and it is not the same as generic. An ordinary interface is unremarkable in use. It behaves the way people already expect, its hit areas are where fingers go, its errors appear where the user is looking. Generic is the other failure: the same cream-and-terracotta palette on every brief, because nothing was decided.

Source on GitHub

In Claude Code: /plugin marketplace add Board-ly/ordinary-interfaces

Commands

Six ways in, when you only need one step

The skill loads itself when a task calls for it. These run one part of it on demand, so a contrast check does not pull in 180 rules. None of them auto-load.

  • read-project[path]

    Reads what your codebase already decided about tokens, scales, colour notation and motion, so a review adopts your system instead of overwriting it.

  • accessibility[file or path]

    The seven floors only: contrast, colour, hit areas, alt text, focus, motion, reflow. Pass, fail or unverified, and one verdict.

  • review[file, component, screenshot]

    The full review, ordered critical to low. Every finding carries a rule id, the measured value and the fix.

  • new-screen[what you are building]

    The workflow for building. Adopt the system, let the floors constrain the space, greyscale first, hardest state first.

  • contrast<fg> <bg> [--fix]

    Measures a pair against WCAG and reports the ratio. --fix returns the nearest passing foreground, hue kept.

  • find-rule[rule-id or topic]

    One rule by id or topic: the value, its evidence grade, and where it stops applying.

Evidence

Every number carries its evidence

Design advice stops being trustworthy the moment a convention gets repeated as a law. So each value is graded, and the grade travels with it into whatever the skill tells you.

[spec]

Normative. WCAG 2.2, ISO, OpenType. Stated as required, never hedged.25 rules

[measured]

From a study, carrying its sample size where that matters, cited to the primary source rather than to someone's summary of it.40 rules

[convention]

Industry practice with no primary source. The 8pt grid lives here. Useful, well reasoned, and not a fact.36 rules

Gates

10 rules are not negotiable

Accessibility floors with legal weight in most jurisdictions. They constrain the solution space before anything gets drawn.

  • wcag-contrast Contrast Ratio
  • red-green-color-blindness Never Color Alone
  • touch-target Size the Hit Area, Not the Glyph
  • wcag-images Equivalent Purpose, Not Description
  • wcag-motion Flashing and Vestibular Safety
  • reduced-motion Gentler, Not Absent
  • native-elements-first Don't Rebuild What Ships
  • focus-visible Style the Right Pseudo-Class
  • keyboard-patterns Follow the APG
  • alt-by-purpose Describe the Job, Not the Picture

Shape of a rule

A ruling, then the numbers, then the exceptions

One schema throughout: what to do, the values, why it holds and who established it, where it stops applying, and the code.

concentric-radiusOuter Equals Inner Plus Padding
outerRadius = innerRadius + padding
empty-statesEmpty Is Three States
All three render zero rows, which is why they get one screen. That screen is wrong for two of them.
animation-necessityAsk Whether, Before Asking Which
Frequency decides. The first question is never the easing curve.
padding-gap-ratioPadding Exceeds the Gap
Container padding ≥ 1.5× the gap to its siblings, at every nesting level.
default-effectPreselection Persists
Defaults are a design decision with a legal boundary.

Before and after

The same component, with and without

Live, not screenshots. Every pane below is the rule applied to real markup, so it renders in your theme and cannot drift from what the rule says.

concentric-radiusOuter Equals Inner Plus Padding

outerRadius = innerRadius + padding

outer 12px · inner 12 + padding 8 = 20breaks the rule

padding-gap-ratioPadding Exceeds the Gap

Container padding ≥ 1.5× the gap to its siblings, at every nesting level.

padding 16px · gap 16px · 1× the gapbreaks the rule

icon-optical-balanceCentre by Mass, Not by Box

Offset 1–3px toward the lighter side. No formula covers every shape.

0px

translateX(0) · centred on the box, not on the massbreaks the rule

icon-stroke-weightMatch the Adjacent Text

Icon weight is a function of the label beside it, not an independent choice.

New project

1.5px stroke beside a 700 labelbreaks the rule

wcag-contrastContrast Ratio

Body text clears 4.5:1 against what it actually renders on. Large text and any control that carries meaning clear 3:1.

Aa

#777777 on #ffffff · 4.48:1breaks the rule

touch-targetSize the Hit Area, Not the Glyph

24×24 is the floor. 44×44 on touch and 40×40 on desktop is the target. Padding counts.

28×28px around a 16px glyphbreaks the rule

default-tellsRecognise Your Own Defaults

Ordinary is decided. Generic is undecided. They look different.

Invoice

INV-0114 is overdue

Sent 12 March. Due 26 March. Studio Sphere has opened it twice.

Send a reminder

ordinary · this project's own tokenssatisfies the rule

dark-mode-color-adaptationThree Axes, Three Jobs

Hold hue, cut chroma, raise tone until it measures. Never invert lightness and call it done.

DarkSpec10.10:1Measured6.71:1Convention14.66:1LightSpec5.89:1Measured6.98:1Convention5.00:1

hue held, tone moved until it measuressatisfies the rule

error-copySay How to Fix It, Where It Broke

An error is an instruction, and it belongs beside the field that failed.

3 to go
That is 13 digits. Visa numbers have 16.

beside the field, stays, says what to dosatisfies the rule

never-scale-zeroNothing Appears From Nothing

Start at scale(0.95) with opacity: 0.

from 0.95 and opacity 0, 180ms ease-outsatisfies the rule

Step 0

It reads your project before it quotes a default

A 7px radius in a system built on 7px is correct, and "should be 8px per the grid" is noise. So the skill looks first. A finding is this breaks the project's own system before it is this differs from the reference.

$ python3 scripts/project-system.py .

Tokens  (159 custom properties across 6 files)
  families: color (37×), ink (5×), font (5×), radius (5×), ease (4×)

Scales
  radius:      999px (13×), 7px (10×), 10px (8×), 6px (6×), 4px (6×)
  spacing:     10px (10×), 6px (10×), 4px (10×), 7px (7×), 14px (6×)
  breakpoints: 720px (2×), 880px, 1160px, 900px, 560px, 40rem, 48rem

Colour notation
  hex      343  (72%)
  oklch    130  (27%)
  → Mixed notation. Match the dominant one (hex).

Flags
  ✓ :focus-visible   ✓ prefers-reduced-motion   ✓ tabular-nums
    67× fixed height on text     1× outline: none

Contents

171 UI rules across 13 areas

Routed, not dumped. The skill loads only the file the task touches. A fifteenth file below sits outside the UI focus and is kept as an appendix.

Colour

21 rules

Contrast, ramps, tokens, dark mode, gradient interpolation.

  • wcag-contrast
  • red-green-color-blindness
  • dark-mode-color-adaptation
  • luminance-vs-lightness
  • cielab-color-space
  • ramp-structure
  • ramp-construction
  • color-naming
  • token-role-discipline
  • one-color-one-meaning
  • fill-one-action
  • color-scale
  • greyscale
  • 60-30-10
  • color-temperature-dominance
  • saturation-control
  • simultaneous-contrast
  • color-constancy
  • color-psychology
  • gradient-interpolation
  • rgb-vs-cmyk

Typography

23 rules

Scale, measure, leading, weight floors, wrapping, web font delivery.

  • type-hierarchy
  • line-length
  • line-height
  • three-line-leading
  • text-alignment
  • font-weight-contrast
  • weight-size-floor
  • x-height
  • font-pairing
  • wcag-typography
  • text-wrap
  • letter-spacing-by-size
  • all-caps-fatigue
  • ios-input-zoom
  • variable-fonts
  • typeface-vs-font
  • font-synthesis
  • css-properties-over-tags
  • smart-punctuation
  • underline-metrics
  • small-caps
  • ligatures
  • font-smoothing

Spacing & layout

17 rules

Proximity, the padding-to-gap rule, grids, breakpoints, translation growth.

  • proximity
  • padding-gap-ratio
  • group-with-space
  • 8pt-grid
  • 4pt-system
  • baseline-grid
  • active-white-space
  • controls-distinct
  • align-to-shared-edges
  • progressive-disclosure-cue
  • content-breakpoints
  • translation-growth
  • content-bleeds-controls-float
  • manuscript-grid
  • twelve-column-grid
  • modular-grid
  • wcag-layout

Controls & forms

8 rules

Hit areas, the six button states, links, form and navigation criteria.

  • touch-target
  • button-design
  • button-padding
  • link-design
  • wcag-forms
  • wcag-navigation
  • wcag-images
  • wcag-motion

Surfaces

5 rules

Concentric radius, shadow-as-border, image outlines, press feedback.

  • concentric-radius
  • shadow-as-border
  • image-outlines
  • press-scale
  • theme-switch-suppression

System craft

8 rules

Elevation, borders, depth strategy, tokens, recognising your own defaults.

  • surface-elevation
  • border-discipline
  • depth-strategy
  • token-architecture
  • interactive-states
  • tabular-numerals
  • icon-restraint
  • default-tells

Depth & icons

10 rules

Light direction, elevation scale, stroke matching, optical centring, RTL.

  • shadow-fundamentals
  • elevation-system
  • raised-vs-inset
  • icon-stroke-weight
  • icon-bounding-box
  • icon-optical-balance
  • icon-alignment
  • icon-color-states
  • icon-render-size
  • icons-rtl

Motion

22 rules

Whether to animate at all, duration, easing, springs, gestures, reduced motion.

  • animation-necessity
  • animation-duration
  • easing-curves
  • enter-exit-asymmetry
  • subtle-exit
  • never-scale-zero
  • transform-origin
  • stagger
  • staged-enter
  • icon-transitions
  • spring-physics
  • gesture-physics
  • animation-performance
  • transition-specificity
  • will-change-discipline
  • hover-gating
  • motion-restraint
  • reduced-motion
  • seam-principle
  • reveal-choreography
  • state-transition-timing
  • numbers-in-motion

Non-happy states

10 rules

The ledger, three empty states, loading guards, error taxonomy, rollback.

  • state-ledger
  • empty-states
  • loading-strategy
  • partial-data
  • error-taxonomy
  • optimistic-rollback
  • overflow-pressure
  • offline-stale
  • permission-states
  • end-of-list

Accessibility

9 rules

Native elements, focus-visible, keyboard patterns, live regions, alt text.

  • native-elements-first
  • focus-visible
  • keyboard-patterns
  • focus-trap
  • hit-area-extension
  • form-controls
  • error-announcement
  • live-regions
  • alt-by-purpose

Interface copy

9 rules

Voice, vocabulary, button labels, errors, empty states, capitalisation.

  • voice-and-tone
  • consistent-vocabulary
  • verb-first-buttons
  • link-text
  • error-copy
  • empty-state-copy
  • toggle-labels
  • capitalization-policy
  • no-string-concatenation

Hierarchy

9 rules

Emphasis, visual weight, framing heuristics, chart encoding.

  • emphasis
  • visual-weight
  • hierarchy-channels
  • rule-of-thirds
  • golden-ratio
  • rule-of-odds
  • corner-radius-tone
  • pie-chart-problem
  • handmade-vs-polished

Cognition

20 rules

Choice cost, memory, attention, defaults, and the numbers people quote wrong.

  • jakobs-law
  • millers-law
  • chunking
  • hicks-law
  • subitizing
  • von-restorff-effect
  • banner-blindness
  • inattentional-blindness
  • default-effect
  • decoy-effect
  • peak-end-rule
  • picture-superiority
  • stroop-effect
  • reward-anticipation
  • ebbinghaus-illusion
  • optical-center
  • center-bias
  • muller-lyer-illusion
  • irradiation-illusion
  • bouba-kiki-effect

Beyond the screen

9 rules

Brand assets, photography, physical scale, print. Outside the UI focus.

  • viewing-distance
  • visual-angle-arcminutes
  • aspect-ratios
  • logo-clearspace
  • logo-variations
  • joint-cropping
  • dieline-bleed
  • cmyk-vs-pantone
  • iso-216