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
| Token | Light Value | Dark Value | Usage |
|---|---|---|---|
--cv-bg | slate-1 | slate-dark-1 | App background |
--cv-bg-secondary | slate-2 | slate-dark-2 | Subtle background (panels, headers) |
--cv-bg-tertiary | slate-3 | slate-dark-3 | UI element background (hover states) |
--cv-text | slate-12 | slate-dark-12 | High-contrast text |
--cv-text-secondary | slate-11 | slate-dark-11 | Low-contrast text (labels, captions) |
--cv-border | slate-6 | slate-dark-6 | Subtle borders |
--cv-border-interactive | slate-7 | slate-dark-7 | Interactive element borders |
--cv-border-hover | slate-8 | slate-dark-8 | Hovered borders |
--cv-secondary | slate-9 | slate-dark-9 | Muted solid fills |
--cv-primary | blue-9 | blue-dark-9 | Accent color (buttons, links) |
--cv-primary-hover | blue-10 | blue-dark-10 | Accent hover state |
--cv-on-primary | #ffffff | #ffffff | Text on primary-colored backgrounds |
--cv-error | red-9 | red-dark-9 | Error states |
--cv-success | green-9 | green-dark-9 | Success states |
--cv-warning | amber-9 | amber-dark-9 | Warning states |
Shape & Layout Tokens
| Token | Default | Description |
|---|---|---|
--cv-radius | 0.375rem | Default border radius |
--cv-radius-sm | 0.25rem | Small border radius |
--cv-radius-lg | 0.5rem | Large border radius |
--cv-shadow-sm | ... | Small shadow |
--cv-shadow-md | ... | Medium shadow |
--cv-shadow-lg | ... | Large shadow |
--cv-panel-width | 260px | Module panel width |
--cv-toolbar-height | 3rem | Toolbar 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>
| Preset | Radius | Feel |
|---|---|---|
default | 0.375rem | Standard — fits most sites |
rounded | 0.75rem | Modern/friendly — larger radius, softer shadows |
sharp | 0 | Corporate/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>
| Value | Effect |
|---|---|
none | No shadow |
sm | Subtle shadow |
md | Medium shadow |
lg | Prominent 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)
| Part | Target |
|---|---|
base | Root wrapper div |
main | Main content row (mainbar + canvas area) |
canvas-area | Canvas area wrapper |
canvas-scroll | Scroll container around canvas |
canvas-sizer | Canvas sizer box (shadow, border-radius) |
cv-canvas (forwarded)
| Part | Target |
|---|---|
canvas | Canvas container div |
canvas-lock-overlay | View lock overlay |
canvas-container | FabricJS-generated wrapper around both canvas layers |
canvas-lower | FabricJS lower (object/render) canvas layer |
canvas-upper | FabricJS upper (interaction) canvas layer |
cv-mainbar (forwarded)
| Part | Target |
|---|---|
mainbar | Navigation rail (both orientations) |
mainbar-vertical | Vertical sidebar rail only |
mainbar-horizontal | Horizontal mobile bar only |
mainbar-item | Individual module tab button |
cv-module-wrapper (forwarded)
| Part | Target |
|---|---|
module-panel | Sidebar/dialog panel |
module-header | Panel header bar |
module-content | Scrollable content area |
cv-element-toolbar (forwarded)
| Part | Target |
|---|---|
toolbar | Toolbar container |
toolbar-nav | Tool tab strip |
toolbar-body | Panel content below tabs |
toolbar-subtabs | Color sub-tab strip (fill / patterns / stroke / shadow) |
toolbar-subtab | Any individual color sub-tab button |
toolbar-subtab-fill | Fill color sub-tab button |
toolbar-subtab-patterns | Patterns sub-tab button |
toolbar-subtab-stroke | Stroke sub-tab button |
toolbar-subtab-shadow | Shadow sub-tab button |
opacity | Opacity 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 throughcv-customizer.
cv-actions-bar (forwarded)
| Part | Target |
|---|---|
actions-bar | Action bar (both top and bottom) |
actions-bar-top | Top action bar only |
actions-bar-bottom | Bottom 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
| Part | Target |
|---|---|
root | Root container |
label | Label text above control |
color-panel | Color control wrapper |
font-panel | Font grid panel wrapper |
font-search | Font search input area |
font-grid | Scrollable font grid |
slider | Font size slider wrapper |
text-input | Text content input wrapper |
cv-color-selection
| Part | Target |
|---|---|
root | Root container |
empty-state | Empty state message |
cv-view-thumbnails
| Part | Target |
|---|---|
root | Root container |
grid | Thumbnails grid |
Modules (common parts)
All modules expose root on their main container. Additional parts vary by module:
| Component | Parts |
|---|---|
cv-module-text | root, input-section, limits, limit, templates, templates-heading, templates-grid, template-item, template-text, template-price |
cv-module-images | root, tabs, tab, tab-upload, tab-pixabay, tab-text2img, tab-qrcode, tab-icon, panel, placeholder, placeholder-label, price |
cv-module-graphics | root, header, search, search-input, grid, category, category-icon, category-thumb, category-title, breadcrumb-item, item, item-thumb, item-title, item-price |
cv-module-layers | root, list, empty-state, row, item, title, title-text, swatch, meta, pin-indicator, drag-handle, actions, action-visibility, action-lock, action-delete |
cv-module-text-layers | root, 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-products | root, grid, item, item-thumb, item-thumb-placeholder, item-title |
cv-module-my-designs | root, save-bar, save-button, title-input, grid, empty-state, item, item-thumb, item-footer, item-title, item-delete |
cv-module-layouts | root, search, search-input, grid, empty-state, item, item-thumb, item-title, confirm, confirm-thumb, confirm-title, confirm-body, confirm-actions |
cv-module-names-numbers | root, list, empty-state, row, name-input, number-input, remove, dropdown, badge, fields, footer, summary-count, summary-price |
cv-module-bulk-variations | root, list, empty-state, row, variation-select, qty, remove, badge, footer, summary-count, summary-total |
cv-image-source-upload | root, grid |
cv-image-source-pixabay | root |
cv-image-source-ai | root |
cv-image-source-qrcode | root |
/* 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;
}
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
- Full Customizer — Setting theme props
- Components — Component-level CSS variables