stitch2 0.25.1 → 0.27.0
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/README.md +1 -1
- package/dist/audit.d.ts +1 -0
- package/dist/audit.js +36 -0
- package/dist/check.js +22 -5
- package/package.json +1 -1
- package/skills/stitch2/SKILL.md +3 -3
- package/skills/stitch2/references/google.md +14 -0
- package/skills/stitch2/references/principles.md +2 -1
- package/skills/stitch2/references/typography.md +33 -2
- package/skills/stitch2-app-sync/SKILL.md +1 -1
- package/skills/stitch2-design-md/SKILL.md +3 -1
package/README.md
CHANGED
|
@@ -283,7 +283,7 @@ layout first, then a shorter natural word, never a smaller type size.
|
|
|
283
283
|
| `stitch2 init --name N --primary #hex [options]` | Writes a complete DESIGN.md from a few choices |
|
|
284
284
|
| `stitch2 extract <url or file…>` | Writes a DESIGN.md measured from an existing site or screens |
|
|
285
285
|
| `stitch2 canvas` | The canvas at http://localhost:4400 (`PORT` and `HOST` to change) |
|
|
286
|
-
| `stitch2 check [filter] [--shots] [--strict] [--locales l,…]` | All checks, in every theme, app state and check language; `--shots` saves renders to `<design>/renders/` (`--light.png`, `--pseudo.png`, `--auth-user.png`…). Reruns visit only the screens that changed; after a change to stitch2, DESIGN.md, the tokens, the components or the catalog every screen is visited again, which takes minutes on a large project. Progress is printed to stderr, and `checks.json` is saved as screens finish and when the run is stopped (Ctrl-C), so the next run continues where it left off |
|
|
286
|
+
| `stitch2 check [filter] [--shots] [--strict] [--archived] [--locales l,…]` | All checks, in every theme, app state and check language, on every version that is not archived (`--archived` adds the outdated ones); `--shots` saves renders to `<design>/renders/` (`--light.png`, `--pseudo.png`, `--auth-user.png`…). Reruns visit only the screens that changed; after a change to stitch2, DESIGN.md, the tokens, the components or the catalog every screen is visited again, which takes minutes on a large project. Progress is printed to stderr, and `checks.json` is saved as screens finish and when the run is stopped (Ctrl-C), so the next run continues where it left off |
|
|
287
287
|
| `stitch2 i18n [filter] [--locale l] [--suggest] [--json]` | Message keys the source or a locale lacks, and screen text with no key |
|
|
288
288
|
| `stitch2 consistency [kind…]` | The consistency report, `<design>/consistency/index.html` |
|
|
289
289
|
| `stitch2 type [filter] [--json]` | The type audit |
|
package/dist/audit.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export declare const LAYOUT_ERRORS: string[];
|
|
|
9
9
|
export declare function audit(opts: {
|
|
10
10
|
comfortable: number;
|
|
11
11
|
durations?: number[];
|
|
12
|
+
secondary?: string;
|
|
12
13
|
}): Promise<Issue[]>;
|
|
13
14
|
/**
|
|
14
15
|
* Runs inside the page with prefers-reduced-motion: reduce. What still moves (an animation of transform,
|
package/dist/audit.js
CHANGED
|
@@ -772,6 +772,42 @@ export async function audit(opts) {
|
|
|
772
772
|
if (longest > 80)
|
|
773
773
|
push('warning', 'measure', el, 'Lines of up to ' + longest + ' characters: keep prose to 45–75 (a max width of about 32em)');
|
|
774
774
|
}
|
|
775
|
+
// 6e. Text tiers: a sentence to read belongs in the body colour (skills/stitch2/references/typography.md, section 3). A block of reading
|
|
776
|
+
// copy, drawn in the secondary colour, is the usual reason a page reads dull although every contrast ratio passes: the strokes of small
|
|
777
|
+
// text reach only their own colour. A block is reading copy when it holds sixty characters and eight words of its own text and sits in
|
|
778
|
+
// the page's content: not in a bar, a table, a menu, a label, a control, a link or a code sample. It needs the secondary colour, which
|
|
779
|
+
// check takes from DESIGN.md's text-muted and passes as a CSS colour the page can resolve (var(--<prefix>-text-muted)).
|
|
780
|
+
if (opts.secondary) {
|
|
781
|
+
const canvas = document.createElement('canvas');
|
|
782
|
+
canvas.width = canvas.height = 1;
|
|
783
|
+
const g = canvas.getContext('2d', { willReadFrequently: true });
|
|
784
|
+
const rgba = (value) => {
|
|
785
|
+
g.clearRect(0, 0, 1, 1);
|
|
786
|
+
g.fillStyle = '#000';
|
|
787
|
+
g.fillStyle = value;
|
|
788
|
+
g.fillRect(0, 0, 1, 1);
|
|
789
|
+
const d = g.getImageData(0, 0, 1, 1).data;
|
|
790
|
+
return [d[0], d[1], d[2], d[3] / 255];
|
|
791
|
+
};
|
|
792
|
+
const probe = document.createElement('span');
|
|
793
|
+
probe.style.color = opts.secondary;
|
|
794
|
+
document.body.append(probe);
|
|
795
|
+
const want = rgba(getComputedStyle(probe).color);
|
|
796
|
+
probe.remove();
|
|
797
|
+
const quiet = (el) => {
|
|
798
|
+
const have = rgba(getComputedStyle(el).color);
|
|
799
|
+
return Math.abs(have[0] - want[0]) <= 2 && Math.abs(have[1] - want[1]) <= 2 && Math.abs(have[2] - want[2]) <= 2 && Math.abs(have[3] - want[3]) <= 0.02;
|
|
800
|
+
};
|
|
801
|
+
const apart = 'nav, footer, table, button, summary, label, a, code, pre, figcaption, caption, [role=navigation], [role=tablist], [role=tab], [role=menu], [role=listbox], [role=tooltip], [role=button], [aria-hidden=true]';
|
|
802
|
+
for (const el of all) {
|
|
803
|
+
if (!ownText(el) || opacity(el) < 0.1 || el.closest(apart))
|
|
804
|
+
continue;
|
|
805
|
+
const own = [...el.childNodes].filter((n) => n.nodeType === 3).map((n) => n.textContent).join(' ').replace(/\s+/g, ' ').trim();
|
|
806
|
+
if (own.length < 60 || own.split(' ').length < 8 || !quiet(el))
|
|
807
|
+
continue;
|
|
808
|
+
push('warning', 'text-tier', el, 'Reading copy in the secondary colour: a sentence to read takes the body colour, and the secondary one is for hints, captions and counts');
|
|
809
|
+
}
|
|
810
|
+
}
|
|
775
811
|
// 6d. Touch targets: Material and Lighthouse want 48×48; a smaller one fails when the 48px square around its
|
|
776
812
|
// centre covers a quarter of its area of another target (about 8px apart is enough). Touch-sized windows only.
|
|
777
813
|
const named = (el) => text(el) || el.getAttribute('aria-label') || el.tagName.toLowerCase();
|
package/dist/check.js
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
* Usage: stitch2 check [path filter…] [--shots] [--strict] [--locales ru,ar | all | none]
|
|
17
17
|
* --shots also save page-tall renders to design/renders/ (one per theme, app state, language and width)
|
|
18
18
|
* --strict exit 1 when any screen has errors (for CI and agent loops)
|
|
19
|
+
* --archived also check archived versions, which are left out otherwise: they are outdated (superseded or rejected),
|
|
20
|
+
* hidden on the canvas, and nothing is built from them, so checking them costs time and reports errors in history
|
|
19
21
|
* Screens run four at a time; reruns only visit screens that changed since design/checks.json (or
|
|
20
22
|
* everything DESIGN.md, the tokens, the components, the catalog or stitch2 itself changed since: a first run after
|
|
21
23
|
* that visits every screen and takes minutes on a large project). Progress goes to stderr, one line per screen
|
|
@@ -30,7 +32,7 @@ import { fingerprintPaths } from './cache.js';
|
|
|
30
32
|
import { colourIssues } from './colours.js';
|
|
31
33
|
import { CONFIG_FILE, checkWidths, config, modes } from './config.js';
|
|
32
34
|
import { collectComponents, collectOptions, consistencyIssues, reuseIssues, } from './consistency.js';
|
|
33
|
-
import { designThemes, motionDurations, typeLevels } from './design-md.js';
|
|
35
|
+
import { designThemes, motionDurations, readDesign, typeLevels } from './design-md.js';
|
|
34
36
|
import { checkLocales } from './i18n.js';
|
|
35
37
|
import { listScreens, ROOT } from './screens.js';
|
|
36
38
|
import { startServer } from './serve.js';
|
|
@@ -43,18 +45,33 @@ const strict = args.includes('--strict');
|
|
|
43
45
|
const localesFlag = args.indexOf('--locales');
|
|
44
46
|
const locales = checkLocales(localesFlag >= 0 ? args[localesFlag + 1] : undefined);
|
|
45
47
|
const filters = args.filter((a, i) => !a.startsWith('--') && (localesFlag < 0 || i !== localesFlag + 1));
|
|
46
|
-
const
|
|
48
|
+
const matching = listScreens().filter((s) => !filters.length || filters.some((f) => s.path.includes(f)));
|
|
49
|
+
const screens = args.includes('--archived') ? matching : matching.filter((s) => s.status !== 'archived');
|
|
50
|
+
const archivedLeftOut = matching.length - screens.length;
|
|
51
|
+
if (archivedLeftOut)
|
|
52
|
+
console.log(`${archivedLeftOut} archived screen${archivedLeftOut === 1 ? ' is' : 's are'} not checked (--archived includes ${archivedLeftOut === 1 ? 'it' : 'them'}).`);
|
|
53
|
+
if (!screens.length && matching.length)
|
|
54
|
+
process.exit(0);
|
|
47
55
|
const levels = typeLevels();
|
|
48
56
|
const themes = designThemes();
|
|
49
57
|
const appModes = modes();
|
|
50
58
|
const collect = collectOptions();
|
|
51
|
-
/** What the layout audit needs: the comfortable tap size
|
|
52
|
-
const auditOpts = {
|
|
59
|
+
/** What the layout audit needs: the comfortable tap size, DESIGN.md's motion durations and its secondary text colour (text-muted, for text-tier). */
|
|
60
|
+
const auditOpts = {
|
|
61
|
+
comfortable: config.comfortableTarget,
|
|
62
|
+
durations: (() => { try {
|
|
53
63
|
return motionDurations();
|
|
54
64
|
}
|
|
55
65
|
catch {
|
|
56
66
|
return [];
|
|
57
|
-
} })()
|
|
67
|
+
} })(),
|
|
68
|
+
secondary: (() => { try {
|
|
69
|
+
return 'text-muted' in readDesign().colors ? 'var(--' + config.prefix + '-text-muted)' : undefined;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return undefined;
|
|
73
|
+
} })(),
|
|
74
|
+
};
|
|
58
75
|
const server = await startServer(0);
|
|
59
76
|
/** The tallest render, in CSS px: a long landing page is shot whole (the canvas draws frames up to the same height). */
|
|
60
77
|
const MAX_RENDER_HEIGHT = 20000;
|
package/package.json
CHANGED
package/skills/stitch2/SKILL.md
CHANGED
|
@@ -53,7 +53,7 @@ References, read before the first screen:
|
|
|
53
53
|
**stitch2-i18n**). Write the text as **stitch2-copy** says (the reader's outcome, plain words, the product's terms),
|
|
54
54
|
and translate it with **stitch2-translate**. Never add classes to a component to change how it looks, and never write a colour value (hex,
|
|
55
55
|
`rgb()`, `hsl()`): only DESIGN.md's colours, as token classes or `var(--<prefix>-<name>)`.
|
|
56
|
-
5. **Check** `stitch2 check <path> --shots --strict
|
|
56
|
+
5. **Check** `stitch2 check <path> --shots --strict` (archived versions are outdated and are not visited; `--archived` includes them). Fix every error (overflow, wrapped labels, content under
|
|
57
57
|
fixed bars, fixed bars overlapping each other, tap targets, contrast, cramped text), a hand-built copy of a
|
|
58
58
|
catalog component (`reuse`: use the component or extend it, never rebuild it), and every warning about type
|
|
59
59
|
(`type-*`), components that differ from the catalog (`consistency`) and colour values (`color`).
|
|
@@ -68,7 +68,7 @@ References, read before the first screen:
|
|
|
68
68
|
Text running into other text (`text-overlap`) or out of its card (`overflow`) is an error; a short label cut
|
|
69
69
|
short with an ellipsis (`truncated`) is a warning to fix with room, not a smaller size. Google's rules are
|
|
70
70
|
warnings too (`text-small`, `edge-margin`, `measure`, `tap-spacing`, `placeholder-label`, `unnamed-control`,
|
|
71
|
-
`nav-destinations`, `focus-visible`; see google.md): fix them, or say in the hand-over why the screen breaks one. When DESIGN.md has a
|
|
71
|
+
`nav-destinations`, `focus-visible`, `text-tier`; see google.md): `text-tier` is a block of reading copy (sixty characters, eight words, in the page's content and not in a bar, table, control or link) drawn in DESIGN.md's `text-muted`; give it the body colour (typography.md, section 3): fix them, or say in the hand-over why the screen breaks one. When DESIGN.md has a
|
|
72
72
|
light and a dark theme, every screen is checked in both: an issue marked with a theme
|
|
73
73
|
("light theme: Low contrast…") is fixed in DESIGN.md's colours for that theme when it shows on many
|
|
74
74
|
screens, or in the screen when it is one element. Look at both renders (`--light.png`). With `i18n`, check
|
|
@@ -132,7 +132,7 @@ References, read before the first screen:
|
|
|
132
132
|
|---|---|
|
|
133
133
|
| `setup [--name N --primary #hex] [options]` | Sets a project up in one step; keeps every file that exists |
|
|
134
134
|
| `canvas` | The canvas at http://localhost:4400: screens and versions, DESIGN.md, the consistency report, approval and notes |
|
|
135
|
-
| `check [filter] [--shots] [--strict] [--locales l,…]` | Layout, type, reuse and consistency checks, in every theme, app state and check language, and at both ends of each variant's widths; `--shots` saves renders |
|
|
135
|
+
| `check [filter] [--shots] [--strict] [--archived] [--locales l,…]` | Layout, type, reuse and consistency checks, in every theme, app state and check language, and at both ends of each variant's widths; `--shots` saves renders; archived versions are left out unless `--archived` asks for them |
|
|
136
136
|
| `i18n [filter] [--locale l] [--suggest]` | Message keys screens use that the source or a locale lacks, and text with no key (stitch2-i18n) |
|
|
137
137
|
| `consistency [kind…]` | Every shared component cropped from every screen, next to the catalog's version |
|
|
138
138
|
| `type [filter] [--json]` | Every text style a screen uses and the type level it matches |
|
|
@@ -34,6 +34,11 @@ the rest are judged from the render. Where Google and DESIGN.md disagree, DESIGN
|
|
|
34
34
|
Map DESIGN.md's levels onto these roles when choosing sizes; the names can stay the project's.
|
|
35
35
|
- **Smallest sizes:** nothing under 11 px (Material's label small), and body text from 12 px up; Lighthouse
|
|
36
36
|
wants at least 12 px for most of a page's text **(check: text-small)**. Prefer 14–16 for reading text.
|
|
37
|
+
- **Reading copy is a body, not a caption.** A sentence a person reads (an introduction, a card's description, an
|
|
38
|
+
answer) is Material's body: 14/20 at the smallest (body medium), 16/24 for long passages (body large). Material 3
|
|
39
|
+
gives the 12 and 11 sizes to labels and captions: buttons, chips, the unit under a number, "very small text in the
|
|
40
|
+
content body, such as captions". The Lighthouse font-size audit (12 px for 60% of a page's text; retired in
|
|
41
|
+
Lighthouse 13) is a floor, not a recommendation. Body line height is about 1.5 times the size.
|
|
37
42
|
- **Line length 45–75 characters, in every language the app ships** (Android's app quality guidelines; about
|
|
38
43
|
66 is ideal, per web.dev). Cap prose with a max width in a relative unit, never in pixels: about `32em` lands on
|
|
39
44
|
45–75 characters in most fonts. `ch` is the width of the font's zero, which is wider than an average letter,
|
|
@@ -61,6 +66,12 @@ the rest are judged from the render. Where Google and DESIGN.md disagree, DESIGN
|
|
|
61
66
|
surface). Depth comes from tonal surface containers (lowest to highest) rather than shadows.
|
|
62
67
|
- **Contrast:** 4.5:1 for text under 18 px (14 px bold), 3:1 above **(check: contrast)**. Never colour alone:
|
|
63
68
|
a link also has an underline or weight; a status also has an icon or word.
|
|
69
|
+
- **Text tiers on a dark theme:** the default text colour is "on surface", and "on surface variant" is the lower-emphasis
|
|
70
|
+
alternative (Material 3). In its baseline dark scheme they are #E6E1E5 and #CAC4D0 on #1C1B1F: about 89% and 77%
|
|
71
|
+
of white. Material 2's dark theme used 87% (high emphasis), 60% (medium emphasis and hints) and 38% (disabled); the
|
|
72
|
+
60% tier reads dim for anything a person reads. Neither uses pure white for text, which vibrates and bleeds on a
|
|
73
|
+
dark surface. A secondary text colour below about 75% of white is a defect for text that carries meaning, and a
|
|
74
|
+
sentence of reading copy in the secondary colour is flagged by `check` **(check: text-tier)**.
|
|
64
75
|
- **Light and dark:** Android's quality guidelines ask for both themes, and for web content shown in the app
|
|
65
76
|
to follow them (stitch2 checks every theme DESIGN.md defines).
|
|
66
77
|
- **States as layers:** hover 8%, focus 10%, pressed 10%, dragged 16% of the content colour over the
|
|
@@ -121,3 +132,6 @@ the rest are judged from the render. Where Google and DESIGN.md disagree, DESIGN
|
|
|
121
132
|
- web.dev accessible tap targets: web.dev/articles/accessible-tap-targets
|
|
122
133
|
- Lighthouse tap targets and font size audits: developer.chrome.com/docs/lighthouse/seo/tap-targets,
|
|
123
134
|
developer.chrome.com/docs/lighthouse/seo/font-size
|
|
135
|
+
- Material 3 typography, applying type (body, label, line height): m3.material.io/styles/typography/applying-type
|
|
136
|
+
- Material 2 dark theme (text emphasis, no pure white): m2.material.io/design/color/dark-theme.html and
|
|
137
|
+
codelabs.developers.google.com/codelabs/design-material-darktheme/
|
|
@@ -42,7 +42,8 @@ short labels never wrap **(check)**.
|
|
|
42
42
|
## Colour and depth
|
|
43
43
|
|
|
44
44
|
- One accent with one meaning ("act here"). Two accent-filled elements in one region: one of them is wrong.
|
|
45
|
-
- Greys carry the structure: a few surface steps and two text colours do almost all the work
|
|
45
|
+
- Greys carry the structure: a few surface steps and two text colours do almost all the work, and the reading copy
|
|
46
|
+
is in the stronger of the two (typography.md, section 3).
|
|
46
47
|
- Status colours appear as small text, icons or thin bars, never as large fills.
|
|
47
48
|
- Text contrast at least 4.5:1, 3:1 for large text **(check)**. Secondary text on raised surfaces is where this
|
|
48
49
|
fails.
|
|
@@ -36,6 +36,9 @@ together. A typical app set (sizes for a 390 px phone):
|
|
|
36
36
|
- Nothing under 11 px, body text from 12 px, reading text 14–16 px **(check: text-small)**; prose at 45–75
|
|
37
37
|
characters a line, a max width of about `32em` **(check: measure)**. Material's fifteen-level scale and its sizes are in
|
|
38
38
|
[google.md](google.md).
|
|
39
|
+
- A meta or caption level (12–13 px) is for counts, dates, units and hints. A sentence a person reads (an
|
|
40
|
+
introduction, a card's description, an answer) takes a body level, 14 px at the smallest: a caption size that
|
|
41
|
+
carries a sentence is the usual cause of a page that reads small.
|
|
39
42
|
|
|
40
43
|
## 2. Hierarchy recipes
|
|
41
44
|
|
|
@@ -53,8 +56,34 @@ To make something stand out inside a row, change its weight or colour, not its s
|
|
|
53
56
|
|
|
54
57
|
## 3. Text colour
|
|
55
58
|
|
|
56
|
-
-
|
|
57
|
-
|
|
59
|
+
- Three tiers, by what the text does and not by how it looks: **strong** for headings and values, **body** for reading
|
|
60
|
+
copy, **secondary** for what the eye may skip (hints, captions, counts, dates, labels); a faint grey only for
|
|
61
|
+
disabled text and separators (it usually fails 4.5:1, so it never carries information).
|
|
62
|
+
- Reading copy takes the body colour, whatever its size. On a dark theme a good set is about 95%, 85–90% and 75–80%
|
|
63
|
+
of white for the three tiers (Material 3's two text roles are about 89% and 77%; see [google.md](google.md)); on a
|
|
64
|
+
light theme the same steps in the ink colour.
|
|
65
|
+
- **A contrast ratio does not show a dull page.** Every tier can pass 4.5:1 and a page still read grey, because the
|
|
66
|
+
strokes of small text reach only their own colour: a thin 13 px stroke in a 70% grey is what the eye sees, not the
|
|
67
|
+
ratio. The glyph edges are not the problem either (they render as sharp as a clean page); the colour and the tier
|
|
68
|
+
are. Measure the share of characters in each tier: when most of a page's characters are in the secondary colour,
|
|
69
|
+
or a paragraph of two sentences is, the copy is in the wrong tier. `check` warns about the second case **(check: text-tier)**: a block of
|
|
70
|
+
reading copy (sixty characters and eight words of its own text, in the page's content and not in a bar, table, menu,
|
|
71
|
+
label, control or link) drawn in DESIGN.md's `text-muted`. It needs that colour in DESIGN.md and is silent without it.
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
// characters per computed colour and size, from the rendered page (run it with Playwright's page.evaluate)
|
|
75
|
+
const share = () => {
|
|
76
|
+
const tally = {}; let total = 0;
|
|
77
|
+
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
|
|
78
|
+
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
79
|
+
const text = node.textContent.trim(), element = node.parentElement;
|
|
80
|
+
if (!text || !element.checkVisibility()) continue;
|
|
81
|
+
const style = getComputedStyle(element), key = style.color + ' ' + style.fontSize;
|
|
82
|
+
tally[key] = (tally[key] ?? 0) + text.length; total += text.length;
|
|
83
|
+
}
|
|
84
|
+
return Object.entries(tally).map(([key, count]) => [key, Math.round(100 * count / total) + '%']).sort((a, b) => parseInt(b[1]) - parseInt(a[1]));
|
|
85
|
+
};
|
|
86
|
+
```
|
|
58
87
|
- Accent-coloured text means "active" or "act here". Check its contrast on every surface it sits on: accent text
|
|
59
88
|
on a tinted accent background over a raised surface is a common failure.
|
|
60
89
|
- Status colours colour short values and words, never sentences.
|
|
@@ -110,3 +139,5 @@ Devanagari; `tokens.css` falls back to Noto and system fonts.
|
|
|
110
139
|
3. Secondary text differs by colour and weight, not just size.
|
|
111
140
|
4. Numbers are tabular; large ones proportional; units smaller and secondary.
|
|
112
141
|
5. At most three levels per region; capitals only in section labels; nothing wraps that should not.
|
|
142
|
+
6. `check` shows no `text-tier` warning: reading copy is in the body colour and at 14 px or more, and most of the page's
|
|
143
|
+
characters are not in the secondary colour (section 3).
|
|
@@ -82,7 +82,7 @@ Read the findings as:
|
|
|
82
82
|
## Before you call it done
|
|
83
83
|
|
|
84
84
|
1. Every screen you implemented is approved, and `stitch2 screens --strict` passes: one current version each.
|
|
85
|
-
2. `stitch2 check --strict` passes on the screens you touched (archived screens
|
|
85
|
+
2. `stitch2 check --strict` passes on the screens you touched (it leaves archived screens out).
|
|
86
86
|
3. `stitch2 compare` has no errors for the screens you touched; warnings are explained (a kept feature) or fixed.
|
|
87
87
|
4. `stitch2 look` and `stitch2 geometry` report nothing on the screens you touched, except differences you can
|
|
88
88
|
name as data.
|
|
@@ -32,7 +32,9 @@ The generated prose is correct but generic. Make it the product's:
|
|
|
32
32
|
1. **Overview**: the product, its users, the mood, in two or three sentences.
|
|
33
33
|
2. **Colors**: keep the role names (other skills and the components use them); give each a short brand name in
|
|
34
34
|
the prose if the team has one. Extracted colours are guesses where the page was ambiguous: confirm text,
|
|
35
|
-
surfaces and the primary with the user.
|
|
35
|
+
surfaces and the primary with the user. Define three text colours (strong, body, secondary) and write which text
|
|
36
|
+
takes which: reading copy is the body colour, the secondary one is for hints, captions, counts and dates (on a
|
|
37
|
+
dark theme about 95%, 85–90% and 75–80% of white; typography.md, section 3 of the stitch2 skill).
|
|
36
38
|
3. **Typography**: keep the levels; adjust sizes only together with the user and only on the scale.
|
|
37
39
|
4. **Components**: name the product's real components (its tab bar items, its core list row) and their states.
|
|
38
40
|
Each interactive one gets hover, pressed, focus, selected and disabled in the prose, in values ("darkens to
|