@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.
Files changed (117) hide show
  1. package/framework/commands/README.md +1 -1
  2. package/framework/commands/review.md +1 -1
  3. package/framework/mcps/README.md +0 -1
  4. package/framework/plugins/ponytail/README.md +0 -1
  5. package/framework/plugins/ponytail/capabilities.md +1 -1
  6. package/framework/references/standards/api.md +0 -1
  7. package/framework/references/standards/architecture.md +0 -1
  8. package/framework/references/standards/database.md +0 -1
  9. package/framework/references/standards/debugging.md +0 -1
  10. package/framework/references/standards/documentation.md +0 -1
  11. package/framework/references/standards/logging.md +0 -1
  12. package/framework/references/standards/naming.md +0 -1
  13. package/framework/references/standards/observability.md +0 -1
  14. package/framework/references/standards/performance.md +0 -1
  15. package/framework/references/standards/pull-requests.md +0 -1
  16. package/framework/references/standards/security.md +0 -1
  17. package/framework/references/standards/testing.md +0 -1
  18. package/framework/skills/README.md +1 -12
  19. package/framework/skills/improve/SKILL.md +1 -3
  20. package/framework/skills/improve/examples.md +1 -1
  21. package/framework/skills/laravel-best-practices/SKILL.md +56 -216
  22. package/framework/skills/laravel-best-practices/references/architecture.md +1 -1
  23. package/framework/skills/laravel-best-practices/references/checklist.md +139 -0
  24. package/framework/skills/laravel-best-practices/references/eloquent.md +4 -2
  25. package/framework/skills/laravel-best-practices/references/infer-conventions.md +97 -0
  26. package/framework/skills/laravel-best-practices/references/pest-testing.md +47 -18
  27. package/framework/skills/laravel-best-practices/references/security.md +1 -1
  28. package/framework/skills/laravel-best-practices/references/style.md +1 -1
  29. package/framework/skills/laravel-best-practices/references/tailwindcss.md +0 -1
  30. package/package.json +1 -1
  31. package/src/catalog.js +1 -13
  32. package/framework/mcps/notion-mcp/README.md +0 -57
  33. package/framework/mcps/notion-mcp/capabilities.md +0 -118
  34. package/framework/mcps/notion-mcp/configs/opencode.json +0 -9
  35. package/framework/mcps/notion-mcp/install.md +0 -70
  36. package/framework/mcps/notion-mcp/troubleshooting.md +0 -95
  37. package/framework/skills/brainstorming/SKILL.md +0 -159
  38. package/framework/skills/brainstorming/examples.md +0 -49
  39. package/framework/skills/brainstorming/scripts/frame-template.html +0 -213
  40. package/framework/skills/brainstorming/scripts/helper.js +0 -167
  41. package/framework/skills/brainstorming/scripts/server.cjs +0 -723
  42. package/framework/skills/brainstorming/scripts/start-server.sh +0 -209
  43. package/framework/skills/brainstorming/scripts/stop-server.sh +0 -120
  44. package/framework/skills/brainstorming/visual-companion.md +0 -291
  45. package/framework/skills/code-review/SKILL.md +0 -72
  46. package/framework/skills/code-review/examples.md +0 -31
  47. package/framework/skills/codenavi/SKILL.md +0 -306
  48. package/framework/skills/codenavi/examples.md +0 -33
  49. package/framework/skills/codenavi/references/coding-principles.md +0 -143
  50. package/framework/skills/codenavi/references/notebook-spec.md +0 -171
  51. package/framework/skills/create-adr/SKILL.md +0 -429
  52. package/framework/skills/create-adr/examples.md +0 -35
  53. package/framework/skills/design/SKILL.md +0 -399
  54. package/framework/skills/design/examples.md +0 -34
  55. package/framework/skills/great-interface/SKILL.md +0 -43
  56. package/framework/skills/great-interface/references/animations.md +0 -205
  57. package/framework/skills/great-interface/references/better-accessibility.md +0 -106
  58. package/framework/skills/great-interface/references/better-colors.md +0 -100
  59. package/framework/skills/great-interface/references/better-interface.md +0 -132
  60. package/framework/skills/great-interface/references/better-layout.md +0 -76
  61. package/framework/skills/great-interface/references/better-typography.md +0 -157
  62. package/framework/skills/great-interface/references/better-ui.md +0 -107
  63. package/framework/skills/great-interface/references/better-writing.md +0 -109
  64. package/framework/skills/great-interface/references/choosing-fonts.md +0 -64
  65. package/framework/skills/great-interface/references/color-formats.md +0 -90
  66. package/framework/skills/great-interface/references/color-usage.md +0 -118
  67. package/framework/skills/great-interface/references/contrast.md +0 -79
  68. package/framework/skills/great-interface/references/css-cheat-sheet.md +0 -65
  69. package/framework/skills/great-interface/references/details-and-accessibility.md +0 -119
  70. package/framework/skills/great-interface/references/enter-exit.md +0 -147
  71. package/framework/skills/great-interface/references/explain-interface.md +0 -126
  72. package/framework/skills/great-interface/references/find-the-effect.md +0 -94
  73. package/framework/skills/great-interface/references/focus-and-keyboard.md +0 -131
  74. package/framework/skills/great-interface/references/forms.md +0 -84
  75. package/framework/skills/great-interface/references/from-an-image.md +0 -55
  76. package/framework/skills/great-interface/references/grouping-and-alignment.md +0 -123
  77. package/framework/skills/great-interface/references/hit-areas.md +0 -94
  78. package/framework/skills/great-interface/references/icon-transitions.md +0 -102
  79. package/framework/skills/great-interface/references/icons.md +0 -110
  80. package/framework/skills/great-interface/references/interface-review.md +0 -148
  81. package/framework/skills/great-interface/references/motion-and-zoom.md +0 -79
  82. package/framework/skills/great-interface/references/no-browser.md +0 -73
  83. package/framework/skills/great-interface/references/palette-generation.md +0 -104
  84. package/framework/skills/great-interface/references/palette-structure.md +0 -76
  85. package/framework/skills/great-interface/references/performance.md +0 -88
  86. package/framework/skills/great-interface/references/picker.md +0 -76
  87. package/framework/skills/great-interface/references/read-the-system.md +0 -178
  88. package/framework/skills/great-interface/references/removed-signals.md +0 -38
  89. package/framework/skills/great-interface/references/review-format.md +0 -46
  90. package/framework/skills/great-interface/references/scope-resolution.md +0 -88
  91. package/framework/skills/great-interface/references/screen-readers.md +0 -101
  92. package/framework/skills/great-interface/references/semantics-and-aria.md +0 -84
  93. package/framework/skills/great-interface/references/spacing-and-adaptivity.md +0 -159
  94. package/framework/skills/great-interface/references/spacing-and-sizing.md +0 -121
  95. package/framework/skills/great-interface/references/surfaces.md +0 -219
  96. package/framework/skills/great-interface/references/token-naming.md +0 -97
  97. package/framework/skills/great-interface/references/variable-fonts-and-opentype.md +0 -105
  98. package/framework/skills/great-interface/references/variant.md +0 -104
  99. package/framework/skills/great-interface/references/wrapping-and-punctuation.md +0 -55
  100. package/framework/skills/learning-opportunities/SKILL.md +0 -140
  101. package/framework/skills/learning-opportunities/examples.md +0 -34
  102. package/framework/skills/learning-opportunities/references/PRINCIPLES.md +0 -42
  103. package/framework/skills/notion-mcp/SKILL.md +0 -57
  104. package/framework/skills/notion-mcp/examples.md +0 -31
  105. package/framework/skills/notion-mcp/references/comments.md +0 -112
  106. package/framework/skills/notion-mcp/references/databases.md +0 -193
  107. package/framework/skills/notion-mcp/references/pages.md +0 -235
  108. package/framework/skills/spec-driven-eval/SKILL.md +0 -341
  109. package/framework/skills/spec-driven-eval/examples.md +0 -35
  110. package/framework/skills/spec-driven-eval/references/quickstart.md +0 -118
  111. package/framework/skills/spec-driven-eval/references/reference.md +0 -295
  112. package/framework/skills/technical-design-doc-creator/README.md +0 -411
  113. package/framework/skills/technical-design-doc-creator/SKILL.md +0 -1484
  114. package/framework/skills/technical-design-doc-creator/examples.md +0 -35
  115. package/framework/skills/web-design-guidelines/SKILL.md +0 -65
  116. package/framework/skills/web-design-guidelines/examples.md +0 -32
  117. package/framework/skills/web-design-guidelines/references/guideline.md +0 -174
@@ -1,159 +0,0 @@
1
- # Spacing and adaptivity
2
-
3
- Space between controls, margins against the viewport, hints at off-screen content and layouts that survive resizing and translation.
4
-
5
- ## Breathing room between targets
6
-
7
- Controls placed too close get mis-tapped and read as one unit. Where the project has no density scale, start here:
8
-
9
- | Between | Starting point |
10
- | --- | --- |
11
- | Adjacent bordered/filled controls (buttons, inputs) | `12px` |
12
- | Around borderless controls (text buttons, icon buttons) | `24px` |
13
- | Unrelated control groups | `24px`+ (2× the intra-group gap) |
14
-
15
- Borderless controls need more clearance, because nothing marks where one target ends and the next begins. The space is the boundary. Compact professional tools may use less where hit areas stay distinct and never overlap. Preserve an established, usable density rather than expanding controls to match these values.
16
-
17
- ```html
18
- <!-- Good: bordered buttons at 12px, icon buttons given room -->
19
- <div class="flex gap-3">
20
- <button class="rounded-lg border px-4 py-2">Cancel</button>
21
- <button class="rounded-lg bg-blue-600 px-4 py-2 text-white">Save</button>
22
- </div>
23
-
24
- <!-- Bad: three borderless icon buttons packed at 4px -->
25
- <div class="flex gap-1">
26
- <button><TrashIcon /></button>
27
- <button><ArchiveIcon /></button>
28
- <button><ShareIcon /></button>
29
- </div>
30
- ```
31
-
32
- WCAG target-size requirements, larger usability targets and pseudo-element expansion belong to `better-accessibility`; these clearances are in addition, so expanded hit areas never overlap.
33
-
34
- ## Inset buttons from the edges
35
-
36
- In content layouts, buttons pressed against the viewport look like system chrome and clip against curved corners or gesture zones. Keep them inside the layout margins. Edge-to-edge actions stay valid where they are deliberately platform chrome and account for safe areas:
37
-
38
- ```css
39
- /* Good: inset action bar */
40
- .action-bar {
41
- padding-inline: 16px;
42
- padding-bottom: calc(16px + env(safe-area-inset-bottom));
43
- }
44
- .action-bar button { width: 100%; border-radius: 12px; }
45
-
46
- /* Bad: button glued to all three edges */
47
- .action-bar button {
48
- width: 100vw;
49
- border-radius: 0;
50
- position: fixed;
51
- bottom: 0;
52
- }
53
- ```
54
-
55
- Start near `16px` inline margin on mobile where the project has no layout token. The button can still span the full content width inside them.
56
-
57
- ## Progressive disclosure needs an affordance
58
-
59
- Hiding complexity is good; hiding it without a cue is a trap. Every piece of off-screen or collapsed content needs a visible hint that it exists. Keep the product's established scroll indicator or disclosure pattern, and use the recipes below only where no cue exists:
60
-
61
- - **Peeking items.** In a horizontal scroller or carousel, size items so the next one peeks `16–32px` past the container edge. A row of cards that ends exactly at the edge looks complete, and nobody scrolls it.
62
- - **Disclosure controls.** Collapsed sections get a chevron or "Show more", labelled with what is hidden: "Show 12 more results", not "More".
63
- - **Truncation cues.** Clamped text shows an ellipsis and a way to expand. Truncation mechanics are `better-typography`'s.
64
-
65
- In the peeking-scroller recipe, the container's padding creates the peek and snap points stay on the content edge.
66
-
67
- ```css
68
- .scroller {
69
- display: flex;
70
- gap: 12px;
71
- overflow-x: auto;
72
- padding-inline: 24px;
73
- scroll-padding-inline: 24px;
74
- scroll-snap-type: x mandatory;
75
- }
76
- .scroller > * {
77
- flex: 0 0 calc(100% - 48px - 24px); /* container minus margins minus peek */
78
- scroll-snap-align: start;
79
- }
80
- ```
81
-
82
- ```html
83
- <!-- Tailwind: the 80% width keeps the next card's leading 16-32px visible -->
84
- <div class="flex gap-3 overflow-x-auto px-6 [scroll-padding-inline:1.5rem] snap-x snap-mandatory">
85
- <div class="w-[80%] shrink-0 snap-start">…</div>
86
- <div class="w-[80%] shrink-0 snap-start">…</div>
87
- </div>
88
- ```
89
-
90
- ## Content bleeds, controls float
91
-
92
- The two layers behave differently at the edges:
93
-
94
- - **Content layer**: backgrounds, hero media and scrollable lists extend to the viewport edges.
95
- - **Control layer**: text and controls stay inside the layout margins and safe areas, floating above the content.
96
-
97
- ```css
98
- /* Good: full-bleed media inside a constrained article */
99
- .article {
100
- display: grid;
101
- grid-template-columns: 1fr min(65ch, calc(100% - 48px)) 1fr;
102
- }
103
- .article > * { grid-column: 2; }
104
- .article > .full-bleed { grid-column: 1 / -1; }
105
- ```
106
-
107
- Sticky headers and floating action buttons account for safe areas:
108
-
109
- ```css
110
- .fab {
111
- position: fixed;
112
- inset-inline-end: calc(16px + env(safe-area-inset-right));
113
- bottom: calc(16px + env(safe-area-inset-bottom));
114
- }
115
- ```
116
-
117
- ## Hold structure until it breaks
118
-
119
- Breakpoints belong to the content, not the device catalog:
120
-
121
- - Break where the layout actually stops fitting, not at `768px` because a preset says so. That is where the sidebar squeezes content below its minimum measure, or the card grid drops below a usable column width.
122
- - Collapse late. A layout keeping its expanded structure as long as it genuinely fits stays stable and familiar. Premature collapsing throws away space users paid for.
123
- - Prefer **container queries** for components. A card adapts to the column it is in, not to the viewport.
124
-
125
- ```css
126
- /* Good: component adapts to its container */
127
- .card-list { container-type: inline-size; }
128
- @container (max-width: 400px) {
129
- .card { grid-template-columns: 1fr; }
130
- }
131
-
132
- /* Bad: viewport media query breaks the card inside a narrow sidebar */
133
- @media (max-width: 768px) {
134
- .card { grid-template-columns: 1fr; }
135
- }
136
- ```
137
-
138
- Test the smallest and largest supported sizes first, since those break first, then the sizes between.
139
-
140
- ## Plan for growth and clipping
141
-
142
- Layouts fail in two directions. Content grows, and viewports shrink.
143
-
144
- **String expansion varies by language and by source-string length.** Never rely on one universal percentage.
145
-
146
- - No fixed widths sized to English labels. Use `max-width` plus wrapping.
147
- - No fixed heights on text containers. Use `min-height` where a floor is needed.
148
- - Buttons size themselves from their label (`padding-inline`), never a hardcoded width.
149
- - Test with pseudo-localization or a long-string locale before shipping.
150
-
151
- ```css
152
- /* Good: label defines the size */
153
- .button { padding-inline: 16px; white-space: nowrap; }
154
-
155
- /* Bad: German will overflow or truncate */
156
- .button { width: 96px; overflow: hidden; }
157
- ```
158
-
159
- **Clipping.** Never park a critical action where it can be cut off: the bottom edge of a resizable pane, below the fold of a fixed-height modal, behind an expanding keyboard. Keep primary actions in stable chrome, a sticky footer with safe-area padding or the top of the view. Where a modal's content scrolls, its action row does not.
@@ -1,121 +0,0 @@
1
- # Spacing and sizing
2
-
3
- A sensible scale and comfortable spacing do more for typography than any effect.
4
-
5
- ## Units
6
-
7
- | Unit | Behavior |
8
- | --- | --- |
9
- | `px` | Fixed |
10
- | `em` | Scales with the current font size |
11
- | `rem` | Scales with the root font size |
12
- | `%` on `font-size` | Relative to the parent's font size, behaves like `em` |
13
-
14
- ## Type scale
15
-
16
- A small set of sizes used across a product, deviated from as little as possible. Hard-coding sizes with no system behind them breaks down at scale.
17
-
18
- ```css
19
- :root {
20
- --text-sm: 0.875rem;
21
- --text-base: 1rem;
22
- --text-lg: 1.125rem;
23
- --text-xl: 1.5rem;
24
- --text-2xl: 2rem;
25
- }
26
- ```
27
-
28
- Pick an existing scale or define one. Tailwind's (`text-xs` through `text-9xl`, each class pairing a size with a matching line height) is a solid ready-made choice.
29
-
30
- Solo, the default names work fine given clear rules for where each size is used. On a team, name sizes semantically. `text-sm` tells you the size but not the use, where `text-body-sm` carries both.
31
-
32
- A role-based scale pairs each size with its line-height and weight, making a role one decision instead of three. A starting point for a product interface:
33
-
34
- | Role | Size | Line-height | Weight |
35
- | --- | --- | --- | --- |
36
- | Display | `2.25rem` (36px) | `1.1` | `600` |
37
- | Title | `1.5rem` (24px) | `1.2` | `600` |
38
- | Heading | `1.125rem` (18px) | `1.3` | `600` |
39
- | Body | `1rem` (16px) | `1.5` | `400` |
40
- | Caption | `0.8125rem` (13px) | `1.4` | `400` |
41
-
42
- Emphasis within a role is one weight step up (`400` → `500`), not a size change.
43
-
44
- ## Heading hierarchy
45
-
46
- Assign each heading level to a descending step of the scale, so hierarchy comes from the scale instead of one-off sizes:
47
-
48
- ```css
49
- h1 { font-size: var(--text-2xl); }
50
- h2 { font-size: var(--text-xl); }
51
- h3 { font-size: var(--text-lg); }
52
- ```
53
-
54
- In Tailwind the same mapping is utility classes per level (`text-2xl`, `text-xl`, `text-lg`), centralized in a component or `@layer base` rather than repeated inline.
55
-
56
- When reviewing, compare the computed size of headings within each semantic section. A child rendering more prominently than its parent breaks the hierarchy. Deep levels may share a size where the scale runs out of comfortable steps, as long as weight or letter-spacing keeps them distinct. A heading is never smaller than body text unless it is deliberately a label-style overline.
57
-
58
- Heading semantics and outline quality belong to `better-accessibility`. Pick the element from the document structure, then use this skill to make that structure visually legible. Never pick a heading element for its browser-default size.
59
-
60
- ## Kerning and letter-spacing
61
-
62
- - **Kerning** adjusts specific pairs such as `AV` or `Ye`. It is built into the font and applied automatically. Switch it off only deliberately, with `font-kerning: none`.
63
- - **`letter-spacing`** adds the same space between every character.
64
-
65
- ```css
66
- /* Good */
67
- .display-heading {
68
- letter-spacing: -0.02em;
69
- }
70
-
71
- .uppercase-label {
72
- text-transform: uppercase;
73
- letter-spacing: 0.05em;
74
- }
75
- ```
76
-
77
- ## Line-height
78
-
79
- | Text | Value |
80
- | --- | --- |
81
- | Headings | ~`1.1` |
82
- | Body copy | `1.5`–`1.6` |
83
-
84
- Tailwind's `leading-snug`, `leading-normal` and `leading-relaxed` are sensible defaults that rarely need overriding. A tightly-leaded paragraph is harder to read than a taller row is to fit.
85
-
86
- ```css
87
- /* Bad: card description at heading leading */
88
- .card-description { line-height: 1.1; }
89
-
90
- /* Good: it wraps to 3 lines, so it reads as body text */
91
- .card-description { line-height: 1.4; }
92
- ```
93
-
94
- ## Text trimming with text-box
95
-
96
- Fonts reserve space above and below the letters, which is why text sits slightly too low in buttons and badges. `text-box` trims it. Two parts: which edges to trim (`trim-both`, `trim-start`, `trim-end`) and where:
97
-
98
- | Keyword | Trims at |
99
- | --- | --- |
100
- | `cap` | The cap height (top) |
101
- | `alphabetic` | The baseline (bottom) |
102
- | `text` | The font's own text edge, keeping room for descenders |
103
-
104
- ```css
105
- /* trim top and bottom */
106
- .badge {
107
- text-box: trim-both cap alphabetic;
108
- }
109
-
110
- /* trim only the top */
111
- .heading {
112
- text-box: trim-start cap;
113
- }
114
-
115
- /* trim only the bottom */
116
- .label {
117
- text-box: trim-end alphabetic;
118
- }
119
- ```
120
-
121
- Supported in Chromium (133+) and Safari (18.2+), not yet Firefox. Treat it as progressive enhancement, where unsupported browsers keep the default leading.
@@ -1,219 +0,0 @@
1
- # Surfaces
2
-
3
- Border radius, optical alignment, shadows and image outlines.
4
-
5
- ## Concentric border radius
6
-
7
- When nesting rounded elements, the outer radius must equal the inner radius plus the padding between them:
8
-
9
- ```
10
- outerRadius = innerRadius + padding
11
- ```
12
-
13
- The rule matters most when nested surfaces sit close together. Past `24px` of padding, treat the layers as separate surfaces and choose each radius independently rather than forcing concentric math.
14
-
15
- ### Example
16
-
17
- ```css
18
- /* Good: concentric radii */
19
- .card {
20
- border-radius: 20px; /* 12 + 8 */
21
- padding: 8px;
22
- }
23
- .card-inner {
24
- border-radius: 12px;
25
- }
26
-
27
- /* Bad: same radius on both */
28
- .card {
29
- border-radius: 12px;
30
- padding: 8px;
31
- }
32
- .card-inner {
33
- border-radius: 12px;
34
- }
35
- ```
36
-
37
- ### Tailwind example
38
-
39
- ```tsx
40
- // Good: outer radius accounts for padding
41
- <div className="rounded-2xl p-2"> {/* 16px radius, 8px padding */}
42
- <div className="rounded-lg"> {/* 8px radius = 16 - 8 ✓ */}
43
- ...
44
- </div>
45
- </div>
46
-
47
- // Bad: same radius on both
48
- <div className="rounded-xl p-2">
49
- <div className="rounded-xl"> {/* same radius, looks off */}
50
- ...
51
- </div>
52
- </div>
53
- ```
54
-
55
- Mismatched radii on closely nested surfaces are a common source of visual tension. Calculate concentrically where the layers share a visible, even inset. Keep an established component token where they are independent or the padding is deliberately asymmetric.
56
-
57
- ## Optical alignment
58
-
59
- When geometric centering looks off, align optically instead.
60
-
61
- ### Buttons with text + icon
62
-
63
- Where an icon makes symmetric padding look unbalanced, use slightly less on the icon side. A starting point:
64
- `icon-side padding = text-side padding - 2px`.
65
-
66
- ```css
67
- /* Good: less padding on icon side */
68
- .button-with-icon {
69
- padding-inline-start: 16px;
70
- padding-inline-end: 14px; /* trailing icon side = text side - 2px */
71
- }
72
-
73
- /* Bad: equal padding looks like icon is pushed too far right */
74
- .button-with-icon {
75
- padding-inline: 16px;
76
- }
77
- ```
78
-
79
- ```tsx
80
- // Tailwind
81
- <button className="ps-4 pe-3.5 flex items-center gap-2">
82
- <span>Continue</span>
83
- <ArrowRightIcon />
84
- </button>
85
- ```
86
-
87
- ### Play button triangles
88
-
89
- Play icons are triangular and their geometric center is not their visual center. Shift slightly right:
90
-
91
- ```css
92
- /* Good: optically centered */
93
- .play-button svg {
94
- transform: translateX(2px); /* physical correction to the glyph itself */
95
- }
96
-
97
- /* Bad: geometrically centered but looks off */
98
- .play-button svg {
99
- /* no adjustment */
100
- }
101
- ```
102
-
103
- ### Asymmetric icons (stars, arrows, carets)
104
-
105
- Some icons carry uneven visual weight. The best fix is adjusting the SVG directly, so the component needs no extra margin or padding.
106
-
107
- ```tsx
108
- // Best: fix in the SVG itself
109
- // Adjust the viewBox or path to visually center the icon
110
-
111
- // Fallback: adjust with margin
112
- <span className="translate-x-px">
113
- <StarIcon />
114
- </span>
115
- ```
116
-
117
- ## Shadows instead of borders
118
-
119
- Where **buttons, cards and containers** use a border for depth or elevation, replace it with a subtle `box-shadow`. Shadows use transparency, so they adapt to any background where solid borders do not. That matters most over images or multiple background colors, which a fixed border color was never designed for.
120
-
121
- **Never apply this to dividers**, meaning `border-b`, `border-t` and side borders, or any border whose purpose is layout separation rather than depth. Those stay borders.
122
-
123
- ### Shadow as border (light mode)
124
-
125
- Three layers. The first acts as a 1px border ring, the second adds subtle lift, the third ambient depth:
126
-
127
- ```css
128
- :root {
129
- --shadow-border:
130
- 0px 0px 0px 1px oklch(0 0 0 / 0.06),
131
- 0px 1px 2px -1px oklch(0 0 0 / 0.06),
132
- 0px 2px 4px 0px oklch(0 0 0 / 0.04);
133
- --shadow-border-hover:
134
- 0px 0px 0px 1px oklch(0 0 0 / 0.08),
135
- 0px 1px 2px -1px oklch(0 0 0 / 0.08),
136
- 0px 2px 4px 0px oklch(0 0 0 / 0.06);
137
- }
138
- ```
139
-
140
- ### Shadow as border (dark mode)
141
-
142
- In dark mode, simplify to one white ring, since layered depth shadows are invisible on dark backgrounds:
143
-
144
- ```css
145
- /* Dark mode: adapt to whatever setup the project uses
146
- (prefers-color-scheme, class, data attribute, etc.) */
147
- --shadow-border: 0 0 0 1px oklch(1 0 0 / 0.08);
148
- --shadow-border-hover: 0 0 0 1px oklch(1 0 0 / 0.13);
149
- ```
150
-
151
- ### Usage with hover transition
152
-
153
- Apply the variable and add `transition-[box-shadow]` for a smooth hover:
154
-
155
- ```css
156
- .card {
157
- box-shadow: var(--shadow-border);
158
- transition-property: box-shadow;
159
- transition-duration: 150ms;
160
- transition-timing-function: ease-out;
161
- }
162
-
163
- .card:hover {
164
- box-shadow: var(--shadow-border-hover);
165
- }
166
- ```
167
-
168
- ### When to use shadows vs. borders
169
-
170
- | Use shadows | Use borders |
171
- | --- | --- |
172
- | Cards, containers with depth | Dividers between list items |
173
- | Buttons with bordered styles | Table cell boundaries |
174
- | Elevated elements (dropdowns, modals) | Form input outlines (for accessibility) |
175
- | Elements on varied backgrounds | Hairline separators in dense UI |
176
- | Hover/focus states for lift effect | |
177
-
178
- ## Image outlines
179
-
180
- Add a `1px` outline at low opacity to images for consistent depth, especially where other elements use borders or shadows.
181
-
182
- ### Color rules (non-negotiable)
183
-
184
- - **Light mode**: pure black, `oklch(0 0 0 / 0.1)`.
185
- - **Dark mode**: pure white, `oklch(1 0 0 / 0.1)`.
186
- - Never a near-black or near-white from the project palette, such as slate-900, zinc-900, `#0a0a0a`, `#111827`, or `#f5f5f7`. Tinted outlines pick up the surrounding surface color and read as dirt on the image edge.
187
- - Never match the outline to the project's accent or ink color. The outline is a neutral separator, not a themed element.
188
-
189
- ### Light mode
190
-
191
- ```css
192
- img {
193
- outline: 1px solid oklch(0 0 0 / 0.1);
194
- outline-offset: -1px; /* draw the ring just inside the image edge */
195
- }
196
- ```
197
-
198
- ### Dark mode
199
-
200
- ```css
201
- img {
202
- outline: 1px solid oklch(1 0 0 / 0.1);
203
- outline-offset: -1px;
204
- }
205
- ```
206
-
207
- ### Tailwind with dark mode
208
-
209
- ```tsx
210
- <img
211
- className="outline outline-1 -outline-offset-1 outline-black/10 dark:outline-white/10"
212
- src={src}
213
- alt={alt}
214
- />
215
- ```
216
-
217
- Use `outline-black/10` and `outline-white/10` specifically, not `outline-slate-*`, `outline-zinc-*`, `outline-neutral-*`, or any tinted scale.
218
-
219
- **Why outline instead of border?** `outline` never affects layout, adding no width or height at any offset, and `outline-offset: -1px` draws the ring just inside the image edge so it hugs the corner radius.
@@ -1,97 +0,0 @@
1
- # Token naming
2
-
3
- Naming is what makes a palette usable by anyone who did not build it. For which ramps exist and what each step does, see [palette-structure.md](palette-structure.md).
4
-
5
- ## Two tiers
6
-
7
- **Primitives** name a value. They are the ramp, named by hue and step: `--blue-500`, `--neutral-200`. A primitive describes what the color *is*, so it never changes meaning between themes and is never applied directly in a component.
8
-
9
- **Semantics** name a job. They point at a primitive and take the name of the role they fill: `--color-text-secondary`, `--color-border-subtle`. Components only ever reference this tier.
10
-
11
- ```css
12
- :root {
13
- /* Tier 1: primitives, named by appearance. Never used directly. */
14
- --blue-500: #3b82f6;
15
- --neutral-200: #e5e7eb;
16
- --neutral-700: #374151;
17
-
18
- /* Tier 2: semantics, named by role. This is what components use. */
19
- --color-accent-solid: var(--blue-500);
20
- --color-border: var(--neutral-200);
21
- --color-text-secondary: var(--neutral-700);
22
- }
23
- ```
24
-
25
- The tiering is what makes theming possible. Dark mode, a white-label theme and an increased-contrast variant all repoint the semantic tier, leaving the primitives and every component untouched. A codebase applying `--blue-500` directly in components has no theming seam. Adding one later means auditing every usage to work out which meant "the accent" and which just wanted blue.
26
-
27
- Add a third, component-level tier (`--color-button-danger-bg`) only where a component genuinely and intentionally diverges from the system. One component token is a documented exception; twenty mean the semantic tier is missing roles.
28
-
29
- ## The role inventory
30
-
31
- A system is complete when every role below has a token. Build against this list rather than adding tokens as components demand them, or the palette ends up shaped like whichever screen came first.
32
-
33
- | Group | Roles |
34
- | --- | --- |
35
- | Surfaces | page background, surface, raised (menus, popovers), sunken (inputs, wells), overlay scrim |
36
- | Text | primary, secondary, disabled, inverse, on-accent |
37
- | Borders | subtle, default, strong, focus ring, separator |
38
- | Accent | subtle background, border, solid, solid hover, text |
39
- | Status | per status shipped: subtle background, border, solid, text |
40
-
41
- Separator and border are separate roles even when they share a value today. A separator divides content; a border encloses a control. They diverge the first time someone restyles inputs, and a system that conflated them gets untangled at that moment.
42
-
43
- ## Naming grammar
44
-
45
- Use one shape and never deviate: `--color-{role}-{variant}-{state}`.
46
-
47
- ```css
48
- --color-bg-surface
49
- --color-text-secondary
50
- --color-border-strong
51
- --color-accent-solid-hover
52
- ```
53
-
54
- Pick one word per concept and use only that word. Consistency matters more than the vocabulary. A reader who has seen `--color-text-primary` must be able to guess `--color-text-disabled` without looking:
55
-
56
- | Concept | Pick one | Never mix in |
57
- | --- | --- | --- |
58
- | Foreground | `text` | `fg`, `foreground`, `content`, `ink` |
59
- | Background | `bg` | `background`, `surface` as a synonym, `fill` |
60
- | Edge | `border` | `stroke`, `outline`, `line` |
61
- | Brand color | `accent` | `primary`, `brand`, `theme` used interchangeably |
62
-
63
- Reserve `primary` for exactly one meaning. `--color-text-primary` for body text beside `--color-primary` for the brand is the most common naming collision there is, and it makes every `primary` token ambiguous until you open its definition. Use `accent` for the brand and let `primary` mean "the most prominent of its group".
64
-
65
- ## Anti-patterns
66
-
67
- | Name | Problem | Instead |
68
- | --- | --- | --- |
69
- | `--color-blue-button` | Appearance at the semantic tier; lies the moment the brand changes | `--color-accent-solid` |
70
- | `--color-sidebar-gray` | Named for where it was used first; the second usage makes it nonsense | `--color-bg-surface` |
71
- | `--color-light-gray` | Lies in dark mode, where it is the dark one | `--neutral-200` as a primitive |
72
- | `--color-text-2` | Numbered semantics carry no meaning; nobody can guess what `3` would be | `--color-text-secondary` |
73
- | `--color-gray-hover` | Mixes a hue with a state and belongs to no tier | `--color-bg-surface-hover` |
74
- | `--blue-500` used in a component | Skips the semantic tier and removes the theming seam | Point a semantic token at it |
75
-
76
- Every one of them is a case of **Use a token only in its role**. See [color-usage.md](color-usage.md).
77
-
78
- ## In Tailwind projects
79
-
80
- Tailwind v4 generates utilities from `@theme`, so names declared there become the API. Declare primitives and semantics in the same block; the `--color-*` namespace is what produces `bg-*`, `text-*` and `border-*`:
81
-
82
- ```css
83
- @theme {
84
- /* Primitives */
85
- --color-brand-50: #eff6ff;
86
- --color-brand-500: #3b82f6;
87
- --color-brand-900: #1e3a8a;
88
-
89
- /* Semantics: what templates should use */
90
- --color-accent-solid: var(--color-brand-500);
91
- --color-text-secondary: var(--color-neutral-700);
92
- }
93
- ```
94
-
95
- That yields `bg-accent-solid` and `text-secondary` alongside `bg-brand-500`. Both are reachable, so the discipline is a convention rather than a constraint. Templates use the semantic utilities, and a raw `bg-brand-500` in a component is the thing to flag.
96
-
97
- Opacity modifiers work on either tier, as in `bg-accent-solid/50`. But a color carrying alpha cannot be contrast-checked against a static background, because what it renders depends on what sits behind it. Use solid tokens for anything with text on it.