Skip to content

Tier 2 refactor: theming, CI, responsive typography#66

Merged
felipebalbi merged 16 commits into
OpenDevicePartnership:mainfrom
felipebalbi:tier2-refactor
May 15, 2026
Merged

Tier 2 refactor: theming, CI, responsive typography#66
felipebalbi merged 16 commits into
OpenDevicePartnership:mainfrom
felipebalbi:tier2-refactor

Conversation

@felipebalbi
Copy link
Copy Markdown
Contributor

Depends on #65

Six commits, each independently reviewable, layered on top of the Tier 1 cleanup PR (#65). Until that lands, this PR's diff will also show the eight Tier 1 commits; GitHub will auto-recompute the diff once #65 merges.

Commits

  • t09 — Centralize the brand palette as + 'surface.' + tokens in + ' ailwind.config.js' + . The + '.background_' + / + '.header_background' + rules now read + '�g-surface-N dark:bg-surface-N-dark' + instead of literal + '�g-[#FFFFFF] dark:bg-[#171717]' + chains. No visual change.
  • ci — Add a PR-triggered GitHub Actions workflow ( + '.github/workflows/ci.yaml' + ) with three jobs: line-endings ( + 'dos2unix -ic' + ), formatting ( + 'leptosfmt --check' + ), and build ( + ' runk build --release' + ). Concurrency cancels superseded PR runs. Existing deploy workflow untouched.
  • t10 — Replace ~30 + '[Npx]' + arbitrary utilities across 13 files with native Tailwind spacing tokens (using nearest defaults: 16/32 for 60/120 px after the follow-up commit). Also drops empty + '{}' + separator nodes from + '�iew!' + macros, fixes one broken + 'md:[120px]' + class missing the + 'px-' + prefix, and migrates four leftover spacing-only inline styles to Tailwind classes.
  • t11 — Rewrite + '.h1' + as + ' ont-size: clamp(2.25rem, 1.33rem + 4.58vw, 5rem)' + (36 px → 80 px between 320 px and 1280 px viewports). Retires + '.h1_mobile' + . First commit with intentional visual changes: addresses the "Building the Future of Trusted System Software Together" hero overflow on mobile and slightly compresses the desktop hero.
  • t12 — Same + 'clamp()' + treatment for + '.h2' + , + '.h3' + , + '.p1' + , + '.p2' + ; retires their + '_mobile' + twins. + '.p' + / + '.p_mobile' + are intentionally retained because the footer uses + 'p_mobile md:p' + to render smaller copy on mobile. Cross-class downgrades ( + 'h2_mobile md:h1' + , + 'p2_mobile md:p1' + ) collapse onto the now-fluid larger class.

Verification

    • 'cargo check' + clean after every commit.
    • 'dos2unix' + + + 'leptosfmt' + run on every modified file before each commit.
  • Visually verified in a browser by reloading after each commit; no unintended visual regressions, fluid typography fixes the documented mobile overflow.

felipebalbi and others added 16 commits May 15, 2026 08:27
wasm-bindgen and web-sys are already declared as runtime dependencies,
and wasm-bindgen-test is unused (no #[wasm_bindgen_test] in the tree).
Removing the duplicates keeps a single source of truth for the WASM
bindings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Three typography classes were referenced from .rs sources but never
defined in style/tailwind.css, so they silently fell back to no
styling:

- announce_banner.rs used .p3 -> replaced with the defined .p body
  class.
- documentation_training.rs used .link_large_mobile (mobile twin of
  .link_large) -> replaced with the defined .link_mobile.
- project_introduction.rs used .p3_mobile -> replaced with the
  defined .p2_mobile, matching the desktop .p1 it was paired with.

No new classes are introduced; this only swaps in existing
definitions so the affected text actually picks up the intended
typography on mobile.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a header comment in style/tailwind.css describing the naming
convention (.hN / .hN_mobile, .pN, .link*, .background_*) and inline
comments above each class explaining its role and any known issues:

  - .h2_mobile (50px) is larger than .h2 (30px) — the pair is likely
    swapped.
  - .p_mobile  (10px) is below the legibility floor on phones.
  - .p1 / .p1_mobile and .h3 / .h3_mobile are identical (no mobile
    shrink today).
  - .p_mono, .mono, .link_large, .icon, .odp-btn-text, and
    .odp-header-btn-text have no mobile twin.

Also groups classes into logical sections (Surfaces, Headings, Body,
Links, Misc) with separator comments. No font-size, padding, or color
values are changed — this is a documentation-only commit so a sibling
follow-up can adjust the bogus sizes with reviewable, isolated diffs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mobile font sizes should never grow past their desktop counterparts,
and no body text should fall below the practical legibility floor on
phones. Three of the .hN_mobile/.pN_mobile classes violated one of
those rules and one was identical to its desktop sibling, defeating
the purpose of the responsive split.

Changes (mobile-only; desktop sizes are untouched):

  .h2_mobile : 50px -> 28px   (was LARGER than desktop 30px)
  .h3_mobile : 25px -> 20px   (was identical to desktop)
  .p_mobile  : 10px -> 16px   (was unreadable; below ~12px floor)
  .p1_mobile : 30px -> 22px   (was identical to desktop)

Also drop the matching BUG/NOTE markers from the doc comments added
in the previous commit, since the issues are now resolved, and trim
the "known issues" header block to only the still-outstanding item
(several classes lack a mobile twin entirely).

Visual impact: phone-width viewports will see smaller, properly
proportioned section headings and paragraphs. Desktop and tablet
(>=768px) layouts are unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The same five-entry vector of DocLinks (Why ODP?, Getting Started,
Tutorials, Specifications, Contributing) was duplicated byte-for-byte
in five page files (home, boot_firmware, embedded_controller,
projects, unified_ec_services). Editing it required touching every
page and was an obvious source of drift.

Promote the vector to `pub const DEFAULT_DOC_LINKS: &[DocLink]` in
components/documentation_training.rs and make the `links` prop on
`DocumentationTraining` default to that constant (instead of the
empty `vec![]` it defaulted to before, which would have rendered an
empty <ul> if any caller forgot the prop).

Pages now render `<DocumentationTraining />` with no prop. The
`DocLink` symbol is no longer needed in the page imports and is
dropped from each `use` line.

No visual change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Every page-level SVG icon was rendered with the same hand-written
boilerplate:

    <picture>
      <source srcset="/images/dark/X.svg"
              media="(prefers-color-scheme: dark)" />
      <img src="/images/light/X.svg" alt="..." class="..." style="..." />
    </picture>

Seventeen copies of that block were spread across header, footer,
landing_page, main, documentation_training, community_teams, and the
three team_* pages.

Introduce components/themed_icon.rs which exposes:

    <ThemedIcon name="X" alt="..." class="..." style="..." />

The component derives the dark and light asset paths from a single
`name` prop and forwards `class` / `style` to the underlying `<img>`,
so callers keep the exact sizing they had before. Every existing
call site is converted; a final grep confirms the only remaining
reference to `prefers-color-scheme` is in themed_icon.rs itself.

No visual change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Strip inline `style="display: block; text-align: left;"` (and the
`word-break: break-word`, `overflow-wrap: break-word`, `margin: 0`,
`padding: 0` variants) from elements that paired them with a
`class="..."` attribute. Each property is replaced by its Tailwind
equivalent (`block`, `text-left`, `break-words`, `m-0`, `p-0`)
appended to the existing class list, deduplicated against utilities
that were already present.

Inline `style` attributes that carry properties Tailwind does not
trivially express (e.g. `color: white;`, `padding-top: 80px;`,
`max-width: 100%;`) are left untouched. No visual changes expected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add `components::page_layout::PageLayout` that wraps every standard
page in:

  * an `ErrorBoundary` with the existing generic fallback,
  * the outer `w-full min-h-screen` container,
  * the site `<Header/>`,
  * the page `children`,
  * the site `<Footer/>`.

Pages that previously used `style=overflow-x: auto;` opt in via
`scrollable_x=true`; the default is `overflow-x-hidden`, matching
what every other page already had.

Migrated 10 pages: home, community, getting_started, projects,
boot_firmware, embedded_controller, unified_ec_services,
team_ec, team_patina, team_ec_services. Each loses ~20 lines of
boilerplate. The announcements page keeps its bespoke shell because
it customizes the Header background and renders content between the
header and footer that does not fit the simple slot model. The
not_found page intentionally has no chrome.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move the nine brand hex codes out of the @apply chains in
`style/tailwind.css` and into `theme.extend.colors` in
`tailwind.config.js` as semantic tokens:

  surface.primary / primary-dark    (#FFFFFF / #171717)
  surface.secondary / secondary-dark (#F1F1F1 / #3B3B3B)
  surface.tertiary / tertiary-dark   (#E2E2E2 / #595959)
  surface.quaternary / quaternary-dark (#CACACA / #797979)
  surface.announcement / announcement-dark (#FEEED6 / #FEEED6)

The `.background_*`, `.header_background`, and the
`.background_quaternary .odp-header-btn` overrides now read
`bg-surface-N dark:bg-surface-N-dark` instead of literal
`bg-[#FFFFFF] dark:bg-[#171717]` chains. Custom utility class names
are unchanged so no call site needs to be touched.

Tailwind compiles to identical output -- the @apply expansion produces
the same hex codes. No visual change expected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds `.github/workflows/ci.yaml` with three jobs that run on every
pull request to `main` (and on direct pushes to `main`):

  * line-endings -- installs `dos2unix` and runs `dos2unix -ic`
    over every file tracked by git. `-ic` is the canonical "info /
    converted" check: it prints the names of files that contain CR
    characters, so a non-empty result fails the job.

  * formatting   -- installs `leptosfmt` 0.1.33 (cached across runs)
    and runs `leptosfmt --check src` to verify all Leptos `view!`
    blocks are formatted consistently.

  * build        -- installs nightly Rust + the `wasm32-unknown-unknown`
    target, downloads Trunk 0.21.14 (matching the Cloudflare deploy
    workflow), and runs `trunk build --release` so we know the site
    actually compiles before merging.

Concurrency is keyed per-ref so superseded PR pushes cancel the
in-flight run. The deploy workflow on `main` is unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Page rhythm in this site is built on five recurring spacing values:
32, 40, 60, 80, and 120 px. Tailwind's default 4-px scale already covers
three of them (8 = 32, 10 = 40, 20 = 80), but the 60 and 120 px steps
were spelled as `[60px]` / `[120px]` arbitrary-value escapes at every
call site -- ~30 instances across the landing page, headers, footers,
team pages, partners and projects components.

Add two extension keys to `theme.extend.spacing` in
`tailwind.config.js`:

  '15': '60px'   ->  used as `gap-15`, `mb-15`, `md:py-15` etc.
  '30': '120px'  ->  used as `md:px-30`, `py-30`, `pb-30` etc.

Naming follows Tailwind's "1 unit = 4 px" mental model so the new
classes look native. All call sites swap their arbitrary brackets for
the tokens; defaults (8/10/20) replace `[32px]` / `[40px]` /
`[80px]` straight up.

While here, fix three style attributes that t02 missed and that mixed
spacing with other declarations is now unnecessary -- they were pure
padding/margin, so they collapse into `py-20`, `py-30`, `pb-30`,
and `mb-20`. Also fix `md:[120px]` (a no-op class missing the
`px-` prefix) on the community-teams `<section>` -- it now
correctly applies the page-x token like its siblings.

Compiled output is unchanged: `15` and `30` resolve to 60 px / 120 px
exactly as the bracket escapes did. No visual change expected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…eparators

Two cleanups on top of t10:

1. Replace the custom `spacing.15 = 60px` and `spacing.30 = 120px`
   tokens with the nearest Tailwind defaults: `16` (64 px) and `32`
   (128 px). The custom extension is removed from
   `tailwind.config.js` entirely. This trades 4 px of vertical /
   horizontal breathing room per occurrence for staying inside the
   stock 4-px scale -- no theme bookkeeping, full IDE autocomplete,
   and the spacing rhythm still doubles cleanly (32 = 2 * 16).

2. Drop the `{}` empty-block separators that the leptosfmt cleanup in
   Tier 1 left behind in `view!` macros. They evaluate to `()`,
   which Leptos renders as nothing, but they make the views noisier
   to read. Removed across all components / pages touched in t10.
   Verified that no real `format!("...{}...", arg)` placeholders
   were swept up by the regex (those live inside string literals).

No visual change beyond the ~4 px snap noted above.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the static `.h1` (100 px desktop) + `.h1_mobile` (60 px
mobile) pair with a single fluid `.h1` rule:

    font-size: clamp(2.25rem, 1.33rem + 4.58vw, 5rem);

Linear interpolation between the two endpoints lands exactly on:

  *  36 px at <= 320 px viewport (smallest phones)
  *  80 px at >= 1280 px viewport (desktop)

Mid-range viewports get a smooth transition instead of a hard
`md:` breakpoint flip. The desktop max is also dropped from 100 px
to 80 px so very wide screens don't dominate the page with the
hero headline.

Sweep call sites:

    h1_mobile md:h1   ->   h1

across community_teams, main (the "Building the Future..." hero
headline that motivated this), partners_grid, projects_component,
and the three team pages. The `.h1_mobile` rule is removed from
`style/tailwind.css` -- it has no remaining users.

Sites that intentionally use a smaller mobile heading
(`h2_mobile md:h1` on landing_page, announcements,
project_introduction) are left alone -- those express a different
design intent (secondary headline) and the now-fluid `.h1` still
behaves correctly above the `md` breakpoint.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Apply the same clamp() treatment used for .h1 in t11 to the rest of
the typography scale, retiring four `_mobile` companion rules:

  .h2  : clamp(1.75rem, 1.71rem + 0.21vw, 1.875rem)   /* 28 -> 30 */
  .h3  : clamp(1.25rem, 1.15rem + 0.52vw, 1.5625rem)  /* 20 -> 25 */
  .p1  : clamp(1.375rem, 1.21rem + 0.83vw, 1.875rem)  /* 22 -> 30 */
  .p2  : clamp(1.125rem, 0.98rem + 0.73vw, 1.5625rem) /* 18 -> 25 */

Each clamp linearly interpolates between the previous mobile and
desktop pixel sizes between 320 px and 1280 px viewports. The static
values were spelled out as `.h2/.h2_mobile` / `.h3/.h3_mobile` /
`.p1/.p1_mobile` / `.p2/.p2_mobile` pairs and required call sites
to write `hN_mobile md:hN` to opt into the responsive flip; with
the fluid clamp a single class covers every viewport smoothly.

`.p` and `.p_mobile` are intentionally retained: the footer
deliberately renders smaller copy on mobile via `p_mobile md:p` and
the spread (16 -> 20 px) is large enough that a hard breakpoint reads
better than a fluid interpolation. Comment in the CSS notes this.

Sweep call sites:

  hN_mobile md:hN      ->  hN
  pN_mobile md:pN      ->  pN
  h2_mobile md:h1      ->  h1   (cross-class downgrade, .h1 fluid covers it)
  p2_mobile md:p1      ->  p1   (cross-class downgrade, .p1 fluid covers it)

The two cross-class downgrades collapse into the larger fluid class
because that class already shrinks to a reasonable mobile size.
Headlines that previously dropped to 28 px on mobile now sit at the
fluid h1 minimum of 36 px; lead paragraphs that previously dropped to
18 px now sit at the fluid p1 minimum of 22 px. Both increases keep
visual hierarchy clear and remove a hard breakpoint flip.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@felipebalbi felipebalbi merged commit 33f7217 into OpenDevicePartnership:main May 15, 2026
3 checks passed
@felipebalbi felipebalbi deleted the tier2-refactor branch May 15, 2026 16:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant