jig-ui 0.26.1 → 0.26.2
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 +24 -0
- package/dist/index.js +23 -0
- package/package.json +1 -1
- package/rules/03-patterns.md +11 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.26.2 (2026-10-13)
|
|
4
|
+
|
|
5
|
+
A button in a table row keeps the row's height, and the render probe reports
|
|
6
|
+
rows it stretches.
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- **A button in a table row takes the row's height.** 0.26.0 said so in the
|
|
11
|
+
tokens chapter, but the Button pattern, which an agent reads to build a
|
|
12
|
+
button, still gave its hit area a 48px floor with no exception, and an
|
|
13
|
+
invoices table on 0.26.1 had its "Mark as paid" rows at 65px among 41px ones.
|
|
14
|
+
The Button and Data table patterns now say it where buttons are built: a
|
|
15
|
+
button in a row is sized to the control height with no minimum of its own,
|
|
16
|
+
and on a touch screen the whole row rises to the touch target instead. On a
|
|
17
|
+
run of this release, every row stood 36px with a mouse and 48px on touch.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **The render probe reports a table whose rows are not one height because of
|
|
22
|
+
a control.** When the rows holding a button or link stand taller than the
|
|
23
|
+
rest, and the control is taller than the short rows, it is a measured
|
|
24
|
+
failure (`P-02`, `P-06`). Rows that differ only because text wraps are left
|
|
25
|
+
alone.
|
|
26
|
+
|
|
3
27
|
## 0.26.1 (2026-10-13)
|
|
4
28
|
|
|
5
29
|
The colour and typeface you decide in `/jig decide` now reach the pages, and
|
package/dist/index.js
CHANGED
|
@@ -6633,6 +6633,25 @@ var PROBE_SCRIPT = `(async () => {
|
|
|
6633
6633
|
if (!table || getComputedStyle(table).display !== 'table' || display === 'table-cell' || display === 'none' || !vis(cell)) continue;
|
|
6634
6634
|
brokenCells.push({ cell: cell.tagName.toLowerCase() + (cell.classList[0] ? '.' + cell.classList[0] : ''), text: (cell.innerText || '').trim().replace(/\\s+/g, ' ').slice(0, 40), display });
|
|
6635
6635
|
}
|
|
6636
|
+
// Rows of one table at different heights, where the taller rows are the
|
|
6637
|
+
// ones holding a control taller than the short rows: a button given the
|
|
6638
|
+
// touch-target floor as its own minimum height. An invoices table had its
|
|
6639
|
+
// "Mark as paid" rows at 65px among 41px ones. Rows that differ because a
|
|
6640
|
+
// cell's text wraps are left alone: only a control can be the cause here.
|
|
6641
|
+
const unevenRows = [];
|
|
6642
|
+
for (const table of [...document.querySelectorAll('table')].slice(0, 20)) {
|
|
6643
|
+
if (unevenRows.length >= 3 || getComputedStyle(table).display !== 'table' || !vis(table)) continue;
|
|
6644
|
+
const rows = [...table.querySelectorAll('tbody tr')].filter((r) => vis(r));
|
|
6645
|
+
if (rows.length < 2) continue;
|
|
6646
|
+
const heights = rows.map((r) => Math.round(r.getBoundingClientRect().height));
|
|
6647
|
+
const short = Math.min(...heights);
|
|
6648
|
+
const control = rows
|
|
6649
|
+
.filter((r, i) => heights[i] > short + 2)
|
|
6650
|
+
.map((r) => [...r.querySelectorAll('button, a[href], input, select')].find((c) => vis(c) && c.getBoundingClientRect().height > short))
|
|
6651
|
+
.find(Boolean);
|
|
6652
|
+
if (!control) continue;
|
|
6653
|
+
unevenRows.push({ table: 'table' + (table.classList[0] ? '.' + table.classList[0] : ''), short, tall: Math.max(...heights), control: control.tagName.toLowerCase() + (control.classList[0] ? '.' + control.classList[0] : ''), controlHeight: Math.round(control.getBoundingClientRect().height) });
|
|
6654
|
+
}
|
|
6636
6655
|
return JSON.stringify({
|
|
6637
6656
|
jigProbe: ${PROBE_VERSION},
|
|
6638
6657
|
url: location.href,
|
|
@@ -6642,6 +6661,7 @@ var PROBE_SCRIPT = `(async () => {
|
|
|
6642
6661
|
sidewaysScroll: doc.scrollWidth > doc.clientWidth,
|
|
6643
6662
|
sidewaysBoxes,
|
|
6644
6663
|
brokenCells,
|
|
6664
|
+
unevenRows,
|
|
6645
6665
|
bodyFont: getComputedStyle(document.body).fontFamily,
|
|
6646
6666
|
defaultFont: getComputedStyle(document.body).fontFamily === defaultFont,
|
|
6647
6667
|
unresolvedTokens: [...unresolved],
|
|
@@ -7128,6 +7148,9 @@ function probeCheck(probes, verdictOf, indexable = true, mode) {
|
|
|
7128
7148
|
const shown = p.brokenCells.map((c) => `${c.cell}${c.text ? ` ("${c.text}")` : ""} is display: ${c.display}`).join("; ");
|
|
7129
7149
|
failures.push(`${at(p)}: ${p.brokenCells.length === 1 ? "a table cell has" : `${p.brokenCells.length} table cells have`} left the table: ${shown}. A cell given its own display stops taking its row's height, so its border and its text drift from the row's. Keep the cell a cell and put the flex on a wrapper inside it (P-06).`);
|
|
7130
7150
|
}
|
|
7151
|
+
for (const u of p.unevenRows ?? []) {
|
|
7152
|
+
failures.push(`${at(p)}: ${u.table}'s rows are not one height: those holding ${u.control} (${u.controlHeight}px tall) stand ${u.tall}px, the rest ${u.short}px. A button in a row takes the row's height and has no minimum height of its own; on a touch screen the row rises to the touch target instead (P-02, P-06).`);
|
|
7153
|
+
}
|
|
7131
7154
|
if (p.defaultFont) {
|
|
7132
7155
|
failures.push(`${at(p)}: the page renders in the browser's default font (${p.bodyFont ?? "unknown"}) \u2014 its styles are not applying. No review of this page can pass until they do.`);
|
|
7133
7156
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jig-ui",
|
|
3
|
-
"version": "0.26.
|
|
3
|
+
"version": "0.26.2",
|
|
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/03-patterns.md
CHANGED
|
@@ -53,7 +53,16 @@ Four numbers, and most button designs in the wild fail at least one:
|
|
|
53
53
|
| Button **shape** — fill or border — against its background | **3:1** |
|
|
54
54
|
| Button **text** against the button | **4.5:1** |
|
|
55
55
|
| Two buttons sharing a style, distinguished only by contrast | **3:1 between them** |
|
|
56
|
-
| Hit area | `--size-touch-target` — **48×48px** floor |
|
|
56
|
+
| Hit area | `--size-touch-target` — **48×48px** floor, except inside a table row (below) |
|
|
57
|
+
|
|
58
|
+
**Inside a table row, a button takes the row's height.** A dense row is shorter
|
|
59
|
+
than the floor, and a button given `min-height: var(--size-touch-target)` there
|
|
60
|
+
stretches the rows that hold it and not the rest: an invoices table had its
|
|
61
|
+
"Mark as paid" rows at 65px among 41px ones, twice. Size it to `--size-control`
|
|
62
|
+
and never give it a minimum height of its own. On a touch screen the row itself
|
|
63
|
+
rises to `--size-touch-target` (the mode files do it under a coarse pointer), so
|
|
64
|
+
a finger still gets the floor. The render probe reports rows made uneven this
|
|
65
|
+
way.
|
|
57
66
|
|
|
58
67
|
A secondary button's fill or border is **not decorative**. It is the only thing identifying the element as a button, so it carries the 3:1 non-text requirement (`02-tokens.md`). Strip it and you have coloured text.
|
|
59
68
|
|
|
@@ -285,6 +294,7 @@ Primarily an `operator` pattern; the rules apply wherever a table appears.
|
|
|
285
294
|
**Rules**
|
|
286
295
|
- 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
296
|
- Numeric columns are right-aligned and use tabular figures (`--font-numeric`). Text columns are start-aligned. Never centre either.
|
|
297
|
+
- Every row is one height. A button or link in a row takes the row's height and has no minimum height of its own (see the Button pattern, Hit area).
|
|
288
298
|
- 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.
|
|
289
299
|
- Column headers state units. "Weight" is ambiguous; "Weight (kg)" is not.
|
|
290
300
|
- Truncation is resolvable by click or expand, never by hover alone (`E-31`, `01-modes.md`).
|