Assist_Design/docs/plans/2026-03-05-parallax-pinned-chapters-design.md
barsa 57f2c543d1 style: update typography and layout across components
- Replaced font references in globals.css to use DM Sans and JetBrains Mono for improved typography consistency.
- Adjusted various components to utilize the new font styles, enhancing visual hierarchy and readability.
- Updated layout properties in AppShell and Sidebar for better alignment and spacing.
- Enhanced button styles to include a new subtle variant for improved UI flexibility.
- Refactored SearchFilterBar to support active filter display, improving user interaction experience.
- Made minor adjustments to the DashboardView and landing page components for better visual consistency.
2026-03-06 10:45:51 +09:00

163 lines
5.8 KiB
Markdown

# Parallax Pinned Chapters + Snap Carousel Design
**Date:** 2026-03-05
**Status:** Approved
## Overview
Redesign the landing page scroll experience using a "chapter" model. Sections are grouped into 4 chapters that pin (sticky) in place as the user scrolls. Each subsequent chapter slides up and covers the previous one, creating a layered card-stack effect. The services carousel is rebuilt with CSS scroll-snap for native horizontal snapping.
## Chapter Structure
| Chapter | Sections | Purpose |
| ------- | -------------------------- | --------------- |
| 1 | HeroSection + TrustStrip | "Who we are" |
| 2 | ServicesCarousel | "What we offer" |
| 3 | WhyUsSection + CTABanner | "Why choose us" |
| 4 | SupportDownloads + Contact | "Get in touch" |
## Scroll Behavior
### Pinning Mechanism
- Each chapter wrapper uses `position: sticky; top: 0`
- Chapters stack with increasing `z-index` (1, 2, 3, 4)
- Each chapter has a solid background so it fully covers the chapter behind it
- A subtle `box-shadow` on the top edge of each chapter creates the "sliding over" depth illusion
- The outer container uses `scroll-snap-type: y proximity` for soft vertical snap (helps chapters land cleanly but does not fight free scrolling)
### Chapter Details
**Chapter 1: Hero + TrustStrip**
- `min-height: 100dvh` to fill the viewport
- Hero fills most of the space, TrustStrip anchored at the bottom
- Pins in place while Chapter 2 slides up over it
- Existing gradient background + dot pattern preserved
**Chapter 2: ServicesCarousel**
- Natural content height (not forced to viewport height)
- Pins in place while Chapter 3 slides up
- Carousel rebuilt with CSS scroll-snap (see Carousel section below)
**Chapter 3: WhyUs + CTABanner**
- Natural content height
- Pins in place while Chapter 4 slides up
- WhyUs image gets a subtle parallax speed difference (scrolls slightly slower than text) for added depth
**Chapter 4: SupportDownloads + Contact**
- Normal scroll, no pinning (last chapter, nothing covers it)
- Existing fade-in animations preserved
## Carousel Rebuild (CSS Scroll-Snap)
The current carousel uses absolute positioning with JS-driven transforms and offset calculations. This will be replaced with a native CSS scroll-snap approach.
### New approach
- Horizontal scroll container with `scroll-snap-type: x mandatory`
- Each card is a snap point with `scroll-snap-align: center`
- Cards are laid out in a flex row, each taking full width of the visible area
- Native touch/swipe works out of the box
- Dot indicators sync with scroll position via `IntersectionObserver` or `scrollLeft` calculation
- Arrow buttons use `scrollBy()` with `behavior: 'smooth'`
- Auto-play uses `scrollBy()` and pauses on user interaction (touch, hover, focus)
- Personal/Business tab toggle resets scroll position to 0
### Benefits over current approach
- No absolute positioning or transform math
- Touch/swipe is native and performant
- Reduced JS complexity
- Better accessibility (native scroll semantics)
- Respects `prefers-reduced-motion` automatically
## Technical Implementation
### New component: ChapterWrapper
A reusable wrapper that applies sticky positioning:
```tsx
interface ChapterProps {
children: React.ReactNode;
zIndex: number;
className?: string;
}
function Chapter({ children, zIndex, className }: ChapterProps) {
return (
<section className={cn("sticky top-0", className)} style={{ zIndex }}>
{children}
</section>
);
}
```
### Updated PublicLandingView structure
```tsx
<main>
<Chapter zIndex={1} className="min-h-dvh">
<HeroSection />
<TrustStrip />
</Chapter>
<Chapter zIndex={2}>
<ServicesCarousel />
</Chapter>
<Chapter zIndex={3}>
<WhyUsSection />
<CTABanner />
</Chapter>
<div>
{" "}
{/* No sticky - last chapter */}
<SupportDownloadsSection />
<ContactSection />
</div>
</main>
```
### Shadow/depth effect
Each Chapter (except Chapter 1) gets a top shadow to enhance the "sliding over" illusion:
```css
.chapter-overlay {
box-shadow: 0 -8px 30px -10px rgba(0, 0, 0, 0.1);
}
```
## Mobile Considerations
- Use `100dvh` (dynamic viewport height) instead of `100vh` to avoid iOS address bar issues
- Carousel CSS scroll-snap is touch-native and works well on mobile
- Sticky positioning works on mobile browsers (iOS Safari, Chrome Android)
- If performance is poor on low-end devices, sticky can be disabled via a CSS class
## Accessibility
- `prefers-reduced-motion: reduce` disables sticky pinning behavior (falls back to normal scroll)
- Carousel maintains keyboard navigation (arrow keys, tab through cards)
- ARIA attributes preserved: `role="region"`, `aria-roledescription="carousel"`, slide labels
- Scroll-snap does not interfere with screen readers
## Files to Modify
| File | Change |
| ------------------------------------------------------- | --------------------------------------- |
| `features/landing-page/views/PublicLandingView.tsx` | Wrap sections in Chapter components |
| `features/landing-page/components/ServicesCarousel.tsx` | Rebuild with CSS scroll-snap |
| `features/landing-page/components/HeroSection.tsx` | Adjust to fill chapter space (flex-1) |
| `features/landing-page/components/TrustStrip.tsx` | Adjust to anchor at bottom of Chapter 1 |
| `features/landing-page/hooks/useInfiniteCarousel.ts` | Replace with scroll-snap hook or remove |
| `features/landing-page/components/index.ts` | Export new Chapter component |
| New: `features/landing-page/components/Chapter.tsx` | Chapter wrapper component |
| New: `features/landing-page/hooks/useSnapCarousel.ts` | Hook for scroll-snap carousel state |