@mohammadhprp/system-prompt 0.12.2 → 0.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/framework/commands/README.md +1 -1
- package/framework/commands/review.md +1 -1
- package/framework/mcps/README.md +0 -1
- package/framework/plugins/ponytail/README.md +0 -1
- package/framework/plugins/ponytail/capabilities.md +1 -1
- package/framework/references/standards/api.md +0 -1
- package/framework/references/standards/architecture.md +0 -1
- package/framework/references/standards/database.md +0 -1
- package/framework/references/standards/debugging.md +0 -1
- package/framework/references/standards/documentation.md +0 -1
- package/framework/references/standards/logging.md +0 -1
- package/framework/references/standards/naming.md +0 -1
- package/framework/references/standards/observability.md +0 -1
- package/framework/references/standards/performance.md +0 -1
- package/framework/references/standards/pull-requests.md +0 -1
- package/framework/references/standards/security.md +0 -1
- package/framework/references/standards/testing.md +0 -1
- package/framework/skills/README.md +1 -12
- package/framework/skills/improve/SKILL.md +1 -3
- package/framework/skills/improve/examples.md +1 -1
- package/framework/skills/laravel-best-practices/SKILL.md +56 -216
- package/framework/skills/laravel-best-practices/references/architecture.md +1 -1
- package/framework/skills/laravel-best-practices/references/checklist.md +139 -0
- package/framework/skills/laravel-best-practices/references/eloquent.md +4 -2
- package/framework/skills/laravel-best-practices/references/infer-conventions.md +97 -0
- package/framework/skills/laravel-best-practices/references/pest-testing.md +47 -18
- package/framework/skills/laravel-best-practices/references/security.md +1 -1
- package/framework/skills/laravel-best-practices/references/style.md +1 -1
- package/framework/skills/laravel-best-practices/references/tailwindcss.md +0 -1
- package/package.json +1 -1
- package/src/catalog.js +1 -13
- package/framework/mcps/notion-mcp/README.md +0 -57
- package/framework/mcps/notion-mcp/capabilities.md +0 -118
- package/framework/mcps/notion-mcp/configs/opencode.json +0 -9
- package/framework/mcps/notion-mcp/install.md +0 -70
- package/framework/mcps/notion-mcp/troubleshooting.md +0 -95
- package/framework/skills/brainstorming/SKILL.md +0 -159
- package/framework/skills/brainstorming/examples.md +0 -49
- package/framework/skills/brainstorming/scripts/frame-template.html +0 -213
- package/framework/skills/brainstorming/scripts/helper.js +0 -167
- package/framework/skills/brainstorming/scripts/server.cjs +0 -723
- package/framework/skills/brainstorming/scripts/start-server.sh +0 -209
- package/framework/skills/brainstorming/scripts/stop-server.sh +0 -120
- package/framework/skills/brainstorming/visual-companion.md +0 -291
- package/framework/skills/code-review/SKILL.md +0 -72
- package/framework/skills/code-review/examples.md +0 -31
- package/framework/skills/codenavi/SKILL.md +0 -306
- package/framework/skills/codenavi/examples.md +0 -33
- package/framework/skills/codenavi/references/coding-principles.md +0 -143
- package/framework/skills/codenavi/references/notebook-spec.md +0 -171
- package/framework/skills/create-adr/SKILL.md +0 -429
- package/framework/skills/create-adr/examples.md +0 -35
- package/framework/skills/design/SKILL.md +0 -399
- package/framework/skills/design/examples.md +0 -34
- package/framework/skills/great-interface/SKILL.md +0 -43
- package/framework/skills/great-interface/references/animations.md +0 -205
- package/framework/skills/great-interface/references/better-accessibility.md +0 -106
- package/framework/skills/great-interface/references/better-colors.md +0 -100
- package/framework/skills/great-interface/references/better-interface.md +0 -132
- package/framework/skills/great-interface/references/better-layout.md +0 -76
- package/framework/skills/great-interface/references/better-typography.md +0 -157
- package/framework/skills/great-interface/references/better-ui.md +0 -107
- package/framework/skills/great-interface/references/better-writing.md +0 -109
- package/framework/skills/great-interface/references/choosing-fonts.md +0 -64
- package/framework/skills/great-interface/references/color-formats.md +0 -90
- package/framework/skills/great-interface/references/color-usage.md +0 -118
- package/framework/skills/great-interface/references/contrast.md +0 -79
- package/framework/skills/great-interface/references/css-cheat-sheet.md +0 -65
- package/framework/skills/great-interface/references/details-and-accessibility.md +0 -119
- package/framework/skills/great-interface/references/enter-exit.md +0 -147
- package/framework/skills/great-interface/references/explain-interface.md +0 -126
- package/framework/skills/great-interface/references/find-the-effect.md +0 -94
- package/framework/skills/great-interface/references/focus-and-keyboard.md +0 -131
- package/framework/skills/great-interface/references/forms.md +0 -84
- package/framework/skills/great-interface/references/from-an-image.md +0 -55
- package/framework/skills/great-interface/references/grouping-and-alignment.md +0 -123
- package/framework/skills/great-interface/references/hit-areas.md +0 -94
- package/framework/skills/great-interface/references/icon-transitions.md +0 -102
- package/framework/skills/great-interface/references/icons.md +0 -110
- package/framework/skills/great-interface/references/interface-review.md +0 -148
- package/framework/skills/great-interface/references/motion-and-zoom.md +0 -79
- package/framework/skills/great-interface/references/no-browser.md +0 -73
- package/framework/skills/great-interface/references/palette-generation.md +0 -104
- package/framework/skills/great-interface/references/palette-structure.md +0 -76
- package/framework/skills/great-interface/references/performance.md +0 -88
- package/framework/skills/great-interface/references/picker.md +0 -76
- package/framework/skills/great-interface/references/read-the-system.md +0 -178
- package/framework/skills/great-interface/references/removed-signals.md +0 -38
- package/framework/skills/great-interface/references/review-format.md +0 -46
- package/framework/skills/great-interface/references/scope-resolution.md +0 -88
- package/framework/skills/great-interface/references/screen-readers.md +0 -101
- package/framework/skills/great-interface/references/semantics-and-aria.md +0 -84
- package/framework/skills/great-interface/references/spacing-and-adaptivity.md +0 -159
- package/framework/skills/great-interface/references/spacing-and-sizing.md +0 -121
- package/framework/skills/great-interface/references/surfaces.md +0 -219
- package/framework/skills/great-interface/references/token-naming.md +0 -97
- package/framework/skills/great-interface/references/variable-fonts-and-opentype.md +0 -105
- package/framework/skills/great-interface/references/variant.md +0 -104
- package/framework/skills/great-interface/references/wrapping-and-punctuation.md +0 -55
- package/framework/skills/learning-opportunities/SKILL.md +0 -140
- package/framework/skills/learning-opportunities/examples.md +0 -34
- package/framework/skills/learning-opportunities/references/PRINCIPLES.md +0 -42
- package/framework/skills/notion-mcp/SKILL.md +0 -57
- package/framework/skills/notion-mcp/examples.md +0 -31
- package/framework/skills/notion-mcp/references/comments.md +0 -112
- package/framework/skills/notion-mcp/references/databases.md +0 -193
- package/framework/skills/notion-mcp/references/pages.md +0 -235
- package/framework/skills/spec-driven-eval/SKILL.md +0 -341
- package/framework/skills/spec-driven-eval/examples.md +0 -35
- package/framework/skills/spec-driven-eval/references/quickstart.md +0 -118
- package/framework/skills/spec-driven-eval/references/reference.md +0 -295
- package/framework/skills/technical-design-doc-creator/README.md +0 -411
- package/framework/skills/technical-design-doc-creator/SKILL.md +0 -1484
- package/framework/skills/technical-design-doc-creator/examples.md +0 -35
- package/framework/skills/web-design-guidelines/SKILL.md +0 -65
- package/framework/skills/web-design-guidelines/examples.md +0 -32
- package/framework/skills/web-design-guidelines/references/guideline.md +0 -174
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
# Accessibility
|
|
2
|
-
|
|
3
|
-
Most accessibility is free if you use the platform. Native elements ship with keyboard support, real labels announce themselves and a visible focus ring is one CSS rule.
|
|
4
|
-
|
|
5
|
-
Write every fix in the project's styling system, and use the exact values below rather than familiar-looking substitutes.
|
|
6
|
-
|
|
7
|
-
Reviewing means two walks. Keyboard-only, where every flow completes without a mouse. Then screen-reader, where every control announces a name, a role and its state. When unsure, take the platform default over a custom rebuild, and remove ARIA rather than add it.
|
|
8
|
-
|
|
9
|
-
Contrast measurement and color fixes belong to `better-colors`. Text sizing and iOS input zoom belong to `better-typography`. Spatial RTL layout belongs to `better-layout`.
|
|
10
|
-
|
|
11
|
-
## Native elements first
|
|
12
|
-
|
|
13
|
-
The first rule of ARIA: don't use ARIA when a native element exists. `<button>` for actions, `<a href>` for navigation, never `<div onClick>`. A real link must support Cmd/Ctrl/middle-click. No ARIA is better than bad ARIA. See [semantics-and-aria.md]() for landmarks, button-vs-link and disabled states.
|
|
14
|
-
|
|
15
|
-
## Visible focus rings
|
|
16
|
-
|
|
17
|
-
Style `:focus-visible`, not bare `:focus`. Keyboard users get a ring and mouse users usually don't. Prefer the browser's unmodified indicator.
|
|
18
|
-
|
|
19
|
-
A custom ring needs a project focus token or another explicit color. Verify the whole indicator against every adjacent color it crosses, `currentColor` included. Use at least a `2px` solid perimeter or an equivalent visible area. Never use `outline: none` without a verified replacement, and preserve system colors in forced-colors mode. Recipes are in [focus-and-keyboard.md]().
|
|
20
|
-
|
|
21
|
-
## Full keyboard support
|
|
22
|
-
|
|
23
|
-
Every pointer interaction needs a keyboard path. Follow the ARIA APG patterns: Escape closes overlays, arrow keys move within composite widgets, Tab moves between widgets, Enter and Space activate.
|
|
24
|
-
|
|
25
|
-
Use only `tabindex="0"` to join the natural tab order and `tabindex="-1"` for programmatic focus. Positive values break that order. Composite widgets use roving tabindex, where the active item is `0` and every other is `-1`.
|
|
26
|
-
|
|
27
|
-
## Trap and restore focus
|
|
28
|
-
|
|
29
|
-
Modals set `inert` on the background content, move focus inside on open and return focus to the trigger on close. Add `overscroll-behavior: contain` so background content doesn't scroll.
|
|
30
|
-
|
|
31
|
-
## Minimum hit area
|
|
32
|
-
|
|
33
|
-
WCAG 2.5.8's Level AA baseline is a 24×24 CSS-pixel target, or one of its spacing, equivalent-control, inline, user-agent and essential exceptions. Aim for 44×44px on touch and 40×40px on desktop where density permits. Extend with a pseudo-element when the visible element should stay smaller.
|
|
34
|
-
|
|
35
|
-
Never let extended hit areas overlap. Give decorative layers `pointer-events: none`, so a glow never swallows the clicks meant for the control beneath it. Sizes and collision rules are in [hit-areas.md]().
|
|
36
|
-
|
|
37
|
-
## Label and type every control
|
|
38
|
-
|
|
39
|
-
Every input gets a `<label for>` or a wrapping `<label>`. A placeholder is never a label. Label and control share one hit target, with no dead zone between a checkbox and its text.
|
|
40
|
-
|
|
41
|
-
Add `autocomplete` with a meaningful `name`, plus the `type` and `inputmode` that summon the right keyboard. Never block paste; users paste passwords and one-time codes. See [forms.md]().
|
|
42
|
-
|
|
43
|
-
## Errors that announce
|
|
44
|
-
|
|
45
|
-
Keep submit enabled until the request starts, then disable with a spinner and the original label. Validate on submit. Mark failing fields `aria-invalid="true"`, point `aria-describedby` at the inline error text and focus the first invalid field.
|
|
46
|
-
|
|
47
|
-
Use native `disabled` when a control is genuinely unavailable. Reach for `aria-disabled="true"` only when it should stay focusable, then block pointer, keyboard and form behavior in code and style the state explicitly.
|
|
48
|
-
|
|
49
|
-
## Accessible names everywhere
|
|
50
|
-
|
|
51
|
-
Icon-only buttons need a descriptive `aria-label`. Visible label text must appear in the accessible name. Decorative elements get `aria-hidden="true"`, never on a focusable element.
|
|
52
|
-
|
|
53
|
-
## Don't rely on color alone
|
|
54
|
-
|
|
55
|
-
Status needs a redundant cue: an icon, text, or an underline alongside the color. Work out which WCAG contrast requirement applies, then use `better-colors` to measure the rendered pair. When it fails, report the pair and the requirement it misses, and leave the colors alone unless asked.
|
|
56
|
-
|
|
57
|
-
## Honor prefers-reduced-motion
|
|
58
|
-
|
|
59
|
-
Wrap motion in `@media (prefers-reduced-motion: no-preference)` so it is opt-in. Under reduced motion, replace slides and scales with opacity crossfades, and kill parallax and autoplay entirely.
|
|
60
|
-
|
|
61
|
-
Two rules hold regardless of the preference. Autoplaying media needs a visible pause control, and toasts carrying an action or an error stay until dismissed. See [motion-and-zoom.md]().
|
|
62
|
-
|
|
63
|
-
## Announce dynamic content
|
|
64
|
-
|
|
65
|
-
Three mechanisms, three jobs. `aria-describedby` carries field-specific validation. A polite live region (`role="status"`) carries non-urgent updates not tied to a control, such as toasts and result counts. `role="alert"` carries urgent untied errors and nothing else.
|
|
66
|
-
|
|
67
|
-
Repeated polite announcements need a stable empty region rendered before its text updates. Dynamically inserted alerts vary in support, so test them on the screen readers you target. See [screen-readers.md]().
|
|
68
|
-
|
|
69
|
-
## Alt text by purpose
|
|
70
|
-
|
|
71
|
-
Decorative images get `alt=""`. Informative images describe the meaning. Functional images describe the action: a search icon button is `alt="Search"`, not `alt="magnifying glass"`.
|
|
72
|
-
|
|
73
|
-
## Structure is navigation
|
|
74
|
-
|
|
75
|
-
Use headings that describe their sections and form a coherent outline. Give the page one `<h1>` and nest the levels below it without skipping. Expose one visible primary `<main>` landmark. When repeated navigation or chrome precedes it, make a "Skip to content" link the first focusable element. Anchored headings get `scroll-margin-top`.
|
|
76
|
-
|
|
77
|
-
## Survive zoom and text resize
|
|
78
|
-
|
|
79
|
-
The page must work at 200% zoom and reflow at 320px width without horizontal scrolling. Use `min-height` rather than fixed `height` on text containers. Prefer `rem` breakpoints where they fit the codebase, and never let the viewport meta cap how far the reader can zoom.
|
|
80
|
-
|
|
81
|
-
## Before you finish
|
|
82
|
-
|
|
83
|
-
| Mistake | Fix |
|
|
84
|
-
| --- | --- |
|
|
85
|
-
| Custom focus color assumed to work everywhere | Verify it against every adjacent color and in forced-colors mode |
|
|
86
|
-
| Repeated polite update inconsistently announced | Keep a stable empty status region and update its text |
|
|
87
|
-
| `assertive` live region for a routine toast | Use `polite`; reserve `assertive` for errors |
|
|
88
|
-
| `aria-hidden="true"` on a focusable element | Remove it or make the element non-focusable |
|
|
89
|
-
| Submit disabled until the form is valid | Keep it enabled; validate on submit and focus the first error |
|
|
90
|
-
| Hover treatment stuck after a tap on touch | Gate hover styling with `@media (hover: hover)` |
|
|
91
|
-
| Tooltip on a natively `disabled` control | Text beside it, or `aria-disabled` so it stays focusable |
|
|
92
|
-
|
|
93
|
-
## Reporting
|
|
94
|
-
|
|
95
|
-
**Severity.** `HIGH` prevents a task, hides content from assistive technology, or creates a systemic failure. `MEDIUM` makes an interaction meaningfully harder. `LOW` is isolated polish.
|
|
96
|
-
|
|
97
|
-
**Verification.** Without a browser: accessible names on every interactive element, keyboard handlers on non-native controls, focus styles, `prefers-reduced-motion` guards and form labels bound to their inputs. With one: tab the flow in order, read computed names and roles from the accessibility tree, confirm a visible focus indicator at every stop and run an automated audit. Report every check you could not run as `Not verified`.
|
|
98
|
-
|
|
99
|
-
**Format.** Group findings under the principle each violates, ordered by severity, one row per root cause listing every location it appears in:
|
|
100
|
-
|
|
101
|
-
| Severity | Location | Before | After | Why |
|
|
102
|
-
| --- | --- | --- | --- | --- |
|
|
103
|
-
|
|
104
|
-
`Location` is `path/to/file:line`. `Why` names the principle and the user impact.
|
|
105
|
-
|
|
106
|
-
End with `Block` when any `HIGH` remains, `Approve` otherwise, leaving the rest in the table as work to do. Never `Approve` coverage you did not inspect. With nothing to report, state "No actionable accessibility findings" and report verification.
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# Colors
|
|
2
|
-
|
|
3
|
-
A color system is a small set of ramps, named by role and verified against the backgrounds they actually render on. Most color bugs are system bugs. A value picked in isolation, a token borrowed because it looked right, a pair nobody measured.
|
|
4
|
-
|
|
5
|
-
Never report a contrast value you did not measure, and never estimate a color you could compute. Colors are one of the few interface concerns with an exact answer, so produce the exact answer.
|
|
6
|
-
|
|
7
|
-
Contrast requirements belong to `better-accessibility`. Surfaces, shadows and icon color belong to `better-ui`.
|
|
8
|
-
|
|
9
|
-
## Match the project's color system
|
|
10
|
-
|
|
11
|
-
Reuse the project's tokens and notation. A second representation added to fix one value makes the palette harder to reason about. A consistent hex system beats hex with `oklch()` scattered through it.
|
|
12
|
-
|
|
13
|
-
For a new system, `oklch()` is the best default, because its numbers behave the way the ramp rules below describe. Everywhere else, a color library produces the same ramp in the project's own notation ([color-formats.md]()).
|
|
14
|
-
|
|
15
|
-
## A system is ramps, not colors
|
|
16
|
-
|
|
17
|
-
One neutral ramp, one accent ramp and only the status ramps the product actually renders. A `warning` ramp nothing imports is maintenance for zero pixels. A second accent hue earns its place only when two things must be distinguishable at a glance.
|
|
18
|
-
|
|
19
|
-
## Every step has a job
|
|
20
|
-
|
|
21
|
-
A ramp is not a gradient to pick from by eye. Each step exists because a role needs it: page background, component hover, border, solid fill, body text. Do not generate a step no role consumes. Both the Tailwind `50`–`950` and Radix `1`–`12` conventions map to those roles ([palette-structure.md]()).
|
|
22
|
-
|
|
23
|
-
## Name primitives by hue, semantics by role
|
|
24
|
-
|
|
25
|
-
Primitives name a value (`--blue-500`) and are never applied in a component. Semantic tokens name a job (`--color-text-secondary`), point at a primitive and are the only tier components reference.
|
|
26
|
-
|
|
27
|
-
That seam is what makes theming possible. Without it, dark mode means auditing every usage to work out which meant "the accent" and which just wanted blue ([token-naming.md]()).
|
|
28
|
-
|
|
29
|
-
## Use a token only in its role
|
|
30
|
-
|
|
31
|
-
Never borrow a token because its value is right today. A separator used as a text color works until borders get lighter, and then the text goes with them. If a role has no token, add the token.
|
|
32
|
-
|
|
33
|
-
## Hold the hue across the ramp
|
|
34
|
-
|
|
35
|
-
Four properties define a well-formed ramp:
|
|
36
|
-
|
|
37
|
-
- Steps step evenly in *perceived* lightness, not in whatever the format calls lightness.
|
|
38
|
-
- Hue stays constant end to end.
|
|
39
|
-
- Vividness peaks mid-ramp and falls off at both ends.
|
|
40
|
-
- Steps sit denser at the light end than at the dark end.
|
|
41
|
-
|
|
42
|
-
Both ends stop short of pure black and white, which cannot carry hue at all. Use a color library rather than eyeballing it ([palette-generation.md]()).
|
|
43
|
-
|
|
44
|
-
## One color, one meaning
|
|
45
|
-
|
|
46
|
-
Use a color for one purpose across the whole interface, treating anything within `15°` of hue as the same color. If the accent means interactive, that hue on static text tells users to click something that is not clickable, and an interactive element rendered neutral misleads just as badly. Color is never the only carrier of meaning, which `better-accessibility` owns.
|
|
47
|
-
|
|
48
|
-
## Fill exactly one action per view
|
|
49
|
-
|
|
50
|
-
When filled color encodes primary emphasis, one primary action gets it and peers stay neutral. Put the color on the background, not the label. A filled button reads as primary across the room; accent-colored text on a neutral button reads as a link.
|
|
51
|
-
|
|
52
|
-
Several colored backgrounds are fine when they encode distinct states or categories rather than competing as peers.
|
|
53
|
-
|
|
54
|
-
## Measure the rendered pair, then report
|
|
55
|
-
|
|
56
|
-
Measure a foreground against the background it actually renders on, not the page background. When a pair fails, report the pair, its measured value and the threshold it misses, then leave the colors alone. They are a design decision. Change them only when asked, and remeasure after ([contrast.md]()).
|
|
57
|
-
|
|
58
|
-
## Pick a gradient's interpolation space
|
|
59
|
-
|
|
60
|
-
The space is a look, not a correctness setting.
|
|
61
|
-
|
|
62
|
-
- **`in oklab`** is the best default: even brightness, no hue surprises.
|
|
63
|
-
- **`in oklch`** travels around the hue wheel rather than through the middle, staying vivid and sweeping every hue between the stops. Reach for it when a two-hue gradient goes gray in the middle.
|
|
64
|
-
- **The sRGB default** darkens and mutes the midpoint. It is what most interfaces already have, because it is what you get without asking.
|
|
65
|
-
|
|
66
|
-
See [color-usage.md]().
|
|
67
|
-
|
|
68
|
-
## Before you finish
|
|
69
|
-
|
|
70
|
-
| Mistake | Fix |
|
|
71
|
-
| --- | --- |
|
|
72
|
-
| A raw value where the project has a token | Reuse or add the role token, in the project's notation |
|
|
73
|
-
| An isolated `oklch()` value dropped into a hex codebase | Keep the established notation unless a migration is in scope |
|
|
74
|
-
| A primitive like `--blue-500` used directly in a component | Point a semantic token at it |
|
|
75
|
-
| Token named for its appearance (`--color-blue-button`) or first use (`--color-sidebar-gray`) | Name it for its role: `--color-accent-solid`, `--color-bg-surface` |
|
|
76
|
-
| `--color-primary` meaning the brand and `--color-text-primary` meaning body text | Reserve `accent` for the brand; let `primary` mean "most prominent of its group" |
|
|
77
|
-
| Semantic token used outside its role (separator as text) | Add a token for the missing role; never borrow by value |
|
|
78
|
-
| Ramp built by varying HSL lightness | Rebuild against perceived lightness with a constant hue |
|
|
79
|
-
| Ramp spaced evenly across the full range | Tighten the light end until `50` and `100` read as two surfaces |
|
|
80
|
-
| Same saturation number reused across hues | Match the proportion of each hue's own maximum, not the raw value |
|
|
81
|
-
| Status hue that collides with the accent hue | Move it until destructive and primary read apart side by side |
|
|
82
|
-
| Dark mode made by mechanically reversing the light palette | Reverse as a starting point, then reduce vividness, widen the dark end and recheck every pair |
|
|
83
|
-
| `prefers-color-scheme` setting some tokens and a `.dark` class setting others | Pick one switching mechanism and use it throughout |
|
|
84
|
-
| Contrast fixed by changing hue | Change lightness, the channel contrast responds to |
|
|
85
|
-
| P3 color with no sRGB fallback | Declare the sRGB value first, then override inside `@media (color-gamut: p3)` |
|
|
86
|
-
|
|
87
|
-
## Reporting
|
|
88
|
-
|
|
89
|
-
**Severity.** `HIGH` makes content unreadable or assigns a misleading semantic color. `MEDIUM` is a noticeable theme, token, or gamut failure. `LOW` is isolated polish.
|
|
90
|
-
|
|
91
|
-
**Verification.** Without a browser: token values, the gamut of every declared color, both theme blocks present and contrast computed from the declared token pair. With one: the background actually rendered behind the text, including opacity and any image beneath it, measured in both light and dark. A failing pair is reported, not repainted. Report every check you could not run as `Not verified`.
|
|
92
|
-
|
|
93
|
-
**Format.** Group findings under the principle each violates, ordered by severity, one row per root cause listing every location it appears in:
|
|
94
|
-
|
|
95
|
-
| Severity | Location | Before | After | Why |
|
|
96
|
-
| --- | --- | --- | --- | --- |
|
|
97
|
-
|
|
98
|
-
`Location` is `path/to/file:line`. `Why` names the principle and the user impact.
|
|
99
|
-
|
|
100
|
-
End with `Block` when any `HIGH` remains, `Approve` otherwise, leaving the rest in the table as work to do. Never `Approve` coverage you did not inspect. With nothing to report, state "No actionable color findings" and report verification.
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
# Interface review
|
|
2
|
-
|
|
3
|
-
This skill runs a cross-discipline review. It routes the interface to each `better-*` skill, collects their evidence and consolidates one ranked verdict.
|
|
4
|
-
|
|
5
|
-
Orchestration is all it owns. Accessibility rules belong to `better-accessibility`, structure to `better-layout`, copy to `better-writing`, type to `better-typography`, color to `better-colors`, visual polish and motion to `better-ui`. Never duplicate or override their rules here.
|
|
6
|
-
|
|
7
|
-
Change-scoped review of uncommitted work, branches and pull requests belongs to `interface-review`, which resolves the scope and classifies findings before handing the review back.
|
|
8
|
-
|
|
9
|
-
## Evidence, not taste
|
|
10
|
-
|
|
11
|
-
Press hard on the escalation triggers and leave deliberate project choices alone. Those pull the same way. A trigger is a failure whatever the style guide says; a density, radius, or voice you merely disagree with is not a finding.
|
|
12
|
-
|
|
13
|
-
So the bar for reporting is evidence, not taste. The bar for `Approve` is that you inspected what you claim to have inspected. A short report from a real inspection beats a long one padded to look thorough.
|
|
14
|
-
|
|
15
|
-
## Core principles
|
|
16
|
-
|
|
17
|
-
### 1. Resolve the scope first
|
|
18
|
-
|
|
19
|
-
Infer the screen, flow, feature, or repository scope from the request and current workspace. State the resolved scope in the output.
|
|
20
|
-
|
|
21
|
-
Cover all of it across every domain skill listed under **Use domain skills as the sources of truth**, including the empty, loading, error and narrow-width states where they exist. Report at most 15 findings.
|
|
22
|
-
|
|
23
|
-
When the scope is too large to inspect credibly, narrow it to one complete flow: the one the request centers on, or failing that the entry path every user must pass through. State the boundary and what it excluded. Never imply uninspected surfaces were reviewed.
|
|
24
|
-
|
|
25
|
-
### 2. Send a change to `interface-review`
|
|
26
|
-
|
|
27
|
-
A request naming a branch, pull request, commit range, or uncommitted changes is a change review, not a screen review. Say so and ask the user to run `interface-review`, which is user-invoked and cannot be started from here.
|
|
28
|
-
|
|
29
|
-
Never resolve a change scope here. Reading a diff, classifying findings and expanding changed files to affected surfaces belong to `interface-review`. Guess at them and the report has a scope nobody can check.
|
|
30
|
-
|
|
31
|
-
When `interface-review` hands a review back, it supplies the change scope, a status per finding and the change-scoped report format. Severity, ranking, the cap and the verdict stay here, and all three cover `Introduced` and `Regression` only.
|
|
32
|
-
|
|
33
|
-
### 3. Recon before judgment
|
|
34
|
-
|
|
35
|
-
Identify the framework, styling system, component library, design tokens, supported viewports and any preview or test command. Write every fix in the project's own idiom, so no finding arrives as a request to adopt a different stack. That governs the form of the fix, not whether the code is good enough.
|
|
36
|
-
|
|
37
|
-
Then read what the project has written about its own interface: `CONTRIBUTING.md`, `CODING_STANDARDS.md`, `AGENTS.md`, `CLAUDE.md`, a design-system doc, Storybook docs, interface ADRs. Name which you found, or that there are none.
|
|
38
|
-
|
|
39
|
-
Read them to find where a finding belongs, not for permission to drop it. A documented convention is no evidence the convention is good, and "it's in the style guide" does not retire a finding. What they change is **where** you report. When a guideline or shared token is the cause, report it once against that source, with the components as its locations.
|
|
40
|
-
|
|
41
|
-
### 4. Use domain skills as the sources of truth
|
|
42
|
-
|
|
43
|
-
Before reviewing, confirm that every owning skill below is available. Load and apply every available owner, and complete each domain review before consolidation.
|
|
44
|
-
|
|
45
|
-
Review in this order so foundational failures are not hidden by polish:
|
|
46
|
-
|
|
47
|
-
1. `better-accessibility`
|
|
48
|
-
2. `better-layout`
|
|
49
|
-
3. `better-writing`
|
|
50
|
-
4. `better-typography`
|
|
51
|
-
5. `better-colors`
|
|
52
|
-
6. `better-ui`
|
|
53
|
-
|
|
54
|
-
From a domain skill loaded here, take its principles, its references and its verification checks. Its severity ladder and its format are for standalone use; the consolidated format, shared severity and finding cap in this file replace them.
|
|
55
|
-
|
|
56
|
-
If an owning skill is unavailable, mark that domain `Not reviewed`, name it and continue with the rest. Do not recreate its rules from memory, substitute a neighbour, or claim holistic coverage.
|
|
57
|
-
|
|
58
|
-
When two skills appear to cover one issue, assign it to the owner of the underlying rule and note secondary effects in the **Why** cell. Report it once.
|
|
59
|
-
|
|
60
|
-
### 5. Require evidence
|
|
61
|
-
|
|
62
|
-
Every finding cites `path/to/file:line` and shows the current implementation. Do not report a code-level finding from visual appearance alone or a visual finding from source code alone when runtime behavior determines the result.
|
|
63
|
-
|
|
64
|
-
### 6. Rank by user impact
|
|
65
|
-
|
|
66
|
-
Use one shared severity scale:
|
|
67
|
-
|
|
68
|
-
- `HIGH`: blocks a task, misleads the user, hides content or controls, causes data-loss risk, or creates a repeated systemic failure.
|
|
69
|
-
- `MEDIUM`: meaningfully harms comprehension, efficiency, adaptability, or consistency.
|
|
70
|
-
- `LOW`: isolated polish with limited task impact.
|
|
71
|
-
|
|
72
|
-
Within a severity, rank by how many places the finding reaches and how much one fix buys. A token or shared-component fix outranks the same symptom in one leaf.
|
|
73
|
-
|
|
74
|
-
**Escalation triggers.** Once the owning skill confirms one of these, it is `HIGH` on sight, never averaged down because the surface is minor:
|
|
75
|
-
|
|
76
|
-
- An interactive control with no accessible name.
|
|
77
|
-
- A keyboard-reachable control with no visible focus indicator.
|
|
78
|
-
- A control or path reachable by pointer but not by keyboard.
|
|
79
|
-
- Motion or auto-playing content that ignores `prefers-reduced-motion`.
|
|
80
|
-
- Content or a control clipped, overlapped, or unreachable at 320px width or 200% zoom.
|
|
81
|
-
- Body or control text whose rendered contrast pair fails its required ratio.
|
|
82
|
-
- State or meaning carried by color alone.
|
|
83
|
-
- A destructive action with no confirmation, undo, or distinct treatment.
|
|
84
|
-
- Truncated content with no way to reach the full value.
|
|
85
|
-
- Content or a control reachable only past a scroll edge or behind a disclosure that has no visible cue.
|
|
86
|
-
- An error that names no way to recover from it.
|
|
87
|
-
- A semantic color used against its meaning, such as the danger hue on a non-destructive action.
|
|
88
|
-
- A state change carried by motion alone, with no color, icon, or label left behind when the animation does not run.
|
|
89
|
-
|
|
90
|
-
Triggers rank above every other finding. When more fire than the cap allows, list them first and say how many the cap excluded. A cap may shorten a report; it may never be why a blocker went unreported.
|
|
91
|
-
|
|
92
|
-
These set severity, not new rules. The owning skill decides whether the symptom is present; this list decides what it costs. In a change review, a confirmed `Regression` against a trigger is `HIGH` even where the same symptom would be `MEDIUM` as pre-existing.
|
|
93
|
-
|
|
94
|
-
### 7. Prefer the cheaper fix
|
|
95
|
-
|
|
96
|
-
Severity says how bad a finding is; this says which fix to propose. When more than one would work, take the earliest that does:
|
|
97
|
-
|
|
98
|
-
1. **Delete.** A separator that space would carry, an animation on a high-frequency interaction, an ARIA attribute a native element makes redundant, a ramp nothing imports.
|
|
99
|
-
2. **Use the platform.** The native element, the native control, the browser's own focus ring, in place of a custom rebuild.
|
|
100
|
-
3. **Reuse what the project has.** An existing token, spacing step, or motion curve, before any new value.
|
|
101
|
-
4. **Correct the value.** The wrong easing, radius, gap, or contrast pair, using the exact value the owning skill gives.
|
|
102
|
-
5. **Add.** A new token, a wrapper, a media query, an ARIA attribute the platform cannot supply.
|
|
103
|
-
|
|
104
|
-
A fix written at step 5 where step 1 was available is its own finding. Report the deletion instead.
|
|
105
|
-
|
|
106
|
-
### 8. Consolidate systemic findings
|
|
107
|
-
|
|
108
|
-
One root cause is one finding. List every confirmed location in the same row rather than one row per occurrence. Never pad to reach the cap; a short review or no findings is a valid result.
|
|
109
|
-
|
|
110
|
-
### 9. Verify what can be verified
|
|
111
|
-
|
|
112
|
-
Run the safe, relevant checks the project offers. Inspect the rendered interface when runtime behavior or visual judgment matters, and report the exact command or interaction and its result. A check you cannot run is **Not verified**, never a finding.
|
|
113
|
-
|
|
114
|
-
### 10. Review without mutating by default
|
|
115
|
-
|
|
116
|
-
Treat a review request as read-only. Do not edit source unless the user also asks you to implement the findings. When they do, keep the consolidated report as the change scope and re-run the relevant verification afterward.
|
|
117
|
-
|
|
118
|
-
## Before you finish
|
|
119
|
-
|
|
120
|
-
| Mistake | Fix |
|
|
121
|
-
| --- | --- |
|
|
122
|
-
| Six disconnected domain reports | One ranked findings table |
|
|
123
|
-
| Visual claim inferred only from source | Inspect the rendered state, or mark it not verified |
|
|
124
|
-
| Silent gaps in coverage | Show which domains and states were actually inspected |
|
|
125
|
-
| Missing owning skill treated as covered | Mark the domain `Not reviewed` and name the skill |
|
|
126
|
-
| Every legacy issue in a touched file reported | Three pre-existing findings, in their own section |
|
|
127
|
-
| A pre-existing issue blocking a change review | Keep pre-existing findings out of the cap and out of the verdict |
|
|
128
|
-
| Domain marked `Clear` when the change never touched it | Mark it `Not reviewed: no evidence in the change scope` |
|
|
129
|
-
|
|
130
|
-
## Review output format
|
|
131
|
-
|
|
132
|
-
The format lives in [review-format.md](): scope and coverage, the findings table, verification and the verdict. A review is not finished until its findings are reported there.
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# Layout
|
|
2
|
-
|
|
3
|
-
Position, spacing and alignment carry hierarchy before a word is read. This skill builds that structure and stress-tests it: resize it, translate it, mirror it for RTL.
|
|
4
|
-
|
|
5
|
-
Write every fix in the project's styling system. The numbers below are starting points for interfaces with no established density system, and where one applies, use it as written rather than a familiar-looking substitute. Keep deliberate platform chrome, compact professional tools and project tokens where they still pass the stress tests.
|
|
6
|
-
|
|
7
|
-
Hit areas and focus behavior belong to `better-accessibility`. Radius, shadows and animation belong to `better-ui`. Line length and text spacing belong to `better-typography`.
|
|
8
|
-
|
|
9
|
-
## Group with space, not lines
|
|
10
|
-
|
|
11
|
-
Space groups first, background shapes second, separator lines last and only where space alone can't carry the structure. The gap between groups must be at least 2× the gap within one (`8px` intra-group to `16px`+ inter-group), or the grouping reads as noise. Alignment edges and importance ordering are in [grouping-and-alignment.md]().
|
|
12
|
-
|
|
13
|
-
## Keep controls distinct from content
|
|
14
|
-
|
|
15
|
-
Give every interactive element a background shape, a border, or a consistent placement zone. A control styled like the static text beside it does not read as a control.
|
|
16
|
-
|
|
17
|
-
## Align to shared edges
|
|
18
|
-
|
|
19
|
-
Pick alignment edges and stick to them; every stray edge reads as noise. Use one project spacing step per level of subordination, where `16px` is a useful default.
|
|
20
|
-
|
|
21
|
-
Use logical properties for direction-dependent layout: `padding-inline-start`, `margin-inline-end`. Reserve physical left and right for genuinely physical geometry.
|
|
22
|
-
|
|
23
|
-
## Order by importance
|
|
24
|
-
|
|
25
|
-
The most important content sits near the top and the leading edge. Reading order flows top-to-bottom, leading-to-trailing. Think in leading and trailing, not left and right.
|
|
26
|
-
|
|
27
|
-
## Hint at hidden content
|
|
28
|
-
|
|
29
|
-
Progressive disclosure needs a visible affordance. Use the project's established cue, or let the next item peek `16–32px` past the scroll edge, or show a disclosure control. Content hidden with zero cue may as well not exist.
|
|
30
|
-
|
|
31
|
-
## Breathing room between targets
|
|
32
|
-
|
|
33
|
-
Without an established density system, start with `12px` between adjacent bordered or filled controls and `24px` around borderless text- and icon-only ones. Compact layouts may use less, as long as `better-accessibility` hit areas don't overlap and the controls stay distinct. Layout margins and breakpoint recipes are in [spacing-and-adaptivity.md]().
|
|
34
|
-
|
|
35
|
-
## Inset buttons from the edges
|
|
36
|
-
|
|
37
|
-
In content layouts, keep full-width buttons inside the layout margins with a visible radius, starting near `16px` inline on mobile. Edge-to-edge actions work when they follow established platform chrome, account for safe areas and stay distinguishable from system UI.
|
|
38
|
-
|
|
39
|
-
## Content bleeds, controls float
|
|
40
|
-
|
|
41
|
-
Backgrounds and media extend to the viewport edges. Controls and text stay inside the layout margins and safe areas (`env(safe-area-inset-*)`). Sticky chrome floats above the content layer rather than blocking it.
|
|
42
|
-
|
|
43
|
-
## Hold structure until it breaks
|
|
44
|
-
|
|
45
|
-
Breakpoints come from the content, not device presets. Keep the expanded layout as long as it genuinely fits and collapse late. Prefer container queries for component-level adaptation, and test the smallest and largest sizes first.
|
|
46
|
-
|
|
47
|
-
## Plan for growth and clipping
|
|
48
|
-
|
|
49
|
-
Translated strings grow, and short ones grow proportionally more, so a one-word button label is the riskiest thing on the screen. Put no fixed width or height on a text container, and let rows wrap. Test with pseudo-localization and one representative locale rather than budgeting a percentage.
|
|
50
|
-
|
|
51
|
-
Never park a critical action where resizing or scrolling clips it. Keep it in the normal flow, or in stable chrome suited to the product.
|
|
52
|
-
|
|
53
|
-
## Before you finish
|
|
54
|
-
|
|
55
|
-
| Mistake | Fix |
|
|
56
|
-
| --- | --- |
|
|
57
|
-
| `margin-left` / `padding-right` in a localizable layout | `margin-inline-start` / `padding-inline-end` |
|
|
58
|
-
| Content-layout button touches the viewport edge | Inset within the project margins; keep intentional platform chrome |
|
|
59
|
-
| Breakpoints at 768/1024 because they're the defaults | Break where the content actually stops fitting |
|
|
60
|
-
| Fixed-width text container sized to one language | `max-width` and wrapping; test pseudo-localization |
|
|
61
|
-
| Primary action at the clip-prone bottom of a pane | Sticky positioning or stable chrome with safe-area padding |
|
|
62
|
-
|
|
63
|
-
## Reporting
|
|
64
|
-
|
|
65
|
-
**Severity.** `HIGH` blocks content or an action at a supported viewport. `MEDIUM` harms hierarchy, reading order, or adaptability. `LOW` is isolated alignment or spacing polish.
|
|
66
|
-
|
|
67
|
-
**Verification.** Without a browser: logical properties in place of physical ones, container and media queries against the supported viewport list and DOM order against the intended reading order. With one: every supported width, 200% zoom and the RTL mirror. Report every check you could not run as `Not verified`.
|
|
68
|
-
|
|
69
|
-
**Format.** Group findings under the principle each violates, ordered by severity, one row per root cause listing every location it appears in:
|
|
70
|
-
|
|
71
|
-
| Severity | Location | Before | After | Why |
|
|
72
|
-
| --- | --- | --- | --- | --- |
|
|
73
|
-
|
|
74
|
-
`Location` is `path/to/file:line`. `Why` names the principle and the user impact.
|
|
75
|
-
|
|
76
|
-
End with `Block` when any `HIGH` remains, `Approve` otherwise, leaving the rest in the table as work to do. Never `Approve` coverage you did not inspect. With nothing to report, state "No actionable layout findings" and report verification.
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
# Typography
|
|
2
|
-
|
|
3
|
-
Typography is mostly restraint: a sensible scale, comfortable spacing, enough contrast. A label, a table cell, a marketing headline and an article paragraph do not share one set of rules.
|
|
4
|
-
|
|
5
|
-
When reviewing, read the rendered page instead of scanning the code. Bad wrapping, widows and truncation only show up at real content lengths.
|
|
6
|
-
|
|
7
|
-
Write every fix in the project's styling system, and use the exact values below rather than familiar-looking equivalents. The [cheat sheet]() maps each declaration to its Tailwind equivalent.
|
|
8
|
-
|
|
9
|
-
The words themselves belong to `better-writing`. Semantic heading structure belongs to `better-accessibility`. Spatial RTL layout and logical properties belong to `better-layout`. Contrast measurement belongs to `better-colors`. This skill owns how text renders, wraps and behaves in mixed-direction content.
|
|
10
|
-
|
|
11
|
-
## Serve the right format
|
|
12
|
-
|
|
13
|
-
Use `.woff2` on the web, for Brotli compression and broad support. `.woff` is a fallback for very old browsers. `.ttf` and `.otf` are desktop formats with no web compression. How the files load is the project's concern.
|
|
14
|
-
|
|
15
|
-
## Properties over raw tags
|
|
16
|
-
|
|
17
|
-
When a CSS property exists, use it. `font-weight: 650` instead of `font-variation-settings: "wght" 650`. `font-optical-sizing: auto` instead of `"opsz"`. `font-variant-numeric: tabular-nums` instead of `font-feature-settings: "tnum" 1`.
|
|
18
|
-
|
|
19
|
-
Properties keep working when a non-variable fallback renders. Reserve raw tags for custom axes (`"GRAD" 80`) and niche features (`"ss01" 1`) with no property of their own. Axes and feature tags are listed in [variable-fonts-and-opentype.md]().
|
|
20
|
-
|
|
21
|
-
## Load intended weights and styles
|
|
22
|
-
|
|
23
|
-
Browsers synthesize a weight or style the active family doesn't provide, distorting the real face. Load the faces the design uses.
|
|
24
|
-
|
|
25
|
-
`font-synthesis: none` turns synthesis off, but it erases emphasis rather than reporting it. Set it only after checking every required bold, italic, small-cap, superscript and subscript form stays distinct across the fallback stack.
|
|
26
|
-
|
|
27
|
-
## Fewer fonts, sizes and weights
|
|
28
|
-
|
|
29
|
-
Rarely use more than three fonts. Weight and size define hierarchy; overusing them hurts readability fast. Pair for contrast, not similarity: a serif headline over a sans body reads as deliberate, two near-identical sans-serifs read as a mistake.
|
|
30
|
-
|
|
31
|
-
Below `18px`, stay at weight `400` or heavier. Weights under `300` are display-only at `28px`+; they disappear at text sizes. Pairing guidance is in [choosing-fonts.md]().
|
|
32
|
-
|
|
33
|
-
## Use a type scale with semantic names
|
|
34
|
-
|
|
35
|
-
Define a small set of sizes and deviate from it as little as possible. Hard-coded sizes with no system behind them break down at scale.
|
|
36
|
-
|
|
37
|
-
Solo, default names like `text-sm` are fine when the usage rules are clear. On a team, name sizes by use (`text-body-sm`) so the rules survive other people. Scale construction is in [spacing-and-sizing.md]().
|
|
38
|
-
|
|
39
|
-
## Heading sizes descend with level
|
|
40
|
-
|
|
41
|
-
Map heading levels to descending steps of the type scale, so a visually subordinate heading never overpowers its parent. Adjacent levels may share a size toward the small end of the scale, as long as weight or spacing keeps them distinct. The semantic element is `better-accessibility`'s; this skill sets only the visual treatment.
|
|
42
|
-
|
|
43
|
-
## Line-height by role
|
|
44
|
-
|
|
45
|
-
Headings tighter, around `1.1`. Body copy `1.5` to `1.6`. Prefer unitless values, so line-height scales with the font size; a fixed `24px` does not.
|
|
46
|
-
|
|
47
|
-
Tight line-height is for short text. Anything that wraps to three or more lines needs at least `1.4`, even in a height-constrained row.
|
|
48
|
-
|
|
49
|
-
## Letter-spacing by size
|
|
50
|
-
|
|
51
|
-
Large headings often look better with slightly negative letter-spacing. Small uppercase labels need a little positive letter-spacing, or the letters feel crowded. Body copy at reading sizes needs neither.
|
|
52
|
-
|
|
53
|
-
## Cap the measure
|
|
54
|
-
|
|
55
|
-
Long lines make it hard for the eye to find the next one. Cap long-form text around 60–75 characters per line. Any unit works, as long as a cap exists and the line length lands in range. See [unit choices and the pixel equivalents]().
|
|
56
|
-
|
|
57
|
-
## Wrap deliberately
|
|
58
|
-
|
|
59
|
-
Four declarations, four jobs:
|
|
60
|
-
|
|
61
|
-
- `text-wrap: balance` distributes text evenly across lines. Use it on headings.
|
|
62
|
-
- `text-wrap: pretty` stops a single short word landing on the final line. Use it on descriptions.
|
|
63
|
-
- `overflow-wrap: break-word` where a long word, link, or ID could escape the container.
|
|
64
|
-
- `white-space: nowrap` on labels and badges where a line break looks broken.
|
|
65
|
-
|
|
66
|
-
Skip `balance` and `pretty` in long-form text.
|
|
67
|
-
|
|
68
|
-
## Tabular numbers on changing values
|
|
69
|
-
|
|
70
|
-
Digits have different widths by default, so timers, counters and prices shift the layout as they update. Apply `font-variant-numeric: tabular-nums` to any value that changes.
|
|
71
|
-
|
|
72
|
-
## Truncate without losing content
|
|
73
|
-
|
|
74
|
-
For a single line, `text-overflow: ellipsis` with `overflow: hidden` and `white-space: nowrap`. For several, `line-clamp`. Truncation hides content. When the missing text matters, keep the full value reachable in a tooltip or an expanded view.
|
|
75
|
-
|
|
76
|
-
## Write copy naturally, style with CSS
|
|
77
|
-
|
|
78
|
-
Store text in natural case and control presentation with `text-transform`, so a redesign never means rewriting copy.
|
|
79
|
-
|
|
80
|
-
Use smart punctuation in rendered text:
|
|
81
|
-
|
|
82
|
-
- Curly quotes in prose, straight quotes in code.
|
|
83
|
-
- An en dash for ranges: `2010–2020`.
|
|
84
|
-
- The single ellipsis character, not three periods.
|
|
85
|
-
- ` ` to hold `16 px` together across a line break.
|
|
86
|
-
- `­` to say where a long word may break.
|
|
87
|
-
|
|
88
|
-
## Underlines from the font
|
|
89
|
-
|
|
90
|
-
Default underlines sit wherever the browser decides. Pull position and thickness from the font's own metrics with `text-underline-position: from-font` and `text-decoration-thickness: from-font`. Tune by hand with `text-decoration-thickness`, `text-underline-offset` and `text-decoration-skip-ink`.
|
|
91
|
-
|
|
92
|
-
`text-decoration-style` draws the line dotted, dashed, or wavy. A dotted underline is a common hint that a word carries extra information, such as an abbreviation or a defined term.
|
|
93
|
-
|
|
94
|
-
Color is the only part of a real underline that animates reliably. So unless the only thing animating is the color, build the underline as a separate element rather than using `text-decoration`.
|
|
95
|
-
|
|
96
|
-
## Inputs at 16px on mobile
|
|
97
|
-
|
|
98
|
-
iOS Safari zooms the whole page when an input's text is smaller than `16px`. Two fixes hold the size at `16px` and look different, so ask which one the design wants:
|
|
99
|
-
|
|
100
|
-
- Size the input up on mobile (`text-base sm:text-sm`). Changes how it looks on small screens.
|
|
101
|
-
- Keep `font-size: 16px` and render the intended size with `transform: scale()`, compensating width and `line-height`. Identical at every viewport, more code to maintain.
|
|
102
|
-
|
|
103
|
-
Both recipes are in [details-and-accessibility.md]().
|
|
104
|
-
|
|
105
|
-
## Size and contrast floors
|
|
106
|
-
|
|
107
|
-
Start long-form body text at `16px`, the browser default. Move off it only for a reason you can name: the typeface runs small, the measure is narrow, or the product is a dense professional tool.
|
|
108
|
-
|
|
109
|
-
UI text can go smaller. `14px` is a useful starting point for inputs and menus, `13px` for captions and rarely below `12px`. Inputs still need `16px` on mobile.
|
|
110
|
-
|
|
111
|
-
When text looks low-contrast, use `better-colors` to measure the rendered pair and `better-accessibility` to classify the requirement. Leave the colors alone unless asked.
|
|
112
|
-
|
|
113
|
-
## Font smoothing on the root
|
|
114
|
-
|
|
115
|
-
On macOS, text renders heavier than intended. Apply `-webkit-font-smoothing: antialiased` and `-moz-osx-font-smoothing: grayscale` once on the root layout, never per component. Tailwind's `antialiased` covers both.
|
|
116
|
-
|
|
117
|
-
## Language and bidi behavior
|
|
118
|
-
|
|
119
|
-
Set `lang` so browsers and assistive technology pick the right pronunciation, quotes and hyphenation. Set `dir` at the document or at the content boundary where direction changes. Preserve digit order, and use `<bdi>` to isolate a mixed-direction value. Spatial mirroring and logical CSS properties belong to `better-layout`.
|
|
120
|
-
|
|
121
|
-
## Keep useful text selectable
|
|
122
|
-
|
|
123
|
-
Keep text selectable by default. `::selection` can carry brand into the reading experience, as long as the selected combination stays legible.
|
|
124
|
-
|
|
125
|
-
`user-select: none` belongs on a draggable or gesture-driven surface where accidental selection interferes. Never across the interface and never because a button label can be highlighted.
|
|
126
|
-
|
|
127
|
-
## Before you finish
|
|
128
|
-
|
|
129
|
-
| Mistake | Fix |
|
|
130
|
-
| --- | --- |
|
|
131
|
-
| Synthesized face differs from the design | Load the real face; disable only the verified synthesis mode |
|
|
132
|
-
| Child heading visually overpowers its parent | Map that section's hierarchy to descending scale steps |
|
|
133
|
-
| Heading element picked for its default size | Choose semantics first, then set the size in CSS |
|
|
134
|
-
| Orphan on the last line of a paragraph | `text-wrap: pretty` |
|
|
135
|
-
| Lopsided two-line heading | `text-wrap: balance` |
|
|
136
|
-
| Justified text in an interface | `text-align: start`; reserve justify for specific editorial layouts |
|
|
137
|
-
| Underline cuts through descenders | `text-decoration-skip-ink: auto`, `from-font` metrics |
|
|
138
|
-
| Mixed-direction value renders in the wrong order | Correct `lang`/`dir`; isolate the value with `<bdi>` |
|
|
139
|
-
| Selection disabled across application chrome | Restore it; suppress only where it conflicts with a drag or gesture |
|
|
140
|
-
| Extra-info hint with no visual cue | Dotted underline via `text-decoration-style: dotted` |
|
|
141
|
-
| Thin/Light weight on `14px` UI text | Weight `400`+ below `18px`; thin weights are display-only |
|
|
142
|
-
| `leading-none` on a three-line card description | At least `1.4` on any text that wraps to 3+ lines |
|
|
143
|
-
|
|
144
|
-
## Reporting
|
|
145
|
-
|
|
146
|
-
**Severity.** `HIGH` makes text unreadable or truncates content with no way to recover it. `MEDIUM` breaks the type system or the heading hierarchy. `LOW` is isolated polish.
|
|
147
|
-
|
|
148
|
-
**Verification.** Without a browser: computed size and weight for each heading level, checked descending; declared line-height and measure; truncation rules against realistic string lengths. With one: resize the viewport to catch wrapping, widows and truncation at real content lengths. Report every check you could not run as `Not verified`.
|
|
149
|
-
|
|
150
|
-
**Format.** Group findings under the principle each violates, ordered by severity, one row per root cause listing every location it appears in:
|
|
151
|
-
|
|
152
|
-
| Severity | Location | Before | After | Why |
|
|
153
|
-
| --- | --- | --- | --- | --- |
|
|
154
|
-
|
|
155
|
-
`Location` is `path/to/file:line`. `Why` names the principle and the user impact.
|
|
156
|
-
|
|
157
|
-
End with `Block` when any `HIGH` remains, `Approve` otherwise, leaving the rest in the table as work to do. Never `Approve` coverage you did not inspect. With nothing to report, state "No actionable typography findings" and report verification.
|