FoundryKit

Composition Patterns

Advanced composition patterns for building complex layouts with FoundryKit blocks

Composition Patterns

Learn how to compose FoundryKit blocks to create complex, beautiful layouts and complete applications.

Basic Composition Patterns

Hero + Content Layout

Combine hero sections with content blocks for engaging landing pages:

import { HeroMinimal, Pricing, Testimonials } from '@foundrykit/blocks'

function HeroContentLayout() {
  return (
    <div className="min-h-screen">
      {/* Hero Section */}
      <HeroMinimal
        title="Transform Your Development Workflow"
        description="Build faster, ship sooner, and scale better with our comprehensive toolkit."
        ctaText="Get Started"
        secondaryCtaText="View Documentation"
        onCtaClick={() => window.location.href = '/signup'}
        onSecondaryCtaClick={() => window.location.href = '/docs'}
        className="min-h-screen"
      />
      
      {/* Content Sections */}
      <div className="space-y-32">
        {/* Features Section */}
        <section className="py-20 bg-gray-50">
          <div className="container mx-auto px-4">
            <div className="text-center mb-16">
              <h2 className="text-4xl font-bold mb-4">Why Choose FoundryKit</h2>
              <p className="text-xl text-gray-600 max-w-2xl mx-auto">
                Built for developers, by developers. Our blocks are designed to accelerate your workflow.
              </p>
            </div>
            
            <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
              <FeatureCard
                icon="⚡"
                title="Fast Development"
                description="Build applications quickly with our pre-built components"
              />
              <FeatureCard
                icon="🎨"
                title="Customizable"
                description="Easily customize components to match your design system"
              />
              <FeatureCard
                icon="✅"
                title="Production Ready"
                description="Built with best practices and accessibility in mind"
              />
            </div>
          </div>
        </section>
        
        {/* Pricing Section */}
        <section className="py-20">
          <Pricing
            plans={pricingPlans}
            title="Choose Your Plan"
            description="Select the perfect plan for your needs"
            onPlanSelect={handlePlanSelect}
          />
        </section>
        
        {/* Testimonials Section */}
        <section className="py-20 bg-gray-50">
          <Testimonials
            testimonials={testimonials}
            title="What Our Customers Say"
            description="Join thousands of developers who trust FoundryKit"
          />
        </section>
      </div>
    </div>
  )
}

function FeatureCard({ icon, title, description }) {
  return (
    <div className="text-center p-6 bg-white rounded-lg shadow-sm">
      <div className="text-4xl mb-4">{icon}</div>
      <h3 className="text-xl font-semibold mb-2">{title}</h3>
      <p className="text-gray-600">{description}</p>
    </div>
  )
}

Sidebar + Main Content Layout

Create layouts with sidebars and main content areas:

import { HeroMinimal, Pricing } from '@foundrykit/blocks'

function SidebarLayout() {
  return (
    <div className="flex min-h-screen">
      {/* Sidebar */}
      <aside className="w-64 bg-gray-900 text-white p-6">
        <div className="mb-8">
          <h1 className="text-xl font-bold">FoundryKit</h1>
        </div>
        
        <nav className="space-y-2">
          <a href="#hero" className="block py-2 px-3 rounded hover:bg-gray-800">Hero</a>
          <a href="#features" className="block py-2 px-3 rounded hover:bg-gray-800">Features</a>
          <a href="#pricing" className="block py-2 px-3 rounded hover:bg-gray-800">Pricing</a>
          <a href="#testimonials" className="block py-2 px-3 rounded hover:bg-gray-800">Testimonials</a>
        </nav>
      </aside>
      
      {/* Main Content */}
      <main className="flex-1">
        <div id="hero">
          <HeroMinimal
            title="Welcome to FoundryKit"
            description="Build amazing applications with our comprehensive toolkit."
            ctaText="Get Started"
            onCtaClick={() => console.log('CTA clicked')}
          />
        </div>
        
        <div id="pricing" className="py-20">
          <Pricing
            plans={pricingPlans}
            onPlanSelect={handlePlanSelect}
          />
        </div>
      </main>
    </div>
  )
}

Advanced Composition Patterns

Conditional Block Rendering

Render blocks conditionally based on user state or preferences:

import { HeroMinimal, Pricing, Testimonials } from '@foundrykit/blocks'
import { useState, useEffect } from 'react'

function ConditionalLayout({ user, preferences }) {
  const [showPricing, setShowPricing] = useState(false)
  const [showTestimonials, setShowTestimonials] = useState(true)

  useEffect(() => {
    // Show pricing for non-subscribed users
    setShowPricing(!user?.isSubscribed)
    
    // Show testimonials based on user preference
    setShowTestimonials(preferences?.showSocialProof !== false)
  }, [user, preferences])

  return (
    <div className="min-h-screen">
      <HeroMinimal
        title="Welcome Back!"
        description={user?.isSubscribed 
          ? "Continue building with your premium features."
          : "Upgrade to unlock all features."
        }
        ctaText={user?.isSubscribed ? "Continue Building" : "Upgrade Now"}
        onCtaClick={() => {
          if (user?.isSubscribed) {
            window.location.href = '/dashboard'
          } else {
            window.location.href = '/pricing'
          }
        }}
      />
      
      {showPricing && (
        <section className="py-20">
          <Pricing
            plans={pricingPlans}
            title="Upgrade Your Plan"
            description="Unlock premium features and accelerate your development"
            onPlanSelect={handlePlanSelect}
          />
        </section>
      )}
      
      {showTestimonials && (
        <section className="py-20 bg-gray-50">
          <Testimonials
            testimonials={testimonials}
            title="What Our Customers Say"
            description="Join thousands of developers who trust FoundryKit"
          />
        </section>
      )}
    </div>
  )
}

Dynamic Block Composition

Create dynamic layouts that adapt to content or user interactions:

import { HeroMinimal, Pricing, Testimonials } from '@foundrykit/blocks'
import { useState, useMemo } from 'react'

function DynamicLayout({ sections, userPreferences }) {
  const [activeSections, setActiveSections] = useState(sections)
  const [layoutMode, setLayoutMode] = useState('default')

  // Dynamically compose sections based on user preferences
  const composedSections = useMemo(() => {
    return activeSections.map(section => {
      switch (section.type) {
        case 'hero':
          return (
            <section key={section.id} className="min-h-screen">
              <HeroMinimal
                title={section.title}
                description={section.description}
                ctaText={section.ctaText}
                onCtaClick={section.onCtaClick}
                className={layoutMode === 'compact' ? 'min-h-[60vh]' : 'min-h-screen'}
              />
            </section>
          )
        
        case 'pricing':
          return (
            <section key={section.id} className="py-20">
              <Pricing
                plans={section.plans}
                title={section.title}
                description={section.description}
                onPlanSelect={section.onPlanSelect}
                layout={layoutMode === 'compact' ? 'list' : 'grid'}
              />
            </section>
          )
        
        case 'testimonials':
          return (
            <section key={section.id} className="py-20 bg-gray-50">
              <Testimonials
                testimonials={section.testimonials}
                title={section.title}
                description={section.description}
                layout={layoutMode === 'compact' ? 'list' : 'grid'}
                maxTestimonials={layoutMode === 'compact' ? 3 : undefined}
              />
            </section>
          )
        
        default:
          return null
      }
    })
  }, [activeSections, layoutMode])

  return (
    <div className="min-h-screen">
      {/* Layout Controls */}
      <div className="fixed top-4 right-4 z-50 bg-white rounded-lg shadow-lg p-4">
        <div className="space-y-2">
          <label className="block text-sm font-medium">Layout Mode</label>
          <select
            value={layoutMode}
            onChange={(e) => setLayoutMode(e.target.value)}
            className="w-full px-3 py-1 border rounded text-sm"
          >
            <option value="default">Default</option>
            <option value="compact">Compact</option>
            <option value="spacious">Spacious</option>
          </select>
        </div>
      </div>
      
      {/* Dynamic Sections */}
      {composedSections}
    </div>
  )
}

// Usage
const sections = [
  {
    id: 'hero-1',
    type: 'hero',
    title: 'Welcome to Our Platform',
    description: 'Build amazing applications with our toolkit.',
    ctaText: 'Get Started',
    onCtaClick: () => console.log('Hero CTA')
  },
  {
    id: 'pricing-1',
    type: 'pricing',
    plans: pricingPlans,
    title: 'Choose Your Plan',
    description: 'Select the perfect plan for your needs',
    onPlanSelect: handlePlanSelect
  },
  {
    id: 'testimonials-1',
    type: 'testimonials',
    testimonials: testimonials,
    title: 'What Our Customers Say',
    description: 'Join thousands of developers who trust us'
  }
]

<DynamicLayout sections={sections} userPreferences={preferences} />

Responsive Block Composition

Create layouts that adapt to different screen sizes:

import { HeroMinimal, Pricing, Testimonials } from '@foundrykit/blocks'
import { useMediaQuery } from '@foundrykit/hooks'

function ResponsiveLayout() {
  const isMobile = useMediaQuery('(max-width: 768px)')
  const isTablet = useMediaQuery('(min-width: 769px) and (max-width: 1024px)')
  const isDesktop = useMediaQuery('(min-width: 1025px)')

  return (
    <div className="min-h-screen">
      {/* Hero Section - Different layouts for different screen sizes */}
      <section className="relative">
        {isMobile ? (
          <HeroMinimal
            title="Mobile-First Design"
            description="Optimized for mobile devices with touch-friendly interactions."
            ctaText="Get Started"
            onCtaClick={() => console.log('Mobile CTA')}
            className="min-h-[80vh] px-4"
            titleClassName="text-3xl font-bold mb-4"
            descriptionClassName="text-lg mb-6"
          />
        ) : isTablet ? (
          <HeroMinimal
            title="Tablet-Optimized Experience"
            description="Perfect balance of content and interaction for tablet users."
            ctaText="Get Started"
            secondaryCtaText="Learn More"
            onCtaClick={() => console.log('Tablet CTA')}
            onSecondaryCtaClick={() => console.log('Tablet Secondary CTA')}
            className="min-h-screen px-8"
            titleClassName="text-4xl font-bold mb-6"
            descriptionClassName="text-xl mb-8"
          />
        ) : (
          <HeroMinimal
            title="Desktop Power User Experience"
            description="Full-featured experience with advanced interactions and rich content."
            ctaText="Get Started"
            secondaryCtaText="View Documentation"
            onCtaClick={() => console.log('Desktop CTA')}
            onSecondaryCtaClick={() => console.log('Desktop Secondary CTA')}
            className="min-h-screen px-16"
            titleClassName="text-5xl font-bold mb-8"
            descriptionClassName="text-2xl mb-10"
          />
        )}
      </section>
      
      {/* Content Sections - Responsive spacing */}
      <div className={`space-y-${isMobile ? '16' : isTablet ? '24' : '32'}`}>
        {/* Pricing Section */}
        <section className={`py-${isMobile ? '12' : isTablet ? '16' : '20'}`}>
          <Pricing
            plans={pricingPlans}
            title="Choose Your Plan"
            description="Select the perfect plan for your needs"
            onPlanSelect={handlePlanSelect}
            layout={isMobile ? 'list' : 'grid'}
          />
        </section>
        
        {/* Testimonials Section */}
        <section className={`py-${isMobile ? '12' : isTablet ? '16' : '20'} bg-gray-50`}>
          <Testimonials
            testimonials={testimonials}
            title="What Our Customers Say"
            description="Join thousands of developers who trust FoundryKit"
            layout={isMobile ? 'list' : 'grid'}
            maxTestimonials={isMobile ? 2 : isTablet ? 3 : undefined}
          />
        </section>
      </div>
    </div>
  )
}

Layout Composition Patterns

Grid-Based Layouts

Create grid-based layouts for content organization:

import { HeroMinimal, Pricing, Testimonials } from '@foundrykit/blocks'

function GridLayout() {
  return (
    <div className="min-h-screen">
      {/* Full-width hero */}
      <div className="col-span-full">
        <HeroMinimal
          title="Grid-Based Layout"
          description="Organize content in a structured grid system."
          ctaText="Explore Grid"
          onCtaClick={() => console.log('Grid CTA')}
        />
      </div>
      
      {/* Grid container */}
      <div className="grid grid-cols-1 lg:grid-cols-12 gap-8 p-8">
        {/* Sidebar */}
        <aside className="lg:col-span-3">
          <div className="bg-gray-50 p-6 rounded-lg">
            <h3 className="text-lg font-semibold mb-4">Navigation</h3>
            <nav className="space-y-2">
              <a href="#pricing" className="block py-2 px-3 rounded hover:bg-gray-100">Pricing</a>
              <a href="#testimonials" className="block py-2 px-3 rounded hover:bg-gray-100">Testimonials</a>
              <a href="#features" className="block py-2 px-3 rounded hover:bg-gray-100">Features</a>
            </nav>
          </div>
        </aside>
        
        {/* Main content */}
        <main className="lg:col-span-9 space-y-16">
          {/* Pricing section */}
          <section id="pricing">
            <Pricing
              plans={pricingPlans}
              title="Choose Your Plan"
              description="Select the perfect plan for your needs"
              onPlanSelect={handlePlanSelect}
            />
          </section>
          
          {/* Testimonials section */}
          <section id="testimonials">
            <Testimonials
              testimonials={testimonials}
              title="What Our Customers Say"
              description="Join thousands of developers who trust FoundryKit"
            />
          </section>
        </main>
      </div>
    </div>
  )
}

Masonry-Style Layouts

Create masonry-style layouts for dynamic content:

import { HeroMinimal, Pricing, Testimonials } from '@foundrykit/blocks'

function MasonryLayout() {
  return (
    <div className="min-h-screen">
      {/* Hero at top */}
      <HeroMinimal
        title="Masonry Layout"
        description="Dynamic content organization with flexible positioning."
        ctaText="Explore Layout"
        onCtaClick={() => console.log('Masonry CTA')}
        className="min-h-[60vh]"
      />
      
      {/* Masonry container */}
      <div className="columns-1 md:columns-2 lg:columns-3 gap-8 p-8">
        {/* Pricing card */}
        <div className="break-inside-avoid mb-8">
          <Pricing
            plans={pricingPlans.slice(0, 2)} // Show fewer plans in masonry
            title="Pricing"
            onPlanSelect={handlePlanSelect}
            className="bg-white rounded-lg shadow-lg"
          />
        </div>
        
        {/* Testimonials card */}
        <div className="break-inside-avoid mb-8">
          <Testimonials
            testimonials={testimonials.slice(0, 2)} // Show fewer testimonials
            title="Testimonials"
            layout="list"
            className="bg-white rounded-lg shadow-lg p-6"
          />
        </div>
        
        {/* Feature card */}
        <div className="break-inside-avoid mb-8">
          <div className="bg-white rounded-lg shadow-lg p-6">
            <h3 className="text-xl font-semibold mb-4">Features</h3>
            <div className="space-y-3">
              <div className="flex items-center">
                <span className="w-2 h-2 bg-green-500 rounded-full mr-3"></span>
                <span>Fast Development</span>
              </div>
              <div className="flex items-center">
                <span className="w-2 h-2 bg-green-500 rounded-full mr-3"></span>
                <span>Customizable</span>
              </div>
              <div className="flex items-center">
                <span className="w-2 h-2 bg-green-500 rounded-full mr-3"></span>
                <span>Production Ready</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

Next Steps