feat(tokens): add editorial typography family#1940
Conversation
Adds a Sora-based editorial typography token family for brand-themed
surfaces (empty states, hero moments, announcements) that need the
marketing-site type system rather than the utility scale.
- New `fontFamily.sora` with Inter fallback
- New `fontSize.editorial.{14..80}` rungs (pixel-named to match size
primitives; avoids style-dictionary CSS font-shorthand emitter
mis-tokenizing 4-digit rung names)
- New `fontWeight.editorial.{medium,semibold,bold}` namespace
- New unitless `lineHeight.editorial.{tight,snug,close,default,relaxed}`
- New top-level `letterSpacing` group with `editorial.*` sub-namespace
(consumers apply alongside the typography shorthand since CSS font
shorthand does not include letter-spacing)
- 7 new `text.editorial.*` compositions: display, h1, h1-alt, h2, h2-alt,
h2-medium, h3 — Sora-only; Söhne mixins deferred pending licensing
- Adds `size.30` and `size.50` primitives required by the new scale
Source of truth: `_typography.scss` and `Text/index.tsx` DEFAULT_WEIGHT
map in launchdarkly-nextjs/ai-refresh.
Phase 2 (gonfalon Sora global preload + fairytale rollout) lands in a
separate PR — see Editorial Typography Tokens proposal.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: e222427 The changes in this PR will be included in the next version bump. This PR includes changesets to release 17 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
nhironaka
left a comment
There was a problem hiding this comment.
do we need to update storybook to demonstrate the new font?
Replaces the single Typography story with two stories so each section renders with its own heading and description above its own canvas. Custom docs page (Title + Description + Stories with includePrimary and no section title) skips the default Primary canvas and removes the "Stories" separator heading. Editorial label rendering: getDisplayText now handles editorial keys by expanding h1/h2/h3 to "Heading 1/2/3" with alt and medium kept as variant suffixes. Component description mentions the two type sets and links to the Utility & Editorial Type System proposal. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1316c55. Configure here.
|
@nhironaka Yes, I updated StoryBook in the second commit on this branch. |
|
@OneHunnid you'll want to generate a changeset: https://github.com/launchdarkly/launchpad-ui/blob/main/CONTRIBUTING.md#step-3-generate-a-changelog-for-your-code it also looks like you have some linting issues https://github.com/launchdarkly/launchpad-ui/actions/runs/28135982421/job/83322799374?pr=1940 |
Storybook now demonstrates the actual Sora editorial type instead of
silently falling back to Inter: the Editorial specimens render with
font-family var(--lp-font-family-sora) ("Sora, Inter, ..."), but no
Sora webfont was loaded in the preview, so they rendered in Inter.
- preview-head.html: load Sora from Google Fonts (OFL) for Storybook
specimens only. The in-product @font-face/preload ships in Phase 2
(gonfalon), so this stays scoped to the docs surface.
- typography.stories.tsx: map editorial-h1/h2/h3 to real h1/h2/h3 tags
in getSemanticElement (previously fell through to a generic div);
drop a stray per-token console.log.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Good catch — we did, and it wasn't actually showing Sora. The Editorial specimens render with Pushed
Editorial specimens now render in actual Sora. |
…angeset The editorial typography tokens nest an `editorial.*` sub-namespace under fontSize, fontWeight, and lineHeight. Box's rainbow-sprinkles passed these groups straight into defineProperties, which expects a flat Record<string, string>, so the nested objects broke its overload typing — cascading into BoxProps and every <Box> consumer (preview, stories, specs) failing Type Check. Flatten those three groups via `flat` (the same treatment the `font` typography group already gets), so editorial.* tokens become flat keys and defineProperties typing holds. Also adds the missing changeset for the @launchpad-ui/tokens + @launchpad-ui/box changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Summary
Adds a Sora-based editorial typography token family for brand-themed surfaces (empty states, hero moments, announcements) that need the marketing-site type system rather than the utility scale.
Proposal: Editorial Typography Tokens — LaunchPad proposal (Phase 1 only; Phase 2 is a separate gonfalon PR for the Sora global preload).
What's in
fontFamily.sorawith an Inter fallback so surfaces rendering before the Sora@font-faceresolves (or in the authenticated bundle before Phase 2 ships) drop cleanly to LaunchPad's base sans-serif.fontSize.editorial.{14..80}rungs — pixel-named to match the size primitives. The original proposal used 100/200/.../1300 step rungs but style-dictionary's CSS font-shorthand emitter mis-tokenizes 4-digit rung names starting with1(it splits e.g.1300into a synthetic line-height reference + trailing digits). Pixel-value names avoid the bug and are self-documenting.fontWeight.editorial.{medium,semibold,bold}namespace — 500/600/700 mirroring the brandDEFAULT_WEIGHTmap inai-refresh/components/Text/index.tsx.lineHeight.editorial.{tight,snug,close,default,relaxed}— unitless multipliers (1, 1.05, 1.1, 1.15, 1.5) per_typography.scss.letterSpacing— brand-new top-level token group witheditorial.*sub-namespace. Consumers apply this alongside the--lp-text-editorial-*shorthand since CSS font shorthand does not include letter-spacing.text.editorial.*compositions — display, h1, h1-alt, h2, h2-alt, h2-medium, h3. Sora-only; Söhne mixins deferred pending Klim licensing.size.30andsize.50primitives added tosize.json.Source of truth
All numeric values mirror
_typography.scssand theDEFAULT_WEIGHTmap fromlaunchdarkly-nextjs/ai-refresh.Verification
pnpm buildpasses--lp-text-editorial-display: var(--lp-font-weight-editorial-bold) var(--lp-font-size-editorial-80)/var(--lp-line-height-editorial-tight) var(--lp-font-family-sora);)stories/typography.stories.tsxis data-driven viaflatten(vars.text)— editorial tokens appear automatically in Storybook with no code changeTest plan
var(--lp-text-editorial-h1)+var(--lp-letter-spacing-editorial-tight-em-05)renders at 64px Sora Bold with -0.05em trackingtext.heading.*,text.body.*,text.display.*compositions (no token references changed)Follow-ups (not in this PR)
via LD Research 🤖
Note
Low Risk
Additive design tokens and a small Box typing fix; no changes to existing utility typography or security-sensitive code.
Overview
Introduces a Sora-based editorial typography token set for brand moments (empty states, heroes, announcements), aligned with
ai-refresh_typography.scss. New primitives includefontFamily.sora(Inter fallback), nestedfontSize/fontWeight/lineHeight/letterSpacingeditorial namespaces,size.30andsize.50, and seventext.editorial.*compositions (display through h3 variants). Existing utilitytext.*tokens are not modified.@launchpad-ui/boxflattensfontSize,fontWeight, andlineHeightin rainbow-sprinkles (likefontalready) so nestededitorial.*keys work withdefinePropertiestyping.Storybook loads Sora from Google Fonts for specimens only (in-product font preload is deferred). Typography docs split into Utility and Editorial stories with editorial-aware labels and semantic heading tags.
Reviewed by Cursor Bugbot for commit e222427. Bugbot is set up for automated code reviews on this repo. Configure here.