Theme Customizations
Suma Elementor v3.0.0 theme with 60+ custom widgets, Laravel Mix build system, and Preact integration.
Overview
The StealthCam site uses Suma Elementor v3.0.0, a custom WordPress theme developed by Rhino Group specifically for BigCommerce headless commerce integrations. Built on Elementor Pro, it provides 60+ specialized widgets and a modern build pipeline.
Theme Architecture
Directory Structure
suma-elementor/
├── style.css # Theme header (v3.0.0)
├── functions.php # Bootstrap and autoload
├── webpack.mix.js # Laravel Mix configuration
├── package.json # npm dependencies
├── composer.json # PHP dependencies
├── inc/
│ ├── class-setup.php # Theme setup hooks
│ ├── class-enqueue.php # Asset loading
│ ├── class-utils.php # Utility functions
│ ├── class-bigcommerce.php # BC integration helpers
│ ├── class-ajax-handlers.php # AJAX endpoints
│ ├── integrations/ # Third-party integrations
│ │ ├── class-facetwp.php
│ │ ├── class-algolia.php
│ │ └── class-klaviyo.php
│ └── widgets/ # Elementor custom widgets (60+)
│ ├── base/ # Base widget class
│ ├── bigcommerce/ # BC-specific widgets
│ ├── content/ # Content widgets
│ ├── navigation/ # Menu and navigation
│ └── utility/ # Utility widgets
├── templates/ # Template files
│ ├── header.php
│ ├── footer.php
│ ├── single-bigcommerce_product.php
│ ├── archive-bigcommerce_product.php
│ └── page-templates/
├── template-parts/ # Reusable template parts
├── assets/
│ ├── src/
│ │ ├── scss/ # Source SCSS files
│ │ │ ├── app.scss # Main stylesheet
│ │ │ ├── _variables.scss
│ │ │ ├── components/
│ │ │ └── layouts/
│ │ ├── js/ # Source JavaScript
│ │ │ ├── app.js # Main JS entry
│ │ │ ├── components/ # JS components
│ │ │ └── modules/ # Feature modules
│ │ └── preact/ # Preact components
│ │ ├── cart-widget.jsx
│ │ ├── product-card.jsx
│ │ └── variant-selector.jsx
│ └── dist/ # Compiled assets
│ ├── css/
│ │ ├── app.css
│ │ └── app.css.map
│ └── js/
│ ├── app.js
│ └── app.js.map
└── vendor/ # Composer dependencies
Technology Stack
- WordPress: 6.7.2+
- PHP: 7.4+ (PSR-4 autoloading)
- Elementor Pro: v3.28.2
- Laravel Mix: v6.0.39 - Build system
- Preact: v10.11.0 - Lightweight React alternative
- Tailwind CSS: v3.0.11 - Utility-first CSS
- Sass: SCSS compilation
- Babel: ES6+ transpilation
- Autoprefixer: Browser compatibility
Custom Elementor Widgets
The theme provides 60+ custom Elementor widgets organized by category. All widgets support Elementor's responsive controls, custom CSS, and conditional display.
BigCommerce Product Widgets (20+)
Product Grid
Widget ID: suma-product-grid
Category: BigCommerce
Display products in a customizable grid layout.
Features:
- Query builder (by category, brand, featured, etc.)
- Column controls (1-6 columns, responsive)
- Product card templates
- Pagination or load more
- Filter integration (FacetWP)
Style Controls:
- Card spacing
- Image aspect ratio
- Hover effects
- Button styling
- Price display options
Product Carousel
Widget ID: suma-product-carousel
Category: BigCommerce
Rotating product showcase with Swiper.js integration.
Features:
- Auto-play with configurable speed
- Navigation arrows
- Pagination dots
- Touch/swipe support
- Lazy loading
Single Product Components
Product Title (suma-product-title)
- Custom typography controls
- SKU display toggle
- Brand display option
Product Price (suma-product-price)
- Sale price highlighting
- Compare at price display
- Custom prefix/suffix text
- Currency formatting
Product Images (suma-product-images)
- Gallery with zoom
- Lightbox integration
- Thumbnail navigation
- Variant image switching
Product Description (suma-product-description)
- Tabbed or accordion layout
- Custom content sections
- Specifications table
- Video embed support
Add to Cart Button (suma-add-to-cart)
- Custom button text
- Quantity selector
- Success message display
- Cart drawer integration
- Loading states
Product Variants (suma-product-variants)
- Dropdown or swatch display
- Color/image swatches
- Stock status display
- Price updates on selection
- Preact-powered reactive UI
Related Products (suma-related-products)
- BC relationship queries
- Custom query fallback
- Grid or carousel display
- Limit products shown
Category & Brand Widgets
Category Grid (suma-category-grid)
- Display BC categories
- Custom images/icons
- Product count badges
- Category descriptions
- Custom links
Brand Showcase (suma-brand-showcase)
- Brand logo display
- Grid or carousel layout
- Link to brand archives
- Custom ordering
Featured Products (suma-featured-products)
- Query featured BC products
- Custom badges/labels
- Sale items highlighting
- Custom sorting
Navigation Widgets (8+)
Mega Menu
Widget ID: suma-mega-menu
Category: Navigation
Multi-column dropdown menu with categories, featured products, and custom content.
Features:
- Category columns with product counts
- Featured product showcases
- Custom HTML content areas
- Sticky menu support
- Mobile hamburger transformation
Configuration:
// Theme filter for menu structure
add_filter('suma_mega_menu_structure', function($structure) {
$structure['main'] = [
'categories' => get_categories(['taxonomy' => 'bigcommerce_category']),
'featured' => get_featured_products(4),
'promo_html' => '<div>Custom promo content</div>'
];
return $structure;
});
Breadcrumbs
Widget ID: suma-breadcrumbs
BC-aware breadcrumb navigation with schema markup.
Mobile Menu Toggle
Widget ID: suma-mobile-menu-toggle
Hamburger button with animation and off-canvas menu trigger.
Account Menu
Widget ID: suma-account-menu
User account dropdown with login/register links and BigCommerce account integration.
Cart Icon
Widget ID: suma-cart-icon
Animated cart icon with item count badge.
Features:
- Real-time cart count updates
- Cart drawer toggle
- Customizable icon library
- Badge styling controls
Search & Filter Widgets (10+)
FacetWP Facet List
Widget ID: suma-facetwp-facets
Display one or more FacetWP facets with custom styling.
Features:
- Select multiple facets
- Collapsible sections
- Mobile filter drawer
- Result count display
Algolia Search Box
Widget ID: suma-algolia-search
Instant search box with autocomplete.
Features:
- Custom placeholder text
- Icon styling
- Autocomplete dropdown
- Recent searches
- Popular searches
Sort Dropdown
Widget ID: suma-sort-dropdown
Product sorting control (price, name, newest, etc.)
Filter Button (Mobile)
Widget ID: suma-filter-button
Mobile-optimized button to reveal filters in drawer/modal.
Active Filters Display
Widget ID: suma-active-filters
Show currently applied filters with remove buttons.
Content Widgets (15+)
Hero Slider
Widget ID: suma-hero-slider
Full-width hero with multiple slides, parallax effects, and video backgrounds.
Features:
- Drag-and-drop slide builder
- Video backgrounds (YouTube, Vimeo, self-hosted)
- Parallax scrolling
- Ken Burns effect
- Custom CTA buttons per slide
- Autoplay controls
Content Tabs
Widget ID: suma-content-tabs
Tabbed content sections with customizable triggers.
Accordion
Widget ID: suma-accordion
Collapsible content panels with icon controls.
Icon Box
Widget ID: suma-icon-box
Icon/image with heading and description. Useful for features, benefits, USPs.
Testimonials
Widget ID: suma-testimonials
Customer testimonial slider with ratings, photos, and quotes.
Video Popup
Widget ID: suma-video-popup
Lightbox video player trigger with custom thumbnail.
Image Comparison
Widget ID: suma-image-compare
Before/after image slider with draggable divider.
Countdown Timer
Widget ID: suma-countdown
JavaScript countdown for sales, launches, events.
Instagram Feed
Widget ID: suma-instagram-feed
Display Instagram posts via API.
Blog Posts
Widget ID: suma-blog-posts
Custom WordPress post query with grid/list layouts.
Utility Widgets (7+)
Modal Trigger
Widget ID: suma-modal-trigger
Button/link that opens a modal popup with custom content.
Use Cases:
- Size charts
- Dealer locator
- Quick product views
- Newsletter signup
- Store policies
Custom Code
Widget ID: suma-custom-code
Raw HTML/CSS/JS injection with syntax highlighting editor.
Alert Bar
Widget ID: suma-alert-bar
Dismissible alert banner for announcements, promotions, shipping info.
Features:
- Sticky positioning
- Cookie-based dismissal
- Countdown integration
- Link/button support
Back to Top
Widget ID: suma-back-to-top
Smooth scroll to top button with reveal animation.
Lazy Load Container
Widget ID: suma-lazy-container
Wrapper that lazy loads child content on viewport intersection.
Laravel Mix Build System
Configuration
File: webpack.mix.js
const mix = require('laravel-mix');
mix
// Compile SCSS
.sass('assets/src/scss/app.scss', 'assets/dist/css')
.options({
postCss: [
require('tailwindcss')('./tailwind.config.js'),
require('autoprefixer')
]
})
// Compile JavaScript
.js('assets/src/js/app.js', 'assets/dist/js')
.babel(['assets/src/js/app.js'], 'assets/dist/js/app.js')
// Preact components
.js('assets/src/preact/index.jsx', 'assets/dist/js/preact.js')
.preact()
// Enable sourcemaps in development
.sourceMaps()
// Enable versioning in production
.version()
// BrowserSync for hot reload
.browserSync({
proxy: 'stealthcam.test',
files: [
'assets/dist/**/*',
'**/*.php',
'**/*.html'
]
});
NPM Scripts
File: package.json
{
"scripts": {
"dev": "npm run development",
"development": "mix",
"watch": "mix watch",
"watch-poll": "mix watch -- --watch-options-poll=1000",
"hot": "mix watch --hot",
"prod": "npm run production",
"production": "mix --production"
},
"devDependencies": {
"laravel-mix": "^6.0.39",
"sass": "^1.49.9",
"sass-loader": "^12.4.0",
"tailwindcss": "^3.0.11",
"autoprefixer": "^10.4.2",
"browser-sync": "^2.27.7",
"browser-sync-webpack-plugin": "^2.3.0",
"@babel/preset-react": "^7.16.7"
},
"dependencies": {
"preact": "^10.11.0",
"swiper": "^8.0.0",
"gsap": "^3.9.1"
}
}
Development Workflow
# Install dependencies
npm install
# Development mode (watch files, recompile on change)
npm run watch
# Production build (minified, optimized)
npm run production
# Hot module reload with BrowserSync
npm run hot
Asset Loading
File: inc/class-enqueue.php
public function enqueue_assets() {
// Get versioned asset path
$css_path = $this->get_asset_path('css/app.css');
$js_path = $this->get_asset_path('js/app.js');
$preact_path = $this->get_asset_path('js/preact.js');
// Enqueue styles
wp_enqueue_style(
'suma-elementor',
get_template_directory_uri() . '/assets/dist/' . $css_path,
[],
$this->get_asset_version($css_path)
);
// Enqueue scripts
wp_enqueue_script(
'suma-elementor',
get_template_directory_uri() . '/assets/dist/' . $js_path,
['jquery'],
$this->get_asset_version($js_path),
true
);
// Preact components (product pages only)
if (is_singular('bigcommerce_product')) {
wp_enqueue_script(
'suma-preact',
get_template_directory_uri() . '/assets/dist/' . $preact_path,
[],
$this->get_asset_version($preact_path),
true
);
}
}
Preact Integration
Purpose
Preact provides reactive UI components for dynamic product features (variant selection, cart updates, etc.) with minimal bundle size (~3KB vs React's ~40KB).
Component Structure
Location: assets/src/preact/
Cart Widget Component
File: assets/src/preact/cart-widget.jsx
import { h, Component } from 'preact';
import { getCart, updateCartItem, removeCartItem } from '../api/cart';
export default class CartWidget extends Component {
state = {
cart: null,
loading: true,
isOpen: false
};
componentDidMount() {
this.loadCart();
}
async loadCart() {
const cart = await getCart();
this.setState({ cart, loading: false });
}
async updateQuantity(itemId, quantity) {
this.setState({ loading: true });
await updateCartItem(itemId, quantity);
await this.loadCart();
}
async removeItem(itemId) {
this.setState({ loading: true });
await removeCartItem(itemId);
await this.loadCart();
}
toggleDrawer = () => {
this.setState({ isOpen: !this.state.isOpen });
};
render() {
const { cart, loading, isOpen } = this.state;
return (
<div class={`cart-widget ${isOpen ? 'is-open' : ''}`}>
<button
class="cart-toggle"
onClick={this.toggleDrawer}
>
<span class="cart-icon">🛒</span>
{cart && (
<span class="cart-count">{cart.item_count}</span>
)}
</button>
{isOpen && (
<div class="cart-drawer">
{loading ? (
<div class="cart-loading">Loading...</div>
) : cart && cart.items.length > 0 ? (
<>
<div class="cart-items">
{cart.items.map(item => (
<CartItem
key={item.id}
item={item}
onUpdate={this.updateQuantity}
onRemove={this.removeItem}
/>
))}
</div>
<div class="cart-footer">
<div class="cart-total">
Total: {cart.total}
</div>
<a href="/checkout" class="btn btn-primary">
Checkout
</a>
</div>
</>
) : (
<div class="cart-empty">Your cart is empty</div>
)}
</div>
)}
</div>
);
}
}
Product Variant Selector
File: assets/src/preact/variant-selector.jsx
import { h, Component } from 'preact';
export default class VariantSelector extends Component {
state = {
selectedOptions: {},
currentVariant: null,
price: this.props.basePrice
};
handleOptionChange = (optionId, valueId) => {
const selectedOptions = {
...this.state.selectedOptions,
[optionId]: valueId
};
this.setState({ selectedOptions });
this.updateVariant(selectedOptions);
};
updateVariant(selectedOptions) {
const { variants } = this.props;
// Find matching variant
const variant = variants.find(v =>
this.variantMatches(v, selectedOptions)
);
if (variant) {
this.setState({
currentVariant: variant,
price: variant.price
});
// Update product images if variant has specific images
if (variant.image_url) {
this.props.onVariantChange(variant);
}
}
}
variantMatches(variant, selectedOptions) {
return variant.option_values.every(ov =>
selectedOptions[ov.option_id] === ov.id
);
}
render() {
const { options } = this.props;
const { selectedOptions, price } = this.state;
return (
<div class="variant-selector">
{options.map(option => (
<div key={option.id} class="option-group">
<label class="option-label">{option.display_name}</label>
{option.type === 'swatch' ? (
<div class="swatch-grid">
{option.values.map(value => (
<button
key={value.id}
class={`swatch ${
selectedOptions[option.id] === value.id
? 'is-selected'
: ''
}`}
onClick={() =>
this.handleOptionChange(option.id, value.id)
}
style={{
backgroundColor: value.data?.colors?.[0]
}}
>
{value.label}
</button>
))}
</div>
) : (
<select
class="option-select"
onChange={(e) =>
this.handleOptionChange(
option.id,
parseInt(e.target.value)
)
}
>
<option value="">Select {option.display_name}</option>
{option.values.map(value => (
<option key={value.id} value={value.id}>
{value.label}
</option>
))}
</select>
)}
</div>
))}
<div class="variant-price">
${price}
</div>
</div>
);
}
}
Mounting Preact Components
File: assets/src/preact/index.jsx
import { h, render } from 'preact';
import CartWidget from './cart-widget';
import VariantSelector from './variant-selector';
// Mount cart widget
const cartMount = document.getElementById('cart-widget-mount');
if (cartMount) {
render(<CartWidget />, cartMount);
}
// Mount variant selector on product pages
const variantMount = document.getElementById('variant-selector-mount');
if (variantMount) {
const props = JSON.parse(variantMount.dataset.props || '{}');
render(<VariantSelector {...props} />, variantMount);
}
Tailwind CSS Integration
Configuration
File: tailwind.config.js
module.exports = {
content: [
'./templates/**/*.php',
'./template-parts/**/*.php',
'./inc/**/*.php',
'./assets/src/**/*.{js,jsx}',
],
theme: {
extend: {
colors: {
brand: {
primary: '#1a5f3f',
secondary: '#8b4513',
accent: '#f4a460'
}
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
display: ['Oswald', 'sans-serif']
},
spacing: {
'128': '32rem',
'144': '36rem'
}
}
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
require('@tailwindcss/aspect-ratio')
]
};
Usage in Widgets
Tailwind classes can be used directly in widget templates:
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<?php foreach ($products as $product) : ?>
<div class="bg-white rounded-lg shadow-md hover:shadow-xl transition-shadow">
<img src="<?php echo esc_url($product->image); ?>"
class="w-full h-64 object-cover rounded-t-lg">
<div class="p-4">
<h3 class="text-xl font-bold mb-2"><?php echo esc_html($product->name); ?></h3>
<p class="text-gray-600 mb-4"><?php echo esc_html($product->description); ?></p>
<div class="flex justify-between items-center">
<span class="text-2xl font-bold text-brand-primary">
$<?php echo esc_html($product->price); ?>
</span>
<button class="bg-brand-primary text-white px-4 py-2 rounded hover:bg-brand-secondary transition-colors">
Add to Cart
</button>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
Complete Widget List
BigCommerce Widgets (20)
suma-product-grid- Product grid displaysuma-product-carousel- Product slidersuma-product-title- Product title/SKUsuma-product-price- Price displaysuma-product-images- Image gallerysuma-product-description- Description tabssuma-add-to-cart- Add to cart buttonsuma-product-variants- Variant selectorsuma-related-products- Related productssuma-category-grid- Category displaysuma-brand-showcase- Brand logossuma-featured-products- Featured itemssuma-product-badge- Custom badgessuma-product-comparison- Compare productssuma-recently-viewed- Browsing historysuma-product-reviews- BazaarVoice integrationsuma-stock-status- Availability displaysuma-product-specifications- Specs tablesuma-product-video- Video gallerysuma-quick-view- Modal quick view
Navigation Widgets (8)
suma-mega-menu- Dropdown menusuma-breadcrumbs- Breadcrumb trailsuma-mobile-menu-toggle- Hamburger buttonsuma-account-menu- User account dropdownsuma-cart-icon- Cart with badgesuma-search-toggle- Search modal triggersuma-category-menu- Category navigationsuma-footer-menu- Footer links
Search & Filter Widgets (10)
suma-facetwp-facets- Filter displaysuma-algolia-search- Search boxsuma-sort-dropdown- Sort controlsuma-filter-button- Mobile filter buttonsuma-active-filters- Applied filterssuma-result-count- Search results countsuma-load-more- Load more buttonsuma-pagination- Pagination controlssuma-filter-drawer- Mobile filter drawersuma-search-suggestions- Search autocomplete
Content Widgets (15)
suma-hero-slider- Homepage herosuma-content-tabs- Tabbed contentsuma-accordion- Collapsible panelssuma-icon-box- Icon with textsuma-testimonials- Customer reviewssuma-video-popup- Video lightboxsuma-image-compare- Before/after slidersuma-countdown- Countdown timersuma-instagram-feed- Instagram postssuma-blog-posts- Blog gridsuma-team-members- Team showcasesuma-pricing-table- Pricing comparisonsuma-progress-bar- Animated progresssuma-image-hotspots- Interactive imagesuma-flip-box- Card flip animationsuma-call-to-action- CTA banner
Utility Widgets (7)
suma-modal-trigger- Modal popupsuma-custom-code- HTML/JS injectionsuma-alert-bar- Alert bannersuma-back-to-top- Scroll to topsuma-lazy-container- Lazy load wrappersuma-cookie-notice- GDPR cookie bannersuma-age-gate- Age verification modal
Theme Hooks & Filters
Product Display Filters
// Modify product card template
add_filter('suma_product_card_template', function($template, $product) {
// Custom template logic
return $template;
}, 10, 2);
// Add custom product badge
add_filter('suma_product_badge', function($badge, $product) {
if ($product->on_sale) {
$badge = '<span class="badge-sale">SALE</span>';
}
return $badge;
}, 10, 2);
// Customize price display
add_filter('suma_product_price_html', function($html, $product) {
// Custom price formatting
return $html;
}, 10, 2);
Cart & Checkout Hooks
// Before add to cart button
add_action('suma_before_add_to_cart', function($product) {
// Custom content before button
});
// After add to cart success
add_action('suma_after_add_to_cart_success', function($product, $cart) {
// Track analytics, show message, etc.
}, 10, 2);
Asset Loading Filters
// Disable default styles on specific pages
add_filter('suma_load_default_styles', function($load) {
if (is_page('custom-landing')) {
return false;
}
return $load;
});
Performance Optimizations
Asset Loading Strategy
- Critical CSS - Inline critical styles in
<head> - Deferred JavaScript - Non-critical JS loaded with
defer - Lazy Loading - Images and components loaded on viewport intersection
- Code Splitting - Separate bundles for different page types
- SVG Icons - Inline SVG sprite instead of icon fonts
Caching Strategy
- Object Cache - Redis/Memcached for database queries
- Page Cache - Full page caching via WP Rocket
- Asset Versioning - Cache busting with Mix versioning
- CDN Integration - Static assets served from CDN
Mobile Optimization
- Responsive Images -
srcsetandsizesattributes - Touch Gestures - Swipe support for carousels
- Reduced Motion - Respect
prefers-reduced-motion - Mobile-First CSS - Tailwind mobile-first breakpoints