Charts and components
Custom Canvas UI

Custom Canvas UI

Custom Canvas is a feature that lets your users build their own dashboards inside your product. This page covers styling and translating its interface; see also Deploying Custom Canvas.

The UI components powering Custom Canvas (panels, forms, buttons, cards) are built on Remarkable UI (opens in a new tab). These components are currently fixed - you can't swap them out or modify their behavior - but you can style them to match your brand using CSS variables.

How to Style Custom Canvas

Add variables to theme.styles in your theme:

// embeddable.theme.ts
const themeProvider = (clientContext: any, parentTheme: Theme): Theme => {
  return defineTheme(parentTheme, {
    styles: {
      "--em-sem-background": "#f8f9fa",
      "--em-sem-text": "#1a1a2e",
    },
  });
};

For full theming details, see Theming Remarkable Pro and How Styling Works.


Translating the Interface

Custom Canvas ships its labels in English - "Add a chart", "Select a template", validation messages, and so on. The drill-down modal does the same. You can replace any of them from your theme, under theme.embeddableApp.i18n.

This is separate from Remarkable Pro's internationalization, which lives under theme.i18n and covers your components. theme.embeddableApp belongs to the platform itself, so it works the same way whether or not you use Remarkable Pro.

How to translate

// embeddable.theme.ts
const themeProvider = (clientContext: any, parentTheme: Theme) => {
  return defineTheme(parentTheme, {
    embeddableApp: {
      i18n: {
        language: clientContext?.language || "en",
        translations: {
          de: {
            customCanvas: {
              addChart: "Diagramm hinzufĂĽgen",
              templateSelection: {
                title: "Vorlage auswählen",
                populateTitle: "{{templateName}} ausfĂĽllen",
              },
              validation: {
                valueRequired: "Wert ist erforderlich",
              },
            },
            drillDown: {
              step: "Schritt {{number}}",
            },
          },
        },
      },
    },
  });
};

Things to notice

  1. embeddableApp.i18n.language selects the active catalogue, and defaults to en. The platform reserves no Client Context fields of its own, so map your own locale field onto it, as above.
  2. Translate only the keys you need. Anything you leave out falls back to the built-in English, so a partial catalogue is a valid catalogue.
  3. {{...}} are placeholders, filled in when the label is rendered. You can move them: Populate {{templateName}} becomes {{templateName}} ausfĂĽllen in German. Never assemble a label by joining pieces together - word order differs between languages.
  4. Each <em-beddable> resolves its own labels, so several embeddables on one page can run different languages.

To try it in the Builder, add presets to your client-contexts.cc.yml:

# src/embeddable.com/presets/client-contexts.cc.yml
 
- name: German
  clientContext:
    language: de
 
- name: Spanish
  clientContext:
    language: es

Switching between them swaps the language of the whole interface:

Image 0

Changing the English wording

The built-in English is a catalogue like any other. If you only want the interface to match your product's terminology, override it without translating anything:

embeddableApp: {
  i18n: {
    language: "en",
    translations: {
      en: {
        customCanvas: { addChart: "Add a widget" },
      },
    },
  },
},

Your en catalogue also acts as the base for every other language. A label you reword there shows up in German too, unless your de catalogue gives it its own value - so terminology changes only need writing once.

Labels resolve in this order:

  1. the catalogue for language
  2. your en catalogue
  3. the built-in English

What isn't translated here

  1. Template names and descriptions are authored in the Builder and are shown exactly as written there.
  2. Your components' own labels - titles, axis labels, column headers and data values - belong to your component library. On Remarkable Pro, translate them under theme.i18n.

Type safety

@embeddable.com/core exports the types for this namespace, so your editor autocompletes the keys and a mistyped key fails the build rather than silently rendering English:

// embeddable.theme.ts
import { defineTheme, EmbeddableTheme } from "@embeddable.com/core";
import { Theme } from "@embeddable.com/remarkable-pro";
 
type AppTheme = Theme & EmbeddableTheme;
 
const themeProvider = (clientContext: any, parentTheme: Theme): AppTheme =>
  defineTheme<AppTheme>(parentTheme, {
    embeddableApp: { i18n: { /* ... */ } },
  });
 
export default themeProvider;

Requires @embeddable.com/core 2.15.0 or later.

Key reference

Keys are grouped by the part of the interface they appear in. The English value is what renders when you don't provide a translation.

Canvas

KeyEnglish default
customCanvas.addChartAdd a chart
customCanvas.editDashboardEdit dashboard
customCanvas.doneDone
customCanvas.emptyStateTitleStart building your dashboard
customCanvas.loadingLoading your dashboard
customCanvas.editingUnavailableOnSmallScreensEditing is only available on larger screens.

Template selection

KeyEnglish default
customCanvas.templateSelection.titleSelect a template
customCanvas.templateSelection.populateTitlePopulate {{templateName}}
customCanvas.templateSelection.searchSearch templates
customCanvas.templateSelection.selectTemplateSelect {{templateName}} template
customCanvas.templateSelection.addAdd
customCanvas.templateSelection.noResultsTitle0 results
customCanvas.templateSelection.noResultsMessageClear your search and try again.
customCanvas.templateSelection.goBackGo back
customCanvas.templateSelection.closeClose
customCanvas.templateSelection.loadingFormLoading form…
customCanvas.templateSelection.formUnavailableForm unavailable

Configurator

defaultCategory is the heading shown above inputs whose component declares no category of its own.

KeyEnglish default
customCanvas.configurator.cancelCancel
customCanvas.configurator.addToDashboardAdd to dashboard
customCanvas.configurator.saveChangesSave changes
customCanvas.configurator.previewPlaceholderPopulate the required fields to see a preview
customCanvas.configurator.requiredRequired
customCanvas.configurator.selectDatasetSelect a dataset
customCanvas.configurator.selectFieldSelect {{field}}
customCanvas.configurator.booleanTrueTrue
customCanvas.configurator.booleanFalseFalse
customCanvas.configurator.moreOptionsMore options
customCanvas.configurator.lessOptionsLess options
customCanvas.configurator.defaultCategoryChart settings

Dimension and measure fields

KeyEnglish default
customCanvas.fields.selectDimensionSelect a dimension
customCanvas.fields.selectMeasureSelect a measure
customCanvas.fields.selectDimensionOrMeasureSelect a dimension or measure
customCanvas.fields.selectGranularitySelect a granularity
customCanvas.fields.selectGranularitiesSelect granularities
customCanvas.fields.granularityGranularity
customCanvas.fields.selectDatasetFirstSelect a dataset first
customCanvas.fields.noDimensionsNo dimensions available
customCanvas.fields.noMeasuresNo measures available
customCanvas.fields.noDimensionsOrMeasuresNo dimensions or measures available

Validation messages

KeyEnglish default
customCanvas.validation.valueRequiredValue is required
customCanvas.validation.filterRequiredFilter is required
customCanvas.validation.operatorRequiredOperator is required
customCanvas.validation.sortByRequiredSort by is required
customCanvas.validation.limitRequiredLimit is required
customCanvas.validation.limitNotANumberMust be a valid number
customCanvas.validation.limitBelowMinimumMinimum limit is {{min}}
customCanvas.validation.limitAboveMaximumLimit can not exceed {{max}}
customCanvas.validation.filtersHaveErrorsOne or more filters have validation errors
customCanvas.validation.sortsHaveErrorsOne or more sorts have validation errors

Widget actions

KeyEnglish default
customCanvas.widgetActions.editEdit widget
customCanvas.widgetActions.cloneClone widget
customCanvas.widgetActions.deleteDelete widget
customCanvas.widgetActions.resizeResize widget

Duplicate dialog

KeyEnglish default
customCanvas.duplicateDialog.titleDuplicate this chart?
customCanvas.duplicateDialog.messageThis will create a copy of the selected chart with the same settings. You can rename and adjust it by clicking edit.
customCanvas.duplicateDialog.confirmYes, duplicate
customCanvas.duplicateDialog.cancelNo, cancel

Dataset settings

KeyEnglish default
customCanvas.datasetSettings.filterFilter
customCanvas.datasetSettings.sortSort
customCanvas.datasetSettings.limitLimit
customCanvas.datasetSettings.addFilterAdd Filter
customCanvas.datasetSettings.addSortAdd Sort
customCanvas.datasetSettings.filterPlaceholderAdd a filter
customCanvas.datasetSettings.selectOperatorSelect operator
customCanvas.datasetSettings.selectValueSelect value
customCanvas.datasetSettings.selectTimeSelect time
customCanvas.datasetSettings.selectRangeSelect range
customCanvas.datasetSettings.enterValueEnter value
customCanvas.datasetSettings.enterLimitEnter limit
customCanvas.datasetSettings.sortBySort by
customCanvas.datasetSettings.sortAscendingSort ascending
customCanvas.datasetSettings.sortDescendingSort descending
customCanvas.datasetSettings.selectSortByFirstSelect sort by first
customCanvas.datasetSettings.deleteFilterDelete
customCanvas.datasetSettings.deleteSortDelete sort
customCanvas.datasetSettings.filterNotInDataModelThe filter "{{member}}" is not included in the selected data model
customCanvas.datasetSettings.sortNotInDataModelThe sort "{{sortBy}}" is not included in the selected data model

Relative date presets

These are the labels shown in filter dropdowns. The underlying values are sent to your data model unchanged, so translating a label doesn't affect filtering.

KeyEnglish default
customCanvas.datasetSettings.timePresets.todayToday
customCanvas.datasetSettings.timePresets.yesterdayYesterday
customCanvas.datasetSettings.timePresets.oneWeekAgo1 week ago
customCanvas.datasetSettings.timePresets.oneMonthAgo1 month ago
customCanvas.datasetSettings.timePresets.threeMonthsAgo3 months ago
customCanvas.datasetSettings.timePresets.sixMonthsAgo6 months ago
customCanvas.datasetSettings.timePresets.oneYearAgo1 year ago
customCanvas.datasetSettings.timePresets.thisWeekThis week
customCanvas.datasetSettings.timePresets.lastWeekLast week
customCanvas.datasetSettings.timePresets.last7DaysLast 7 days
customCanvas.datasetSettings.timePresets.thisMonthThis month
customCanvas.datasetSettings.timePresets.lastMonthLast month
customCanvas.datasetSettings.timePresets.last30DaysLast 30 days
customCanvas.datasetSettings.timePresets.thisQuarterThis quarter
customCanvas.datasetSettings.timePresets.lastQuarterLast quarter
customCanvas.datasetSettings.timePresets.last6MonthsLast 6 months
customCanvas.datasetSettings.timePresets.last12MonthsLast 12 months
customCanvas.datasetSettings.timePresets.thisYearThis year
customCanvas.datasetSettings.timePresets.lastYearLast year

Drill-down

KeyEnglish default
drillDown.goBackGo back
drillDown.closeClose
drillDown.closeModalClose modal
drillDown.breadcrumbNavigationBreadcrumb navigation
drillDown.stepStep {{number}}
drillDown.loadingLoading...
drillDown.loadErrorFailed to load embeddable

Common Customizations

Override only what you need. Start with these high-impact variables.

Brand Colors

Set the main background and text colors that define your look:

VariableDescriptionDefault
--em-background-color-defaultMain background color#ffffff
--em-background-color-subtleSecondary/muted backgrounds#f8f9fa
--em-foreground-color-defaultPrimary text color#1a1a2e
--em-primary-btn-background-color-defaultPrimary button backgroundBrand blue

Cards

Chart cards are the containers for each visualization:

VariableDescription
--em-card-border-radius-defaultCorner rounding for cards
--em-card-padding-defaultInner spacing
--em-card-title-color-defaultCard title text color
--em-card-title-font-weightCard title boldness
--em-box-shadow-default-colorCard shadow color
--em-box-shadow-default-blurCard shadow blur radius

Buttons

Style the action buttons throughout the interface:

VariableDescription
--em-primary-btn-background-color-defaultPrimary button fill
--em-primary-btn-background-color-disabledDisabled state fill
--em-secondary-btn-background-color-defaultSecondary button fill
--em-secondary-btn-background-color-hoverSecondary button hover
--em-icon-btn-background-color-defaultIcon button fill
--em-icon-btn-background-color-hoverIcon button hover

Forms & Inputs

Customize dropdowns, text inputs, and form sections:

VariableDescription
--em-form-background-color-defaultForm panel background
--em-form-border-radius-defaultForm panel corners
--em-form-header-font-font-colorForm section header color
--em-text-input-label-color-defaultInput label color
--em-select-menu-label-color-defaultDropdown label color

Typography

Fine-tune font sizes and weights:

VariableDescription
--em-font-size-smSmall text size
--em-font-size-mdMedium text size
--em-font-weight-mediumMedium font weight
--em-line-height-smSmall line height

Custom Canvas Overlay

The overlay is the modal that hosts the template selector and the chart configurator. Its variables sit in their own --em-canvas-overlay-* namespace, so overriding them doesn't affect the rest of your dashboard.

Coverage and box

VariableDescriptionDefault
--em-canvas-overlay-positionfixed (viewport) or absolute (parent container)fixed
--em-canvas-overlay-insetInset for the modal and the dim0
--em-canvas-overlay-max-widthMaximum content width78rem
--em-canvas-overlay-paddingInner spacing of the content area0 2rem 2.25rem
--em-canvas-overlay-border-radiusCorner rounding of the content area1.75rem
  • --em-canvas-overlay-position accepts fixed (default - the modal and the dim cover the viewport) or absolute (they cover only the embeddable's region). When using absolute, the embeddable's parent must be a positioned ancestor, e.g. position: relative.
  • --em-canvas-overlay-inset accepts any CSS inset shorthand (5rem, 1rem 2rem, 1rem 2rem 3rem 4rem) and insets the modal and the dim layer together.

Colors

VariableDescriptionDefault
--em-canvas-overlay-backdrop-backgroundDim layer behind the modalvar(--em-overlay-background)
--em-canvas-overlay-content-backgroundContent panel filltransparent
--em-canvas-overlay-title-colorOverlay title colorvar(--em-sem-text--inverted)
--em-canvas-overlay-action-button-backgroundBack / close button fillvar(--em-buttonicon-background--secondary)
--em-canvas-overlay-action-button-colorBack / close icon colorvar(--em-buttonicon-color--secondary)
  • the background is split in two: --em-canvas-overlay-backdrop-background is the dim behind the modal, --em-canvas-overlay-content-background is the panel holding the topbar, template grid and configurator. The content panel defaults to transparent, which is why cards appear to float over the dim.
  • the action-button variables only apply to the overlay's back and close buttons - other icon buttons keep their own styling.

Configurator actions bar

VariableDescriptionDefault
--em-canvas-overlay-actions-justify-contentHorizontal position of the cancel / confirm pill: flex-start, center or flex-endcenter
--em-canvas-overlay-actions-positionsticky floats the pill while scrolling, static lets it scroll with the contentsticky

For the complete set, see Canvas Overlay in the full variable reference below.


Full Variable Reference

Below is the complete list of supported CSS variables, organized by category.

Backgrounds & Surfaces

--em-background-color-default
--em-background-color-neutral
--em-background-color-subtle
--em-background-inverted
--em-foreground-color-default
--em-foreground-color-inverted
--em-content-inverted
--em-gray-800
--em-gray-900

Cards

--em-card-border-radius-default
--em-card-padding-default
--em-card-title-color-default
--em-card-title-font-weight
--em-card-title-font-line-height
--em-card-title-padding-default
--em-card-subtitle-color-default
--em-card-subtitle-font-font-family
--em-card-info-font-font-family
--em-card-info-font-size
--em-card-info-font-line-height
--em-card-info-font-title-weight
--em-card-empty-title-font-color-default
--em-card-loader-icon-size-height
--em-card-loader-icon-size-width

Buttons

--em-primary-btn-background-color-default
--em-primary-btn-background-color-disabled
--em-primary-btn-label-color-disabled
--em-primary-btn-label-font-small-size
--em-secondary-btn-background-color-default
--em-secondary-btn-background-color-hover
--em-icon-btn-background-color-default
--em-icon-btn-background-color-hover
--em-icon-btn-border-radius-default
--em-icon-btn-icon-color-default
--em-icon-btn-icon-color-call-to-action
--em-icon-btn-icon-size-height
--em-icon-btn-icon-size-width
--em-icon-btn-size-height
--em-icon-btn-size-width
--em-btn-island-background-color-default

Forms & Inputs

--em-form-background-color-default
--em-form-border-radius-default
--em-form-padding-default
--em-form-padding-small
--em-form-padding-large
--em-form-font-font-size-title
--em-form-font-font-weight
--em-form-font-line-height
--em-form-header-font-font-color
--em-form-header-font-font-family
--em-form-header-font-font-size
--em-form-header-font-font-weight
--em-form-header-font-line-height
--em-form-header-icon-color-default
--em-form-section-font-font-color
--em-form-section-font-font-family
--em-form-section-font-font-size
--em-form-section-font-font-weight
--em-form-section-font-line-height
--em-form-group-background-color-hover
--em-form-group-padding-default
--em-form-group-padding-small
--em-form-group-icon-size-height
--em-form-group-icon-size-width
--em-text-input-label-color-default
--em-text-input-size-min-width
--em-select-menu-label-color-default
--em-select-menu-label-font-size
--em-select-menu-label-font-weight
--em-select-list-item-isolate-background-color-default
--em-select-list-item-isolate-border-radius-default
--em-select-list-item-isolate-label-color-default
--em-select-list-item-isolate-label-font-size
--em-select-list-item-isolate-label-font-weight
--em-select-list-item-isolate-padding-default

Typography

--em-font-size-xs
--em-font-size-sm
--em-font-size-md
--em-font-weight-medium
--em-line-height-sm
--em-line-height-l

Borders & Shadows

--em-border-radius-200
--em-border-radius-400
--em-border-radius-500
--em-border-width-0
--em-border-width-default
--em-box-shadow-default-blur
--em-box-shadow-default-color
--em-box-shadow-default-position-x
--em-box-shadow-default-position-y
--em-box-shadow-default-spread

Spacing

--em-padding-100
--em-padding-200
--em-padding-300
--em-padding-400
--em-padding-800

Empty States

--em-empty-state-background-color-default
--em-empty-state-icon-color-default
--em-empty-state-icon-size-height
--em-empty-state-icon-size-width
--em-empty-state-padding-default

Lightbox & Overlays

--em-lightbox-font-color-default
--em-lightbox-font-font-family
--em-lightbox-font-font-size
--em-lightbox-font-font-weight
--em-lightbox-font-line-height
--em-overlay-z

Status Colors

--em-status-error
--em-status-negative-foreground
--em-switch-thumb-background-color

Canvas Overlay

Variables for the Custom Canvas overlay. Defaults and accepted values for the most-used ones are listed in the sub-section above.

Coverage and placement:

--em-canvas-overlay-position
--em-canvas-overlay-inset

Content box:

--em-canvas-overlay-width
--em-canvas-overlay-max-width
--em-canvas-overlay-height
--em-canvas-overlay-max-height
--em-canvas-overlay-padding
--em-canvas-overlay-border-radius

Backgrounds:

--em-canvas-overlay-backdrop-background
--em-canvas-overlay-content-background

Topbar title and action buttons (back, close):

--em-canvas-overlay-title-color
--em-canvas-overlay-action-button-background
--em-canvas-overlay-action-button-color
--em-canvas-overlay-action-button-border-color
--em-canvas-overlay-action-button-border-width
--em-canvas-overlay-action-button-border-radius

Configurator actions bar:

--em-canvas-overlay-actions-justify-content
--em-canvas-overlay-actions-position
--em-canvas-overlay-actions-grid-column
--em-canvas-overlay-actions-grid-row
--em-canvas-overlay-actions-justify-self
--em-canvas-overlay-actions-align-self

Template grid:

--em-canvas-overlay-grid-template-columns
--em-canvas-overlay-grid-template-columns--tablet
--em-canvas-overlay-grid-template-columns--mobile
--em-canvas-overlay-grid-auto-rows
--em-canvas-overlay-grid-auto-flow
--em-canvas-overlay-grid-gap
--em-canvas-overlay-grid-align-items

Configurator layout and form panel:

--em-canvas-overlay-configurator-grid-template-columns
--em-canvas-overlay-configurator-grid-template-columns--tablet
--em-canvas-overlay-configurator-grid-template-columns--mobile
--em-canvas-overlay-configurator-gap
--em-canvas-overlay-configurator-form-background
--em-canvas-overlay-configurator-form-padding
--em-canvas-overlay-configurator-form-padding-bottom
--em-canvas-overlay-configurator-form-border-radius
--em-canvas-overlay-configurator-form-gap

Tips

  • Override sparingly: Change only what's needed to match your brand. Fewer overrides means easier maintenance.
  • Test both themes: If you support light and dark modes, verify your changes work in both contexts.
  • Check accessibility: Ensure sufficient color contrast between text and backgrounds.