Qaid
ARTICLE

Styling the Feedback Embed: CSS, Tokens and Dark Mode

How your CSS reaches the feedback widget, every class it draws, the tokens it reads, dark mode, the phone sheet and the thank-you screen.

Qaid Team
TL;DR

Styles meet the widget only from inside its own shadow roots, so hand them over as an option rather than a page stylesheet. Every class and token it has is listed here. The box, thank-you screen included, takes its light or dark look from your page.

This is the reference for styling the feedback widget. For one task at a time, see colours, button styles, icons and presets.

Add your own CSS

The widget draws into two shadow roots. One holds the buttons. The other, made the first time it is needed, holds everything that covers the page: the targeting marks, the message box, the markup editor and the video controls. Your page’s stylesheet reaches neither.

The CSS you pass is copied into both roots, after the widget’s own sheet. So a rule of yours with the same selector as a built-in one wins: your button.qaid-btn-submit beats the widget’s button.qaid-btn-submit.

You install with Pass the CSS as
JavaScript css: "…"
A JSON config block "cssSelector": "#qaid-theme", naming a <style> element on the page
The script tag data-css-selector="#qaid-theme", the same
<style id="qaid-theme" media="not all">
  .qaid-modal-box { border-radius: 6px; }
</style>
<script
  src="https://unpkg.com/@qaiddev/thumbs-embed/dist/embed.js"
  defer
  data-api-key="YOUR_PROJECT_KEY"
  data-endpoint="https://qaid.dev/api/feedback"
  data-css-selector="#qaid-theme"
></script>

The widget reads the block’s text once, when it starts. media="not all" stops your page from applying the same rules to itself. The Customize page builds exactly this; see The Embed Customizer.

Know the class names

Selector What it is
.qaid-buttons The row, or column, of buttons
button.qaid-btn A default button. With buttonClass set it is .qaid-btn-structural plus your class
.qaid-btn-up, .qaid-btn-down, .qaid-btn-feedback, .qaid-btn-record Thumbs up, thumbs down, the single button, the record button
.qaid-dismiss-btn, .qaid-tooltip-text The × and the tooltip
.qaid-backdrop The dimmed page behind the box
.qaid-modal-container The placed wrapper, with .qaid-below or .qaid-above
.qaid-modal-arrow, .qaid-modal-box The point toward the picked element, and the card
.qaid-modal-header, .qaid-modal-header-text The header row and its text column
button.qaid-type-toggle The up/down badge, with .qaid-type-up or .qaid-type-down
.qaid-type-static The badge in single-button mode
.qaid-modal-title, .qaid-modal-subtitle The heading and the line under it
.qaid-textarea, .qaid-btn-row, button.qaid-btn-submit The field, the button row and its one button
.qaid-bottom-sheet, .qaid-bottom-sheet-content, .qaid-bottom-sheet-handle The phone layout
.qaid-confirm, .qaid-confirm-icon, .qaid-confirm-title, .qaid-confirm-message, .qaid-confirm-close The thank-you screen. The error screen adds .qaid-confirm-error
.qaid-selected-marker, .qaid-highlight-box, .qaid-vignette Targeting marks
.qaid-annotate and .qaid-annotate-* The screenshot markup editor
.qaid-video-preview-box, .qaid-recording-indicator, .qaid-video-error Video review, the pill shown while recording, and the line shown when an upload fails

Use a setting before a rule

Option Script attribute Default Notes
modalWidth data-modal-width 400 Pixels. Ignored on phones
backdropOpacity data-backdrop-opacity 0.3 Written as an inline style, so a .qaid-backdrop rule needs !important
fontFamily data-font-family system-ui, -apple-system, sans-serif The box, sheet, editor and video review
fontSize data-font-size 16 Pixels. Every text size in the box, sheet, tooltip, editor and video review is a multiple of it. Needs thumbs-embed 1.8.0 or later
buttonSize data-button-size medium 36, 48 or 64 pixel buttons
colors data-positive-color and friends See Brand color matching

Read and set the tokens

Token Comes from Used for
--qaid-positive, --qaid-negative colors Hover fills, targeting marks, the up/down badge
--qaid-marker colors.marker Submit button, focus rings, the picked-element ring
--qaid-marker-text Black or white, worked out from the marker Text on marker-coloured buttons
--qaid-btn-size, --qaid-icon-size buttonSize Default button and icon size
--qaid-modal-width, --qaid-font-family, --qaid-font-size The options above The box
--qaid-hover-up-bg, --qaid-hover-up-color, --qaid-hover-down-bg, --qaid-hover-down-color Declared on button.qaid-btn Default hover fill and icon colour
--qaid-success Nothing; #22c55e The thank-you check mark
--qaid-error Nothing; #dc2626 The error screen’s mark
--qaid-text, --qaid-text-muted Nothing; dark greys on a light box, light greys on a dark one Thank-you and error title and message
--qaid-primary Nothing; #6365f1 Focus ring on the thank-you title

Change the first five rows through the options: the widget writes them onto each of its containers as inline styles. A button.qaid-btn { … } rule of yours can change the hover tokens, which live in the default button rule. Nothing sets the last five, so set them on :host, which is how a rule inside a shadow root names the root’s own element.

Restyle the message box

One theme, a flat paper card. Click a button to open it, send a message to see the thank-you screen.

Loading the live demo…
.qaid-modal-box,
.qaid-bottom-sheet-content {
  background: #fffdf7;
  border: 2px solid #1c1917;
  border-radius: 4px;
  box-shadow: 6px 6px 0 #1c1917;
}
/* The arrow is a border: one rule for a box below the element, one for above. */
.qaid-modal-container.qaid-below .qaid-modal-arrow { border-bottom-color: #1c1917; }
.qaid-modal-container.qaid-above .qaid-modal-arrow { border-top-color: #1c1917; }
.qaid-modal-title { color: #1c1917; font-family: Georgia, serif; }
.qaid-modal-subtitle { color: #57534e; }
.qaid-textarea { background: #fff; color: #1c1917; border: 2px solid #1c1917; border-radius: 0; }
button.qaid-btn-submit { border-radius: 0; }
:host { --qaid-text: #1c1917; --qaid-text-muted: #57534e; --qaid-success: #1c1917; }

Pair it with colors: { marker: "#1c1917" } for the dark submit button. The widget places the box as if it were about 280 pixels tall. Heavy padding can push it past the edge of a short window, where it scrolls inside itself.

Force light or dark

The box, the sheet, the video review and the editor’s toolbar use the CSS light-dark() function. It follows the color-scheme of your page, not the visitor’s system on its own.

Your page declares The widget shows
Nothing Light, always
color-scheme: light dark Light or dark, following the system
color-scheme: dark Dark, always

To pin the widget whatever the page says, add :host { color-scheme: dark; } (or light) to your CSS.

Loading the film…

The thank-you and error screens switch too, in thumbs-embed 1.8.0 or later. Setting --qaid-text or --qaid-text-muted fixes their colour in both modes.

Style the phone sheet

In a window under 640 pixels wide, the box opens as a sheet along the bottom: .qaid-bottom-sheet holding .qaid-bottom-sheet-content, which starts with the grab bar .qaid-bottom-sheet-handle. It has no arrow, ignores modalWidth, and pads itself clear of the phone’s home bar. Inside, the header, field and button keep their usual classes. Wherever you style .qaid-modal-box, style .qaid-bottom-sheet-content too.

Style the thank-you screen

Once the message is sent, the card’s contents are swapped for .qaid-confirm: a round check mark (.qaid-confirm-icon, filled with --qaid-success), a title, a message, and a Close button. That button also carries button.qaid-btn-submit, so your submit rules reach it.

Loading the film…

The screen shows once the server takes the message. Set hideConfirmation: true (data-hide-confirmation="true") to close the box straight away instead. The words come from text.confirmationTitle, confirmationMessage and confirmationClose; see Text customization.

If the server refuses the message, or the network fails, the same card shows with .qaid-confirm-error added: a red mark filled with --qaid-error, the errorTitle and errorMessage text, and the same Close button. It shows even with hideConfirmation.

For visitors whose system asks for less motion, the widget switches off every transition and animation, yours included. Custom button styles has more.

Back to all articles