Weaverse LogoWeaverse
All ArticlesLee
5 mins read

How to Set Up Color Swatches in Your Shopify Hydrogen Store

How to Set Up Color Swatches in Your Shopify Hydrogen Store If you're building a Hydrogen storefront with variant-heavy catalogs, swatches are one of the highest-impact UX improvements you can ship quickly. This guide walks through the full implement...
#frontend#-hydrogen-#shopify#shopify-development

How to Set Up Color Swatches in Your Shopify Hydrogen Store

If you're building a Hydrogen storefront with variant-heavy catalogs, swatches are one of the highest-impact UX improvements you can ship quickly. This guide walks through the full implementation path from Shopify Admin setup to production-ready React components.

Color swatches transform the shopping experience by allowing customers to visualize product variants at a glance. Instead of reading through dropdown menus, customers see the actual colors—making purchase decisions faster and more intuitive.

In this comprehensive tutorial, we'll walk through implementing color swatches in a Shopify Hydrogen store, from configuring the data in Shopify Admin to rendering the swatches in your React components using the modern optionValues API (released in 2024-07).

Part 1: Setting Up Swatches in Shopify Admin

Step 1: Access Product Variant Options

  1. Log in to your Shopify Admin

  2. Navigate to Products → Select a product with color variants

  3. Scroll to the Variants section

  4. Click Edit Options next to the "Color" option

Step 2: Configure Swatch Data

For each color value, you can set:

Swatch TypeWhen to UseExample
Solid Color (Hex)Single, uniform colors#FF0000 for Red
Image UploadPatterns, textures, gradientsPlaid, Leopard print, Tie-dye
Named ColorStandard CSS colors"Navy", "Tomato", "Teal"

Best Practices for Swatch Configuration

Use Hex Codes for Accuracy: #1E3A8A is more reliable than color names

Optimize Swatch Images: Keep them under 200x200px

Consistent Naming: Use "Navy Blue" across all products, not sometimes "Navy"

Fallback Ready: If no hex is set, the code will attempt to parse the option name as a color

Part 2: Querying Swatch Data with GraphQL

The optionValues API

Shopify's Storefront API provides the optionValues field—a dedicated, efficient way to fetch product option data including swatches.

GraphQL Fragment

Add this fragment to your app/graphql/fragments.ts:

fragment ProductOption on ProductOption {
name
optionValues {
name
firstSelectableVariant {
id
availableForSale
price {
amount
currencyCode
}
image {
url
altText
}
}
swatch {
color
image {
previewImage {
# Optimize: Resize swatch images server-side
url(transform: { width: 100, height: 100, crop: CENTER })
altText
}
}
}
}
}

Key fields:

  • swatch.color: Hex code (e.g., #FF5733)

  • swatch.image.previewImage: Optimized image for patterns/textures

  • firstSelectableVariant: First available variant with this option—critical for navigation

Using the Fragment in Product Queries

query Product($handle: String!) {
product(handle: $handle) {
id
title
options {
...ProductOption
}
variants(first: 100) {
nodes {
id
availableForSale
selectedOptions {
name
value
}
}
}
}
}

Part 3: Building the React Components

1. Color Utility Functions

Create helpers to handle edge cases like light colors on white backgrounds.

// app/utils/colors.ts
import { colord } from "colord";
/**
* Validates if a string is a parseable color
* Supports hex, RGB, HSL, and named colors
*/
export function isValidColor(color: string): boolean {
return colord(color).isValid();
}
/**
* Detects if a color is "light" (brightness > threshold)
* Used to add borders to white/cream/yellow swatches
*/
export function isLightColor(color: string, threshold = 0.8): boolean {
const c = colord(color);
return c.isValid() && c.brightness() > threshold;
}

Install the dependency:

npm install colord

2. Swatch Component

Create a reusable swatch component with local type definitions:

// app/components/product/ProductOptionSwatches.tsx
import { Image } from "@shopify/hydrogen";
import { cn } from "~/utils/cn";
import { isLightColor, isValidColor } from "~/utils/colors";
// Define types locally for better portability
export type SwatchOptionValue = {
name: string;
selected: boolean; // Computed prop
available: boolean; // Computed prop
swatch?: {
color?: string | null;
image?: {
previewImage?: {
url: string;
altText?: string | null;
} | null;
} | null;
} | null;
};
type SwatchProps = {
optionValues: SwatchOptionValue[];
onSelect: (value: SwatchOptionValue) => void;
};
export function ProductOptionSwatches({ optionValues, onSelect }: SwatchProps) {
return (
<div className="flex flex-wrap gap-3">
{optionValues.map((value) => (
<SwatchButton
key={value.name}
value={value}
onClick={() => onSelect(value)}
/>
))}
</div>
);
}
function SwatchButton({
value,
onClick
}: {
value: SwatchOptionValue;
onClick: () => void;
}) {
const { name, selected, available, swatch } = value;
const hexColor = swatch?.color || name; // Fallback to name
const image = swatch?.image?.previewImage;
return (
<button
type="button"
disabled={!available}
onClick={onClick}
title={name}
className={cn(
"size-8 overflow-hidden rounded-full transition-all",
"outline-1 outline-offset-2",
selected
? "outline outline-gray-900"
: "outline-transparent hover:outline hover:outline-gray-400",
!available && "opacity-50 cursor-not-allowed diagonal-strike"
)}
>
{image ? (
<Image
data={image}
className="h-full w-full object-cover"
width={32}
height={32}
sizes="32px"
/>
) : (
<span
className={cn(
"block h-full w-full",
(!isValidColor(hexColor) || isLightColor(hexColor)) &&
"border border-gray-200"
)}
style={{ backgroundColor: hexColor }}
>
<span className="sr-only">{name}</span>
</span>
)}
</button>
);
}

3. Diagonal Strike-Through for Unavailable Variants

Add this CSS utility to your app/styles/app.css:

.diagonal-strike {
position: relative;
}
.diagonal-strike::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(
to bottom right,
transparent calc(50% - 1px),
#999 calc(50% - 1px),
#999 calc(50% + 1px),
transparent calc(50% + 1px)
);
pointer-events: none;
}

4. Using the Component

In your route file, map the raw GraphQL data to the SwatchOptionValue type by calculating selected and available status.

// app/routes/products.$handle.tsx
import { useNavigate, useLoaderData } from "@remix-run/react";
import { ProductOptionSwatches, type SwatchOptionValue } from "~/components/product/ProductOptionSwatches";
export default function ProductPage() {
const { product, selectedVariant } = useLoaderData<typeof loader>();
const navigate = useNavigate();
// 1. Find the color option
const colorOption = product.options.find(
(opt) => ["Color", "Colors", "Colour", "Colours"].includes(opt.name)
);
// 2. Map raw data to component props
// We need to calculate 'selected' and 'available' based on current context
const swatches: SwatchOptionValue[] | undefined = colorOption?.optionValues.map((value) => {
// Check if this is the currently selected value
const isSelected = selectedVariant?.selectedOptions.some(
(opt) => opt.name === colorOption.name && opt.value === value.name
);
return {
...value,
selected: !!isSelected,
available: !!value.firstSelectableVariant?.availableForSale,
};
});
const handleSwatchSelect = (value: SwatchOptionValue) => {
// Navigate to the corresponding variant URL
if (value.firstSelectableVariant) {
navigate(`?variant=${value.firstSelectableVariant.id.split('/').pop()}`, {
preventScrollReset: true,
replace: true
});
}
};
return (
<div>
{colorOption && swatches && (
<div className="space-y-2">
<h3 className="font-medium">Color: {selectedVariant?.selectedOptions.find(o => o.name === colorOption.name)?.value}</h3>
<ProductOptionSwatches
optionValues={swatches}
onSelect={handleSwatchSelect}
/>
</div>
)}
</div>
);
}

Final checklist

Before shipping, verify:

  • Swatch data is configured for every color option in Shopify Admin
  • Variant availability is reflected visually (disabled + strike-through)
  • Light colors have visible borders
  • Swatch images are optimized and transformed server-side
  • URL/state updates correctly when users change swatches

With this setup, shoppers can scan options faster, reduce misclicks, and reach purchase decisions with less friction.

Reactions

Like
Love
Celebrate
Insightful
Cool!
Thinking

Join the Discussion

Continue Reading

More insights from the Weaverse team

Agentic Commerce in 2026: What Shopify Merchants Need to Know About ACP and UCP

Agentic Commerce in 2026: What Shopify Merchants Need to Know About ACP and UCP

Agentic Commerce in 2026: What Shopify Merchants Need to Know About ACP and UCP AI-assisted buying is no longer hypothetical. In 2026, commerce is shifting from search and click to ask and buy. For Shopify merchants, that means your storefront is no longer just a website — it’s a machine-readable commerce surface that AI agents can query and transact against. The Shift: from search UX to agent UX Traditional ecommerce optimization focused on: PDP design Checkout friction SEO rankings Agentic commerce adds a new layer: Structured product data API reliability Protocol compatibility If agents can’t parse your catalog cleanly, they’ll route buyers elsewhere. The Two Protocols: ACP and UCP ACP (Agentic Commerce Protocol) ACP powers AI-native buying flows like ChatGPT commerce integrations, including in-chat purchasing experiences. Source: https://openai.com/index/buy-it-in-chatgpt/ Docs: https://developers.openai.com/commerce/ UCP (Universal Commerce Protocol) UCP is positioned as a shared protocol direction for broader AI-discoverable commerce surfaces, including Google/Shopify ecosystem momentum. Source: https://www.htt.it/en/agentic-ecommerce-acp-ucp-shopify-ai-commerce/ Source: https://wearepresta.com/shopify-ucp-how-to-implement-2026-guide/ Context: https://shopify.com/news/ai-commerce-at-scale Practical merchant view: ACP and UCP are not mutually exclusive. ACP helps with AI-native checkout channels; UCP-style readiness helps with cross-agent discoverability. Opportunity: new demand channels AI agents are becoming a new demand interface between users and merchants. That changes where conversion starts. Instead of: user lands on homepage → browses → compares It becomes: user asks assistant → agent evaluates merchant data → transaction decision This rewards merchants with: clean catalog schema strong availability/pricing consistency dependable APIs Cost structure: what to watch In AI-assisted checkout channels, economics can include: platform/agent commission layers payment processing (e.g., Stripe rails) Exact percentages vary by channel and configuration, so merchants should model margin impact per channel before scaling. 4-step action plan for Shopify + Hydrogen merchants Normalize product data Standardize titles, attributes, variants, inventory, and pricing logic. Publish machine-readable commerce surfaces Prepare manifests/feeds/endpoints for agent parsing as standards mature. Harden API flows Keep product, cart, pricing, and availability APIs fast and predictable. Instrument conversion by channel Track AI-assisted sessions and compare CPA/margin vs paid channels. Why this matters for Weaverse users Hydrogen merchants are already API-first — that’s an advantage. At Weaverse, we’re aligning theme architecture for both human storefront conversion and AI-agent readability. Agentic commerce is still evolving, but the preparation window is now. Sources https://openai.com/index/buy-it-in-chatgpt/ https://developers.openai.com/commerce/ https://www.htt.it/en/agentic-ecommerce-acp-ucp-shopify-ai-commerce/ https://wearepresta.com/shopify-ucp-how-to-implement-2026-guide/ https://shopify.com/news/ai-commerce-at-scale

By Paul Phan
Read
Shopify’s 2026 Headless Priority: Migrate Customer Accounts, Upgrade Checkout, Then Scale with AI Simulation

Shopify’s 2026 Headless Priority: Migrate Customer Accounts, Upgrade Checkout, Then Scale with AI Simulation

Shopify’s 2026 Headless Priority: Migrate Customer Accounts, Upgrade Checkout, Then Scale with AI Simulation Most teams are still executing headless in the wrong order. They start with a full rebuild, spend months on architecture, then discover their biggest risks were in customer accounts, checkout behavior, and release reliability. In 2026, Shopify’s platform signals point to a better sequence: Migrate risk-first flows (customer accounts) Capture conversion wins (PDP + checkout) Maintain reliability under release velocity (Hydrogen ops discipline) Add AI simulation/testing loops (after core flows are stable) Why Sequence Matters More Than Ambition A big-bang transformation looks strategic, but it often delays learning and increases production risk. A partial-headless operating model usually wins faster: stabilize critical flows first ship measurable conversion improvements second scale experimentation third This gives teams momentum without sacrificing reliability. Signal #1: Legacy Customer Accounts Are Deprecated Customer account migration is no longer optional planning work. If account flows remain fragile, every release carries hidden conversion and support risk. Operational implication: treat account migration as a reliability milestone, not a backlog task. Source: https://shopify.dev/changelog/legacy-customer-accounts-are-deprecated Signal #2: Accelerated Checkout Is Expanding on PDP Checkout capability is moving closer to product discovery paths. That means faster opportunities for measurable conversion lift if teams can ship safely. Operational implication: prioritize PDP/checkout experiments where impact is direct and measurable. Source: https://shopify.dev/changelog/accelerated-checkout-now-supports-addons-from-the-product-page Signal #3: Hydrogen Release Velocity Still Rewards Disciplined Ops Hydrogen continues to ship reliability/security updates and workflow improvements. Operational implication: teams need a repeatable weekly upgrade/testing process instead of ad hoc updates. Source: https://github.com/Shopify/hydrogen/releases.atom Signal #4: AI Simulation Is Becoming a Practical Layer AI-native testing and recommendation systems are moving from concept to practical workflow patterns. Operational implication: AI loops become high leverage only after core account/checkout flows are stable. Sources: https://shopify.engineering/simgym https://shopify.engineering/generative-recommendations A Practical 2-Week Execution Model Week 1 — Risk First complete customer account migration scope run account + checkout edge-case QA define rollback plans for high-risk flows Week 2 — Conversion Second ship 1–2 high-impact PDP/checkout experiments instrument conversion metrics and guardrail alerts run post-release reliability checks Week 3+ — AI Loops Third add simulation/testing workflows accelerate iteration cadence with tighter feedback cycles keep release quality gates fixed The Storefront Ops Layer (Non-Negotiable) To absorb platform changes without breaking revenue, teams need: fixed weekly release cadence pre-release QA gates (PDP → cart → checkout, account paths) rollback-safe releases shared runbooks for upgrades and migrations clear ownership across engineering + growth Without this ops layer, every update feels risky. With it, release velocity compounds. Where Weaverse Fits Hydrogen provides flexibility. Weaverse helps teams operationalize that flexibility: reusable section architecture for faster iteration safer workflows for non-dev merchandising teams structured collaboration between engineering and growth release-friendly storefront operations instead of one-off page work Final Take In 2026, headless advantage is not just about who can build faster. It’s about who can operate faster with lower risk: migrate critical flows early ship conversion wins continuously add AI loops on top of stable foundations That is the execution order that compounds. Sources Legacy customer accounts deprecated: https://shopify.dev/changelog/legacy-customer-accounts-are-deprecated Accelerated checkout add-ons on PDP: https://shopify.dev/changelog/accelerated-checkout-now-supports-addons-from-the-product-page Hydrogen releases: https://github.com/Shopify/hydrogen/releases.atom SimGym: https://shopify.engineering/simgym Generative recommendations: https://shopify.engineering/generative-recommendations

By Paul Phan
Read
Hydrogen 2026.1: What You Need to Know About the API Update

Hydrogen 2026.1: What You Need to Know About the API Update

Hydrogen 2026.1: What You Need to Know About the API Update Shopify released Hydrogen 2026.1.0, aligning with their quarterly API release cycle. Most changes are additive, but there's one breaking change that requires immediate attention if you have custom cart discount logic. Developer reviewing Hydrogen 2026.1 API updates The Breaking Change The cartDiscountCodesUpdate mutation now requires the discountCodes argument. Before (Implicit) cartDiscountCodesUpdate(cartId: $cartId) After (Explicit) cartDiscountCodesUpdate( cartId: $cartId discountCodes: [] # Required field ) Release planning timeline for quarterly API versions What Else Changed Hydrogen 2026.1.0 updates both: Storefront API → 2026-01 Customer Account API → 2026-01 This is a quarterly version update aligned with Shopify's API release schedule. Action Items Update packages to Hydrogen 2026.1.0 Search codebase for cartDiscountCodesUpdate mutations Add explicit discountCodes argument to all calls Test cart discount functionality Official Changelogs For complete details, review: Storefront API 2026-01 Changelog Customer Account API 2026-01 Changelog Bottom Line 10-minute fix if you have custom discount code logic. Otherwise, smooth upgrade. The migration is straightforward but critical if your store uses programmatic discount code management. Don't skip testing cart functionality after the upgrade. Building with Hydrogen? Weaverse helps you ship faster with AI-powered theme development. Get started.

By Paul Phan
Read

Never miss an update

Subscribe to get the latest insights, tutorials, and best practices for building high-performance headless stores delivered to your inbox.

Join the community of developers building with Weaverse.