feat(editor): give the recipe editor a real typographic system - #286
Merged
Conversation
The editor had a type scale but no type system. Measuring the rendered stories in Chromium showed h1 and h2 were both 24px because the theme mapped them to the same class, blockquotes were byte-identical to paragraphs, `<hr>` carried no class at all and fell back to Chrome's grey default, every gap came from user-agent margins because Typography declares none, and lines ran ~95-100 characters wide. Adds a token vocabulary to :root — a nine-step type scale plus leading, tracking, weight and prose-rhythm tokens — so no stylesheet holds raw literals. Typography stays a margin-free shared primitive (it is used by the recipe header, card gallery, carousel, settings and search flyout, which position text with flex gap) and is only tokenised, so the rhythm lives in TextEditor.module.css scoped under `.input >`, which outranks the primitives without disturbing them. The theme composes both layers via Lexical's space-separated class lists, adds the missing `hr` key, and separates h1 from h2. Paragraphs keep zero margin by design: markdown blank lines import as real empty paragraphs under shouldPreserveNewLines, so adjacent paragraphs are a soft line continuation and must sit flush, while a blank paragraph is the author's own one-line gap. Structural blocks add their own margin-top on top of that. Measured: heading ladder 28/22/18px, one shared 624px measure (~72 characters) across every block, body leading 24px to 26.4px, and ~54px above an H2 against ~26px below for correct proximity. The measure is expressed in rem rather than ch because ch resolves against each element's own font, which had produced five different column widths. Validation: 22 TextEditor tests including 4 new theme regressions, 360 tests across the suite, lint clean, build green, and before/after Chromium measurement of all three TextEditor stories in light and dark with zero console errors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: da97c874-01d2-4c51-a1ac-2c15f6f7ae48
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Measured the rendered TextEditor stories in Chromium before changing anything. Six defects were real: h1 and h2 were both 24px because the theme mapped both to
sectionHeading; blockquotes were byte-identical to paragraphs;<hr>carried no class and fell back to Chrome's grey default instead of--ui-Divider; all spacing came from user-agent margins because Typography declares none; lines ran ~95-100 characters; and.listItemhardcoded its own font-size.Approach
global.cssgains a token vocabulary beside the existing--ui-*/--brand-*sets: a nine-step type scale, leading, tracking, weight, and--prose-*rhythm tokens. No stylesheet keeps raw literals.Typography.module.cssstays a margin-free shared primitive — it is consumed by RecipeHeader, RecipeCardGallery, RecipeCardCarousel, Settings, NewRecipeDialog, RecipeSearchFlyout and the recipes page, all of which space text with flex gap. It is only tokenised at unchanged computed sizes, plus letter-spacing andtext-wrap: balance.TextEditor.module.cssowns the rhythm under.input > …selectors, which outrank the single-class primitives without touching them.editorThemecomposes both layers using Lexical's space-separated class lists, adds the missinghrkey, and finally separates h1 from h2.Why paragraphs keep zero margin
importRecipeMarkdownusesshouldPreserveNewLines, so markdown blank lines become real empty paragraphs. Adjacent paragraphs are therefore a soft line continuation and must sit flush, while a blank paragraph is the author's own one-line gap. Adding paragraph margins would double-space exactly where the author already asked for space. Structural blocks add their ownmargin-topon top of that, so separation is guaranteed either way.Measured before → after
<hr>rgb(128,128,128)--ui-DividerThe measure is
rem, notch:chresolves against each element's own font, which produced five different column widths (752 / 720 / 621 / 576px) in one document.Validation
npm run lintclean,npm run buildexit 0