Skip to main content

Overview

The ProductSection component displays product showcases with alternating layouts, automatic image rotation, and flexible content types (features or categories). It’s designed to highlight PROVESA’s main product lines with rich visual presentations.

Import

import ProductSection from '$lib/components/ProductSection.svelte';

Props

dbProducts
array
default:"[]"
Array of product objects from the database. If empty, displays two default products (Arroz Premium Salguero and Abarrotes category).Product Structure:
{
  id: number;
  name: string;                    // Product name/title
  description: string;             // Product description
  images: string[];                // Array of image URLs for slider
  align: 'left' | 'right';        // Layout alignment
  accentColor: 'primary' | 'accent'; // Color theme
  displayType: 'features' | 'categories'; // Content display mode
  
  // For displayType: 'features'
  features?: Array<{
    title: string;
    desc: string;
  }>;
  
  // For displayType: 'categories'
  categories?: Array<{
    num: string;      // e.g., '01', '02'
    name: string;     // Category name
    desc: string;     // Category description
  }>;
}

Usage

Basic Usage with Database Products

<script>
  let { data } = $props();
</script>

<ProductSection dbProducts={data.products} />

Default Behavior (No Products)

<ProductSection />
Displays two default products:
  1. Arroz Premium Salguero (features mode)
  2. Abarrotes category overview (categories mode)

Custom Product

<script>
  const products = [
    {
      id: 1,
      name: 'Arroz Premium',
      description: 'El mejor arroz para tu familia.',
      images: [
        'https://example.com/rice1.jpg',
        'https://example.com/rice2.jpg'
      ],
      features: [
        { title: 'Grano Largo', desc: 'Perfecta cocción' },
        { title: 'Alta Calidad', desc: 'Selección premium' }
      ],
      align: 'left',
      accentColor: 'primary',
      displayType: 'features'
    }
  ];
</script>

<ProductSection dbProducts={products} />

Display Types

Features Mode

Displays a list of product features with icons:
displayType: 'features'
features: [
  { title: 'Grano Largo y Envejecido', desc: 'Perfecto para cocción uniforme.' },
  { title: 'Ideal para el Hogar', desc: 'Presentaciones de 1kg, 2kg y 5kg.' },
  { title: 'Distribución Directa', desc: 'Llegamos a tu negocio sin intermediarios.' }
]
Each feature is displayed with:
  • Icon from featureIcons array (BadgeCheck, ShoppingBasket, Truck, Award)
  • Feature title (bold)
  • Feature description (smaller text)

Categories Mode

Displays numbered category cards:
displayType: 'categories'
categories: [
  { num: '01', name: 'Aceites', desc: 'Variedad de marcas y presentaciones.' },
  { num: '02', name: 'Azúcar', desc: 'Distribución directa de ingenios.' },
  { num: '03', name: 'Harinas', desc: 'Para panificación y uso doméstico.' },
  { num: '04', name: 'Granos', desc: 'Lentejas, frejoles y más.' }
]
Each category is displayed as a card with:
  • Large numbered badge (01, 02, etc.)
  • Category name
  • Brief description

Layout Alignment

Left Alignment

align: 'left'
  • Image on the left side
  • Text content on the right side
  • Default rotation: -rotate-2

Right Alignment

align: 'right'
  • Image on the right side (using order-2)
  • Text content on the left side (using order-1)
  • Rotation: rotate-2

Image Slider

Each product features an automatic image slider:

Automatic Rotation

onMount(() => {
  products.forEach((_, i) => {
    const interval = setInterval(
      () => nextImage(i, products[i].images?.length || 1),
      4000 + i * 500  // Staggered timing
    );
    intervals.push(interval);
  });
  return () => intervals.forEach(clearInterval);
});
  • Each product’s slider rotates independently
  • Base interval: 4 seconds
  • Staggered by 500ms per product to avoid simultaneous transitions

Slider Controls

Dot navigation appears at the bottom of each image:
{#each product.images as _, j}
  <button
    onclick={() => (imageIndexes[i] = j)}
    class="rounded-full transition-all duration-300
           {imageIndexes[i] === j ? 'h-2 w-8 bg-white shadow-lg' : 'h-2 w-2 bg-white/50'}"
  >
  </button>
{/each}

Smooth Transitions

Images fade and scale during transitions:
transition-all duration-[1200ms] ease-in-out
opacity-100 scale-100 (active)
opacity-0 scale-105 (inactive)

Accent Colors

Primary Accent

accentColor: 'primary'
  • Blue color scheme
  • Badge: “Producto Estrella” with Award icon
  • Primary blue decorative elements

Secondary Accent

accentColor: 'accent'
  • Orange/warm color scheme
  • Badge: “Abarrotes” with ShoppingBasket icon
  • Accent orange decorative elements

Visual Effects

Decorative Background Elements

Floating gradient orbs provide subtle visual interest:
<!-- Top right -->
<div class="absolute -top-40 -right-40 h-96 w-96 rounded-full 
            bg-primary/[0.03] blur-3xl"></div>

<!-- Bottom left -->
<div class="absolute -bottom-40 -left-40 h-96 w-96 rounded-full 
            bg-secondary/[0.05] blur-3xl"></div>

Rotated Background Card

Each product image has a rotated background card:
<div class="absolute -inset-3 rounded-[2rem] transition-transform 
            duration-700 group-hover:rotate-0
            {product.align === 'left' 
              ? '-rotate-2 bg-gradient-to-br from-primary/10 to-primary/5' 
              : 'rotate-2 bg-gradient-to-br from-secondary/15 to-accent/5'}"
></div>
Rotation straightens on hover for a subtle interaction effect.

Image Container Effects

  • Shadow: shadow-2xl shadow-slate-200/80
  • Ring: ring-1 ring-black/5
  • Hover scale: group-hover:scale-[1.01]
  • Rounded corners: rounded-3xl

Section Header

The section includes a styled header:
<div class="mb-20 max-w-2xl md:mb-28">
  <span class="text-sm font-bold tracking-widest text-primary uppercase">
    Nuestros Productos
  </span>
  <h2 class="text-4xl font-extrabold text-slate-900 md:text-5xl">
    Tu Despensa <span class="text-primary">Completa</span>
  </h2>
  <!-- Decorative lines -->
  <div class="flex items-center gap-2">
    <div class="h-1.5 w-16 rounded-full bg-secondary"></div>
    <div class="h-1.5 w-6 rounded-full bg-accent"></div>
    <div class="h-1.5 w-3 rounded-full bg-primary/30"></div>
  </div>
  <p class="text-lg text-slate-500 md:text-xl">
    Desde el ahorro para tu hogar hasta el abastecimiento de tu negocio.
  </p>
</div>

Responsive Design

Mobile (< 768px)

  • Single column layout
  • Full-width images
  • Text below images
  • 2-column category grid

Tablet/Desktop (≥ 768px)

  • Two-column grid
  • Side-by-side image and text
  • Alternating layouts based on align
  • Larger spacing and typography

Feature Icons

Rotates through four icons for features:
const featureIcons = [BadgeCheck, ShoppingBasket, Truck, Award];
Icon assignment: featureIcons[fi % featureIcons.length]

Real-World Example

From routes/+page.svelte:
<script>
  import ProductSection from '$lib/components/ProductSection.svelte';
  
  let { data } = $props();
</script>

<ProductSection dbProducts={data.products} />

Performance Considerations

  • Images are preloaded but hidden with opacity
  • Staggered intervals prevent simultaneous transitions
  • Intervals are properly cleaned up on component unmount
  • Smooth transitions use GPU-accelerated properties (opacity, transform)

Dependencies

  • lucide-svelte - BadgeCheck, ShoppingBasket, Truck, Award icons
  • svelte - onMount lifecycle function