jig-ui 0.25.0 → 0.26.1
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 +70 -8
- package/dist/index.js +631 -426
- package/package.json +1 -1
- package/rules/02-tokens.md +10 -0
- package/rules/03-patterns.md +12 -4
- package/templates/COMMAND.md.tmpl +17 -4
- package/tokens/brand.default.css +6 -2
- package/tokens/mode.operator.css +9 -0
- package/tokens/mode.product.css +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jig-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.1",
|
|
4
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",
|
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.
|
|
@@ -572,10 +573,17 @@ everything else follows from.
|
|
|
572
573
|
- **A code block** keeps its line breaks and indents and wraps a long line
|
|
573
574
|
(`white-space: pre-wrap`, `overflow-wrap: anywhere`). What is copied is
|
|
574
575
|
the source as written, not the wrapped lines.
|
|
575
|
-
- **A table too wide to fit** stacks its rows: each row a block,
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
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.
|
|
579
587
|
- **A long identifier** (a URL, a hash, a file path) breaks where it must
|
|
580
588
|
(`overflow-wrap: anywhere`).
|
|
581
589
|
6. **Each transition happens where the content needs it.** The width at which
|
|
@@ -78,12 +78,13 @@ came from, and the surfaces it used — the output says whether they came from
|
|
|
78
78
|
`jig.config.json` or from the default.
|
|
79
79
|
|
|
80
80
|
If the token layer does not exist yet, this is the command that creates it. **Do
|
|
81
|
-
not
|
|
81
|
+
not write the token files by hand.** `init` derives the brand colour, checks it
|
|
82
82
|
against the contrast floor in both light and dark, and records a checksum for
|
|
83
83
|
each file it writes; a file you write by hand is untracked, so `jig update` can
|
|
84
|
-
never refresh it again.
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
never refresh it again. The brand file it writes is the project's own, though:
|
|
85
|
+
once `DECISIONS.md` records a colour, a typeface or corners, change those values
|
|
86
|
+
in it to match (see `decide`). `jig check` reads the token layer back and holds it
|
|
87
|
+
to those floors, so a value that fails one is caught however it got there.
|
|
87
88
|
|
|
88
89
|
## check
|
|
89
90
|
|
|
@@ -1973,6 +1974,18 @@ the user as left out on purpose, with the reason. Then go the other way: every
|
|
|
1973
1974
|
and ask. A `Why (inferred):` traces to what it was inferred from; say what that was.
|
|
1974
1975
|
Include this mapping in your message, below the file.
|
|
1975
1976
|
|
|
1977
|
+
**Then put the answers into the brand file.** The type, the colour and the
|
|
1978
|
+
corners each name the token they become, and the brand file `init` wrote is the
|
|
1979
|
+
project's own: `jig update` refreshes the mode files and never touches it. Change
|
|
1980
|
+
its values to match what the user decided: the brand hue, saturation and lightness
|
|
1981
|
+
for the colour, `--font-text` and `--font-display` for the type (and load the face
|
|
1982
|
+
wherever the pages load their styles, if it is a web font), and the `--radius-*`
|
|
1983
|
+
scale for the corners. A value the user did not decide stays as `init` wrote it.
|
|
1984
|
+
Then run `{{scripts_path}} check`: it holds the brand file to the contrast floors
|
|
1985
|
+
in light and dark, and says if a decided colour or typeface never reached it. Of
|
|
1986
|
+
six runs whose owner named a colour and a typeface, four recorded both in this file
|
|
1987
|
+
and built every page in Jig's unbranded default, because no step said to apply them.
|
|
1988
|
+
|
|
1976
1989
|
Show it and ask the user to confirm it is right before you stop. Leave no
|
|
1977
1990
|
`[TODO]` markers — the gate treats them as an unwritten file, correctly, because
|
|
1978
1991
|
a placeholder decision is not a decision.
|
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
|
+
}
|