Skip to main content

Blocks

Pre-built page sections for common storefront layouts. These are larger compositions that combine multiple elements into complete sections.

Hero

Store hero section with logo, title, description, and stats.
// @validate
import { Hero } from '@shoppex/ui';
import type { Shop, Product } from '@shoppex/sdk';

const store = {
  id: 'shop_123',
  name: 'My Store',
  slug: 'my-store',
  currency: 'USD',
} satisfies Shop;

const products: Product[] = [];

export function Example() {
  return <Hero store={store} products={products} />;
}

Props

store
Shop
required
Store object from SDK
products
Product[]
default:"[]"
Products array (used for stats)
stats
HeroStat[]
Custom stats to display
showStats
boolean
default:"true"
Show statistics bar
Show “Visit Website” link if store has URL
showRatingBadge
boolean
default:"true"
Show star badge on logo if rated

Title Highlighting

Use curly braces in the store title to highlight text:
"Welcome to {Our Store}" → "Welcome to Our Store"
                                       ^^^^^^^^^ (muted color)

Custom Stats

// @validate
import { Hero } from '@shoppex/ui';
import type { Shop } from '@shoppex/sdk';

const store = {
  id: 'shop_123',
  name: 'My Store',
  slug: 'my-store',
  currency: 'USD',
} satisfies Shop;

<Hero
  store={store}
  stats={[
    { label: 'CUSTOMERS', value: '10k+' },
    { label: 'PRODUCTS', value: '500+' },
    { label: 'RATING', value: '4.9' },
  ]}
/>
// @validate
import { Hero } from '@shoppex/ui';
import type { Shop } from '@shoppex/sdk';

const store = {
  id: 'shop_123',
  name: 'My Store',
  slug: 'my-store',
  currency: 'USD',
  logo: 'https://cdn.example.com/logo.png',
} satisfies Shop;

<Hero
  store={store}
  renderLogo={(store) => (
    <img
      src={store.logo}
      alt={store.name}
      className="custom-logo-class"
    />
  )}
/>

ProductGrid

Responsive product grid with optional filtering and sorting.
// @validate
import { ProductGrid } from '@shoppex/ui';
import type { Product } from '@shoppex/sdk';

const products: Product[] = [];

export function Example() {
  return <ProductGrid products={products} />;
}

Props

products
Product[]
required
Products to display
columns
1 | 2 | 3 | 4 | 5 | 6
default:"4"
Number of grid columns
gap
'sm' | 'md' | 'lg'
default:"'md'"
Gap between cards
showFilters
boolean
default:"false"
Show category filter buttons
showSort
boolean
default:"false"
Show sort dropdown
hideOutOfStock
boolean
default:"false"
Hide out of stock products
getProductHref
(product: Product) => string
Generate product link URL
Custom link component

With Filters and Sort

// @validate
import { ProductGrid } from '@shoppex/ui';
import type { Product } from '@shoppex/sdk';

const products: Product[] = [];

<ProductGrid
  products={products}
  showFilters
  showSort
  initialSort="newest"
  hideOutOfStock
/>

Custom Rendering

// @validate
import { ProductGrid } from '@shoppex/ui';
import type { Product } from '@shoppex/sdk';

const products: Product[] = [];

function CustomProductCard({ product }: { product: Product; priority?: boolean }) {
  return <div>{product.title}</div>;
}

<ProductGrid
  products={products}
  renderProduct={(product, index) => (
    <CustomProductCard
      key={product.uniqid}
      product={product}
      priority={index < 4}
    />
  )}
/>

Loading State

// @validate
import { ProductGrid, ProductGridSkeleton } from '@shoppex/ui';
import type { Product } from '@shoppex/sdk';

const isLoading = false;
const products: Product[] = [];

export function Example() {
  return isLoading ? (
    <ProductGridSkeleton count={8} columns={4} />
  ) : (
    <ProductGrid products={products} />
  );
}

WhyChooseUs

Trust/features section with bento grid layout.
// @validate
import { WhyChooseUs } from '@shoppex/ui';

export function Example() {
  return <WhyChooseUs />;
}

Props

title
string
default:"'Why Choose Us?'"
Section title
subtitle
string
Section subtitle
mainFeature
object
Large feature card on the left
features
FeatureItem[]
Smaller feature cards on the right
layout
'bento' | 'grid' | 'list'
default:"'bento'"
Layout style

Custom Features

// @validate
import { WhyChooseUs } from '@shoppex/ui';
import { Shield, Zap, Star, Lock } from '@shoppex/ui/blocks';

export function Example() {
  return (
    <WhyChooseUs
      title="Why Shop With Us?"
      mainFeature={{
        icon: Zap,
        title: 'Lightning Fast',
        description: 'Get your products instantly.',
        stats: [
          { value: '50ms', label: 'Delivery' },
          { value: '100%', label: 'Uptime' },
        ],
        backgroundText: '24',
      }}
      features={[
        {
          icon: Shield,
          title: 'Secure',
          description: 'Bank-level encryption.',
        },
        {
          icon: Star,
          title: 'Quality',
          description: 'Premium products only.',
        },
        {
          icon: Lock,
          title: 'Private',
          description: 'Your data stays yours.',
        },
      ]}
    />
  );
}

Layout Options

Large card on left, 2x2 grid on right

FAQ

Accordion FAQ section.
// @validate
import { FAQ } from '@shoppex/ui';

export function Example() {
  return (
    <FAQ
      title="Frequently Asked Questions"
      items={[
        {
          question: 'How do I receive my purchase?',
          answer: 'After completing your purchase, you will receive an email...',
        },
        {
          question: 'What payment methods do you accept?',
          answer: 'We accept all major credit cards, PayPal, and crypto.',
        },
      ]}
    />
  );
}

Props

items
FAQItem[]
required
FAQ items to display
title
string
Section title
subtitle
string
Section subtitle
allowMultiple
boolean
default:"false"
Allow multiple items open at once
defaultOpenIndex
number
Index of item to open by default
layout
'default' | 'cards' | 'minimal'
default:"'default'"
Visual style

Default FAQ Items

// @validate
import { FAQ, defaultFAQItems } from '@shoppex/ui';

export function Example() {
  return (
    <>
      <FAQ items={defaultFAQItems} />
      <FAQ items={[...defaultFAQItems, { question: 'Custom?', answer: 'Yes!' }]} />
    </>
  );
}

Store footer with links and social icons.
// @validate
import { Footer } from '@shoppex/ui';
import type { Shop } from '@shoppex/sdk';

const store = {
  id: 'shop_123',
  name: 'My Store',
  slug: 'my-store',
  currency: 'USD',
} satisfies Shop;

export function Example() {
  return <Footer store={store} />;
}

Props

store
Shop
Store object (extracts name, logo, socials)
sections
FooterSection[]
Link sections
Custom copyright text
showPoweredBy
boolean
default:"true"
Show “Powered by Shoppex” link
Override social links
// @validate
import { Footer } from '@shoppex/ui';
import type { Shop } from '@shoppex/sdk';

const store = {
  id: 'shop_123',
  name: 'My Store',
  slug: 'my-store',
  currency: 'USD',
} satisfies Shop;

<Footer
  store={store}
  sections={[
    {
      title: 'Products',
      links: [
        { label: 'All Products', href: '/' },
        { label: 'New Arrivals', href: '/new' },
        { label: 'Best Sellers', href: '/best' },
      ],
    },
    {
      title: 'Support',
      links: [
        { label: 'Contact Us', href: '/contact' },
        { label: 'FAQ', href: '/faq' },
        { label: 'Terms', href: '/terms', external: true },
      ],
    },
  ]}
/>
// @validate
import { Footer } from '@shoppex/ui';
import type { Shop } from '@shoppex/sdk';

const store = {
  id: 'shop_123',
  name: 'My Store',
  slug: 'my-store',
  currency: 'USD',
} satisfies Shop;

<Footer
  store={store}
  copyright={
    <>
      © 2024 My Store. Built with{' '}
      <a href="https://shoppex.io">Shoppex</a>
    </>
  }
/>