Skip to main content

Theming & Dark Mode

ChamevoJS uses CSS custom properties (--cv-* tokens) for all visual styling. Override them to match your brand — no rebuild required.

Quick Theming

Override variables on the <cv-customizer> element or any ancestor:

cv-customizer {
--cv-primary: #e11d48;
--cv-primary-hover: #be123c;
--cv-radius: 0.5rem;
}

Color Tokens

All colors derive from Radix UI Colors — a 12-step scale with built-in light/dark mode support and WCAG-compliant contrast.

Token Reference

TokenLight ValueDark ValueUsage
--cv-bgslate-1slate-dark-1App background
--cv-bg-secondaryslate-2slate-dark-2Subtle background (panels, headers)
--cv-bg-tertiaryslate-3slate-dark-3UI element background (hover states)
--cv-textslate-12slate-dark-12High-contrast text
--cv-text-secondaryslate-11slate-dark-11Low-contrast text (labels, captions)
--cv-borderslate-6slate-dark-6Subtle borders
--cv-border-interactiveslate-7slate-dark-7Interactive element borders
--cv-border-hoverslate-8slate-dark-8Hovered borders
--cv-secondaryslate-9slate-dark-9Muted solid fills
--cv-primaryblue-9blue-dark-9Accent color (buttons, links)
--cv-primary-hoverblue-10blue-dark-10Accent hover state
--cv-on-primary#ffffff#ffffffText on primary-colored backgrounds
--cv-errorred-9red-dark-9Error states
--cv-successgreen-9green-dark-9Success states
--cv-warningamber-9amber-dark-9Warning states

Shape & Layout Tokens

TokenDefaultDescription
--cv-radius0.375remDefault border radius
--cv-radius-sm0.25remSmall border radius
--cv-radius-lg0.5remLarge border radius
--cv-shadow-sm...Small shadow
--cv-shadow-md...Medium shadow
--cv-shadow-lg...Large shadow
--cv-panel-width260pxModule panel width
--cv-toolbar-height3remToolbar height

Dark Mode

Toggle via the colorScheme prop:

<!-- HTML attribute -->
<cv-customizer color-scheme="dark"></cv-customizer>
// JavaScript property
customizer.colorScheme = 'dark';

The .cv-dark class is applied to the host element, which overrides all color tokens. Since CSS custom properties cascade through shadow DOM, all child components automatically adapt.

UI Style Presets

The uiStyle prop controls shape-related tokens independent of colors:

<cv-customizer ui-style="rounded"></cv-customizer>
PresetRadiusFeel
default0.375remStandard — fits most sites
rounded0.75remModern/friendly — larger radius, softer shadows
sharp0Corporate/minimal — no radius, crisp shadows

Custom Theme Example

/* Brand theme */
cv-customizer {
/* Colors */
--cv-primary: #7c3aed; /* Purple accent */
--cv-primary-hover: #6d28d9;
--cv-bg: #faf5ff; /* Light purple tint */
--cv-bg-secondary: #f3e8ff;

/* Shapes */
--cv-radius: 0.75rem;
--cv-radius-sm: 0.5rem;
--cv-radius-lg: 1rem;

/* Layout */
--cv-panel-width: 300px;
}

/* Dark variant */
cv-customizer[color-scheme="dark"] {
--cv-bg: #1e1033;
--cv-bg-secondary: #2d1b4e;
--cv-text: #f5f3ff;
--cv-border: #4c3769;
}

Shadow Presets

<cv-customizer shadow="lg"></cv-customizer>
ValueEffect
noneNo shadow
smSubtle shadow
mdMedium shadow
lgProminent shadow

Combining Options

<cv-customizer
color-scheme="dark"
ui-style="rounded"
shadow="lg"
></cv-customizer>

CSS Parts

All key structural elements expose ::part() selectors, allowing you to style shadow DOM internals from outside — no custom properties needed.

Available Parts

cv-customizer (own elements)

PartTarget
baseRoot wrapper div
mainMain content row (mainbar + canvas area)
canvas-areaCanvas area wrapper
canvas-scrollScroll container around canvas
canvas-sizerCanvas sizer box (shadow, border-radius)

cv-canvas (forwarded)

PartTarget
canvasCanvas container div
canvas-lock-overlayView lock overlay
canvas-containerFabricJS-generated wrapper around both canvas layers
canvas-lowerFabricJS lower (object/render) canvas layer
canvas-upperFabricJS upper (interaction) canvas layer

cv-mainbar (forwarded)

PartTarget
mainbarNavigation rail (both orientations)
mainbar-verticalVertical sidebar rail only
mainbar-horizontalHorizontal mobile bar only
mainbar-itemIndividual module tab button

cv-module-wrapper (forwarded)

PartTarget
module-panelSidebar/dialog panel
module-headerPanel header bar
module-contentScrollable content area

cv-element-toolbar (forwarded)

PartTarget
toolbarToolbar container
toolbar-navTool tab strip
toolbar-bodyPanel content below tabs
toolbar-subtabsColor sub-tab strip (fill / patterns / stroke / shadow)
toolbar-subtabAny individual color sub-tab button
toolbar-subtab-fillFill color sub-tab button
toolbar-subtab-patternsPatterns sub-tab button
toolbar-subtab-strokeStroke sub-tab button
toolbar-subtab-shadowShadow sub-tab button
opacityOpacity row wrapper

Note: The opacity slider track/thumb itself is available as cv-element-toolbar::part(opacity-slider) on a standalone <cv-element-toolbar> element, but is not forwarded through cv-customizer.

cv-actions-bar (forwarded)

PartTarget
actions-barAction bar (both top and bottom)
actions-bar-topTop action bar only
actions-bar-bottomBottom action bar only

External Components & Modules

When components are mounted outside the customizer (via registerModule() or standalone), use ::part() directly on the component tag — no exportparts chain needed.

cv-property-control

PartTarget
rootRoot container
labelLabel text above control
color-panelColor control wrapper
font-panelFont grid panel wrapper
font-searchFont search input area
font-gridScrollable font grid
sliderFont size slider wrapper
text-inputText content input wrapper

cv-color-selection

PartTarget
rootRoot container
empty-stateEmpty state message

cv-view-thumbnails

PartTarget
rootRoot container
gridThumbnails grid

Modules (common parts)

All modules expose root on their main container. Additional parts vary by module:

ComponentParts
cv-module-textroot, input-section, limits, limit, templates, templates-heading, templates-grid, template-item, template-text, template-price
cv-module-imagesroot, tabs, tab, tab-upload, tab-pixabay, tab-text2img, tab-qrcode, tab-icon, panel, placeholder, placeholder-label, price
cv-module-graphicsroot, header, search, search-input, grid, category, category-icon, category-thumb, category-title, breadcrumb-item, item, item-thumb, item-title, item-price
cv-module-layersroot, list, empty-state, row, item, title, title-text, swatch, meta, pin-indicator, drag-handle, actions, action-visibility, action-lock, action-delete
cv-module-text-layersroot, list, empty-state, item, header, header-content, preview, title, swatch, caret, font-row, font-family, font-size, formatting, format-group, format-btn, format-btn format-bold, format-btn format-italic, format-btn format-underline, format-btn format-align-left, format-btn format-align-center, format-btn format-align-right
cv-module-productsroot, grid, item, item-thumb, item-thumb-placeholder, item-title
cv-module-my-designsroot, save-bar, save-button, title-input, grid, empty-state, item, item-thumb, item-footer, item-title, item-delete
cv-module-layoutsroot, search, search-input, grid, empty-state, item, item-thumb, item-title, confirm, confirm-thumb, confirm-title, confirm-body, confirm-actions
cv-module-names-numbersroot, list, empty-state, row, name-input, number-input, remove, dropdown, badge, fields, footer, summary-count, summary-price
cv-module-bulk-variationsroot, list, empty-state, row, variation-select, qty, remove, badge, footer, summary-count, summary-total
cv-image-source-uploadroot, grid
cv-image-source-pixabayroot
cv-image-source-airoot
cv-image-source-qrcoderoot
/* Style externally-mounted property control */
cv-property-control::part(font-grid) {
grid-template-columns: repeat(3, 1fr);
}

/* Style externally-mounted layers module */
cv-module-layers::part(list) {
max-height: 400px;
}

Usage Examples (inside customizer)

/* Round the canvas box */
cv-customizer::part(canvas-sizer) {
border-radius: 24px;
overflow: hidden;
}

/* Custom mainbar background */
cv-customizer::part(mainbar) {
background: #1a1a2e;
}

/* Style the module panel */
cv-customizer::part(module-panel) {
border-right: 2px solid #e0e0e0;
}

/* Style only the bottom actions bar */
cv-customizer::part(actions-bar-bottom) {
background: #f5f5f5;
}
tip

CSS custom properties (--cv-*) cascade through shadow DOM and are best for colors, sizes, and tokens. Use ::part() when you need full CSS control over specific structural elements — layout, border-radius, overflow, etc.

Rules for Component Authors

  • Always use var(--cv-*) tokens for colors — never hardcode hex values
  • Use var(--cv-radius) / var(--cv-radius-sm) / var(--cv-radius-lg) — never hardcode border-radius
  • Use var(--cv-shadow-*) — never hardcode box-shadow
  • For text on colored backgrounds, use var(--cv-on-primary) instead of #ffffff

Next Steps