Colab Commerce
window.CCWidgetsJS SDK

Widgets — JavaScript SDK

The same store locator, quote form, and store detail experiences from @colabcommerce/elements — built into a browser-ready bundle for non-React pages. Drop in a CSS file, a script tag, and a data-cc-widget element to mount.

On this page

Introduction

The Widgets SDK is a precompiled browser bundle that exposes three mountable widgets on a single global — window.CCWidgets. Internally it renders the same React components as @colabcommerce/elements, so behavior, props, and providers match. You do not need React, a bundler, or any context wiring on the host page.

Three widgets are exposed: StoreLocator, QuoteForm, and Store.

Assets

The SDK is served from the Colab Commerce CDN:

  • Stylesheethttps://cdn.colabcommerce.com/elements.0.9.7.css
  • Scripthttps://cdn.colabcommerce.com/elements.v0.9.7.js

Reference both the JS and CSS files in your page. Pin both URLs to a specific version — window.CCWidgets.version reports the running version at runtime.

Quick start

Two ways to mount: declarative (auto-scan on load) or programmatic (when you need callbacks or dynamic props).

<link rel="stylesheet" href="https://cdn.colabcommerce.com/elements.0.9.7.css" />

<div
  data-cc-widget="StoreLocator"
  data-config='{"organizationId":"4f155976-8631-445a-b1b7-c8ccac28cca1","locale":"en"}'
></div>

<script src="https://cdn.colabcommerce.com/elements.v0.9.7.js"></script>
<link rel="stylesheet" href="https://cdn.colabcommerce.com/elements.0.9.7.css" />
<div id="locator"></div>
<script src="https://cdn.colabcommerce.com/elements.v0.9.7.js"></script>
<script>
  const el = document.getElementById('locator')
  window.CCWidgets.mount('StoreLocator', el, {
    organizationId: '4f155976-8631-445a-b1b7-c8ccac28cca1',
    locale: 'en',
    showProducts: true,
    productLimit: 12,
    baseUrl: '/retailers',
  })
</script>

When the script loads, the SDK scans the document for any[data-cc-widget] elements and mounts each one using the JSON in its data-config attribute. Callbacks cannot be expressed in JSON — use a programmatic mount when you need onClose, onSuccess, or other functions.

SDK surface

The SDK exposes a single global runtime object, window.CCWidgets:

window.CCWidgets
interface CCWidgets {
  /** Mount a widget by name onto an element with the given props. */
  mount(name: 'StoreLocator' | 'QuoteForm' | 'Store', element: Element, props: object): void

  /** Unmount whatever widget is currently mounted on the element. */
  unmount(element: Element): void

  /** Scan a root (or document) for [data-cc-widget] elements and mount them. */
  scan(root?: Element | Document): void

  /** Bundle version string, matches the SDK filename. */
  version: string
}

Widget reference

Three widgets are mountable through the SDK registry. All config props are forwarded directly to the underlying React component, so their behavior mirrors the matching entry in Elements.

StoreLocator

Full store locator experience with search, map, list, and message dialog. Internally wraps its own TranslationsProvider, StoreLocatorProvider, and APIProvider — no external context required.

Props

  • organizationIdstringrequired
  • localestring
  • showProductsbooleandefault false
  • productLimitnumberdefault 10
  • baseUrlstringdefault /retailers
data-config
{
  "organizationId": "YOUR_ORG_ID",
  "locale": "en",
  "showProducts": true,
  "productLimit": 12,
  "baseUrl": "/retailers"
}

QuoteForm

Multi-step quote request flow: search a store, submit the lead, render a success state. Wraps its own TranslationsProvider and QuoteFormProvider internally, and uses Google Maps where needed.

Props

  • organizationIdstringrequired
  • productsarray
  • localestring
  • onClosefunction
  • onSuccessfunction
{
  "organizationId": "YOUR_ORG_ID",
  "locale": "en",
  "products": [
    { "sku": "SKU-1", "name": "Product 1" }
  ]
}

Note: function props like onClose and onSuccess cannot be supplied via JSON. Use a programmatic mount whenever you need them.

Store

Store detail page widget — store info, contact, map, and products. Wraps its own TranslationsProvider and StoreProvider internally.

Props

  • storeIdstringrequired
  • localestringdefault "en"
  • initialDataobject
data-config
{
  "storeId": "STORE_ID",
  "locale": "en"
}

Mounting patterns

Auto-scan

Add one or more elements with data-cc-widget and data-config, include the SDK script, and the SDK will scan and mount them automatically on DOMContentLoaded.

Manual scan

After dynamically injecting widget elements into the page, ask the SDK to scan for them:

scan
window.CCWidgets.scan(document)

Unmount

When removing a widget — for example, during a SPA route change — unmount it first:

unmount
const el = document.getElementById('locator')
window.CCWidgets.unmount(el)

Styling

Every widget mounts inside an open Shadow DOM boundary so that host-page CSS cannot leak in and break the layout. The bundled stylesheet is adopted into each shadow root automatically (via adoptedStyleSheets, with an inline <style> fallback on older engines), and a :host { all: initial; display: block; … } reset wall blocks inherited typography and colors from the surrounding page.

Because the shadow boundary blocks normal selectors, styling the widgets from your page CSS uses one of three supported mechanisms — listed in order of preference:

  1. CSS custom properties set on the host element (or :root) — inherit across the shadow boundary.
  2. ::part() selectors targeting exposed shadow parts from outside.
  3. Opt out of Shadow DOM with data-cc-no-shadow and target the cc-* hook classes directly.

1. CSS custom properties (recommended)

The widgets read every color, radius, and shadow value from CSS variables defined on the .cc container (and mirrored on :host for the phone-input variables). Custom properties inherit through the shadow boundary, so setting them on the light-DOM host element — or globally on :root — re-themes the widget without any other configuration.

/* Re-theme every Colab widget on the page */
:root {
  --primary: #ff5a1f;
  --primary-foreground: #ffffff;
  --radius: 0.5rem;
}
/* Scoped to a single anchor */
#my-quote-widget {
  --primary: #0f766e;
  --primary-foreground: #ffffff;
  --radius: 999px;
}

Available tokens

Colors (light defaults; dark variants are applied when .cc.dark is present):

  • Surfaces — --background, --foreground, --card / --card-foreground, --popover / --popover-foreground, --muted / --muted-foreground
  • Actions — --primary / --primary-foreground, --secondary / --secondary-foreground, --accent / --accent-foreground, --destructive / --destructive-foreground
  • Chrome — --border, --input, --ring
  • Charts & status — --chart-1 --chart-5, --color-green, --color-orange, --color-red, --color-blue, --color-black, --color-white
  • Sidebar — --sidebar, --sidebar-foreground, --sidebar-primary / --sidebar-primary-foreground, --sidebar-accent / --sidebar-accent-foreground, --sidebar-border, --sidebar-ring

Radius--radius (default 1.4rem). Derived utility steps --radius-sm, --radius-md, --radius-lg, and --radius-xl are exposed automatically.

Shadow--shadow-x, --shadow-y, --shadow-blur, --shadow-spread, --shadow-opacity, --shadow-color. Derived steps --shadow-2xs through --shadow-2xl are exposed automatically.

Phone input (react-phone-number-input, defined on :host, .cc) — --PhoneInput-color--focus, --PhoneInputCountryFlag-height, --PhoneInputCountryFlag-aspectRatio, --PhoneInputCountryFlag-borderColor, --PhoneInputCountryFlag-borderColor--focus, --PhoneInputCountryFlag-borderWidth, --PhoneInputCountryFlag-backgroundColor--loading, --PhoneInputCountrySelect-marginRight, --PhoneInputCountrySelectArrow-width, --PhoneInputCountrySelectArrow-marginLeft, --PhoneInputCountrySelectArrow-borderWidth, --PhoneInputCountrySelectArrow-opacity, --PhoneInputCountrySelectArrow-color, --PhoneInputCountrySelectArrow-color--focus, --PhoneInputCountrySelectArrow-transform, --PhoneInputInternationalIconPhone-opacity, --PhoneInputInternationalIconGlobe-opacity.

2. ::part() selectors

For changes that go beyond what the design tokens expose — bespoke gradients, custom border treatments, typography overrides — every widget's key surfaces carry a part attribute. Standard W3C ::part() selectors style them from outside the shadow root, with no opt-out required.

<div
  id="my-quote-mount"
  data-cc-widget="QuoteForm"
  data-config='{"organizationId":"YOUR_ORG_ID","locale":"en"}'
></div>

Exposed parts

  • StoreLocator store-locator, store-locator-layout, store-locator-sidebar, store-locator-search
  • Storestore, store-main, store-details, store-products-section
  • QuoteFormquote-form, quote-form-button, quote-form-button-trigger, quote-form-button-overlay, quote-form-button-dialog, lead-form, lead-form-actions, lead-form-submit, lead-form-cancel

3. Light-DOM opt-out

For debugging, legacy DOM introspection, or when an existing design system needs to reach inside the widget with regular selectors, add the data-cc-no-shadow attribute to the mount anchor. The widget will render in the light DOM and your page CSS will apply normally — including against the stable cc-<component> and cc-<component>__<part> hook classes that mirror the shadow parts.

<div
  data-cc-widget="StoreLocator"
  data-cc-no-shadow
  data-config='{"organizationId":"YOUR_ORG_ID","locale":"en"}'
></div>

Opting out of Shadow DOM also removes the isolation wall — any global CSS on the host page (resets, utility frameworks, base typography) will cascade into the widget. Prefer CSS variables or ::part() selectors when possible and use data-cc-no-shadow only when you accept that trade-off.

Errors & debug behavior

  • Invalid JSON in data-config logs a console warning and falls back to an empty config.
  • An unknown widget name logs a console warning and skips the mount.
  • Calling mount() without an element throws an error.
  • Repeated mount() calls on the same element are ignored until the element is unmount()ed.

Limits

  • Only StoreLocator, QuoteForm, and Store are mountable through the SDK registry.
  • Other entries published by @colabcommerce/elements are not exposed on window.CCWidgets unless added to the registry in a future SDK build.
  • The version in your script tag must match the built SDK filename — confirm via window.CCWidgets.version.

Bundles are produced by yarn build:widgets (or yarn build:all) in the @colabcommerce/elements repo.