Deskbell

Theming

Restyle the widget from the outside with CSS custom properties for colour, ::part() selectors for shape and layout, and named slots for your own markup, plus the side-panel recipe.

Colour is a token, shape is a part, and a region you want to own outright is a slot. Host-page CSS beats everything the widget resolves at runtime, and no rule in the widget uses !important. Every table below is rendered from the descriptor the widget reads.

Theme tokens

CSS custom properties, set on the element or anywhere above it.

deskbell-widget {
  --deskbell-accent: #2b6b4f;
  --deskbell-radius: 12px;
}
Custom propertyControls
--deskbell-surfacePanel background
--deskbell-surface-subtleAssistant bubbles, pills, chips
--deskbell-surface-hoverHover background for rows and buttons
--deskbell-surface-activePressed/active background
--deskbell-textPrimary text
--deskbell-text-secondaryChip and pill text
--deskbell-text-mutedSecondary text, refusals, empty state
--deskbell-text-subtleTimestamps, labels, placeholders
--deskbell-borderDividers and input borders
--deskbell-border-strongChip borders
--deskbell-accentBrand colour
--deskbell-accent-contrastText on the accent colour
--deskbell-accent-subtleTinted accent background
--deskbell-header-bgPanel header background
--deskbell-header-textPanel header text
--deskbell-bubble-user-bgVisitor message background
--deskbell-bubble-user-fgVisitor message text
--deskbell-bubble-assistant-bgAnswer background
--deskbell-bubble-assistant-fgAnswer text
--deskbell-bubble-radiusMessage bubble radius
--deskbell-launcher-bgLauncher background
--deskbell-launcher-fgLauncher icon colour
--deskbell-launcher-sizeLauncher diameter
--deskbell-launcher-offset-xLauncher distance from the side
--deskbell-launcher-offset-yLauncher distance from the bottom
--deskbell-radiusPanel corner radius
--deskbell-panel-widthPanel width
--deskbell-panel-heightPanel height
--deskbell-shadowPanel shadow
--deskbell-zStacking order
--deskbell-fontFont stack
--deskbell-font-sizeBase font size
--deskbell-control-radiusPills and buttons
--deskbell-input-radiusText inputs
--deskbell-focus-ringFocus outline colour
--deskbell-code-bgFenced code block background in answers
--deskbell-code-fgFenced code block text in answers

Parts

Shape and layout, through ::part(). Rules the host page writes against a part beat the widget's own, because normal declarations from the outer page win over shadow-tree rules.

  • ::part(launcher-container)
  • ::part(launcher)
  • ::part(launcher-icon)
  • ::part(launcher-label)
  • ::part(panel)
  • ::part(header)
  • ::part(header-title)
  • ::part(header-subtitle)
  • ::part(back-button)
  • ::part(close-button)
  • ::part(list)
  • ::part(empty-state)
  • ::part(suggestion)
  • ::part(message)
  • ::part(bubble)
  • ::part(citations)
  • ::part(citation-pill)
  • ::part(citation-label)
  • ::part(feedback)
  • ::part(feedback-button)
  • ::part(conversation)
  • ::part(new-question-button)
  • ::part(composer)
  • ::part(composer-input)
  • ::part(send-button)
  • ::part(powered-by)
  • ::part(md-heading)
  • ::part(md-list)
  • ::part(md-code)
  • ::part(md-link)
  • ::part(header-actions)
  • ::part(disclaimer)
  • ::part(typing)
  • ::part(welcome-title)
  • ::part(welcome)
  • ::part(welcome-card)
  • ::part(welcome-card-icon)
  • ::part(welcome-card-title)
  • ::part(welcome-card-description)
  • ::part(welcome-prompt)
  • ::part(feedback-note)
  • ::part(feedback-thanks)
  • ::part(sidebar)
  • ::part(sidebar-toggle)
  • ::part(new-thread-button)
  • ::part(scope-tabs)
  • ::part(scope-tab)
  • ::part(thread)
  • ::part(thread-title)
  • ::part(thread-meta)
  • ::part(thread-delete)
  • ::part(thread-confirm)
  • ::part(clarify-options)
  • ::part(clarify-option)
  • ::part(actions)
  • ::part(action)
  • ::part(action-title)
  • ::part(action-status)
  • ::part(action-buttons)
  • ::part(action-card)
  • ::part(action-details)

A citation pill also carries citation-kind-<type>, where the type is the connector of the source the page came from, for example docs-crawler. Style one kind apart from the others, or label it:

deskbell-widget::part(citation-kind-docs-crawler)::before {
  content: "Docs ";
  font-weight: 600;
}

A cited written answer is labelled by the widget itself: a pen glyph, the question, and a second line reading "Written answer". The line is the writtenAnswer copy key, so rename or translate it with copy, and it carries the citation-label part for styling. The pill's own part is citation-kind-corrections.

Slots

Replace a region with your own markup.

<deskbell-widget project-key="pk_live_...">
  <button slot="launcher">Ask the docs</button>
</deskbell-widget>
  • slot="launcher"
  • slot="header"
  • slot="header-actions"
  • slot="empty-state"
  • slot="footer"

Following the page's theme

color-scheme-selector names the element your site keeps its theme on, usually html. When its class, data-theme, data-color-mode or data-bs-theme says dark or light, the widget follows it and keeps following as the visitor toggles. Otherwise the configured color-scheme applies.

<deskbell-widget project-key="pk_live_..." color-scheme-selector="html"></deskbell-widget>

Recipes

A full-height side panel

<script
  async
  src="https://your-deskbell.example.com/deskbell.js"
  data-project-key="pk_live_..."
  data-position="bottom-left"
  data-launcher="none"
  data-open-on-load="true"
></script>
deskbell-widget::part(panel) {
  top: 0;
  bottom: 0;
  left: 0;
  height: auto;
  width: min(420px, 100vw);
  border-radius: 0;
}

/* The widget is position: fixed and overlays the page. Make room for it. */
body {
  padding-left: min(420px, 100vw);
}

Pinning top and bottom is enough. Leave height: auto and the panel fills the gap; height: 100vh is wrong on mobile, where browser chrome overlaps the viewport.

Set position="bottom-left" even though the ::part() rule already sets left. It clears the default right offset, which a right-to-left page would otherwise honour, snapping the rail back to the opposite edge.

launcher="none" drops the bubble and open-on-load keeps the rail up. Omit both to open it from your own control instead. The close button still renders; hide it with deskbell-widget::part(close-button) { display: none } if the rail should never close.

Reach of CSS

Recent conversations and the open thread are one view, not two panes. The widget shows one or the other, never both. A layout with the conversation list permanently beside the thread is out of reach from CSS, because the markup for both never exists at the same time.

On this page