partforge 0.117.1 → 0.118.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/docs/AUTHORING-PARTS.md +34 -5
- package/package.json +1 -1
- package/src/framework/app.css +32 -7
package/docs/AUTHORING-PARTS.md
CHANGED
|
@@ -1060,12 +1060,41 @@ export function tilePicker(host) {
|
|
|
1060
1060
|
listener you attach yourself with `addEventListener`, rather than through `host.h`,
|
|
1061
1061
|
is **not** guarded — wire listeners through `host.h`, or wrap your own in try/catch.
|
|
1062
1062
|
|
|
1063
|
-
**Looking native.** The slot inherits the rail's font,
|
|
1064
|
-
|
|
1065
|
-
|
|
1063
|
+
**Looking native.** The slot inherits the rail's font and text colour, and the
|
|
1064
|
+
built-in looks come for free: bare `<button>`, `<input>` and `<select>` elements
|
|
1065
|
+
are already styled, the built-in classes are there by name for the exact thing —
|
|
1066
1066
|
`row`, `seg` (a segmented row of buttons), `action`, `ghost`, `num`, `text-input`,
|
|
1067
|
-
`select-input
|
|
1068
|
-
|
|
1067
|
+
`select-input` — and sub-controls mounted through `host.controls` *are* the
|
|
1068
|
+
built-in widgets. For SVG there are two classes: `pf-hit` (a clickable region,
|
|
1069
|
+
with a `selected` state) and `pf-drag`.
|
|
1070
|
+
|
|
1071
|
+
**Colour only with the rail's tokens.** Inheriting the rail's colours covers the
|
|
1072
|
+
text you did not style; it does not cover anything you colour yourself. For that,
|
|
1073
|
+
use a `--pf-*` custom property and never a hex literal or a named colour — the
|
|
1074
|
+
tokens flip with the light/dark theme and a literal cannot, so a `#333` border is
|
|
1075
|
+
a widget that is unreadable in one of the two themes. The ones worth knowing:
|
|
1076
|
+
`var(--pf-text)` and `var(--pf-text-2)` for text, `var(--pf-muted)` for a
|
|
1077
|
+
secondary label, `var(--pf-border)` for a rule or an outline,
|
|
1078
|
+
`var(--pf-surface-2)` for a filled chip, `var(--pf-accent)` with
|
|
1079
|
+
`var(--pf-on-accent)` for the selected or primary thing, and `var(--pf-err)` for
|
|
1080
|
+
a problem. That palette is the whole palette: the accent blue for the one thing
|
|
1081
|
+
that is chosen or primary, the surface and border greys for everything else. A
|
|
1082
|
+
widget that reaches past it for a red or a green is a widget that has stopped
|
|
1083
|
+
looking like the rest of the panel.
|
|
1084
|
+
|
|
1085
|
+
**Nest a region's label inside the region.** The common case then needs no colour
|
|
1086
|
+
from you at all: an SVG shape you leave unfilled inherits `var(--pf-text-2)`
|
|
1087
|
+
rather than SVG's own black, a `pf-hit` region is filled and outlined at rest,
|
|
1088
|
+
and a `<text>` *inside* that region stays readable through all three states —
|
|
1089
|
+
the rail gives it `var(--pf-text-2)` at rest and `var(--pf-on-accent)` once the
|
|
1090
|
+
region is selected and has gone solid accent underneath it, and clears the
|
|
1091
|
+
stroke it would otherwise inherit from the region's outline (SVG paints that
|
|
1092
|
+
around every glyph, which at label sizes leaves a pale ghost of the number).
|
|
1093
|
+
Draw the label as a sibling instead and none of that reaches it: a dark number
|
|
1094
|
+
sitting on the selected blue is the result, and you have to colour it yourself.
|
|
1095
|
+
To colour a
|
|
1096
|
+
region from your own data, set an inline `style` — a `fill="…"` attribute loses
|
|
1097
|
+
to the rail's rule.
|
|
1069
1098
|
|
|
1070
1099
|
**Reading the part's own files.** Artwork can live beside the code (the tree is text,
|
|
1071
1100
|
so an SVG, a `partforge-vector` JSON document or a JSON data file — not a PNG).
|
package/package.json
CHANGED
package/src/framework/app.css
CHANGED
|
@@ -387,10 +387,10 @@ button.action:disabled { opacity: .5; cursor: default; }
|
|
|
387
387
|
/* Custom controls (type: "custom"): a part-authored widget in the rail. The
|
|
388
388
|
slot inherits the rail's cascade (font, colours, --pf-* tokens); these rules
|
|
389
389
|
give BARE elements the built-in controls' look so a widget written with
|
|
390
|
-
plain <button>/<input>/<select> still reads as native,
|
|
391
|
-
opt-in classes for SVG: .pf-hit
|
|
392
|
-
dragged one — touch-action: none is
|
|
393
|
-
instead of scrolling the sheet). */
|
|
390
|
+
plain <button>/<input>/<select> still reads as native, supply a themed
|
|
391
|
+
floor for hand-drawn SVG, and provide two opt-in classes for SVG: .pf-hit
|
|
392
|
+
(a clickable region) and .pf-drag (a dragged one — touch-action: none is
|
|
393
|
+
what lets a finger drag it on a phone instead of scrolling the sheet). */
|
|
394
394
|
.pf-custom { margin: 9px 0; }
|
|
395
395
|
.pf-custom.hidden { display: none; }
|
|
396
396
|
.pf-custom-slot { display: flow-root; }
|
|
@@ -400,7 +400,12 @@ button.action:disabled { opacity: .5; cursor: default; }
|
|
|
400
400
|
like .text-input (0,1,0) or .row .num (0,2,0). At true zero specificity,
|
|
401
401
|
any class rule wins, so a named built-in class (.seg button, .text-input,
|
|
402
402
|
select.select-input, …) always beats these bare-element defaults. */
|
|
403
|
-
|
|
403
|
+
/* `fill` inherits in SVG, so this is the floor for everything the widget draws
|
|
404
|
+
and did not colour — including <text>. SVG's own initial fill is BLACK, which
|
|
405
|
+
is invisible on the dark theme, and that is what an author gets for free
|
|
406
|
+
unless the rail supplies a token. Inherited rather than matched, so a child
|
|
407
|
+
carrying its own fill="…" attribute still wins. */
|
|
408
|
+
:where(.pf-custom) :where(svg) { display: block; max-width: 100%; height: auto; fill: var(--pf-text-2); }
|
|
404
409
|
:where(.pf-custom) :where(button) {
|
|
405
410
|
font: inherit; font-size: 12px; padding: 5px 9px; cursor: pointer;
|
|
406
411
|
background: transparent; border: 1px solid var(--pf-border); color: var(--pf-text-2);
|
|
@@ -417,9 +422,29 @@ button.action:disabled { opacity: .5; cursor: default; }
|
|
|
417
422
|
outline: none; border-color: var(--pf-accent);
|
|
418
423
|
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pf-accent) 35%, transparent);
|
|
419
424
|
}
|
|
420
|
-
|
|
425
|
+
/* A region the reader clicks. The RESTING fill and stroke are what make it read
|
|
426
|
+
as a control: without them a .pf-hit polygon is a black slab with no border
|
|
427
|
+
until it is hovered or selected. Zero specificity, so a widget that colours
|
|
428
|
+
regions from its own data still wins — with an inline `style`, since a
|
|
429
|
+
`fill="…"` attribute loses to any rule that matches the element, even this
|
|
430
|
+
one. Hover and selected below keep their own (0,2,x) weight. */
|
|
431
|
+
:where(.pf-custom) :where(.pf-hit) { cursor: pointer; fill: var(--pf-surface-2); stroke: var(--pf-border); }
|
|
421
432
|
.pf-custom .pf-hit:hover { fill: color-mix(in oklab, var(--pf-accent) 25%, transparent); }
|
|
422
|
-
|
|
433
|
+
/* Selected is the SOLID accent, not a wash of it. A translucent accent lands on a
|
|
434
|
+
different value in each theme — pale over the light background, dark over the
|
|
435
|
+
dark one — so no single label colour is readable on both. Solid accent is one
|
|
436
|
+
colour in both, which is what makes --pf-on-accent below a rule rather than a
|
|
437
|
+
guess. A widget that would rather tint its own region overrides with `style`. */
|
|
438
|
+
.pf-custom .pf-hit.selected { fill: var(--pf-accent); stroke: var(--pf-accent); }
|
|
439
|
+
/* A label NESTED inside the region — the structure to recommend, because it is the
|
|
440
|
+
only one where the rail can keep the text readable as the region changes colour
|
|
441
|
+
underneath it. `fill` inherits, so without these the label takes the region's OWN
|
|
442
|
+
fill: grey on grey at rest, and accent on accent once selected. `stroke` inherits
|
|
443
|
+
too, and that one is worse than it looks: the region's outline colour gets painted
|
|
444
|
+
around every glyph, which at label sizes is most of the glyph — pale ghosts of the
|
|
445
|
+
numbers at rest, blue ones when selected. Hence stroke: none, not just a fill. */
|
|
446
|
+
:where(.pf-custom) :where(.pf-hit) text { fill: var(--pf-text-2); stroke: none; }
|
|
447
|
+
.pf-custom .pf-hit.selected text { fill: var(--pf-on-accent); }
|
|
423
448
|
.pf-custom .pf-drag { touch-action: none; }
|
|
424
449
|
.pf-custom-error {
|
|
425
450
|
margin: 4px 0; padding: 6px 8px; border: 1px solid var(--pf-err); border-radius: var(--pf-radius-control);
|