jig-ui 0.24.0 → 0.26.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/CHANGELOG.md +149 -8
- package/README.md +14 -10
- package/dist/index.js +274 -168
- package/examples/J-164.html +7 -0
- package/package.json +2 -2
- package/rules/00-anti-patterns.md +8 -2
- package/rules/01-modes.md +2 -2
- package/rules/02-tokens.md +10 -0
- package/rules/03-patterns.md +22 -4
- package/rules/05-copy.md +1 -1
- package/rules.index.json +7 -0
- package/templates/COMMAND.md.tmpl +72 -7
- package/templates/SKILL.md.tmpl +1 -1
- package/tokens/brand.default.css +6 -2
- package/tokens/mode.operator.css +9 -0
- package/tokens/mode.product.css +7 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<!-- J-164 · An indexable page a link preview cannot read -->
|
|
2
|
+
<figure data-example="dont">
|
|
3
|
+
<div style="font-family:system-ui,-apple-system,'Segoe UI',sans-serif;font-size:13px;line-height:1.45;color:#1f1f1f;background:#f5f5f4;padding:16px;min-height:176px;box-sizing:border-box;"><div style="font-size:12px;color:#57534e;margin-bottom:6px">Sam, in a team chat:</div><div style="background:#fff;border:1px solid #d6d3d1;border-radius:8px;padding:10px;"><div style="color:#1a0dab;font-size:13px">tidewell.io/pricing</div><div style="border-left:3px solid #d6d3d1;margin-top:8px;padding-left:8px;font-size:12px;color:#4d5156">Tidewell<br>Home · Product · Docs · Pricing · Sign in</div></div><div style="font-size:11px;color:#5c5c5c;margin-top:8px">No preview tags: the card is the site's name and its navigation.</div></div>
|
|
4
|
+
</figure>
|
|
5
|
+
<figure data-example="do">
|
|
6
|
+
<div style="font-family:system-ui,-apple-system,'Segoe UI',sans-serif;font-size:13px;line-height:1.45;color:#1f1f1f;background:#f5f5f4;padding:16px;min-height:176px;box-sizing:border-box;"><div style="font-size:12px;color:#57534e;margin-bottom:6px">Sam, in a team chat:</div><div style="background:#fff;border:1px solid #d6d3d1;border-radius:8px;padding:10px;"><div style="color:#1a0dab;font-size:13px">tidewell.io/pricing</div><div style="border-left:3px solid #3f6212;margin-top:8px;padding-left:8px;font-size:12px;color:#1f1f1f"><b>Pricing · Tidewell</b><br><span style="color:#4d5156">Three plans, billed monthly or yearly. Cancel any time.</span></div></div><div style="font-size:11px;color:#5c5c5c;margin-top:8px">og:title and og:description: the card says what the page is.</div></div>
|
|
7
|
+
</figure>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jig-ui",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A design system for coding agents.
|
|
3
|
+
"version": "0.26.0",
|
|
4
|
+
"description": "A design system for coding agents. 160 numbered UI rules, brand x mode design tokens, and an installer for Claude Code, Codex, Cursor and opencode.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -365,7 +365,7 @@ Without `viewport-fit=cover`, the browser keeps the page inside the safe area on
|
|
|
365
365
|
|
|
366
366
|
### D-115 The page scrolls sideways on a phone
|
|
367
367
|
❌ At phone width the whole page is wider than the screen — a data table, a long URL, an image, a `width: 100vw` element or a fixed-width block pushes it out, and the reader can drag the page left and right
|
|
368
|
-
✅ At every width, nothing makes the page wider than the screen. Content that is genuinely wider — a data table, a code block — scrolls inside its own container with a visible edge (`E-62`), and the page itself never does. `editorial` goes further and allows no scrolling regions on mobile at all (`M-01`).
|
|
368
|
+
✅ At every width, nothing makes the page wider than the screen. Content that is genuinely wider — a data table, a code block — scrolls inside its own container with a visible edge (`E-62`), and the page itself never does. `editorial` goes further and allows no scrolling regions on mobile at all (`M-01`): there a code block wraps its long lines and a wide table stacks its rows (`L-01`, step 6).
|
|
369
369
|
Judge it on a render, not in the source: at 360px, `document.documentElement.scrollWidth` must not be greater than `document.documentElement.clientWidth`. The usual causes are each one line to fix — `overflow-wrap: anywhere` on text the author does not control, `max-width: 100%` on media, `width: 100%` instead of `100vw` (which includes the scrollbar), and a wrapper with `overflow-x: auto` around anything tabular.
|
|
370
370
|
A page that scrolls sideways is not merely untidy. The reader's vertical swipes drift, the page slides half off the screen, and every line of text needs re-centring before it can be read.
|
|
371
371
|
|
|
@@ -376,6 +376,7 @@ Agents render the happy path. This section exists because that is the single mos
|
|
|
376
376
|
### E-28 Missing states
|
|
377
377
|
❌ A component with only a default appearance
|
|
378
378
|
✅ Every interactive element defines: `hover`, `focus-visible`, `active`, `disabled`. Every data view defines: loading, empty, error, and partial/truncated.
|
|
379
|
+
A browser makes an `<iframe>` a tab stop whether or not anything in it can be used. One that only shows something, with nothing inside to operate or scroll, is taken out of the tab order (`tabindex="-1"`) rather than given states it has no use for; a keyboard reader otherwise meets a stop with nothing to see. One the reader uses (a player, a map, a form) keeps its stop and shows focus.
|
|
379
380
|
|
|
380
381
|
### E-29 Focus removed without replacement
|
|
381
382
|
❌ `outline: none` with nothing in its place
|
|
@@ -411,7 +412,7 @@ Where disabling is genuinely right, put a message beside it or a tooltip on it e
|
|
|
411
412
|
❌ A toolbar of icon-only buttons whose meaning depends on recognising the glyph
|
|
412
413
|
✅ A visible text label beside the icon, or the icon plus label on the primary path.
|
|
413
414
|
This is **not** the same problem as `E-34`. An `aria-label` serves a screen reader and does nothing for a sighted user with low computer literacy, or anyone meeting an unfamiliar glyph. Both are required.
|
|
414
|
-
Icon-only is acceptable for a small set of near-universal glyphs
|
|
415
|
+
Icon-only is acceptable for a small set of near-universal glyphs and in `operator`, where repetition builds recognition — and even there, on first-run surfaces the label stays. Close, search and menu are examples, not the whole list: the test is whether most readers would name the glyph the same way without the label. A sun and moon for the theme, or a service's own widely known mark linking to it, usually pass; a funnel, a sparkle or a lightning bolt does not. An icon-only control still carries its name in text a screen reader reads (`E-34`).
|
|
415
416
|
|
|
416
417
|
### E-52 Unconventional controls
|
|
417
418
|
❌ A bespoke form field, checkbox or select that looks and behaves unlike every other one the user has met
|
|
@@ -713,6 +714,11 @@ A second copy of the positioning is a second thing to keep in step by hand, whic
|
|
|
713
714
|
✅ Concatenate the static routes unconditionally, and let a failed read yield the stale list rather than an empty one. When a list is genuinely empty, prove it before shipping.
|
|
714
715
|
An empty sitemap is not a missing sitemap. It is a positive claim, and the crawler believes it.
|
|
715
716
|
|
|
717
|
+
### J-164 An indexable page a link preview cannot read
|
|
718
|
+
❌ A link pasted into a message or a post that shows a bare address, or the site's name over a line of its navigation
|
|
719
|
+
✅ Every indexable page states its own preview: `og:title` and `og:description`, beside its `<title>` and meta description, and `og:type` for what it is (`article` for a post). An image and `og:url` take the page's full address: add them once the site has one, never as a relative path.
|
|
720
|
+
The card is met before the page, often by someone who never opens it. Without these tags each service builds the card from whatever it finds, and they find different things. A preview is copy, like the title and description: the change that rewrites the page rewrites its card (`J-120`), and a value the page already holds is read, not typed again (`J-126`).
|
|
721
|
+
|
|
716
722
|
---
|
|
717
723
|
|
|
718
724
|
## K. Safety at the interface
|
package/rules/01-modes.md
CHANGED
|
@@ -85,7 +85,7 @@ Resolved values: `02-tokens.md` — the option sets for type, spacing, radius an
|
|
|
85
85
|
- One hero maximum, at the top. A second full-viewport section is a second hero.
|
|
86
86
|
- Every page states its subject above the fold in text, not only in an image.
|
|
87
87
|
- Prose blocks are measure-capped even when the container is wide.
|
|
88
|
-
- No horizontal scrolling regions on mobile. Reflow instead.
|
|
88
|
+
- No horizontal scrolling regions on mobile. Reflow instead: a code block wraps its long lines, keeping its line breaks and indents, and a table too wide for the screen stacks its rows, each cell with its column's name (`L-01`, step 6).
|
|
89
89
|
- JavaScript: **none by default.** A content page ships no script unless a feature on it needs some: a theme toggle, a search box, a filter. That is a default, not an absolute zero. Each script names, in a comment, the feature and the decision or rule that asks for it, and a review judges whether the feature needs it and whether it is as small as the feature allows, not whether it exists. What the budget forbids is script no feature asks for: a framework runtime to render static text, a library for one effect, tracking bundled into the page. **Behaviour a rule requires is not a feature and is not counted**: a few lines whose only job is something a rule asks for and the browser does not give, such as `Escape` closing a `<details>` menu, or a tap outside closing a menu in a fixed header (`P-14`), are allowed in every mode, under 1 KB, with the rule named in a comment. Nothing else rides along in them.
|
|
90
90
|
|
|
91
91
|
---
|
|
@@ -190,7 +190,7 @@ Attempting to vary these by mode is a category error:
|
|
|
190
190
|
- **Accessibility floors.** Contrast, focus indication, target size, semantic markup. Identical in all three. `operator` being dense does not license a 24px tap target or a 3:1 body contrast.
|
|
191
191
|
- **Brand identity.** Palette, typeface, logo, voice.
|
|
192
192
|
- **State completeness.** Every mode renders loading, empty, error and disabled.
|
|
193
|
-
- **The anti-pattern file.** All
|
|
193
|
+
- **The anti-pattern file.** All 129 rules in it apply everywhere.
|
|
194
194
|
|
|
195
195
|
---
|
|
196
196
|
|
package/rules/02-tokens.md
CHANGED
|
@@ -262,6 +262,16 @@ It is an accessibility floor, so it is excluded from the table above — there i
|
|
|
262
262
|
nothing per-mode about it to resolve. The same is true of `--focus-ring-width`
|
|
263
263
|
and `--focus-ring-offset`, which live in the brand file for that reason.
|
|
264
264
|
|
|
265
|
+
**Inside a table row, the row is the target, and every row is one height.** A
|
|
266
|
+
dense row is shorter than the floor (`operator`'s 36px), and a control that
|
|
267
|
+
sets its own `min-height` to the floor stretches the rows that hold it and not
|
|
268
|
+
the rest: in a run, an invoices table whose "Mark paid" rows stood 48px tall
|
|
269
|
+
among 36px ones. So a control in a row takes the row's height and never its
|
|
270
|
+
own. For a mouse, a dense row is above WCAG 2.2's 24px minimum; for a finger it
|
|
271
|
+
is not, so under `@media (pointer: coarse)` the mode files raise `--size-row`
|
|
272
|
+
(and `--size-row-compact`) to `--size-touch-target`, and every row grows
|
|
273
|
+
together.
|
|
274
|
+
|
|
265
275
|
**Layout sizes.** Three tokens size a page's frame, where the others size what
|
|
266
276
|
is inside it. A real site found none of them and made up its own three:
|
|
267
277
|
|
package/rules/03-patterns.md
CHANGED
|
@@ -285,6 +285,7 @@ Primarily an `operator` pattern; the rules apply wherever a table appears.
|
|
|
285
285
|
**Rules**
|
|
286
286
|
- Row identity is stable across refresh, sort and filter. A row that moves under a click causes the wrong record to be acted on — the most damaging bug this pattern has.
|
|
287
287
|
- Numeric columns are right-aligned and use tabular figures (`--font-numeric`). Text columns are start-aligned. Never centre either.
|
|
288
|
+
- A cell stays a table cell. To line up what is inside it (a name and a tag, an icon and a label), put `display: flex` on a wrapper inside the cell, never on the `<td>` or `<th>` itself: a cell given its own display stops taking its row's height, so its text and its border drift from the rest of the row. A table stacked on a phone, the whole table set to `block`, is the exception (`L-01`, step 6). The render probe reports a cell that has left its table.
|
|
288
289
|
- Column headers state units. "Weight" is ambiguous; "Weight (kg)" is not.
|
|
289
290
|
- Truncation is resolvable by click or expand, never by hover alone (`E-31`, `01-modes.md`).
|
|
290
291
|
- Sort state is visible in the header and reflected in the URL, so a view can be shared.
|
|
@@ -564,10 +565,27 @@ everything else follows from.
|
|
|
564
565
|
fluid: they track the viewport between a floor and a ceiling with no media
|
|
565
566
|
query at all. A hand-written ladder of sizes per breakpoint reintroduces the
|
|
566
567
|
jumps the scale exists to remove, and goes stale the moment the scale changes.
|
|
567
|
-
5. **Content that is genuinely wider scrolls inside itself
|
|
568
|
-
|
|
569
|
-
(`E-62`), keeps its type size, and
|
|
570
|
-
|
|
568
|
+
5. **Content that is genuinely wider scrolls inside itself, except in
|
|
569
|
+
`editorial` on a phone.** A code block, a wide table, a long identifier: its
|
|
570
|
+
own container scrolls with a visible edge (`E-62`), keeps its type size, and
|
|
571
|
+
the page never scrolls sideways (`D-115`). `editorial` allows no scrolling
|
|
572
|
+
region on mobile (`M-01`), so there each one reflows instead:
|
|
573
|
+
- **A code block** keeps its line breaks and indents and wraps a long line
|
|
574
|
+
(`white-space: pre-wrap`, `overflow-wrap: anywhere`). What is copied is
|
|
575
|
+
the source as written, not the wrapped lines.
|
|
576
|
+
- **A table too wide to fit** stacks its rows: each row a block, led by the
|
|
577
|
+
cell that names the row (a person, an invoice, a rule) as the block's own
|
|
578
|
+
heading, with no label in front of it. The other cells follow beneath it,
|
|
579
|
+
and a cell carries its column's name only where its value does not say
|
|
580
|
+
what it is: a bare "Yes", a number, a date. An email address, a role, a
|
|
581
|
+
status badge or a price says what it is, so it gets no "Email:", "Role:"
|
|
582
|
+
or "Status:". The row's actions sit together at the block's end, side by
|
|
583
|
+
side where they fit, with no "Actions" label. It stays a `<table>` with
|
|
584
|
+
its header row, so a screen reader still reads it as one. Where it fits,
|
|
585
|
+
it stays a table: the switch is the width at which its columns stop
|
|
586
|
+
fitting.
|
|
587
|
+
- **A long identifier** (a URL, a hash, a file path) breaks where it must
|
|
588
|
+
(`overflow-wrap: anywhere`).
|
|
571
589
|
6. **Each transition happens where the content needs it.** The width at which
|
|
572
590
|
three columns stop fitting is a property of the columns, not of a device. Set
|
|
573
591
|
it from the content, and expect the numbers to differ per component.
|
package/rules/05-copy.md
CHANGED
|
@@ -90,7 +90,7 @@ Whichever you choose, be consistent across sibling elements — a list where thr
|
|
|
90
90
|
Interface text is read in fragments, at a glance, in a space someone else's content has to fit too. An em dash is a pause the reader has to interpret: it stands in for a comma, a colon, a bracket or a full stop, and which one it is only becomes clear after reading past it. The punctuation that says exactly one thing is faster.
|
|
91
91
|
It is also the clearest tell of machine-written copy. Generated text reaches for the em dash far more often than a person does, and readers have learned to notice. Copy that reads as generated is copy the reader trusts less, whatever it says.
|
|
92
92
|
This is about interface strings: labels, buttons, headings, errors, empty states, help text, and the prose a page ships. Markdown counts where a framework renders it as a page, which is most of them (`src/content`, `content/`, MDX routes). A repository document does not: `README.md`, `CHANGELOG.md`, `AGENTS.md` and their kin are written for whoever works on the code, and so are your commit messages and this file.
|
|
93
|
-
A verbatim quotation keeps its own punctuation. Text a page quotes from another source (a document, a spec, a person), marked as a quotation with `<blockquote>` or `<q>`, is that source's words, and
|
|
93
|
+
A verbatim quotation keeps its own punctuation. Text a page quotes from another source (a document, a spec, a person), marked as a quotation with `<blockquote>` or `<q>`, is that source's words, and so is a program's own output or code shown as it is, in `<pre>`, `<code>`, `<samp>` or `<kbd>`. Changing either to satisfy this rule would misquote it. The page's own copy around the quotation, and any heading or label it gives it, is still held to the rule.
|
|
94
94
|
The en dash keeps its one job: ranges, where it is read as "to" (`2–10 seats`, `Mon–Fri`). That is not a pause, and it is not affected.
|
|
95
95
|
|
|
96
96
|
### I-87 Inconsistent vocabulary
|
package/rules.index.json
CHANGED
|
@@ -322,10 +322,12 @@ Write the answer as `critique: each` or `critique: at-ship`.
|
|
|
322
322
|
|
|
323
323
|
### 2. Run `L-01`
|
|
324
324
|
|
|
325
|
-
Read `L-01 · Layout method` in `{{rules_path}}/03-patterns.md` and run its
|
|
325
|
+
Read `L-01 · Layout method` in `{{rules_path}}/03-patterns.md` and run its six
|
|
326
326
|
steps against the answers. The spec's structural half **is** that output — group,
|
|
327
|
-
order by importance, space from the inside out, align to a grid,
|
|
328
|
-
hierarchy plainly enough that the squint question can be answered against it
|
|
327
|
+
order by importance, space from the inside out, align to a grid, state the
|
|
328
|
+
hierarchy plainly enough that the squint question can be answered against it,
|
|
329
|
+
and decide how it collapses. Step 6 is where the phone composition comes from,
|
|
330
|
+
including what this mode does with a code block or table wider than the screen.
|
|
329
331
|
|
|
330
332
|
### 3. Write it down — one composition per screen size
|
|
331
333
|
|
|
@@ -483,7 +485,7 @@ to the spec, never the spec to the decisions.
|
|
|
483
485
|
- **"The design system decides" is not a value.** When the user defers — "you decide",
|
|
484
486
|
"whatever Jig says", "leave it to the system" — that is an instruction to look the
|
|
485
487
|
answer up, not a phrase to copy into the spec. Search in this order: the `P-`
|
|
486
|
-
pattern for the component (`{{command_prefix}}explain <component>`), `L-01`'s
|
|
488
|
+
pattern for the component (`{{command_prefix}}explain <component>`), `L-01`'s six
|
|
487
489
|
steps, then the rules. Write the composition that lookup gives — "stacked, Pro
|
|
488
490
|
first", "Menu button, links in a vertical list" — and cite the id it came from.
|
|
489
491
|
Three of six specs in a live run wrote "arrangement decided by design system" into
|
|
@@ -599,6 +601,34 @@ its size's frame of the drawing at `mockup_at:`. Otherwise a spec can go through
|
|
|
599
601
|
several confirmed rounds after its drawing was approved and still say `approved`
|
|
600
602
|
over a drawing of none of them.
|
|
601
603
|
|
|
604
|
+
### Before you stop: what the gate holds a spec to
|
|
605
|
+
|
|
606
|
+
With the Stop hook, each of these keeps the session open until it is fixed. Get
|
|
607
|
+
them right as you write, not after the gate names them:
|
|
608
|
+
|
|
609
|
+
- **A spec writes under `.jig/` only.** A change to `DECISIONS.md`, a stylesheet or
|
|
610
|
+
a page is for `{{command_prefix}}decide`, `make` or `tweak`: record in the spec
|
|
611
|
+
what the owner said, and hand the change on.
|
|
612
|
+
- **The front matter holds Jig's fields and nothing else.** Anything more goes in
|
|
613
|
+
the prose below it.
|
|
614
|
+
- **Quotation marks within a few words after "owner", or after "the user said",
|
|
615
|
+
mark the owner's words.** What is inside them must be what the owner said: in
|
|
616
|
+
this conversation, in `DECISIONS.md`, or already in the spec. To name a
|
|
617
|
+
decision, a heading or a file near the word "owner", leave the quotation marks
|
|
618
|
+
off.
|
|
619
|
+
- **`<name>.checked.json` is of the spec as it stands.** Its `spec` value matches
|
|
620
|
+
`{{scripts_path}} checksum <name>`, so an edit after the check means a second
|
|
621
|
+
check, of what changed.
|
|
622
|
+
- **Each fact has one `source`:** a path from the project root, `path:line`, or a
|
|
623
|
+
URL, and nothing else. The file exists and the line is in it. Two places are two
|
|
624
|
+
facts; what you found at the source goes in `note`.
|
|
625
|
+
- **`holds` is `true`, `false` or `"unchecked"`, with a `note` for anything but
|
|
626
|
+
`true`.** A fact found false is fixed in the spec before the owner is asked.
|
|
627
|
+
- **`confirmed: true` only on the owner's yes, in this session, to the sheet you
|
|
628
|
+
showed them.** Words in the request that started the session came before the
|
|
629
|
+
sheet existed, and are not a reply to it, even when they say the owner
|
|
630
|
+
confirms. Show the sheet and stop.
|
|
631
|
+
|
|
602
632
|
## mockup
|
|
603
633
|
|
|
604
634
|
**Low-fidelity design.** Draw the confirmed spec in grayscale, at every size it
|
|
@@ -849,6 +879,22 @@ confirmed again.
|
|
|
849
879
|
With the Stop hook, the gate reads the quotation after `approved` or `skipped` and
|
|
850
880
|
holds it to what the owner said in this session.
|
|
851
881
|
|
|
882
|
+
### Before you stop: what the gate holds a mockup to
|
|
883
|
+
|
|
884
|
+
- **A mockup writes under `.jig/` only:** the drawing in `.jig/mockups/`, and the
|
|
885
|
+
spec's `mockup:` and `mockup_at:` lines.
|
|
886
|
+
- **The drawing shows what the spec lists**, at every size, and either side of each
|
|
887
|
+
switch the page crosses. The gate checks this before you put it to the owner.
|
|
888
|
+
- **`mockup:` stays `pending` until the owner answers.** Then it is `approved` or
|
|
889
|
+
`skipped`, followed by their words in quotation marks: the reply that approves
|
|
890
|
+
this drawing, or says to skip it. Words that only say they looked at it, or
|
|
891
|
+
that are about something else, are not their word on the drawing. Ask them
|
|
892
|
+
whether they approve it for `make`, and quote the answer.
|
|
893
|
+
- **`mockup_at:` names the approved drawing**, a file under `.jig/mockups/` that
|
|
894
|
+
exists, or a link.
|
|
895
|
+
- **An approved drawing does not change.** Changing it after approval sets
|
|
896
|
+
`mockup: pending` and puts it to the owner again.
|
|
897
|
+
|
|
852
898
|
Then stop. The next step is `{{command_prefix}}make`.
|
|
853
899
|
|
|
854
900
|
## make
|
|
@@ -1242,9 +1288,13 @@ The probe opens the phone menu, presses Escape, measures sideways scroll, and re
|
|
|
1242
1288
|
whether the styles and tokens actually applied. `verdicts` refuses `rendered: true`
|
|
1243
1289
|
without a probe at each width, and refuses an `ok` the probe contradicts — a `P-14`
|
|
1244
1290
|
"ok" on a menu that did not open, a `D-115` "ok" on a page that scrolls sideways. It
|
|
1245
|
-
also
|
|
1246
|
-
|
|
1247
|
-
|
|
1291
|
+
also names what the page fails whatever the verdicts say: it renders in the
|
|
1292
|
+
browser's default font, shows `${` or an em dash to readers, or serves a missing
|
|
1293
|
+
or overlong title or description. Those are findings on the page, listed under
|
|
1294
|
+
`!` and counted as `measured=` on the `JIG_VERDICTS` line. Put each in the report;
|
|
1295
|
+
make or tweak fixes them, and the critique leaves the page as it is.
|
|
1296
|
+
Never write a probe file yourself: when it disagrees with you, it is the review
|
|
1297
|
+
that is wrong.
|
|
1248
1298
|
Then run:
|
|
1249
1299
|
|
|
1250
1300
|
```
|
|
@@ -1540,6 +1590,21 @@ judges it, and leave the verdicts alone. The page then owes a critique, and
|
|
|
1540
1590
|
`{{command_prefix}}ship` will not pass until one has judged it. Never defer it
|
|
1541
1591
|
on your own account: the gate refuses a deferral nobody gave.
|
|
1542
1592
|
|
|
1593
|
+
### Before you stop: what the gate holds a tweak to
|
|
1594
|
+
|
|
1595
|
+
- **The spec is confirmed, and its mockup approved or skipped.** A page that has
|
|
1596
|
+
neither goes through `mockup` and `make`.
|
|
1597
|
+
- **The page's regions and its approved drawing stay as they were.** A change to
|
|
1598
|
+
what the page holds goes through `spec` and `mockup`.
|
|
1599
|
+
- **`tweak.json` holds `at`, `change`, `ids` and, when the owner said so,
|
|
1600
|
+
`deferred`, and no other field.**
|
|
1601
|
+
- **`change` is the owner's words for the change, exactly as they gave them in
|
|
1602
|
+
this session.** Nothing goes before or after them, not even a label such as
|
|
1603
|
+
"the owner's words:". What you made of them goes in the spec's Tweak entry.
|
|
1604
|
+
- **`ids` names at least one rule or decision**, and each is re-judged by a reader
|
|
1605
|
+
that did not make the change, unless `deferred` quotes the owner telling you to
|
|
1606
|
+
leave it for later (or is `true` where the page's critique waits for ship).
|
|
1607
|
+
|
|
1543
1608
|
### Finish
|
|
1544
1609
|
|
|
1545
1610
|
Report what changed, in the owner's words; the decision and spec lines you
|
package/templates/SKILL.md.tmpl
CHANGED
|
@@ -49,7 +49,7 @@ cite the number when you follow or deliberately break one.
|
|
|
49
49
|
says is lost to every check. If it keeps recurring, tell the owner, since
|
|
50
50
|
Jig may be missing a field.
|
|
51
51
|
**Building a screen rather than a single component?** Read `L-01 · Layout
|
|
52
|
-
method` in `{{rules_path}}/03-patterns.md` and run its
|
|
52
|
+
method` in `{{rules_path}}/03-patterns.md` and run its six steps before
|
|
53
53
|
writing any markup. It is a procedure, not a component, so step 4 never
|
|
54
54
|
selects it and nothing else will. (`explain L-01` prints it too, but the
|
|
55
55
|
file is the source — do not skip the step if the command is unavailable.)
|
package/tokens/brand.default.css
CHANGED
|
@@ -117,9 +117,13 @@
|
|
|
117
117
|
--focus-ring-offset: 2px;
|
|
118
118
|
|
|
119
119
|
/* ================= TYPE ================= */
|
|
120
|
-
|
|
120
|
+
/* Each platform's own interface face, named one by one: San Francisco,
|
|
121
|
+
Segoe UI, Roboto, then Noto Sans and Helvetica/Arial for the rest.
|
|
122
|
+
`system-ui` is left out on purpose: on Linux it resolves to the desktop's
|
|
123
|
+
own font, often DejaVu Sans, before any face below it is tried. */
|
|
124
|
+
--font-text: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", "Helvetica Neue", Arial, sans-serif;
|
|
121
125
|
--font-display: var(--font-text);
|
|
122
|
-
--font-mono: ui-monospace, "SF Mono", "Cascadia Code", monospace;
|
|
126
|
+
--font-mono: ui-monospace, "SF Mono", Menlo, Consolas, "Cascadia Code", "Liberation Mono", monospace;
|
|
123
127
|
--font-numeric-features: "tnum" 1, "lnum" 1;
|
|
124
128
|
|
|
125
129
|
/* ================= RADIUS — four, by element size ================= */
|
package/tokens/mode.operator.css
CHANGED
|
@@ -102,3 +102,12 @@
|
|
|
102
102
|
@media (prefers-reduced-motion: reduce) {
|
|
103
103
|
:root { --duration-fast: 1ms; --duration-base: 1ms; --duration-slow: 1ms; }
|
|
104
104
|
}
|
|
105
|
+
|
|
106
|
+
/* On a touch screen a table row is a finger's target. A dense row (36px, 32px
|
|
107
|
+
compact) is above WCAG 2.2's 24px minimum for a mouse, and below the 48px a
|
|
108
|
+
finger needs, so under a coarse pointer every row rises to the floor. A
|
|
109
|
+
control inside a row never sets its own height to reach it: every row in a
|
|
110
|
+
table is one height, and here the tokens make that height the right one. */
|
|
111
|
+
@media (pointer: coarse) {
|
|
112
|
+
:root { --size-row: var(--size-touch-target); --size-row-compact: var(--size-touch-target); }
|
|
113
|
+
}
|
package/tokens/mode.product.css
CHANGED
|
@@ -105,3 +105,10 @@
|
|
|
105
105
|
@media (prefers-reduced-motion: reduce) {
|
|
106
106
|
:root { --duration-fast: 1ms; --duration-base: 1ms; --duration-slow: 1ms; }
|
|
107
107
|
}
|
|
108
|
+
|
|
109
|
+
/* On a touch screen a table row is a finger's target: a compact row (40px)
|
|
110
|
+
rises to the 48px floor under a coarse pointer, as `operator`'s rows do. A
|
|
111
|
+
control inside a row never sets its own height to reach it. */
|
|
112
|
+
@media (pointer: coarse) {
|
|
113
|
+
:root { --size-row-compact: var(--size-touch-target); }
|
|
114
|
+
}
|