v0.29.0 — Fonts that say when they are missing
A fifth pass over the interface, and four bugs. Two of the four were reported as something looking wrong rather than as something being broken.
Fixed
- A configuration loaded without its font files produced families that looked installed and loaded nothing.
build_css()wrote an@font-facefor every mapped file without checking the file was there, and an export with the files unbundled carries the mapping and none of the bytes. A rule pointing at a 404 is worse than no rule: it declares the family, so the browser acceptsfont-familyand then falls back silently, which looks correct in a browser already holding the face and wrong in a clean profile, incognito included.preload_files()had the same gap. Both now go through onefile_present()guard, and any family missing its files says so on its Library card. - The Google Fonts search dropped characters and threw the caret backwards.
state.querywas assigned inside the debounce, so it trailed the field, and every render rebuilds the input from it. A search fires two renders, so anything typed during the debounce or the round trip was overwritten. Simulated: typingseku, pausing, then typingyawhile the request was in flight left the field readingsekuwith the caret pulled from 6 back to 4. The read is immediate now and only the search is deferred. The Library filter and the preview text field had the same shape. - "None" in Export did nothing. An empty
exportPickwas read back as "every family", so the button set the list empty and the next render turned that straight back into all of them. Deselecting the last family by hand did the same.nullnow means unset and an empty array means none;exportConfig()refuses an empty choice rather than quietly downloading everything. - The cross in a clear button sat off centre and never brightened, in the Library filter and the Google Fonts search but not the preview text field.
.efm-search svgwas a descendant selector, so the rule written for the magnifier caught the clear button's icon too: 8px from the button's left edge, 5px off centre in a 20px box, with its colour pinned so the hover never reached it. All three now sit at 3 and reachrgb(225,225,229).
Changed
- Confirmation dialogs are Etch's, measured from
.confirm-dialogin the builder bundle rather than approximated: an 18px radius behind a 1px border, the icon beside a centred title, the message centred at three quarters opacity, and two buttons of equal width filling the foot. The destructive answer takes the danger colour at a fifth of an alpha behind a full-strength danger border, with near-white words and only the glyph in danger. - A dialog that lists file names shows them as a list, not as more centred sentences.
- Unused files in Import & export are in that same block. They were a
ulwhose classes carry no CSS at all. - The save bar says what is unsaved — which family and what changed about it — instead of "Unsaved changes". It diffs against a stringified snapshot of the last confirmed state, which is how Etch tracks its own. Discard is a ghost so it no longer competes with Save fonts.
- The family name in the type tester takes the heading band every other heading has.
- Primary buttons hover to
--e-base-light, with a divider border so they keep their edges inside a section box filled with the same value.
Translators
Thirteen new strings, eleven for the save bar's vocabulary and two for the missing-files badge. Nothing was removed or renamed.