Files
ui-essentials/UI_LANDING_PAGES_PLAN_UPDATED.md
skyai_dev 246c62fd49 Add landing pages library with comprehensive components and demos
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-06 13:52:41 +10:00

23 KiB

UI Landing Pages Library Implementation Plan

Executive Summary

This document outlines the implementation strategy for creating a comprehensive ui-landing-pages library within the SSuite Angular workspace. The library will provide production-ready components specifically designed for building modern websites and landing pages, leveraging Angular 19 features and integrating seamlessly with existing libraries: ui-design-system, ui-essentials, ui-animations, ui-backgrounds, ui-code-display, and shared-utils.

Technical Foundation

Angular 19 Requirements

  • Standalone Components: All components will be standalone (no NgModules)
  • Control Flow Syntax: Use @if, @for, @switch (not *ngIf, *ngFor)
  • Signals: Prefer signals over observables for state management
  • Inject Function: Use inject() function over constructor injection
  • OnPush Change Detection: Default for all components
  • @defer: Implement lazy loading where appropriate

Design System Integration

Token Import Path

// Correct import path for semantic tokens
@use '../../../../../ui-design-system/src/styles/semantic/index' as *;

Typography Strategy

The design system provides comprehensive typography tokens as maps and single values:

  • Headings: Use $semantic-typography-heading-h1 through h5 (maps)
  • Body Text: Use $semantic-typography-body-large/medium/small (maps)
  • Component Text: Use $semantic-typography-button-* variants (maps)

Component Architecture Principles

  • NO hardcoded values: All styling must use semantic tokens
  • BEM methodology: Consistent class naming convention
  • Component composition: Leverage existing ui-essentials components
  • Accessibility first: WCAG 2.1 AA compliance required

Architecture Overview

Library Structure

projects/ui-landing-pages/
├── src/
│   ├── lib/
│   │   ├── components/
│   │   │   ├── heroes/              # Hero section components
│   │   │   ├── features/            # Feature showcase components
│   │   │   ├── social-proof/        # Testimonials, logos, stats
│   │   │   ├── conversion/          # CTAs, pricing, forms
│   │   │   ├── navigation/          # Headers, menus, footers
│   │   │   ├── content/             # FAQ, team, timeline
│   │   │   └── templates/           # Complete page templates
│   │   ├── services/                # Landing page utilities
│   │   ├── interfaces/              # TypeScript interfaces
│   │   └── directives/              # Reusable directives
│   ├── public-api.ts
│   └── test.ts
├── ng-package.json
├── package.json
├── tsconfig.lib.json
├── tsconfig.lib.prod.json
├── tsconfig.spec.json
└── README.md

Component Naming Convention

All components follow the pattern: ui-lp-[component-name]

  • Prefix: ui-lp- (ui landing pages)
  • Examples: ui-lp-hero, ui-lp-feature-grid, ui-lp-pricing-table

Implementation Phases


Phase 1: Foundation & Hero Components

Objective

Establish library foundation and implement essential hero section components using Angular 19 best practices.

Components to Implement

1.1 HeroSection Component (ui-lp-hero)

TypeScript Implementation:

import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ViewEncapsulation, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ButtonComponent } from 'ui-essentials';
import { ContainerComponent } from 'ui-essentials';
import { AnimationDirective } from 'ui-animations';

export interface HeroConfig {
  title: string;
  subtitle?: string;
  ctaPrimary?: CTAButton;
  ctaSecondary?: CTAButton;
  backgroundType?: 'solid' | 'gradient' | 'image' | 'video' | 'animated';
  alignment?: 'left' | 'center' | 'right';
  minHeight?: 'full' | 'large' | 'medium';
  animationType?: 'fade' | 'slide' | 'zoom';
}

export interface CTAButton {
  text: string;
  variant: 'primary' | 'secondary' | 'outline';
  size?: 'sm' | 'md' | 'lg';
  icon?: string;
  action: () => void;
}

@Component({
  selector: 'ui-lp-hero',
  standalone: true,
  imports: [CommonModule, ButtonComponent, ContainerComponent, AnimationDirective],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  template: `
    <section 
      class="ui-lp-hero"
      [class.ui-lp-hero--{{config().backgroundType}}]="config().backgroundType"
      [class.ui-lp-hero--{{config().alignment}}]="config().alignment"
      [class.ui-lp-hero--{{config().minHeight}}]="config().minHeight"
      [attr.aria-label]="'Hero section'"
      uiAnimation
      [animationType]="config().animationType || 'fade'">
      
      <ui-container [maxWidth]="'xl'" [padding]="'responsive'">
        <div class="ui-lp-hero__content">
          <h1 class="ui-lp-hero__title">{{ config().title }}</h1>
          
          @if (config().subtitle) {
            <p class="ui-lp-hero__subtitle">{{ config().subtitle }}</p>
          }
          
          @if (config().ctaPrimary || config().ctaSecondary) {
            <div class="ui-lp-hero__actions">
              @if (config().ctaPrimary) {
                <ui-button
                  [variant]="config().ctaPrimary.variant"
                  [size]="config().ctaPrimary.size || 'lg'"
                  (clicked)="handleCTAClick(config().ctaPrimary)">
                  {{ config().ctaPrimary.text }}
                </ui-button>
              }
              
              @if (config().ctaSecondary) {
                <ui-button
                  [variant]="config().ctaSecondary.variant"
                  [size]="config().ctaSecondary.size || 'lg'"
                  (clicked)="handleCTAClick(config().ctaSecondary)">
                  {{ config().ctaSecondary.text }}
                </ui-button>
              }
            </div>
          }
        </div>
      </ui-container>
      
      @if (config().backgroundType === 'animated') {
        <div class="ui-lp-hero__animated-bg" aria-hidden="true"></div>
      }
    </section>
  `,
  styleUrl: './hero-section.component.scss'
})
export class HeroSectionComponent {
  config = signal<HeroConfig>({
    title: '',
    alignment: 'center',
    backgroundType: 'solid',
    minHeight: 'large'
  });
  
  @Input() set configuration(value: HeroConfig) {
    this.config.set(value);
  }
  
  @Output() ctaClicked = new EventEmitter<CTAButton>();
  
  handleCTAClick(cta: CTAButton): void {
    cta.action();
    this.ctaClicked.emit(cta);
  }
}

SCSS Implementation:

@use '../../../../../ui-design-system/src/styles/semantic/index' as *;

.ui-lp-hero {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  
  // Min Height Variants
  &--full {
    min-height: 100vh;
  }
  
  &--large {
    min-height: 80vh;
  }
  
  &--medium {
    min-height: 60vh;
  }
  
  // Background Variants
  &--solid {
    background: $semantic-color-surface-primary;
  }
  
  &--gradient {
    background: linear-gradient(
      135deg,
      $semantic-color-primary,
      $semantic-color-secondary
    );
  }
  
  &--animated {
    background: $semantic-color-surface-primary;
    overflow: hidden;
  }
  
  // Content Container
  &__content {
    position: relative;
    z-index: $semantic-z-index-dropdown;
    padding: $semantic-spacing-layout-section-lg 0;
  }
  
  // Alignment Variants
  &--left &__content {
    text-align: left;
  }
  
  &--center &__content {
    text-align: center;
    margin: 0 auto;
    max-width: 800px;
  }
  
  &--right &__content {
    text-align: right;
  }
  
  // Typography
  &__title {
    font-family: map-get($semantic-typography-heading-h1, font-family);
    font-size: map-get($semantic-typography-heading-h1, font-size);
    font-weight: map-get($semantic-typography-heading-h1, font-weight);
    line-height: map-get($semantic-typography-heading-h1, line-height);
    color: $semantic-color-text-primary;
    margin-bottom: $semantic-spacing-content-heading;
    
    .ui-lp-hero--gradient &,
    .ui-lp-hero--image & {
      color: $semantic-color-on-primary;
    }
  }
  
  &__subtitle {
    font-family: map-get($semantic-typography-body-large, font-family);
    font-size: map-get($semantic-typography-body-large, font-size);
    font-weight: map-get($semantic-typography-body-large, font-weight);
    line-height: map-get($semantic-typography-body-large, line-height);
    color: $semantic-color-text-secondary;
    margin-bottom: $semantic-spacing-content-paragraph;
    
    .ui-lp-hero--gradient &,
    .ui-lp-hero--image & {
      color: $semantic-color-on-primary;
      opacity: $semantic-opacity-subtle;
    }
  }
  
  &__actions {
    display: flex;
    gap: $semantic-spacing-component-md;
    margin-top: $semantic-spacing-layout-section-sm;
    
    .ui-lp-hero--center & {
      justify-content: center;
    }
    
    .ui-lp-hero--right & {
      justify-content: flex-end;
    }
  }
  
  // Animated Background
  &__animated-bg {
    position: absolute;
    inset: 0;
    background: linear-gradient(
      -45deg,
      $semantic-color-primary,
      $semantic-color-secondary,
      $semantic-color-primary,
      $semantic-color-secondary
    );
    background-size: 400% 400%;
    animation: gradientShift 15s ease infinite;
    z-index: $semantic-z-index-dropdown - 1;
  }
  
  // Responsive Design
  @media (max-width: $semantic-breakpoint-md - 1) {
    &--full {
      min-height: 100svh; // Use small viewport height for mobile
    }
    
    &__title {
      font-family: map-get($semantic-typography-heading-h2, font-family);
      font-size: map-get($semantic-typography-heading-h2, font-size);
      font-weight: map-get($semantic-typography-heading-h2, font-weight);
      line-height: map-get($semantic-typography-heading-h2, line-height);
    }
    
    &__actions {
      flex-direction: column;
      align-items: stretch;
    }
  }
  
  @media (max-width: $semantic-breakpoint-sm - 1) {
    &__title {
      font-family: map-get($semantic-typography-heading-h3, font-family);
      font-size: map-get($semantic-typography-heading-h3, font-size);
      font-weight: map-get($semantic-typography-heading-h3, font-weight);
      line-height: map-get($semantic-typography-heading-h3, line-height);
    }
    
    &__subtitle {
      font-family: map-get($semantic-typography-body-medium, font-family);
      font-size: map-get($semantic-typography-body-medium, font-size);
      font-weight: map-get($semantic-typography-body-medium, font-weight);
      line-height: map-get($semantic-typography-body-medium, line-height);
    }
  }
}

// Keyframes for animated background
@keyframes gradientShift {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

1.2 HeroWithImage Component (ui-lp-hero-image)

Similar structure with image handling capabilities, lazy loading, and responsive image optimization.

1.3 HeroSplitScreen Component (ui-lp-hero-split)

Implements 50/50 layouts with flexible content positioning and mobile-first responsive design.

Integration with Existing Libraries

UI Essentials Components:

  • ButtonComponent for CTAs
  • ContainerComponent for responsive layout
  • ImageComponent for optimized image loading
  • FlexComponent for flexible layouts

UI Animations:

  • AnimationDirective for entrance effects
  • ScrollTriggerDirective for scroll-based animations
  • ParallaxDirective for depth effects

UI Backgrounds:

  • GradientBackgroundComponent for dynamic backgrounds
  • ParticleBackgroundComponent for animated effects
  • VideoBackgroundComponent for video backgrounds

Phase 2: Feature Sections & Social Proof

Components to Implement

2.1 FeatureGrid Component (ui-lp-feature-grid)

Features:

  • Responsive grid layout using CSS Grid
  • Icon integration with FontAwesome
  • Card-based or minimal layouts
  • Hover animations using ui-animations

SCSS Pattern:

.ui-lp-feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: $semantic-spacing-grid-gap-lg;
  
  &__item {
    padding: $semantic-spacing-component-lg;
    background: $semantic-color-surface-elevated;
    border-radius: $semantic-border-card-radius;
    box-shadow: $semantic-shadow-card-rest;
    transition: all $semantic-motion-duration-fast $semantic-motion-easing-ease;
    
    &:hover {
      box-shadow: $semantic-shadow-card-hover;
      transform: translateY(-2px);
    }
  }
  
  &__icon {
    font-size: $semantic-sizing-icon-navigation;
    color: $semantic-color-primary;
    margin-bottom: $semantic-spacing-component-md;
  }
  
  &__title {
    font-family: map-get($semantic-typography-heading-h4, font-family);
    font-size: map-get($semantic-typography-heading-h4, font-size);
    font-weight: map-get($semantic-typography-heading-h4, font-weight);
    line-height: map-get($semantic-typography-heading-h4, line-height);
    color: $semantic-color-text-primary;
    margin-bottom: $semantic-spacing-component-sm;
  }
  
  &__description {
    font-family: map-get($semantic-typography-body-medium, font-family);
    font-size: map-get($semantic-typography-body-medium, font-size);
    font-weight: map-get($semantic-typography-body-medium, font-weight);
    line-height: map-get($semantic-typography-body-medium, line-height);
    color: $semantic-color-text-secondary;
  }
}

2.2 TestimonialCarousel Component (ui-lp-testimonials)

Leverages existing carousel functionality with custom testimonial card design.

2.3 LogoCloud Component (ui-lp-logo-cloud)

Implements partner/client logos with various display modes.

2.4 StatisticsDisplay Component (ui-lp-stats)

Animated number counters with intersection observer triggers.


Phase 3: Conversion Components

Components to Implement

3.1 PricingTable Component (ui-lp-pricing)

Features:

  • Monthly/yearly toggle with smooth transitions
  • Popular plan highlighting
  • Feature comparison matrix
  • Responsive card layout

Angular Implementation Pattern:

import { Component, Input, signal, computed } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SwitchComponent } from 'ui-essentials';
import { TableComponent } from 'ui-essentials';

@Component({
  selector: 'ui-lp-pricing',
  standalone: true,
  imports: [CommonModule, SwitchComponent, TableComponent],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div class="ui-lp-pricing">
      <div class="ui-lp-pricing__header">
        <h2 class="ui-lp-pricing__title">{{ title }}</h2>
        
        @if (showBillingToggle) {
          <div class="ui-lp-pricing__toggle">
            <span [class.active]="!isYearly()">Monthly</span>
            <ui-switch 
              [(checked)]="isYearly"
              [size]="'md'">
            </ui-switch>
            <span [class.active]="isYearly()">
              Yearly
              @if (yearlySavings) {
                <span class="ui-lp-pricing__badge">Save {{ yearlySavings }}%</span>
              }
            </span>
          </div>
        }
      </div>
      
      <div class="ui-lp-pricing__plans">
        @for (plan of plans(); track plan.id) {
          <div 
            class="ui-lp-pricing__plan"
            [class.ui-lp-pricing__plan--popular]="plan.popular">
            
            @if (plan.badge) {
              <div class="ui-lp-pricing__plan-badge">{{ plan.badge }}</div>
            }
            
            <h3 class="ui-lp-pricing__plan-name">{{ plan.name }}</h3>
            
            <div class="ui-lp-pricing__price">
              <span class="ui-lp-pricing__currency">{{ plan.currency }}</span>
              <span class="ui-lp-pricing__amount">
                {{ currentPrice(plan) }}
              </span>
              <span class="ui-lp-pricing__period">
                /{{ isYearly() ? 'year' : 'month' }}
              </span>
            </div>
            
            <ul class="ui-lp-pricing__features">
              @for (feature of plan.features; track feature.id) {
                <li class="ui-lp-pricing__feature"
                    [class.ui-lp-pricing__feature--included]="feature.included">
                  @if (feature.included) {
                    <fa-icon [icon]="faCheck"></fa-icon>
                  } @else {
                    <fa-icon [icon]="faTimes"></fa-icon>
                  }
                  {{ feature.text }}
                </li>
              }
            </ul>
            
            <ui-button
              [variant]="plan.popular ? 'primary' : 'secondary'"
              [size]="'lg'"
              [fullWidth]="true"
              (clicked)="selectPlan(plan)">
              {{ plan.ctaText || 'Get Started' }}
            </ui-button>
          </div>
        }
      </div>
    </div>
  `
})
export class PricingTableComponent {
  @Input() plans = signal<PricingPlan[]>([]);
  @Input() title = 'Choose Your Plan';
  @Input() showBillingToggle = true;
  @Input() yearlySavings = 20;
  
  isYearly = signal(false);
  
  currentPrice = computed(() => (plan: PricingPlan) => {
    return this.isYearly() ? plan.yearlyPrice : plan.monthlyPrice;
  });
  
  selectPlan(plan: PricingPlan): void {
    // Implementation
  }
}

3.2 CTASection Component (ui-lp-cta)

High-converting call-to-action sections with urgency indicators.

3.3 NewsletterSignup Component (ui-lp-newsletter)

Email capture with validation and success states.


Phase 4: Navigation & Layout

Components to Implement

4.1 LandingHeader Component (ui-lp-header)

Features:

  • Sticky navigation with scroll behavior
  • Transparent to solid transition
  • Mobile hamburger menu
  • Mega menu support

Comprehensive footer with multiple column layouts and newsletter integration.


Phase 5: Content & Templates

Content Components

5.1 FAQSection Component (ui-lp-faq)

Accordion-style FAQ with search functionality.

5.2 TeamGrid Component (ui-lp-team)

Team member cards with social links.

5.3 TimelineSection Component (ui-lp-timeline)

Visual timeline for roadmaps and milestones.

Page Templates

5.4 Complete Landing Page Templates

Pre-built templates combining all components:

  • SaaS Landing Page: Hero → Features → Social Proof → Pricing → CTA
  • Product Landing Page: Hero → Product Showcase → Reviews → Purchase
  • Agency Landing Page: Hero → Services → Portfolio → Team → Contact

Technical Implementation Guidelines

Performance Optimization

  • Lazy Loading: Use @defer for below-fold components
  • Image Optimization: Implement responsive images with srcset
  • Bundle Size: Tree-shakeable exports, <50kb per component
  • Critical CSS: Inline critical styles for above-fold content

Accessibility Requirements

  • ARIA Labels: Proper semantic HTML and ARIA attributes
  • Keyboard Navigation: Full keyboard support with visible focus
  • Screen Readers: Meaningful alt text and announcements
  • Color Contrast: Minimum 4.5:1 ratio for text

Testing Strategy

// Example test structure
describe('HeroSectionComponent', () => {
  let component: HeroSectionComponent;
  let fixture: ComponentFixture<HeroSectionComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [HeroSectionComponent]
    }).compileComponents();

    fixture = TestBed.createComponent(HeroSectionComponent);
    component = fixture.componentInstance;
  });

  it('should apply correct alignment class', () => {
    component.configuration = { 
      title: 'Test', 
      alignment: 'left' 
    };
    fixture.detectChanges();
    
    const element = fixture.nativeElement.querySelector('.ui-lp-hero');
    expect(element).toHaveClass('ui-lp-hero--left');
  });

  it('should emit CTA click events', () => {
    const spy = spyOn(component.ctaClicked, 'emit');
    const mockCTA = { 
      text: 'Click', 
      variant: 'primary' as const, 
      action: () => {} 
    };
    
    component.handleCTAClick(mockCTA);
    expect(spy).toHaveBeenCalledWith(mockCTA);
  });
});

Demo Application Integration

Each component will have a comprehensive demo in demo-ui-essentials:

// demos.routes.ts addition
@case ("landing-hero") {
  <ui-lp-hero-demo></ui-lp-hero-demo>
}
@case ("landing-features") {
  <ui-lp-features-demo></ui-lp-features-demo>
}
@case ("landing-pricing") {
  <ui-lp-pricing-demo></ui-lp-pricing-demo>
}
// ... etc

Build Configuration

// ng-package.json
{
  "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
  "dest": "../../dist/ui-landing-pages",
  "lib": {
    "entryFile": "src/public-api.ts"
  }
}

Quality Assurance Checklist

Design System Compliance

  • All colors from $semantic-color-* tokens only
  • All spacing from $semantic-spacing-* tokens only
  • Typography using map-get() for map tokens
  • Shadows from $semantic-shadow-* tokens only
  • Borders from $semantic-border-* tokens only
  • No hardcoded values anywhere

Angular 19 Standards

  • Standalone components throughout
  • New control flow syntax (@if, @for, @switch)
  • Signals for state management
  • OnPush change detection
  • Proper TypeScript typing

Component Quality

  • BEM class naming convention
  • Responsive design implemented
  • Accessibility standards met
  • Unit tests with >90% coverage
  • Demo component created
  • Public API exports added

Integration

  • Works with existing ui-essentials components
  • Leverages ui-animations directives
  • Uses ui-backgrounds where applicable
  • Follows workspace patterns

Implementation Timeline

Week 1-2: Foundation Setup

  • Library scaffolding and configuration
  • Hero components (3 variants)
  • Basic demo application integration

Week 3-4: Feature Components

  • Feature grid and showcase
  • Social proof components
  • Statistics and counters

Week 5-6: Conversion Components

  • Pricing tables
  • CTA sections
  • Newsletter signup
  • Contact forms

Week 7: Navigation & Layout

  • Landing page header
  • Footer variations
  • Sticky navigation

Week 8-9: Content & Templates

  • FAQ, Team, Timeline components
  • Complete page templates
  • Documentation

Week 10: Polish & Optimization

  • Performance optimization
  • Accessibility audit
  • Final testing
  • Documentation completion

Success Metrics

Development Metrics

  • 100% TypeScript coverage
  • Zero accessibility violations
  • All components use semantic tokens
  • Bundle size under 200kb total
  • Lighthouse score >95

Quality Metrics

  • All components have demos
  • Unit test coverage >90%
  • Documentation complete
  • No hardcoded values
  • Consistent API patterns

Conclusion

This implementation plan provides a comprehensive roadmap for building a production-ready ui-landing-pages library that:

  • Leverages Angular 19's latest features
  • Strictly adheres to the design token system
  • Integrates seamlessly with existing SSuite libraries
  • Provides high-quality, accessible components
  • Enables rapid landing page development

The library will empower developers to create professional, performant landing pages while maintaining consistency with the SSuite design system and development standards.