Add landing pages library with comprehensive components and demos
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
810
UI_LANDING_PAGES_PLAN_UPDATED.md
Normal file
810
UI_LANDING_PAGES_PLAN_UPDATED.md
Normal file
@@ -0,0 +1,810 @@
|
||||
# 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
|
||||
```scss
|
||||
// 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**:
|
||||
```typescript
|
||||
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**:
|
||||
```scss
|
||||
@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**:
|
||||
```scss
|
||||
.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**:
|
||||
```typescript
|
||||
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
|
||||
|
||||
#### 4.2 FooterSection Component (`ui-lp-footer`)
|
||||
|
||||
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
|
||||
```typescript
|
||||
// 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`:
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```json
|
||||
// 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.
|
||||
Reference in New Issue
Block a user