Skip to content

Commit fefe825

Browse files
bloveclaude
andauthored
Website refactor: Statusbrew-inspired aesthetic across marketing, docs, cockpit (Phases 1-8) (#270)
* docs(specs): website statusbrew-inspired refactor design Design spec for refactoring apps/website to a modern, no-nonsense SaaS aesthetic inspired by Statusbrew while preserving the existing brand. Covers tokens, shared component primitives, homepage IA (12 sections), migration plan for /pilot-to-prod, /angular, /chat, /render, /solutions, /pricing, and 6-phase implementation phasing. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(plans): Phase 1 plan — website tokens + UI primitives Implementation plan for Phase 1 of the Statusbrew-inspired website refactor. Additive-only changes to @ngaf/design-tokens (new surfaces, shadows, radius, space namespaces + colors/typography extensions), plus nine new UI primitives in apps/website/src/components/ui/, a cn() helper, Tailwind @theme additions, and a /_dev/primitives showcase route with Playwright coverage. 23 tasks, no production-page changes. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(design-tokens): add surfaces/shadows/radius/space + type scale (v0.0.30) Additive-only changes for the website Statusbrew-aesthetic refactor (Phase 1): - new namespaces: surfaces, shadows, radius, space - colors: add accentHover, textInverted - typography: add h1/h2/h3/eyebrow/bodyLg/body/caption type scale - tokens.css: mirror everything as --ds-* custom properties - tokens aggregator + index.ts updated - tokens.spec.ts: vitest assertions for all additions No existing tokens modified. Version bumped 0.0.29 → 0.0.30 per repo patch-only policy. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(website): wire new tokens, add cn() helper - apps/website/lib/design-tokens.ts: re-export from @ngaf/design-tokens so the website has one source of truth (was a stale partial duplicate) - src/app/global.css: extend Tailwind @theme with new surface/border colors, radii, and shadow variables (additive — no existing variables removed) - src/lib/cn.ts: clsx + tailwind-merge composition helper for the upcoming UI primitives No visible site changes — primitives that consume these tokens land in the next bundle. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(website): add 9 UI primitives for the new design system - Container — max-width wrapper with responsive padding - Section — vertical rhythm + surface variants (canvas/tinted/white) - Eyebrow — mono uppercase label with brand-tone variants - Pill — small rounded tag with neutral/accent/angular variants - Button — primary/secondary/ghost × md/lg; renders <a> when href set - Card — white surface with hoverable lift via CSS - BrowserFrame — Mac-style chrome for screenshots and live demos - LogoMark — 🛩️ + wordmark - FAQ — native <details> accordion, kbd-accessible by default All server components except FAQ (which works without 'use client' because <details> is a native element). Styled via inline style props against @ngaf/design-tokens, matching the existing codebase pattern. global.css gets Card hover styles + FAQ chevron rotation + summary focus ring. No production page uses these yet — wiring lands in Bundle 6's /_dev/primitives showcase. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(website): add /dev/primitives showcase + Playwright coverage A dev-only route that renders one of each UI primitive (LogoMark, Eyebrow, Pill, Button, Card, BrowserFrame, Section, FAQ) so the new design-system primitives are both eyeball-verifiable and asserted in CI. The route will be deleted in a later phase once the marketing pages have migrated. Note: route is /dev/primitives (not _dev/primitives) because Next.js App Router treats leading-underscore folders as private and unrouted. Playwright spec covers all 9 primitives plus FAQ open/close + keyboard focus. Verification (this commit): all 23 website e2e tests pass — 10 new primitives tests + 13 existing tests unchanged. Phase 1 complete with zero regressions to visible pages. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(website): drop unused card-primitive className Reviewer flagged: Card.tsx applied a 'card-primitive' className but no CSS selector references it (hover styles target the data-ui attribute instead). Trivial dead code cleanup. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(plans): Phase 2 — Nav + Footer + AnnouncementToast refactor Plan to refactor the three site-wide shared components to use the Phase 1 primitives and tokens. Drops glassmorphism site-wide, removes framer-motion from the shell layer, swaps in LogoMark/Button/Eyebrow primitives. Preserves all analytics tracking and the deep mobile-docs nav. 4 tasks, ~3 commits. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(website): Phase 2 — Nav/Footer/AnnouncementToast use new primitives Site-wide chrome refactor to the Statusbrew-shaped aesthetic: Nav.tsx: - White surface with hairline bottom border + shadow-sm (was glass blur) - LogoMark for the brand mark (was inline serif text) - Get Started CTA uses Button primitive (desktop + mobile) - Mobile overlay solid white with shadow-lg (was glass blur) - All analytics tracking + deep mobile-docs nav preserved Footer.tsx: - White surface with hairline top border (was glass blur) - LogoMark for the brand mark - Eyebrow primitive for column headings (Product/Libraries/Solutions/Resources) - Newsletter Subscribe button uses Button primitive - framer-motion removed (in-view fade dropped — footer is below the fold) - Input uses surface tokens (was glass.border) AnnouncementToast.tsx: - White surface with shadow-lg (was glass blur + custom shadow) - framer-motion + AnimatePresence removed; replaced with rAF-driven mounted-state CSS transition (opacity + translateY) - Get the Guide + Send me the guide buttons use Button primitive - Input uses surface tokens - All analytics tracking preserved e2e/primitives.spec.ts: - LogoMark + Eyebrow assertions scoped to `main` since the shell now renders these primitives site-wide Verification: all 23 e2e tests pass. No regressions to visible pages beyond the intended shell restyle. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(plans): Phase 4 — homepage refactor 12 tasks covering 10 new landing components, LiveCockpitFrame (IntersectionObserver lazy iframe for the signature demo), and page.tsx rewrite to the new 11-section IA. Phase 3 (screenshot capture) deferred — uses placeholder content in BrowserFrames. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(website): Phase 4 — rebuild homepage to 11-section IA Drops the gradient blob ambient background and 7-section narrative spine. Replaces with a developer-first, product-led homepage built on Phase 1 primitives. New landing components in apps/website/src/components/landing/: - Hero.tsx — eyebrow + h1 + subhead + CTA pair + Pill trust row + layered 2-frame BrowserFrame collage - ProofStrip.tsx — 5 honest signals as Cards (no borrowed customer logos) - Differentiator.tsx — editorial POV ("Built for Angular, not retrofitted") + 4-card sub-grid carrying forward the current Runtime/Streaming/GenUI/License copy from PositioningStrip - FeatureBlock.tsx — reusable two-column section primitive consumed by Stream/Render/Ship; supports visualLeft alternation - LiveCockpitFrame.tsx — IntersectionObserver lazy iframe for the signature live demo on the Ship block - PilotBlock.tsx — tinted section, 8-week Discover/Build/Harden/Train timeline as Cards, dual CTA - WhitePaperBlock.tsx — email-gated download with tilted PDF cover in BrowserFrame; always-visible direct-download fallback for returning visitors - Promises.tsx — 5-card "what we won't do" grid - HomeFAQ.tsx — 8-question accordion using the FAQ primitive (drafts for user revision) - FinalCTA.tsx — italic-headline closing band page.tsx: 11 sections, no gradient blobs, no ambient washes. Stream/ Render/Ship feature blocks alternate visualLeft; Ship hosts the live cockpit iframe. e2e: hero / differentiator / feature-block assertions replace the obsolete architecture / libraries selectors. WhitePaperBlock keeps a direct /whitepaper.pdf link visible so the existing whitepaper-link test passes. All 23 e2e tests pass. Phase 3 (screenshot capture) deferred — BrowserFrames currently show placeholder content + ascii prose. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(website): /pricing uses new primitives, drops glass PricingGrid: 2 Cards using Eyebrow/Button primitives; highlighted tier uses surface=dim + 2px accent border instead of glow. LeadForm: Card-wrapped form, inputs use surface tokens, focus rings use shadow-focus token; submit becomes Button primitive. page.tsx: clean Hero-style header, drops blob background, adds FinalCTA at the end for cross-page rhythm. Tests: pricing-related e2e (plan cards + lead-form validation + nav-pricing-link) all pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(website): /pilot-to-prod uses new primitives, drops blobs Rewrites the page to the new dev-tool-SaaS aesthetic: centered Hero with Pill trust row, 3 FeatureBlocks (Discover/Build/Harden) keyed to the 8-week timeline, a tinted outcomes-grid section, the shared WhitePaperBlock, Promises (the 5 ‘what we won't do' commitments), a contact anchor, and FinalCTA. The old PilotHero/WhatIsIncluded/ HowItWorks/ProblemSection/PricingSignal/RiskRemoval/WhitePaperGate/ PilotFooterCTA sections are no longer imported — they become orphans for Phase 6 cleanup. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(website): /angular, /chat, /render use new primitives Each library landing page now shares the same shape: - Centered Hero with library-specific Pill trust row - 2 FeatureBlocks — one for the library's defining capability, one for its escape-hatch / power-user surface - WhitePaperBlock — shared with homepage + pilot-to-prod - FinalCTA The existing AngularCodeShowcase / ChatLandingCodeShowcase / RenderCodeShowcase components are reused as the visual for one FeatureBlock per page (they already use shiki/HighlightedCode and are valuable). Everything else from the old library-page chrome (AngularHero, AngularProblemSolution, AngularFeaturesGrid, etc.) becomes orphaned and gets deleted in Phase 6. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(website): /solutions index + per-library whitepaper variants /solutions index: clean Hero + 3 Card grid driven by SOLUTIONS data (displays eyebrow, title, subtitle, top 2 proof Pills, hover lift, clickable to the slug page). Drops the framer-motion-heavy old SolutionsGrid. Adds WhitePaperBlock + FinalCTA at the bottom. Note: /solutions/[slug] pages still use the old per-solution components (SolutionHero, SolutionProblem, etc.) — those are data-rich and need their own focused pass. Deferred. WhitePaperBlock now takes an optional `paper` prop with library variants ('overview' | 'angular' | 'render' | 'chat'). PDF paths and analytics tags routed accordingly. /angular, /chat, /render each pass their library variant so the existing whitepapers-link-from-marketing-pages e2e test (which asserts each library page links to /whitepapers/{lib}.pdf) keeps passing. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(website): Phase 6 — delete orphaned landing components Deletes 31 landing components + 1 shared component that are no longer referenced by any route after Phases 4 and 5: - ArchDiagram, CockpitCTA, FeatureStrip, HeroTwoCol, HomePilotCTA, HowItWorks, PilotHero, PilotSolution, PricingSignal, RiskRemoval, SocialProof, TheStack, ValueProps, ValuePropsTabs, FairComparisonSection, DeepAgentsShowcase, LangGraphShowcase, LibrariesSection, ChatFeaturesSection, ProblemSection, PilotFooterCTA, WhitePaperGate, PositioningStrip, WhatIsIncluded, CapabilityCard, GenerativeUIFrame, EmbedFrame, CodeBlock, CitationBadge, solutions/SolutionsGrid, shared/InstallStrip - Library subfolders: 7 of 8 components each in angular/, chat-landing/, render/ (kept only the *CodeShowcase.tsx — still used as visuals in the new library pages, and they use shiki under the hood) Kept (still referenced): - landing/Hero/ProofStrip/Differentiator/FeatureBlock/PilotBlock/ WhitePaperBlock/Promises/HomeFAQ/FinalCTA/LiveCockpitFrame — new - landing/HighlightedCode — used by the 3 *CodeShowcase components - landing/WhitePaperSection — still used by /solutions/[slug] - landing/solutions/Solution{Hero,Problem,Architecture,ProofPoints, FooterCTA} — still used by /solutions/[slug] Verification: all 23 e2e tests pass. Deferred: framer-motion still imported by WhitePaperSection and /solutions/[slug] components. Final removal of the dep waits on a focused /solutions/[slug] refactor (out of scope for the current Statusbrew sweep — those detail pages are data-rich and need their own pass). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(website): /solutions/[slug] uses new primitives; drop framer-motion /solutions/[slug] page rewritten against Phase 1 primitives: - Hero with per-solution accent color (from solution.color) - PainPoints — Card grid driven by solution.painPoints - Architecture — editorial intro + Card grid for the 3 architecture layers; Agent/Render/Chat cards link to their library page - Capabilities — replaces the old proof-points section; uses the reframed metric/label shape as honest framework claims - WhitePaperBlock (overview) - FinalCTA — now takes optional headline/subtext/primary/secondary/ caption props; solution pages pass their ctaHeadline/ctaSubtext and override the CTA pair to point at /pricing#lead-form + /docs Content updates in solutions-data.ts: - Replaced speculative numeric proof points (10x, 70%, <5min) with honest capability framings (Every / Required / Replayable for compliance; Plain English / Streaming / Inline for analytics; Preserved / Required / Visible for customer support) - Softened overstated language: "immutable audit trails" → audit trail, "Resolve tickets autonomously" → "Resolve routine tickets autonomously" - Tightened a few descriptions to match what the libraries actually do (e.g., dropped "Pre-built generative UI panel" in favor of "Generative UI surfaces") Deletions (now safe): - SolutionHero, SolutionProblem, SolutionArchitecture, SolutionProofPoints, SolutionFooterCTA - WhitePaperSection (its last consumer was /solutions/[slug]) - framer-motion dep removed from package.json + package-lock.json (surgical edit per repo memory: don't regenerate lockfile on macOS) - tokens.glass.border → tokens.surfaces.border swap in the 3 *CodeShowcase components New e2e: apps/website/e2e/solutions.spec.ts covers all 3 slug pages + 404 path + package pill. All 28 e2e tests pass. Remaining `tokens.glass.*` usage is /docs/* only (out of scope per spec — docs styling preserved). Phase 6 token purge of glass / gradient / glow waits on a separate docs refactor pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(specs): website refactor Phase 7 — docs pages design Skin refresh + minor IA polish for apps/website/src/app/docs/** and apps/website/src/components/docs/**. Drops glass/gradient washes, migrates to Phase 1 tokens, wires the unused DocsBreadcrumb + DocsPrevNext, consolidates mdx/Card + mdx/FeatureChips against the ui/Card + ui/Pill primitives, adds hash-anchor affordance on H2/H3. 3-commit phasing. Cockpit (Phase 8) explicitly deferred. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(plans): Phase 7 — docs pages refactor 23-task plan, 3 commits. Commit 7.1 reskins page chrome (landing, slug wrapper, sidebar, search, TOC, breadcrumb, global.css for anchor + 70ch column). Commit 7.2 restyles 7 MDX primitives in place (Callout, Tabs, Steps, CodeGroup, CodeBlock, Card+CardGroup, FeatureChips) — the original spec's consolidation against ui/Card + ui/Pill was dropped after verification showed the MDX primitives have docs-specific shapes. Commit 7.3 handles ancillary components, wires DocsPrevNext, adds heading-anchor affordance, ships a new e2e/docs.spec.ts. Also fixes the FeatureChips broken hrefs (chip links pointed at /docs/guides/... missing the library segment) as part of its restyle. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(website): docs chrome — drop glass, use new tokens (Phase 7.1) Migrates docs page chrome to Phase 1 design tokens: - /docs landing rewritten as Hero + library grid + popular topics + search prompt; drops --gradient-bg-flow - slug-page wrapper drops glass + gradient; content well sits on surfaces.surface, page wrapper on surfaces.canvas - DocsSidebar: white surface, hairline right border, no blur - DocsSearch: drop glass on modal; use shadows.lg + surfaces.border - DocsBreadcrumb wired in at top of slug content column (was unused) - DocsTOC: normalized to surfaces tokens - global.css: heading-anchor affordance CSS (used in Phase 7.3) No MDX or content changes. All 28 e2e tests pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(website): docs MDX primitives — drop glass, use new tokens (Phase 7.2) Restyles 7 MDX primitives in apps/website/src/components/docs/mdx/ to drop glassmorphism and use the Phase 1 token namespaces: - Callout — 4px left accent stripe per tone (tip/warning/info/danger) on surfaceTinted body, with an inline tone-circle icon - Tabs — white tab bar with hairline bottom border; active tab gets 2px accent underline + accent text - Steps — 32x32 accent number circles with surfaces.border vertical connector (matches PilotBlock timeline) - CodeGroup — same tab-bar treatment as Tabs; body wraps the active shiki block in surfaces.border chrome (code body stays tokyo-night) - CodeBlock (the MDX wrapper) — BrowserFrame-style chrome: traffic lights + filename pill, surfaces.surface chrome, code body stays dark - Card / CardGroup — preserved clickable-link-tile shape; drops glass + glow for surfaces tokens + shadows.sm/md - FeatureChips — drops gradient + glass; also fixes 8 broken hrefs (chip links pointed at /docs/guides/... missing the library segment; fixed to /docs/agent/guides/...) No MDX content edits. Prop APIs preserved. All 28 e2e tests pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(website): restore copy-to-clipboard button in mdx/CodeBlock (Phase 7.2 follow-up) Phase 7.2's CodeBlock.tsx replacement dropped the copy-to-clipboard button + docsCopyCodeClick analytics tracking, and replaced the prop API with { filename, language, children } — a shape the MDX pipeline never passes (filenames come via rehype-pretty-code's data-rehype-pretty-code-title attribute, styled in global.css). This restores Pre's original prop API (React.HTMLAttributes<HTMLPreElement>), the copy button, and the analytics event. Button styling keeps raw light-on-dark rgba colors since the button sits on tokyo-night code background and the new surface tokens would make it invisible. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(website): docs ancillary refactor + DocsPrevNext + anchor links (Phase 7.3) - MdxRenderer: H2/H3 component overrides emit a leading `<a class= "heading-anchor">#</a>` linked to the heading's rehype-slug ID. CSS affordance (hover fades the # in) landed in Phase 7.1's global.css. - ApiDocRenderer / ApiRefTable: migrated off tokens.glass.* to surfaces + shadow.sm; param-table headers use surfaceTinted. - ArchFlowDiagram: nodes + edges on surface tokens. - CopyPromptButton: white button with surface border, accent on hover/copied state. - DocsPrevNext: refactored to use ui/Card hoverable; finds siblings by flattening docsConfig.sections.pages in declaration order; wired in at the bottom of every slug page (renders nothing if no siblings exist). - New apps/website/e2e/docs.spec.ts: covers landing page, slug page breadcrumb + prev/next + heading IDs, and the ⌘K search modal. Workspace-wide grep for `tokens.glass` in apps/website/src/app/docs and components/docs returns zero. All e2e tests pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(website): Phase 7 review fixes — dedupe breadcrumb + normalize imports - Remove duplicate DocsBreadcrumb render from MdxRenderer (the slug page already renders it; the MdxRenderer-internal render produced two stacked breadcrumbs on every doc page) - Normalize MdxRenderer's tokens import: '../../../lib/design-tokens' (website-local shim) → '@ngaf/design-tokens' (matches every other Phase 7 docs file) - e2e: tighten library-card count + add breadcrumb-once assertion to guard the dedupe fix Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(specs): Phase 8 — cockpit + final token purge design Migrates apps/cockpit to a Linear-style light app shell using the Phase 1 tokens (surface-tinted sidebar with border-strong divider, flat mode-switcher pill, hairline-bordered code-file frames, 2px accent rail on active sidebar nav). Extends libs/ui-react's cssVars with the new namespaces as a prerequisite. Final commit deletes the legacy glass/gradients/glow files from @ngaf/design-tokens AND 9 orphaned glass-using components from @ngaf/ui-react (workspace grep confirmed nothing consumes them outside ui-react itself). After Phase 8 ships, the design-tokens library is at 0.0.31 with a tighter surface; ui-react is a thin {cssVars, cn} utility. 3 commits: 8.1 prereq + 8.2 cockpit refactor + 8.3 purge. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(plans): Phase 8 — cockpit refactor + final token purge 20-task plan, 3 commits. Commit 8.1 extends libs/ui-react's cssVars with Phase 1 namespaces (surfaces, shadows, radius, space) plus adds css-vars.spec.ts. Commit 8.2 refactors 9 cockpit files to the new design system (sidebar surface-tinted with border-strong divider, flat mode-switcher, hairline-bordered code frames, 2px accent rail on active sidebar nav). Commit 8.3 deletes glass/gradient/glow files from @ngaf/design-tokens, 8 orphaned glass-using components from @ngaf/ui-react (none consumed outside the lib), and trims website re-exports + global.css :root vars. @ngaf/design-tokens bumps 0.0.30 → 0.0.31. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(ui-react): extend cssVars with Phase 1 token namespaces (Phase 8.1) Adds surfaces / shadows / radius / space CSS vars to the @ngaf/ui-react cssVars map plus extended colors (accentHover, textInverted). Legacy glass / gradient / glow vars stay until Phase 8.3 purge. New libs/ui-react/src/lib/css-vars.spec.ts locks down which vars are exposed; the legacy-namespace assertions will be removed alongside the legacy tokens in Phase 8.3. Also adds @ngaf/design-tokens path alias to tsconfig.base.json (source) and a build-time override in libs/ui-react/tsconfig.lib.json (dist types) so both the Vite test runner and the @nx/js:tsc build executor resolve the package correctly within this worktree. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(cockpit): migrate to Linear-style light app shell (Phase 8.2) Drops glassmorphism and the --ds-gradient-bg-flow body background across the cockpit app. Replaces with the Phase 1 token namespaces: - layout.tsx: body uses --ds-surface - cockpit-shell.tsx: content section --ds-surface, no backdrop-blur; header gets a hairline --ds-border bottom edge - cockpit-sidebar.tsx: --ds-surface-tinted background, --ds-border-strong right edge, no blur - navigation-groups.tsx: active link gets a 2px --ds-accent left rail (devtools convention — Linear, VS Code Explorer) - language-picker.tsx: trigger + dropdown drop glass; dropdown uses --ds-shadow-md - mobile-nav-overlay.tsx: panel uses --ds-surface + --ds-shadow-lg, no blur; inner sub-section borders use --ds-border - mode-switcher.tsx: flat pill (--ds-surface-tinted track + --ds-border outline); sliding indicator keeps --ds-accent - code-mode.tsx: CodeFileContent outer container uses --ds-border + --ds-shadow-sm + --ds-radius-md; dark tokyo-night code header stays - ui/tabs.tsx: tab-list bottom hairline switches to --ds-border; active tab underline stays --ds-accent apps/cockpit grep for glass/gradient/backdrop returns zero. All cockpit tests + cockpit e2e + website e2e green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore: purge legacy glass/gradient/glow tokens + orphaned ui-react components (Phase 8.3) Final cleanup of the multi-phase Statusbrew-inspired refactor. @ngaf/design-tokens (bumped 0.0.30 → 0.0.31): - Deleted libs/design-tokens/src/lib/glass.ts - Deleted libs/design-tokens/src/lib/gradients.ts - Deleted libs/design-tokens/src/lib/glow.ts - tokens.ts aggregator drops glass/gradient/glow - tokens.css drops --ds-glass-*, --ds-gradient-*, --ds-glow-* - tokens.spec.ts drops the corresponding test blocks - index.ts trimmed @ngaf/ui-react becomes a thin {cssVars, cn} utility lib: - Deleted 8 orphaned glass-using components (GlassPanel, GlassButton, Card, CardGroup, CodeGroup, Callout, Steps, Tabs, NavLink) — none were consumed outside libs/ui-react itself - Deleted components.spec.tsx (tested the deleted components) - index.ts trimmed to {cssVars, cn} - css-vars.ts no longer exposes legacy --ds-glass-*/--ds-gradient-*/ --ds-glow-* vars - css-vars.spec.ts assertions consolidated Website-side cleanup: - apps/website/lib/design-tokens.ts: drop glass/gradient/glow re-exports - apps/website/src/app/global.css: drop legacy :root vars - apps/website/src/components/pricing/CompareTable.tsx: migrate from tokens.glass to tokens.surfaces (missed in Phase 7) Workspace-wide grep for tokens.glass / tokens.gradient / tokens.glow / --ds-glass / --ds-gradient / --ds-glow / --glass- / --gradient-bg-flow returns zero. All tests green: design-tokens, ui-react, cockpit, website (e2e + unit). Multi-phase Statusbrew refactor complete. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 288d3b0 commit fefe825

169 files changed

Lines changed: 13753 additions & 10264 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/cockpit/src/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export default function RootLayout({ children }: RootLayoutProps) {
1717
<body
1818
className="min-h-screen font-sans antialiased"
1919
style={{
20-
background: 'var(--ds-gradient-bg-flow)',
20+
background: 'var(--ds-surface)',
2121
color: 'var(--ds-text-primary)',
2222
}}
2323
>

apps/cockpit/src/components/cockpit-shell.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,11 @@ export function CockpitShell({
7979
onClose={() => setIsSidebarOpen(false)}
8080
/>
8181

82-
<section className="grid grid-rows-[auto_1fr] gap-2 p-4 overflow-hidden bg-[var(--ds-glass-bg)] backdrop-blur-[var(--ds-glass-blur)]">
83-
<header className="flex flex-col gap-2 md:flex-row md:items-center md:justify-between">
82+
<section className="grid grid-rows-[auto_1fr] gap-2 p-4 overflow-hidden bg-[var(--ds-surface)]">
83+
<header
84+
className="flex flex-col gap-2 md:flex-row md:items-center md:justify-between pb-3"
85+
style={{ borderBottom: '1px solid var(--ds-border)' }}
86+
>
8487
<div className="flex items-center gap-3">
8588
<button
8689
className="md:hidden"

apps/cockpit/src/components/code-mode/code-mode.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ function CodeFileContent({ path, content }: { path: string; content: string | un
2020

2121
return (
2222
<div className="code-mode-block" style={{
23-
borderRadius: 8,
24-
border: '1px solid var(--ds-glass-border)',
25-
boxShadow: 'var(--ds-glass-shadow)',
23+
borderRadius: 'var(--ds-radius-md)',
24+
border: '1px solid var(--ds-border)',
25+
boxShadow: 'var(--ds-shadow-sm)',
2626
overflow: 'hidden',
2727
}}>
2828
<div style={{

apps/cockpit/src/components/mobile-nav-overlay.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,8 @@ export function MobileNavOverlay({
6464
data-state={state}
6565
className="fixed inset-0 z-50 md:hidden flex flex-col"
6666
style={{
67-
background: 'var(--ds-glass-bg)',
68-
backdropFilter: 'blur(var(--ds-glass-blur))',
69-
WebkitBackdropFilter: 'blur(var(--ds-glass-blur))',
67+
background: 'var(--ds-surface)',
68+
boxShadow: 'var(--ds-shadow-lg)',
7069
opacity: state === 'open' ? 1 : 0,
7170
transform: state === 'open' ? 'translateY(0)' : 'translateY(8px)',
7271
transition: state === 'open'
@@ -77,7 +76,7 @@ export function MobileNavOverlay({
7776
{/* Header */}
7877
<header
7978
className="flex items-center justify-between px-4 py-3"
80-
style={{ borderBottom: '1px solid var(--ds-glass-border)' }}
79+
style={{ borderBottom: '1px solid var(--ds-border)' }}
8180
>
8281
<p
8382
className="font-mono text-xs font-semibold uppercase tracking-wide"
@@ -118,8 +117,8 @@ export function MobileNavOverlay({
118117
<div
119118
key={product.product}
120119
style={{
121-
background: 'var(--ds-glass-bg)',
122-
border: '1px solid var(--ds-glass-border)',
120+
background: 'var(--ds-surface-tinted)',
121+
border: '1px solid var(--ds-border)',
123122
borderRadius: 10,
124123
padding: 12,
125124
}}

apps/cockpit/src/components/modes/mode-switcher.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,8 @@ export function ModeSwitcher<T extends string>({
4040
gap: 0,
4141
padding: 3,
4242
borderRadius: 999,
43-
background: 'var(--ds-glass-bg)',
44-
border: '1px solid var(--ds-glass-border)',
45-
boxShadow: 'var(--ds-glass-shadow)',
43+
background: 'var(--ds-surface-tinted)',
44+
border: '1px solid var(--ds-border)',
4645
}}
4746
>
4847
{/* Sliding indicator */}
@@ -75,7 +74,7 @@ export function ModeSwitcher<T extends string>({
7574
borderRadius: 999,
7675
border: 'none',
7776
background: 'transparent',
78-
color: isActive ? '#fff' : 'var(--ds-text-secondary)',
77+
color: isActive ? 'var(--ds-text-inverted)' : 'var(--ds-text-secondary)',
7978
fontFamily: 'var(--ds-font-mono)',
8079
fontSize: '0.8rem',
8180
fontWeight: isActive ? 500 : 400,

apps/cockpit/src/components/sidebar/cockpit-sidebar.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,13 @@ export function CockpitSidebar({
2020
return (
2121
<aside
2222
aria-label="Cockpit sidebar"
23-
className="grid gap-4 py-6 px-0 border-r border-[var(--ds-glass-border)] bg-[var(--ds-glass-bg)] backdrop-blur-[var(--ds-glass-blur)] content-start overflow-y-auto"
24-
style={{ position: 'sticky', top: 0, minHeight: '100vh' }}
23+
className="grid gap-4 py-6 px-0 border-r bg-[var(--ds-surface-tinted)] content-start overflow-y-auto"
24+
style={{
25+
position: 'sticky',
26+
top: 0,
27+
minHeight: '100vh',
28+
borderRightColor: 'var(--ds-border-strong)',
29+
}}
2530
>
2631
<header className="flex items-center justify-between px-4">
2732
<p className="text-[var(--ds-text-muted)] font-mono text-xs font-medium tracking-wide uppercase">Cockpit</p>

apps/cockpit/src/components/sidebar/language-picker.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,8 @@ export function LanguagePicker({ manifest, entry }: LanguagePickerProps) {
5050
style={{
5151
padding: '4px 10px',
5252
borderRadius: 6,
53-
border: '1px solid var(--ds-accent-border)',
54-
background: 'rgba(255, 255, 255, 0.7)',
55-
backdropFilter: 'blur(var(--ds-glass-blur))',
53+
border: '1px solid var(--ds-border)',
54+
background: 'var(--ds-surface)',
5655
color: 'var(--ds-text-secondary)',
5756
fontSize: '0.75rem',
5857
fontFamily: 'var(--ds-font-mono)',
@@ -73,11 +72,9 @@ export function LanguagePicker({ manifest, entry }: LanguagePickerProps) {
7372
minWidth: 120,
7473
padding: 4,
7574
borderRadius: 8,
76-
border: '1px solid var(--ds-glass-border)',
77-
background: 'rgba(255, 255, 255, 0.92)',
78-
backdropFilter: 'blur(var(--ds-glass-blur))',
79-
WebkitBackdropFilter: 'blur(var(--ds-glass-blur))',
80-
boxShadow: 'var(--ds-glass-shadow)',
75+
border: '1px solid var(--ds-border)',
76+
background: 'var(--ds-surface)',
77+
boxShadow: 'var(--ds-shadow-md)',
8178
zIndex: 50,
8279
}}
8380
>

apps/cockpit/src/components/sidebar/navigation-groups.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,13 @@ function ProductGroup({
7878
aria-current={isActive ? 'page' : undefined}
7979
style={{
8080
display: 'block',
81-
padding: '5px 16px',
81+
padding: isActive ? '5px 16px 5px 14px' : '5px 16px',
8282
margin: '0 8px',
8383
borderRadius: 6,
8484
fontSize: '0.825rem',
8585
color: isActive ? 'var(--ds-accent)' : 'var(--ds-text-secondary)',
8686
background: isActive ? 'var(--ds-accent-surface)' : 'transparent',
87+
borderLeft: isActive ? '2px solid var(--ds-accent)' : 'none',
8788
textDecoration: 'none',
8889
transition: 'all 0.15s',
8990
}}

apps/cockpit/src/components/ui/tabs.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const TabsList = React.forwardRef<
1313
<TabsPrimitive.List
1414
ref={ref}
1515
className={cn(
16-
'inline-flex items-center gap-0 border-b border-[var(--ds-accent-border)]',
16+
'inline-flex items-center gap-0 border-b border-[var(--ds-border)]',
1717
className
1818
)}
1919
{...props}

apps/website/e2e/docs.spec.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
test.describe('Docs landing page', () => {
4+
test('renders library cards + popular topics + search prompt', async ({ page }) => {
5+
await page.goto('/docs');
6+
// Header
7+
await expect(page.locator('#docs-heading')).toBeVisible();
8+
// Library grid — all 4 libraries (agent, render, chat, ag-ui)
9+
await expect(page.locator('main a[href="/docs/agent/getting-started/introduction"]').first()).toBeVisible();
10+
await expect(page.locator('main a[href="/docs/render/getting-started/introduction"]').first()).toBeVisible();
11+
await expect(page.locator('main a[href="/docs/chat/getting-started/introduction"]').first()).toBeVisible();
12+
await expect(page.locator('main a[href="/docs/ag-ui/getting-started/introduction"]').first()).toBeVisible();
13+
// Popular topics — 3 cards
14+
await expect(page.getByText('Streaming with signals').first()).toBeVisible();
15+
await expect(page.getByText('Generative UI fundamentals').first()).toBeVisible();
16+
await expect(page.getByText('Production patterns').first()).toBeVisible();
17+
// Search prompt
18+
await expect(page.getByText('Looking for something specific?').first()).toBeVisible();
19+
});
20+
});
21+
22+
test.describe('Docs slug page', () => {
23+
const route = '/docs/agent/getting-started/introduction';
24+
25+
test('renders breadcrumb + h1 + sidebar', async ({ page }) => {
26+
await page.goto(route);
27+
await expect(page.locator('aside').first()).toBeVisible();
28+
await expect(page.locator('nav[aria-label="Breadcrumb"]').first()).toBeVisible();
29+
await expect(page.locator('article').first()).toBeVisible();
30+
});
31+
32+
test('breadcrumb shows the library + page title', async ({ page }) => {
33+
await page.goto(route);
34+
const breadcrumb = page.locator('nav[aria-label="Breadcrumb"]').first();
35+
await expect(breadcrumb).toContainText('Docs');
36+
});
37+
38+
test('renders DocsPrevNext at the bottom (next-only for the first page)', async ({ page }) => {
39+
await page.goto(route);
40+
const prevNext = page.locator('nav[aria-label="Previous and next page"]').first();
41+
await expect(prevNext).toBeVisible();
42+
});
43+
44+
test('headings have ID anchors for hash links', async ({ page }) => {
45+
await page.goto(route);
46+
const h2 = page.locator('article h2').first();
47+
await expect(h2).toBeVisible();
48+
const id = await h2.getAttribute('id');
49+
expect(id).toBeTruthy();
50+
expect(id?.length).toBeGreaterThan(0);
51+
});
52+
53+
test('breadcrumb renders exactly once', async ({ page }) => {
54+
await page.goto('/docs/agent/getting-started/introduction');
55+
await expect(page.locator('nav[aria-label="Breadcrumb"]')).toHaveCount(1);
56+
});
57+
});
58+
59+
test.describe('Docs search', () => {
60+
test('Cmd+K opens the search modal', async ({ page, browserName }) => {
61+
await page.goto('/docs/agent/getting-started/introduction');
62+
// Mac uses Meta; other platforms emulate the same shortcut via keydown.
63+
const modifier = browserName === 'webkit' ? 'Meta' : 'Control';
64+
await page.keyboard.press(`${modifier}+KeyK`);
65+
// The modal mounts somewhere — assert by visible input role with placeholder text.
66+
await expect(page.locator('input[placeholder*="Search"], input[type="search"]').first()).toBeVisible({ timeout: 3000 });
67+
});
68+
});

0 commit comments

Comments
 (0)