Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.ringg.ai/llms.txt

Use this file to discover all available pages before exploring further.

Every notable element rendered by the widget carries a stable data-ringg="<name>" attribute, and state-bearing elements carry additional data-ringg-<state> attributes that update as the widget changes state. Use them as CSS selectors or JS query targets to restyle, hide, rearrange, or script the widget.
Do not target the internal ringg_ai-* class names. They are minified output and change between releases. Style and script the widget through data-ringg attributes only.

Quick example

[data-ringg="trigger-button"] {
  background: #4F46E5;
  border-radius: 50%;
}

[data-ringg="message"][data-ringg-role="agent"] [data-ringg="message-bubble"] {
  font-style: italic;
}
document.querySelector('[data-ringg="mute-button"]')?.click();

State attributes

State-bearing elements expose additional data-ringg-<state> attributes. They update live, so you can drive CSS off them with attribute selectors or watch them with MutationObserver.
AttributeValuesEmitted on
data-ringg-active"true" / "false"tab, slash-command-item
data-ringg-lit"true" / "false"voice-animation-dot
data-ringg-role"agent" / "user"message
data-ringg-level"info" / "error"system-log
data-ringg-step-active"true" / "false"flow-step
data-ringg-step-completed"true" / "false"flow-step
data-ringg-tab-idtab id string, for example "audio", "text"tab
Compound selector example:
[data-ringg="tab"][data-ringg-active="true"] {
  color: var(--brand-primary);
  border-bottom-color: var(--brand-primary);
}
Observer example:
const audioTab = document.querySelector(
  '[data-ringg="tab"][data-ringg-tab-id="audio"]'
);

new MutationObserver(() => {
  console.log("audio tab active?", audioTab.getAttribute("data-ringg-active"));
}).observe(audioTab, {
  attributes: true,
  attributeFilter: ["data-ringg-active"],
});

Element reference

Elements are grouped by where they appear in the widget.

Top level

data-ringgElement
trigger-buttonFloating launcher button. Visible when the widget is closed.
trigger-iconThe <img> rendered inside the trigger button.
widget-rootOuter widget container that wraps every other widget element. Top of the panel tree.
widget-bodyInner flex column inside the widget. Wraps the panel and footer.
widget-panelPadded main panel. Header, body, and controls render here.
minimize-buttonTop-right minimize icon. Only present during a call.
close-buttonTop-right close icon. Aria label flips to "End call" during a call.
voice-animation-wrapperContainer around the voice visualizer. Audio mode only.
body-spacerEmpty placeholder that keeps controls anchored when the body is empty.
transcriptScrollable message area.
transcript-listInner flex list of messages.
attached-buttonsWrapper for inline buttons attached to an agent message.
error-messageInline error text.
legal-disclaimerPre-call legal <p>.
legal-link-privacyPrivacy policy link inside the legal disclaimer.
legal-link-termsT&C link inside the legal disclaimer.
data-ringgElement
headerHeader container. Only present during a call (absolute-positioned band).
header-logoLogo circle. Both pre-call and in-call.
header-logo-imageThe <img> inside the logo circle.
header-textText column wrapper that holds the title and description/status.
header-titleTitle <h2>.
header-descriptionPre-call description <p>. Only present pre-call.
header-statusStatus <p> shown during a call ("Connecting…", "Call in Progress").

Call controls (audio mode)

data-ringgElement
call-controlsRow container holding the call control buttons.
mute-controlMute column wrapping the button + label.
mute-buttonMute toggle button.
mute-label"Mute" / "Unmute" text under the button.
end-call-controlEnd-call column wrapping the button + label.
end-call-buttonEnd-call button.
end-call-label"End Call" text under the button.

Action buttons (start screen)

data-ringgElement
start-call-buttonStart-call button. Rendered when callMode === "audio".
start-chat-buttonStart-chat button. Rendered when callMode === "text".

Loading bar

data-ringgElement
loading-barLoading bar container.
loading-bar-trackBackground track.
loading-bar-fillAnimated fill.

Tabs

data-ringgElement
tabsOuter container with top border.
tabs-listRow of tab buttons.
tabIndividual tab button. Carries data-ringg-tab-id and data-ringg-active.
tab-labelTab label <span>.

Messages

data-ringgElement
messageOuter message row. Carries data-ringg-role="agent" / "user".
message-bubbleThe bubble inside a message row.
message-contentInner column inside the bubble.
message-bodyMarkdown-rendered message body.
message-source”Source:” link rendered below a message.
message-attachmentWrapper for embedded interactive content (buttons, forms, etc).

System log pill

The system log pill renders the inline activity feed in the transcript. It only shows up when you opt in via loadAgent({ eventLogs: { enabled: true } }). See Agent Actions for details.
data-ringgElement
system-logOuter container. Carries data-ringg-level="info" / "error".
system-log-pillPill body.
system-log-dotStatus dot.
system-log-labelLabel text.
system-log-metaOptional meta text.

Slash command menu

data-ringgElement
slash-command-menuOuter container.
slash-command-headerHeader bar with the title.
slash-command-heading”Commands” label.
slash-command-listScrollable list of command items.
slash-command-itemEach command button. Carries data-ringg-active.
slash-command-iconIcon square inside an item.
slash-command-textText column inside an item.
slash-command-nameCommand display name.
slash-command-descriptionCommand description text.

Voice animation

data-ringgElement
voice-animationVisualizer root (set on the same element that receives localTrack/remoteTrack).
voice-animation-columnOne column of dots (22 columns per visualizer).
voice-animation-dotIndividual dot. Carries data-ringg-lit, which flips per audio frame.
data-ringg-lit updates at audio rate. Keep CSS transitions on it lightweight, for example transition: opacity 50ms. Heavy transitions or expensive observers on this attribute will fire every frame.

Interactive flow

data-ringgElement
interactive-flowOuter container.
flow-stepperStepper header (shown only when multi-step).
flow-stepper-progressRow of step indicators.
flow-stepEach step + connector pair. Carries data-ringg-step-active and data-ringg-step-completed.
flow-step-indicatorNumbered/check circle for each step.
flow-step-connectorLine between steps.
flow-step-titleCurrent step title <p>.
flow-contentStep body wrapper.
flow-back-buttonBack navigation button.
flow-submitted-selectionSubmitted-state wrapper.
flow-submitted-pillPill showing the selected choice.

Message input (text mode)

data-ringgElement
message-input-formThe <form> element.
message-inputOuter pill container. Also wraps the slash menu when open.
message-input-rowRow containing the input field + send button.
message-input-fieldThe <input> element.
message-send-buttonSend arrow button.

Feedback screen

data-ringgElement
feedback-screenContainer.
feedback-headerTitle + description block.
feedback-titleTitle <h3>.
feedback-descriptionDescription <p>.
feedback-starsStar row.
feedback-starEach star button.
feedback-commentComment <textarea>.
feedback-actionsSubmit + skip wrapper.
feedback-submitSubmit button.
feedback-skipSkip button.
data-ringgElement
footerFooter bar at the bottom of the widget.
footer-brand”Ringg AI” brand text.

End-call confirm dialog

The end-call confirm dialog renders in a portal outside [data-ringg="widget-root"]. Scope its selectors at the document level.
data-ringgElement
end-call-dialogDialog content root.
end-call-dialog-headerHeader wrapper inside the dialog.
end-call-dialog-titleDialog title <h2>.
end-call-dialog-descriptionDialog description <p>.
end-call-dialog-footerDialog footer wrapper.
end-call-cancelCancel button.
end-call-confirmEnd-call confirm button.

Common recipes

Restyle the launcher

[data-ringg="trigger-button"] {
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  box-shadow: 0 10px 25px rgba(99, 102, 241, 0.4);
}

Highlight the active tab

[data-ringg="tab"][data-ringg-active="true"] {
  color: var(--brand-primary);
  border-bottom-color: var(--brand-primary);
}

Glow on lit visualizer dots

[data-ringg="voice-animation-dot"][data-ringg-lit="true"] {
  box-shadow: 0 0 8px currentColor;
}

Italicize agent messages

[data-ringg="message"][data-ringg-role="agent"] [data-ringg="message-bubble"] {
  font-style: italic;
}
[data-ringg="footer"] {
  display: none;
}

Wait for the widget to mount

function onWidgetReady(cb) {
  const found = document.querySelector('[data-ringg="widget-root"]');
  if (found) return cb(found);

  const observer = new MutationObserver(() => {
    const el = document.querySelector('[data-ringg="widget-root"]');
    if (el) {
      observer.disconnect();
      cb(el);
    }
  });
  observer.observe(document.body, { childList: true, subtree: true });
}

onWidgetReady((root) => {
  analytics.track("Ringg Widget Mounted");
});

Capture feedback submissions

document.addEventListener("click", (event) => {
  if (event.target.closest('[data-ringg="feedback-submit"]')) {
    analytics.track("Ringg Feedback Submitted");
  }
});
For lifecycle hooks like open/close, conversation start/end, and the feedback payload itself, listen to the events documented in Widget Lifecycle Events. Use data-ringg attributes for UI affordances the widget does not surface as events.

QA notes

All your selectors target [data-ringg="..."] attributes, not internal ringg_ai-* class names.
Compound selectors with state attributes (for example [data-ringg="tab"][data-ringg-active="true"]) update live as the widget changes state.
Selectors for the end-call confirm dialog are document-scoped, not nested under [data-ringg="widget-root"].
CSS transitions on [data-ringg-lit] are lightweight, so per-frame state changes do not cause jank.