NEW: Try out the Theme Playground to visually customize and preview your themes.
Velt components can be styled in two main ways:
- Themes
- Custom CSS
Direct classes and inline styles on Velt components are not applied. Passing className or style to a Velt component does not change its UI. Add classes/styles to your HTML inside the corresponding Wireframe template, or use CSS overrides after disabling Shadow DOM.
Themes
You can use the Theme Playground to customize and preview the themes fast.
CSS Variables
- You can customize:
- Border radius
- Spacing
- Typography
- Colors for light and dark modes
- Z-Index
- Set CSS variables on your
<body> tag to customize all Velt components:
Example:
body {
/* Colors */
--velt-light-mode-accent: #0BA528;
/* Border Radius */
--velt-border-radius-sm: 4px;
/* Spacing */
--velt-spacing-sm: 8px;
}
Available Theme Variables:
Border Radius
Spacing
Typography
Colors - Light Mode
Colors - Dark Mode
Z-Index
--velt-border-radius-2xs: 0.125rem; // 2px
--velt-border-radius-xs: 0.25rem; // 4px
--velt-border-radius-sm: 0.5rem; // 8px
--velt-border-radius-md: 0.75rem; // 12px
--velt-border-radius-lg: 1rem; // 16px
--velt-border-radius-xl: 1.25rem; // 20px
--velt-border-radius-2xl: 1.5rem; // 24px
--velt-border-radius-3xl: 2rem; // 32px
--velt-border-radius-full: 5rem; // 80px
--velt-spacing-2xs: 0.125rem; // 2px
--velt-spacing-xs: 0.25rem; // 4px
--velt-spacing-sm: 0.5rem; // 8px
--velt-spacing-md: 0.75rem; // 12px
--velt-spacing-lg: 1rem; // 16px
--velt-spacing-xl: 1.25rem; // 20px
--velt-spacing-2xl: 1.5rem; // 24px
--velt-default-font-family: sans-serif;
--velt-font-size-2xs: 0.625rem; // 10px
--velt-font-size-xs: 0.75rem; // 12px
--velt-font-size-sm: 0.875rem; // 14px
--velt-font-size-md: 1rem; // 16px
--velt-font-size-lg: 1.5rem; // 24px
--velt-font-size-xl: 1.75rem; // 28px
--velt-font-size-2xl: 2rem; // 32px
/* Base Colors */
--velt-light-mode-green: #0DCF82;
--velt-light-mode-magenta: #A259FE;
--velt-light-mode-amber: #FF7162;
--velt-light-mode-purple: #625DF5;
--velt-light-mode-cyan: #4BC9F0;
--velt-light-mode-orange: #FE965C;
--velt-light-mode-black: #080808;
--velt-light-mode-white: #FFFFFF;
--velt-light-mode-gray: #EBEBEB;
/* Accent Colors */
--velt-light-mode-accent: #625DF5;
--velt-light-mode-accent-text: #9491F8;
--velt-light-mode-accent-hover: #534FCF;
--velt-light-mode-accent-foreground: #FFFFFF;
--velt-light-mode-accent-light: #F2F2FE;
--velt-light-mode-accent-transparent: rgba(148, 145, 248, 0.08);
/* Text Shades */
--velt-light-mode-text-0: #0A0A0A;
--velt-light-mode-text-1: #141414;
--velt-light-mode-text-2: #1F1F1F;
--velt-light-mode-text-3: #292929;
--velt-light-mode-text-4: #3D3D3D;
--velt-light-mode-text-5: #525252;
--velt-light-mode-text-6: #666666;
--velt-light-mode-text-7: #7A7A7A;
--velt-light-mode-text-8: #858585;
--velt-light-mode-text-9: #999999;
--velt-light-mode-text-10: #B8B8B8;
--velt-light-mode-text-11: #A3A3A3;
--velt-light-mode-text-12: #8F8F8F;
/* Background Shades */
--velt-light-mode-background-0: #FFFFFF;
--velt-light-mode-background-1: #FAFAFA;
--velt-light-mode-background-2: #F5F5F5;
--velt-light-mode-background-3: #F0F0F0;
--velt-light-mode-background-4: #EBEBEB;
--velt-light-mode-background-5: #E5E5E5;
--velt-light-mode-background-6: #E0E0E0;
--velt-light-mode-background-7: #DBDBDB;
--velt-light-mode-background-8: #D6D6D6;
--velt-light-mode-background-9: #D1D1D1;
--velt-light-mode-background-10: #CCCCCC;
/* Border Shades */
--velt-light-mode-border-0: #FFFFFF;
--velt-light-mode-border-1: #FAFAFA;
--velt-light-mode-border-2: #F5F5F5;
--velt-light-mode-border-3: #F0F0F0;
--velt-light-mode-border-4: #EBEBEB;
--velt-light-mode-border-5: #E5E5E5;
--velt-light-mode-border-6: #E0E0E0;
--velt-light-mode-border-7: #DBDBDB;
--velt-light-mode-border-8: #D6D6D6;
--velt-light-mode-border-9: #D1D1D1;
--velt-light-mode-border-10: #CCCCCC;
/* Status Colors */
/* Error */
--velt-light-mode-error: #FF7162;
--velt-light-mode-error-hover: #DE5041;
--velt-light-mode-error-foreground: #FFFFFF;
--velt-light-mode-error-light: #FFF4F2;
--velt-light-mode-error-transparent: rgba(255, 113, 98, 0.08);
/* Warning */
--velt-light-mode-warning: #FFCD2E;
--velt-light-mode-warning-hover: #C69400;
--velt-light-mode-warning-foreground: #474747;
--velt-light-mode-warning-light: #FFFBEE;
--velt-light-mode-warning-transparent: rgba(255, 205, 46, 0.08);
/* Success */
--velt-light-mode-success: #198F65;
--velt-light-mode-success-hover: #006B41;
--velt-light-mode-success-foreground: #FFFFFF;
--velt-light-mode-success-light: #EDF6F3;
--velt-light-mode-success-transparent: rgba(25, 143, 101, 0.08);
/* Transparent Colors */
--velt-light-mode-background-transparent: rgba(255, 255, 255, 0.80);
--velt-light-mode-border-transparent: rgba(0, 0, 0, 0.16);
--velt-light-mode-animation-transparent: rgba(255, 255, 255, 0.2);
/* Base Colors */
--velt-dark-mode-green: #0DCF82;
--velt-dark-mode-magenta: #A259FE;
--velt-dark-mode-amber: #FF7162;
--velt-dark-mode-purple: #625DF5;
--velt-dark-mode-cyan: #4BC9F0;
--velt-dark-mode-orange: #FE965C;
--velt-dark-mode-black: #080808;
--velt-dark-mode-white: #FFFFFF;
--velt-dark-mode-gray: #EBEBEB;
/* Accent Colors */
--velt-dark-mode-accent: #625DF5;
--velt-dark-mode-accent-text: #9491F8;
--velt-dark-mode-accent-hover: #534FCF;
--velt-dark-mode-accent-foreground: #FFFFFF;
--velt-dark-mode-accent-light: #F2F2FE;
--velt-dark-mode-accent-transparent: rgba(148, 145, 248, 0.08);
/* Text Shades */
--velt-dark-mode-text-0: #FFFFFF;
--velt-dark-mode-text-1: #F5F5F5;
--velt-dark-mode-text-2: #EBEBEB;
--velt-dark-mode-text-3: #E0E0E0;
--velt-dark-mode-text-4: #D6D6D6;
--velt-dark-mode-text-5: #C2C2C2;
--velt-dark-mode-text-6: #ADADAD;
--velt-dark-mode-text-7: #8F8F8F;
--velt-dark-mode-text-8: #7A7A7A;
--velt-dark-mode-text-9: #666666;
--velt-dark-mode-text-10: #525252;
--velt-dark-mode-text-11: #474747;
--velt-dark-mode-text-12: #3D3D3D;
/* Background Shades */
--velt-dark-mode-background-0: #0F0F0F;
--velt-dark-mode-background-1: #1A1A1A;
--velt-dark-mode-background-2: #1F1F1F;
--velt-dark-mode-background-3: #242424;
--velt-dark-mode-background-4: #292929;
--velt-dark-mode-background-5: #2E2E2E;
--velt-dark-mode-background-6: #333333;
--velt-dark-mode-background-7: #383838;
--velt-dark-mode-background-8: #3D3D3D;
--velt-dark-mode-background-9: #424242;
--velt-dark-mode-background-10: #474747;
/* Border Shades */
--velt-dark-mode-border-0: #0F0F0F;
--velt-dark-mode-border-1: #1A1A1A;
--velt-dark-mode-border-2: #1F1F1F;
--velt-dark-mode-border-3: #242424;
--velt-dark-mode-border-4: #292929;
--velt-dark-mode-border-5: #2E2E2E;
--velt-dark-mode-border-6: #333333;
--velt-dark-mode-border-7: #383838;
--velt-dark-mode-border-8: #3D3D3D;
--velt-dark-mode-border-9: #424242;
--velt-dark-mode-border-10: #474747;
/* Status Colors */
/* Error */
--velt-dark-mode-error: #FF7162;
--velt-dark-mode-error-hover: #DE5041;
--velt-dark-mode-error-foreground: #FFFFFF;
--velt-dark-mode-error-light: #FFF4F2;
--velt-dark-mode-error-transparent: rgba(255, 113, 98, 0.08);
/* Warning */
--velt-dark-mode-warning: #FFCD2E;
--velt-dark-mode-warning-hover: #C69400;
--velt-dark-mode-warning-foreground: #474747;
--velt-dark-mode-warning-light: #FFFBEE;
--velt-dark-mode-warning-transparent: rgba(255, 205, 46, 0.08);
/* Success */
--velt-dark-mode-success: #198F65;
--velt-dark-mode-success-hover: #006B41;
--velt-dark-mode-success-foreground: #FFFFFF;
--velt-dark-mode-success-light: #EDF6F3;
--velt-dark-mode-success-transparent: rgba(25, 143, 101, 0.08);
/* Transparent Colors */
--velt-dark-mode-background-transparent: rgba(0, 0, 0, 0.80);
--velt-dark-mode-border-transparent: rgba(255, 255, 255, 0.16);
--velt-dark-mode-animation-transparent: rgba(255, 255, 255, 0.2);
/* Comment Pin, Triangle */
--velt-comment-pin-z-index: 2147483557;
/* Comments Minimap */
--velt-comments-minimap-z-index: 2147483637;
/* Persistent Comment Frame */
--velt-persistent-comment-frame-z-index: 2147483647;
/* Global Overlay */
--velt-global-overlay-z-index: 2147483637;
/* Recorder Player */
--velt-recorder-player-z-index: 2147483557;
/* Cursor */
--velt-cursor-z-index: 2147483647;
/* Arrow */
--velt-arrow-z-index: 2147483557;
/* Toast Popup */
--velt-toast-popup-z-index: 2147483647;
/* Live State Sync Overlay */
--velt-live-state-sync-overlay-z-index: 2147483647;
/* Follow Mode Overlay */
--velt-follow-mode-overlay-z-index: 2147483647;
Dark Mode
- Enable dark mode globally or per component.
- Most components accept a
darkMode prop (dark-mode="true" for non-React).
- Some components that are not directly injected by you like dialogs and pins use specific props (e.g.
dialogDarkMode, pinDarkMode). You can add these props to the root component responsible for injecting them.
- Check each component’s UI customization documentation for its dark mode props.
React / Next.js
Other Frameworks
// Global
const client = useVeltClient();
client.setDarkMode(true);
// Per component example
<VeltComments
darkMode={true}
dialogDarkMode={true}
pinDarkMode={true}
/>
// Global
const client = useVeltClient();
client.setDarkMode(true);
// Per component example
<velt-comments
dark-mode="true"
dialog-dark-mode="true"
pin-dark-mode="true"
></velt-comments>
Custom CSS or libraries
You can use your own CSS or libraries like Tailwind CSS to style the Velt components. You will need to disable the Shadow DOM to apply your styles.
1. Using CSS on rendered components
- Inspect the DOM using browser dev tools to find the class names and selectors of the target Velt components.
- Override the styles using your CSS.
- Make sure to disable the Shadow DOM to apply your styles.
React / Next.js
Other Frameworks
.velt-composer--input-button {
background-color: red;
border-radius: 0;
}
.velt-composer--input-button {
background-color: red;
border-radius: 0;
}
2. Using CSS on Wireframes
- Add the relevant wireframe component.
- Add class or inline styles to the wireframe component like you would on a normal HTML element.
- When the actual component is rendered, the styles will be applied to that component.
- Make sure to disable the Shadow DOM to apply your styles.
- Passing
className or style directly to Velt components does not change their UI; apply styling in the Wireframe template (or your own elements within it).
React / Next.js
Other Frameworks
<VeltWireframe>
<VeltCommentsSidebarWireframe.Header>
{/* Use CSS classes */}
<div className="bg-white shadow-lg p-4">
<VeltCommentsSidebarWireframe.Search />
<VeltCommentsSidebarWireframe.FilterButton />
</div>
{/* Or inline styles */}
<VeltCommentsSidebarWireframe.Status style={{backgroundColor: 'red'}} />
</VeltCommentsSidebarWireframe.Header>
</VeltWireframe>
<velt-wireframe style="display:none;">
<velt-comments-sidebar-header-wireframe>
<!-- Use CSS classes -->
<div class="bg-white shadow-lg p-4">
<velt-comments-sidebar-search-wireframe class="w-full"></velt-comments-sidebar-search-wireframe>
<velt-comments-sidebar-filter-button-wireframe class="mt-2"></velt-comments-sidebar-filter-button-wireframe>
</div>
<!-- Or inline styles -->
<velt-comments-sidebar-status-wireframe style="background-color: red"></velt-comments-sidebar-status-wireframe>
</velt-comments-sidebar-header-wireframe>
</velt-wireframe>
Component-Specific CSS Classes
Certain Velt components include CSS classes for specific states that you can target for custom styling. For example, the assign dropdown checkbox includes a CSS class to indicate the selected state on checkboxes.
To target the selected state, inspect the assign dropdown checkbox element in your browser dev tools to find the specific class name, then apply your custom styles. Make sure to disable the Shadow DOM first.
React / Next.js
Other Frameworks
/* Example: Style selected checkboxes in assign dropdown */
/* Inspect the DOM to find the exact class name */
.velt-assign-dropdown-checkbox--selected {
background-color: #625DF5;
border-color: #625DF5;
}
/* Example: Style selected checkboxes in assign dropdown */
/* Inspect the DOM to find the exact class name */
.velt-assign-dropdown-checkbox--selected {
background-color: #625DF5;
border-color: #625DF5;
}
Disable Shadow DOM
- By default, Velt components use Shadow DOM to isolate their styles from your application’s CSS. This ensures that styles don’t conflict with each other.
- If you want your application’s CSS to affect the styling of Velt components, you can disable the Shadow DOM.
- Most components accept a
shadowDom prop (shadow-dom="false" for non-React).
- Some components that are not directly injected by you like dialogs and pins use specific props (e.g.
dialogShadowDom, pinShadowDom).
- Check each component’s UI customization documentation for its shadow DOM props.
React / Next.js
Other Frameworks
<VeltComments shadowDom={false} />
<velt-comments shadow-dom="false"></velt-comments>
Disable Global Styles
When implementing custom themes, you can disable Velt’s default global CSS styles by setting globalStyles: false in the SDK configuration. This prevents conflicts with your custom styling.
React / Next.js
Other Frameworks
// Using VeltProvider
<VeltProvider apiKey='API_KEY' config={{
globalStyles: false
}}>
{/* Your app content */}
</VeltProvider>
// Using API method
const client = useVeltClient();
client.initConfig('API_KEY', {
globalStyles: false
});
<script>
Velt.initConfig('API_KEY', {
globalStyles: false
});
</script>
Conditional Classes
Apply classes conditionally based available template variables.
Syntax:
React / Next.js
Other Frameworks
<SomeVeltWireframe veltClass="<evaluation-string>" />
<some-velt-wireframe velt-class="<evaluation-string>"></some-velt-wireframe>
<evaluation-string>: 'class-name': {velt-template-variable} <operator> 'value'
- class-name: The class name to apply. This should be within single quotes
'.
- template-variable: The template variable to evaluate. This should be within curly braces
{}.
- operator: The operator to use for the comparison. This should be one of the following:
===, !==, >, >=, <, <=. You can also use && and || to combine multiple conditions.
- value: The value to compare the template variable to. This should be within single quotes
'.
Example:
React / Next.js
Other Frameworks
<VeltWireframe>
<VeltCommentDialogWireframe.Header veltClass="'bg-yellow-500': {annotation.status.id} === 'IN_PROGRESS'" />
</VeltWireframe>
<velt-wireframe style="display:none;">
<velt-comment-dialog-header-wireframe velt-class="bg-yellow-500: {annotation.status.id} === 'IN_PROGRESS'"></velt-comment-dialog-header-wireframe>
</velt-wireframe>