> ## 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.

> ## Agent Instructions
> To search or read these docs, connect the Ringg docs MCP server at https://docs.ringg.ai/mcp (no key needed; tools search_ringg_ai and query_docs_filesystem_ringg_ai) instead of browsing pages one by one. Setup for each client: https://docs.ringg.ai/resources/mcp-server/docs-mcp-server/mcp-for-ai-assistants.md
> The dashboard labels agents "Assistants"; these docs say "agent". Both mean the same object, identified by agent_id.
> API base URL: https://prod-api.ringg.ai/ca/api/v0. Send the workspace API key in the X-API-KEY header, from server-side code only.
> Placing a call dials a real phone number and spends credits. Confirm the number with the user before calling.
> To act on a Ringg workspace (place calls, edit agents, read transcripts), use the separate Ringg workspace MCP server at https://mcp.ringg.ai/mcp: https://docs.ringg.ai/resources/mcp-server/workspace-mcp-server/overview.md

# Web widget styling

> Restyle, hide or script any part of the Ringg AI web widget with stable data-ringg attributes and live state attributes, plus the full element reference.

Target the widget's `data-ringg` attributes from CSS or JavaScript when the [configuration options](/documentation/deploy/web-and-apps/web-widget/configuration) don't cover what you need. Don't target the `ringg_ai-*` class names: they are generated and change between releases.

## Before you start

<Columns cols={2}>
  <Card title="An installed widget" icon="globe" href="/documentation/deploy/web-and-apps/web-widget/overview" horizontal>
    The attributes are on the elements it renders.
  </Card>

  <Card title="A 2.0 widget version" icon="git-branch" href="/documentation/deploy/web-and-apps/web-widget/launch-checklist#version-pinning" horizontal>
    The attributes ship in the `2.0.0-beta` builds; the 1.0 line doesn't have them.
  </Card>
</Columns>

## Recipes

### Restyle the launcher

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

### Mute from your own button

```javascript theme={null}
document.querySelector('[data-ringg="mute-button"]')?.click();
```

### Glow on lit visualizer dots

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

### Wait for the widget to load

The trigger renders when `loadAgent` finishes; `widget-root` appears only once the panel opens.

```javascript theme={null}
function onWidgetReady(cb) {
  const found = document.querySelector('[data-ringg="trigger-button"]');
  if (found) return cb(found);

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

onWidgetReady(() => analytics.track("Ringg widget loaded"));
```

For open, close, conversation and rating changes, listen to the [widget events](/documentation/deploy/web-and-apps/web-widget/events) instead of watching the DOM.

## State attributes

These update live. Use them in attribute selectors, or watch them with `MutationObserver`.

| Attribute | Values | Emitted on |
| - | - | - |
| `data-ringg-role` | `"agent"` / `"user"` | `message` |
| `data-ringg-muted` | `"true"` / `"false"` | `mute-button` |
| `data-ringg-connecting` | `"true"` / `"false"` | `header-status-dot` |
| `data-ringg-align` | `"center"` / `"end"` | `quick-replies` (centered in voice, right-aligned in chat) |
| `data-ringg-style` | `"primary"` / `"secondary"` / `"outline"` / `"destructive"` | `quick-reply-button`, `option-row` |
| `data-ringg-variant` | `"transcript"` | `feedback-screen` (present when the ended transcript stays readable) |
| `data-ringg-active` | `"true"` / `"false"` | `slash-command-item` |
| `data-ringg-filled` | `"true"` / `"false"` | `feedback-star` |
| `data-ringg-lit` | `"true"` / `"false"` | `voice-animation-dot` |
| `data-ringg-level` | `"info"` / `"error"` | `system-log` |
| `data-ringg-step-active` | `"true"` / `"false"` | `flow-step` |
| `data-ringg-step-completed` | `"true"` / `"false"` | `flow-step` |
| `data-block-id` | authored id string | any Block Kit node with an author id |
| `data-action-id` | action id string | `block-button` |

```css theme={null}
[data-ringg="mute-button"][data-ringg-muted="true"] {
  background: var(--brand-danger);
}
```

```javascript theme={null}
const muteButton = document.querySelector('[data-ringg="mute-button"]');

new MutationObserver(() => {
  console.log("muted?", muteButton.getAttribute("data-ringg-muted"));
}).observe(muteButton, {
  attributes: true,
  attributeFilter: ["data-ringg-muted"],
});
```

## Element reference

Elements are grouped by where they appear in the widget.

### Top level

| `data-ringg` | Element |
| - | - |
| `trigger-button` | Floating launcher button. Visible when the widget is closed. |
| `trigger-icon` | The `<img>` rendered inside the trigger button. |
| `widget-root` | Outer widget container that wraps every other widget element. Top of the panel tree. |
| `widget-body` | Inner flex column inside the widget. Wraps the panel and footer. |
| `widget-panel` | Padded main panel. Header, body, and controls render here. |
| `minimize-button` | Top-right minimize icon. Only present during a call. |
| `close-button` | Top-right close icon. Aria label flips to `"End call"` during a call. |
| `voice-animation-wrapper` | Container around the voice visualizer. Audio mode only. |
| `body-spacer` | Empty placeholder that keeps controls anchored when the body is empty. |
| `transcript` | Scrollable message area. |
| `transcript-list` | Inner flex list of messages. |
| `controls-bar` | Transparent bar anchoring the message input over the transcript (chat mode). The transcript scrolls underneath it. |
| `attached-buttons` | Full-width wrapper for quick replies rendered directly below an agent message. |
| `connecting-status` | Wrapper for the pre-call connecting state ("Connecting…" label + loading bar). |
| `connecting-label` | The `"Connecting…"` `<p>` above the loading bar. |
| `error-message` | Inline error text. |
| `legal-disclaimer` | Pre-call legal `<p>`. |
| `legal-link-privacy` | Privacy policy link inside the legal disclaimer. |
| `legal-link-terms` | T\&C link inside the legal disclaimer. |

### Header

| `data-ringg` | Element |
| - | - |
| `header` | In-call header band. Only present during a call, which integrators use to detect an active call (e.g. `:has([data-ringg="header"])`). Absolute-positioned frosted overlay. |
| `intro` | Pre-call container. Centered logo/title/description block on the start screen (the pre-call counterpart to `header`). |
| `header-logo` | Logo chip. Both pre-call (rounded square) and in-call. |
| `header-logo-image` | The `<img>` inside the logo chip. |
| `header-text` | Text wrapper that holds the title and description. |
| `header-title` | Title `<h2>`. |
| `header-description` | Description `<p>`. Shown pre-call and in-call. Truncated in-call (full text on hover via `title`). |
| `header-status-dot` | Presence dot. In-call only. Carries `data-ringg-connecting`: muted and pulsing while connecting, success-colored once live. |
| `header-status` | Screen-reader-only status `<p>`. In-call only; visible status is the dot. The pre-call connecting status moved to `connecting-label`. |

### Call controls (audio mode)

Compact centered mute/end pair, no text labels, since icons carry the meaning.

| `data-ringg` | Element |
| - | - |
| `call-controls` | Row container holding the call control buttons. |
| `mute-button` | Mute toggle button (aria-label `"Mute"` / `"Unmute"`). Carries `data-ringg-muted`. |
| `end-call-button` | End-call button (aria-label `"End call"`). |

### Action buttons (start screen)

The start screen shows both buttons side by side (Chat left, Call right), each starting its mode directly. With `hideTabSelector: true` only the `defaultTab` mode's button renders, full-width.

| `data-ringg` | Element |
| - | - |
| `start-actions` | Row wrapping the Chat + Call pair. Only when both buttons are shown. |
| `start-call-button` | Starts a voice call. |
| `start-chat-button` | Starts a chat. |

### Loading bar

| `data-ringg` | Element |
| - | - |
| `loading-bar` | Loading bar container. |
| `loading-bar-track` | Background track. |
| `loading-bar-fill` | Animated fill. |

### Quick replies and options

Quick-reply chips (`free` presentation) and boxed option lists rendered below an agent message.

| `data-ringg` | Element |
| - | - |
| `quick-replies` | Chip row container. Carries `data-ringg-align` (`"center"` in voice, `"end"` in chat). |
| `quick-reply-button` | Each pill chip. Carries `data-ringg-style`. |
| `buttons-step-title` | Optional title `<p>` above the chips. |
| `options-list` | Boxed single-choice list container (rows divided by hairlines). |
| `option-row` | Each option row. Carries `data-ringg-style`. |
| `option-radio` | Radio affordance inside an option row. |

### Typing indicator

Shown while an agent reply is pending. Cycles through the `typingWords` config, each word rendered with a left→right text shimmer.

| `data-ringg` | Element |
| - | - |
| `typing-indicator` | Outer row. |
| `typing-indicator-word` | The shimmering current word `<span>`. |

### Messages

| `data-ringg` | Element |
| - | - |
| `message` | Outer message row. Carries `data-ringg-role="agent"` / `"user"`. |
| `message-bubble` | The bubble inside a message row. Agent messages are bubble-less unless the theme sets `agentBubbleColor`. |
| `message-content` | Inner column inside the bubble. |
| `message-body` | Markdown-rendered message body. |
| `message-source` | "Source:" link rendered below a message. |

### System log pill

The inline activity feed in the transcript. Rendered only with `eventLogs: { enabled: true }` in `loadAgent`; see [Agent actions](/documentation/deploy/web-and-apps/web-widget/data#agent-actions).

| `data-ringg` | Element |
| - | - |
| `system-log` | Outer container. Carries `data-ringg-level="info"` / `"error"`. |
| `system-log-pill` | Pill body. |
| `system-log-dot` | Status dot. |
| `system-log-label` | Label text. |
| `system-log-meta` | Optional meta text. |

### Slash command menu

| `data-ringg` | Element |
| - | - |
| `slash-command-menu` | Outer container. |
| `slash-command-header` | Header bar with the title. |
| `slash-command-heading` | "Commands" label. |
| `slash-command-list` | Scrollable list of command items. |
| `slash-command-item` | Each command button. Carries `data-ringg-active`. |
| `slash-command-icon` | Icon square inside an item. |
| `slash-command-text` | Text column inside an item. |
| `slash-command-name` | Command display name. |
| `slash-command-description` | Command description text. |

### Voice animation

| `data-ringg` | Element |
| - | - |
| `voice-animation` | Visualizer root (set on the same element that receives `localTrack`/`remoteTrack`). |
| `voice-animation-column` | One column of dots (22 columns per visualizer). |
| `voice-animation-dot` | Individual dot. Carries `data-ringg-lit`, which flips per audio frame. |

`data-ringg-lit` updates at audio rate, so a heavy transition or an expensive observer on it runs every frame. Keep transitions light, for example `transition: opacity 50ms`.

### Interactive flow

| `data-ringg` | Element |
| - | - |
| `interactive-flow` | Outer container. |
| `flow-stepper` | Stepper header (shown only when multi-step). |
| `flow-stepper-progress` | Row of step indicators. |
| `flow-step` | Each step + connector pair. Carries `data-ringg-step-active` and `data-ringg-step-completed`. |
| `flow-step-indicator` | Numbered/check circle for each step. |
| `flow-step-connector` | Line between steps. |
| `flow-step-title` | Current step title `<p>`. |
| `flow-content` | Step body wrapper. |
| `flow-back-button` | Back navigation button. |
| `flow-submitted-selection` | Submitted-state wrapper. |
| `flow-submitted-pill` | Pill showing the selected choice. |

### Message input (text mode)

| `data-ringg` | Element |
| - | - |
| `message-input-form` | The `<form>` element. |
| `message-input` | Outer pill container carrying the frosted-glass treatment; transparent gutters. Also wraps the slash menu when open (going solid). |
| `message-input-row` | Row containing the input field + send button. |
| `message-input-field` | The `<input>` element. |
| `message-send-button` | Send arrow button. |

### Feedback screen

When the ended conversation has text messages, the transcript stays readable and the rating renders as a footer below it (`data-ringg-variant="transcript"`); tapping a star submits immediately. The legacy centered card (comment box + submit/skip) renders when there is no transcript.

With a transcript:

| `data-ringg` | Element |
| - | - |
| `feedback-screen` | Container. Carries `data-ringg-variant="transcript"`. |
| `feedback-footer` | Divider + prompt + stars block below the read-only conversation. |
| `conversation-ended` | "Conversation ended" hairline divider row. |
| `feedback-prompt` | "Please rate your experience" `<p>`. |
| `feedback-stars` | Star row. |
| `feedback-star` | Each star button. Carries `data-ringg-filled`. |

Without a transcript:

| `data-ringg` | Element |
| - | - |
| `feedback-screen` | Container. |
| `feedback-header` | Title + description block. |
| `feedback-title` | Title `<h3>`. |
| `feedback-description` | Description `<p>`. |
| `feedback-stars` | Star row. |
| `feedback-star` | Each star button. |
| `feedback-comment` | Comment `<textarea>`. |
| `feedback-actions` | Submit + skip wrapper. |
| `feedback-submit` | Submit button. |
| `feedback-skip` | Skip button. |

### Components

The cards, forms and pickers built under **Embed & Widgets → Components** (see [Components](/documentation/deploy/web-and-apps/web-widget/components)). They render full-width in the transcript.

| `data-ringg` | Element |
| - | - |
| `blocks-widget` | Transcript wrapper around one Block Kit instance. |
| `blocks` | Root of the rendered tree. |
| `block-<type>` | Every rendered node, named by its catalog type (e.g. `block-card`, `block-carousel`, `block-table`, `block-steps`, `block-input_rating`). Carries `data-block-id` when the author set one. |
| `block-button` | Action button. Carries `data-block-id` and `data-action-id`. |
| `block-image-loading` | Placeholder shown while a `block-image` loads. |
| `blocks-unsupported` | Fallback `<p>` when the payload needs a newer widget version. |

### 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-ringg` | Element |
| - | - |
| `end-call-dialog` | Dialog content root. |
| `end-call-dialog-header` | Header wrapper inside the dialog. |
| `end-call-dialog-title` | Dialog title `<h2>`. |
| `end-call-dialog-description` | Dialog description `<p>`. |
| `end-call-dialog-footer` | Dialog footer wrapper. |
| `end-call-cancel` | Cancel button. |
| `end-call-confirm` | End-call confirm button. |

## Next steps

<Card title="Prepare for launch" icon="shield-check" href="/documentation/deploy/web-and-apps/web-widget/launch-checklist" horizontal>
  Domains, <Tooltip tip="Content Security Policy: the header that controls which scripts and styles your site may load.">CSP</Tooltip>, version pinning and browser QA before production.
</Card>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.