🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
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-h1throughh5(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-essentialscomponents - 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:
ButtonComponentfor CTAsContainerComponentfor responsive layoutImageComponentfor optimized image loadingFlexComponentfor flexible layouts
UI Animations:
AnimationDirectivefor entrance effectsScrollTriggerDirectivefor scroll-based animationsParallaxDirectivefor depth effects
UI Backgrounds:
GradientBackgroundComponentfor dynamic backgroundsParticleBackgroundComponentfor animated effectsVideoBackgroundComponentfor 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
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
@deferfor 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.