refactor(page-header): migrate to design-system primitives [Phase 1c]#621
Merged
barach6662001-bit merged 1 commit intomainfrom Apr 24, 2026
Merged
refactor(page-header): migrate to design-system primitives [Phase 1c]#621barach6662001-bit merged 1 commit intomainfrom
barach6662001-bit merged 1 commit intomainfrom
Conversation
First real consumer of the Phase 1b primitives. PageHeader.tsx is now
zero-CSS — the entire layout, typography and spacing flow through
`Stack`, `Cluster`, `Heading` and `Text` (which themselves consume
the Phase 1a tokens).
Why this component first
- Used by ~20 pages, so any visual regression would surface immediately.
- Public API is tiny (`title`, `subtitle`, `actions`, `breadcrumbs`),
so the contract is easy to preserve verbatim.
- Old implementation was the textbook anti-pattern: cryptic class names
(`text22`, `flex_between`), hard-coded pixel sizes, and a #fff
gradient on the title that was visually broken on the new light theme.
Changes
- Re-author PageHeader.tsx using primitives only.
- Delete PageHeader.module.css entirely (no replacement file).
- Title is now a fluid `Heading level={1}` (clamp(24px, …, 32px)) — no
more theme-broken gradient.
- Subtitle is `Text size="sm" tone="tertiary"` — adapts to dark/light
semantic colors automatically.
- Wrapper is a semantic `<header>` (was a generic `<div>`).
- Header divider (border-bottom) and the 24 px / 20 px rhythm are
expressed via inline token vars — no magic numbers, no module CSS.
Public API and visual rhythm preserved. Three new tests cover the new
semantic guarantees:
• title is queryable via `getByRole('heading', { level: 1 })`
• actions slot is rendered
• the wrapper is a real `<header>`
Verification
- 137 / 137 tests green (3 new on PageHeader, 36 from Phase 1b).
- Lint clean, tsc clean, vite build OK.
No other file is modified. All 20+ consumer pages keep the same import
and the same prop contract.
This was referenced Apr 24, 2026
barach6662001-bit
added a commit
that referenced
this pull request
Apr 24, 2026
…[Phase 1f] (#625) Finishes the DashboardV2 row-card migration. Both remaining sibling panels (OperationsTimeline in row 4, UpcomingPanel in row 5) now use the design-system <Card> primitive instead of the local `s.card` wrapper. Combined with Phase 1d (WarehouseSnapshot) and Phase 1e (AlertsPanel), every dashboard surface in this row is now driven by the same primitive. Wrapper migration (DashboardV2.tsx) ----------------------------------- - <div className={s.card}><OperationsTimeline …/></div> → <Card>…</Card> - <div className={s.card}><UpcomingPanel …/></div> → <Card>…</Card> Both sites are pure wrapper swaps. <Card> defaults (variant=subtle, radius=xl=16px, padding=5=20px, bordered=true) are an exact drop-in for the legacy `.card` rule, so the visual contract (background, border, radius, padding) is preserved. The internal list/item content of each panel is untouched. CSS dead-code removal (DashboardV2.module.css) ---------------------------------------------- With both consumers gone, these rules become unreferenced and are deleted (≈39 lines): - .card (background, border, radius, padding, transition) - .card:hover (subtle background lift) - .card::before (decorative top hairline) - .cardHeader (flex justify-between row, never used in DashboardV2.tsx) - .cardLink, .cardLink:hover (eyebrow link button, never used in DashboardV2.tsx) A short tombstone comment is left in place so future readers see why the section is empty and where to look (Card primitive path). Out of scope ------------ - No route changes - No API changes - No business-logic changes - No refactor of inner panel markup - No new dependencies - No Card highlight prop introduction - No new tests (spec: only update if coverage exists; none did) Verification (local) -------------------- - frontend tsc -b: clean - frontend lint: 0 errors (warning count unchanged) - vitest design-system + dashboard subset: 67/67 passing - Full test + build run delegated to CI. Phase 1 status after this PR ---------------------------- - ✅ 1a — TS tokens (#616) - ✅ 1b — Layout + Typography primitives (#620) - ✅ 1c — PageHeader migration (#621) - ✅ 1d — Surface + Card primitives + first dashboard adoption (#622) - ✅ 1e — AlertsPanel adoption (#624) - ✅ 1f — OperationsTimeline + UpcomingPanel adoption (this PR) Co-authored-by: replit-agent <agent@replit.local>
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.
Phase 1c — Перший консумер примітивів: PageHeader
Перша реальна міграція компонента на нові примітиви Phase 1b.
PageHeader.tsxтепер zero-CSS — вся розкладка, типографіка та відступи йдуть черезStack/Cluster/Heading/Text.Чому саме
PageHeadertitle,subtitle,actions,breadcrumbs) — контракт легко зберегти буква в букву.text22,flex_between), магічні пікселі, і#fffградієнт на заголовку, який був візуально зламаний на новій світлій темі.Зміни (3 файли, +57 / -54)
PageHeader.tsxPageHeader.module.css__tests__/PageHeader.test.tsxДо/після (суть)
Було:
Стало:
Що покращилось семантично
clamp(24px, …, 32px)— масштабується між брейкпоінтами автоматично.--text-tertiary).<header>(було<div>).#fff-градієнт, що ламав світлу тему.Перевірки
eslint— 0 errors (warnings успадковані)tsc -b— cleanvitest— 137 / 137 passed (3 нових тести на семантику + старі)vite build— OKAPI не змінився
Усі 20+ консумерів продовжують працювати без змін: той самий імпорт, ті самі пропси. Безпечно мерджити.
Що далі
Phase 1d — мігрувати ще одну точку дотику (можливо, шапку
AppLayoutабоSidebar), або перейти до Phase 2 (нові primitives:Card,Surface,Field).