Skip to main content

Blocks

Pre-built page sections for common storefront layouts. These are larger compositions that combine multiple elements into complete sections.
These blocks are for custom React storefronts outside Shoppex hosting. Hosted Shoppex themes use Liquid templates and the platform commerce runtime.

Hero

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

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 '@shoppexio/storefront';

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 '@shoppexio/storefront';

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 '@shoppexio/storefront';

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 '@shoppexio/storefront';

const products: Product[] = [];

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

Custom Rendering

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

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 '@shoppexio/storefront';

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 '@shoppexio/storefront';

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 '@shoppexio/storefront';

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 '@shoppexio/storefront';

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>
    </>
  }
/>