Skip to content

feat: Complete visual redesign with indigo/Swiss glassmorphism theme#20

Closed
Zheckan wants to merge 1 commit intomainfrom
redesign/indigo-swiss-glassmorphism
Closed

feat: Complete visual redesign with indigo/Swiss glassmorphism theme#20
Zheckan wants to merge 1 commit intomainfrom
redesign/indigo-swiss-glassmorphism

Conversation

@Zheckan
Copy link
Owner

@Zheckan Zheckan commented Feb 8, 2026

Summary

  • Complete visual redesign of all 4 main pages with a cohesive indigo/violet color system, refined glassmorphism surfaces, and CSS mesh gradient background
  • Fixed width switcher hydration bug: state now initializes correctly from persisted value (localStorage/cookie) after hydration, instead of reading dataset.contentWidth during useState init which caused wrong default
  • Redesigned table of contents: Uses IntersectionObserver for active section tracking, useRef-based click-outside detection (replaces fragile querySelector('nav[style*="top:"]')), clean mobile slide-over with backdrop, explicit toggle/close/pin buttons

Pages redesigned:

  • Home (/): Hero section with animated entrance, gradient text, staggered card reveals, features section with scroll-triggered animations
  • Junior Frontend (/frontend/junior): Numbered topic cards with status badges, progress bar, back navigation, animated grid
  • Content (/frontend/junior/html&css): Redesigned section cards, code blocks with indigo highlights, typography system, callouts
  • Test (/test): Inherits new theme

Design system:

  • Indigo/violet gradient accent (#818cf8#a78bfa#c084fc)
  • Layered surface tokens (--surface-0 through --surface-3)
  • CSS mesh gradient ambient background (no external image dependency)
  • Glass utilities with backdrop-filter
  • text-gradient utility class
  • Light mode support via prefers-color-scheme

Test plan

  • Open / and verify hero animation, card hover, features section
  • Open /frontend/junior and verify numbered cards, progress bar, disabled states
  • Open /frontend/junior/html&css and verify:
    • Width switcher shows correct persisted width on load
    • Changing width persists across page refresh
    • TOC opens/closes cleanly with toggle button
    • TOC highlights active section while scrolling
    • TOC mobile slide-over with backdrop works
  • Check responsive at 375px, 768px, 1440px
  • Verify zero console errors
  • bunx tsc --noEmit passes
  • bun run build passes

🤖 Generated with Claude Code

Redesign the entire Prep platform with a cohesive indigo/violet accent
color system, refined glassmorphism surfaces, CSS mesh gradient background,
and Framer Motion animations throughout.

Key changes:
- New color system: indigo/violet accents, layered surface tokens, gradient text
- CSS mesh gradient ambient background (replaces external image dependency)
- Redesigned home page with animated hero, staggered card reveals, features section
- Redesigned junior frontend page with numbered topic cards, progress bar, status badges
- Redesigned content page components: section cards, code blocks, typography, callouts
- Fixed width switcher hydration bug: state now initializes from persisted value after
  hydration instead of reading dataset during useState init
- Redesigned table of contents: IntersectionObserver for active section tracking,
  ref-based click-outside detection (replaces fragile querySelector), clean mobile
  slide-over with backdrop, explicit toggle/close/pin buttons
- All pages responsive across mobile (375px), tablet (768px), desktop (1440px)
- Zero TypeScript errors, zero console errors, production build passes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 8, 2026 20:14
@vercel
Copy link
Contributor

vercel bot commented Feb 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
prep Ready Ready Preview, Comment Feb 8, 2026 8:15pm

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR delivers a cohesive indigo/violet “Swiss glassmorphism” visual redesign across core pages/components, while also improving content-width persistence and replacing the table-of-contents behavior with a more robust, ref/IntersectionObserver-based implementation.

Changes:

  • Introduces a new design system via CSS variables/utilities (glass/surface layers, mesh gradient ambient background, gradient text, light mode tokens).
  • Refactors content width persistence/hydration to sync from persisted values on mount and avoid the prior hydration mismatch.
  • Rebuilds the Table of Contents UI/UX (mobile toggle/backdrop, pin/close controls, active heading tracking, click-outside handling).

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/components/width-switcher/width-switcher.tsx Updated width switcher styling and preset button UI
src/components/typography/text.tsx Switched text colors to CSS-variable tokens
src/components/typography/subheader.tsx Updated subheader styling to new token system
src/components/typography/header.tsx Updated header styling + accent underline token
src/components/typography/code-span.tsx Updated inline code styling to new surfaces/accent
src/components/typography/callout.tsx Updated callout styling to new surfaces/accent
src/components/table-of-contents/table-of-contents.tsx Major TOC redesign with IntersectionObserver + mobile UX
src/components/section-card/section-card.tsx Updated section card styling + gradient title
src/components/page-header/page-header.tsx Updated header styling and simplified breakpoint listener
src/components/notes-area/notes-area.tsx Updated notes UI to new surface/border tokens
src/components/layout/page-container.tsx Refactored width persistence + hydration gating for switcher
src/components/layout/content-page.tsx Updated base text color to variable token
src/components/code-block/code-block.tsx Updated code block styling + font token usage
src/components/ambient-background/ambient-background.tsx Replaced external image background with CSS mesh/noise
src/app/layout.tsx Updated metadata description (and retains width bootstrapping)
src/app/globals.css New palette/tokens, utilities (glass/surface/gradient text), light mode
src/app/frontend/junior/frontend-junior.tsx Redesigned Junior Frontend page with motion + new components styling
src/app/(main)/home.tsx Redesigned Home page with hero + features section + motion
REDESIGN_PROMPT.md Added redesign prompt documentation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 7 to 14
<section
className='mb-12 rounded-lg border border-zinc-800 bg-zinc-900/90 p-6 backdrop-blur supports-[backdrop-filter]:bg-zinc-900/65'
className='mb-10 rounded-xl border border-[var(--border)] bg-[var(--surface-1)] p-6 sm:p-8'
id={id}
>
<h2
className='mb-4 border-zinc-700 border-b pb-2 font-bold text-2xl text-white'
className='mb-5 border-[var(--border-strong)] border-b pb-3 font-bold text-2xl text-[var(--foreground)]'
id={id}
>
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SectionCard assigns the same id to both the wrapping <section> and the <h2>. Duplicate IDs are invalid HTML and can break TOC behavior (e.g., document.getElementById() may return the <section> instead of the heading, so scroll offsets / intersection tracking won’t match the heading). Use a single element as the anchor target (typically keep the id on the heading and remove it from the wrapper, or generate distinct IDs).

Copilot uses AI. Check for mistakes.
const touchStartRef = useRef<number | null>(null);
const openRef = useRef(open);
const pinnedRef = useRef(pinned);
const navRef = useRef<HTMLDivElement>(null);
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

navRef is typed as HTMLDivElement, but it’s attached to a <motion.nav> element. With strict TS this can cause a ref type mismatch (a <nav> is not a HTMLDivElement). Type the ref as HTMLElement/HTMLNavElement (or React.ElementRef<'nav'>) to match the element actually being referenced.

Suggested change
const navRef = useRef<HTMLDivElement>(null);
const navRef = useRef<HTMLElement | null>(null);

Copilot uses AI. Check for mistakes.
Comment on lines +170 to +175
<button
aria-label='Open table of contents'
className={`fixed left-4 z-50 rounded-lg p-2 transition-all duration-200 ${
open ? 'pointer-events-none opacity-0' : 'opacity-100'
} glass hover:bg-[var(--surface-2)]`}
onClick={() => setOpen(true)}
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When open is true, the TOC toggle button is visually hidden via opacity-0/pointer-events-none but remains focusable for keyboard users and still exposed to assistive tech. Prefer conditionally rendering the button only when closed, or set tabIndex={-1} / disabled / aria-hidden when open is true to keep it out of the tab order.

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +14
const presets: { key: WidthPreset; icon: string }[] = [
{ key: 'narrow', icon: '┃' },
{ key: 'comfortable', icon: '┃┃' },
{ key: 'wide', icon: '┃┃┃' },
{ key: 'full', icon: '┃┃┃┃' },
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

presets includes an icon field but it’s never used (the button renders preset.key). Either render the icon or drop the unused property to avoid dead data and keep the component easier to maintain.

Suggested change
const presets: { key: WidthPreset; icon: string }[] = [
{ key: 'narrow', icon: '┃' },
{ key: 'comfortable', icon: '┃┃' },
{ key: 'wide', icon: '┃┃┃' },
{ key: 'full', icon: '┃┃┃┃' },
const presets: { key: WidthPreset }[] = [
{ key: 'narrow' },
{ key: 'comfortable' },
{ key: 'wide' },
{ key: 'full' },

Copilot uses AI. Check for mistakes.
@Zheckan Zheckan closed this Feb 9, 2026
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

Comments