UI / Component library

Small parts. One system.

Practical Tailwind components for everyday IVR work. Compare themes and inspect the HTML.

This page covers Tailwind equivalents for TWR’s 24 Bootstrap component categories, plus forms, tables, and IVR-specific patterns. Examples use fictional data; interactions affect this page only. HTML disclosures are included by the Hugo build and remain readable without JavaScript. Component styles live in brand/components.css; demo behavior lives in site/site.js.

Buttons

Use one clear primary action per decision. Secondary actions keep the same size and boundary. Destructive actions explicitly name what will be removed or stopped. Disabled controls need a nearby explanation when the reason is not obvious.

Actions / Primary, secondary, destructive, disabled

Publicarea este indisponibilă în acest specimen. Celelalte acțiuni deschid dialoguri demonstrative.

View HTML
<p class="demo-caption">Actions / Primary, secondary, destructive, disabled</p>
<div class="flex flex-wrap gap-3">
  <button class="ivr-btn" type="button" data-dialog-open="save-demo">Salvează ciorna</button>
  <button class="ivr-btn ivr-btn-secondary" type="button" data-dialog-open="save-demo">Vezi detaliile</button>
  <button class="ivr-btn ivr-btn-danger" type="button" data-dialog-open="delete-demo">Șterge contactul</button>
  <button class="ivr-btn" type="button" disabled>Publică versiunea</button>
</div>
<p class="ivr-help">Publicarea este indisponibilă în acest specimen. Celelalte acțiuni deschid dialoguri demonstrative.</p>

Forms

Labels persist above the field. Help describes the expected value. Errors explain the problem using text and a stronger border. Native browser validation is enabled in this demo.

Un nume ușor de recunoscut de echipă.

View HTML
<form data-demo-form>
  <div class="grid gap-5 sm:grid-cols-2">
    <div>
      <label class="ivr-label" for="flow-name">Numele fluxului</label>
      <input class="ivr-input" id="flow-name" name="name" value="Asistență clienți" aria-describedby="flow-help" required>
      <p id="flow-help" class="ivr-help">Un nume ușor de recunoscut de echipă.</p>
    </div>
    <div>
      <label class="ivr-label" for="flow-locale">Limba mesajelor</label>
      <select id="flow-locale" name="locale" class="ivr-input">
        <option>Română</option>
        <option>English</option>
      </select>
    </div>
    <div class="sm:col-span-2">
      <label class="ivr-label" for="flow-message">Mesaj de întâmpinare</label>
      <textarea class="ivr-input" id="flow-message" name="message" rows="3" required>Bun venit. Pentru vânzări, apasă 1. Pentru suport, apasă 2.</textarea>
    </div>
    <div>
      <label class="flex min-h-11 items-center gap-3 text-sm">
        <input type="checkbox" name="schedule" class="size-4 accent-brand">
        Folosește programul de lucru
      </label>
    </div>
  </div>
  <button class="ivr-btn mt-5" type="submit">Salvează exemplul</button>
  <p class="ivr-help min-h-5" role="status" aria-live="polite"></p>
</form>

Introdu un număr valid, inclusiv prefixul de țară.

View HTML
<label class="ivr-label" for="invalid-number">Număr de telefon</label>
<input class="ivr-input max-w-md" id="invalid-number" value="abc" aria-invalid="true" aria-describedby="number-error">
<p id="number-error" class="mt-2 text-xs text-danger">Introdu un număr valid, inclusiv prefixul de țară.</p>

Badge

Always include written status. Distinguish lifecycle states instead of using a generic green “Done” for everything.

Fără rutăCiornăPublicat · v3Activ pe număr · v2Activare eșuată
View HTML
<div class="flex flex-wrap gap-3">
  <span class="ivr-badge ivr-badge-neutral">Fără rută</span>
  <span class="ivr-badge ivr-badge-warning">Ciornă</span>
  <span class="ivr-badge ivr-badge-info">Publicat · v3</span>
  <span class="ivr-badge">Activ pe număr · v2</span>
  <span class="ivr-badge ivr-badge-danger">Activare eșuată</span>
</div>

Alerts

Static specimens do not announce themselves as urgent errors on page load. Add role="alert" when an urgent error is actually inserted by an application.

Versiune publicată. Poți activa v3 pe un număr de telefon.
Pas neconectat. Leagă acest pas de traseul principal înainte de publicare.
Nu am putut activa versiunea. Verifică starea rutei înainte de a încerca din nou.
Exemplu informativ. Poți închide acest mesaj.
View HTML
<div class="ivr-alert">
  <strong>Versiune publicată.</strong>
  Poți activa v3 pe un număr de telefon.
</div>
<div class="ivr-alert ivr-alert-warning">
  <strong>Pas neconectat.</strong>
  Leagă acest pas de traseul principal înainte de publicare.
</div>
<div class="ivr-alert ivr-alert-danger">
  <strong>Nu am putut activa versiunea.</strong>
  Verifică starea rutei înainte de a încerca din nou.
</div>
<div class="ivr-alert flex items-center justify-between gap-4" data-dismissible>
  <span>
    <strong>Exemplu informativ.</strong>
    Poți închide acest mesaj.
  </span>
  <button type="button" class="ivr-close" data-dismiss aria-label="Închide mesajul demonstrativ"></button>
</div>

Card

IVR / CUSTOMER-SUPPORT

Asistență clienți

Ciornă · v4

Rutare după program, mesaj de întâmpinare și meniu principal.

Pași în ciornă
6
Ultima versiune publicată
v3
Versiune pe rută
v2
View HTML
<article class="ivr-card">
  <div class="flex flex-wrap items-start justify-between gap-3">
    <div>
      <p class="text-xs text-muted">IVR / CUSTOMER-SUPPORT</p>
      <h3 class="mt-2 text-xl font-semibold">Asistență clienți</h3>
    </div>
    <span class="ivr-badge ivr-badge-warning">Ciornă · v4</span>
  </div>
  <p class="mt-4 text-sm text-muted">Rutare după program, mesaj de întâmpinare și meniu principal.</p>
  <dl class="mt-6 grid gap-5 sm:grid-cols-3">
    <div>
      <dt class="text-xs text-muted">Pași în ciornă</dt>
      <dd class="mt-1 font-semibold tabular-nums">6</dd>
    </div>
    <div>
      <dt class="text-xs text-muted">Ultima versiune publicată</dt>
      <dd class="mt-1 font-semibold">v3</dd>
    </div>
    <div>
      <dt class="text-xs text-muted">Versiune pe rută</dt>
      <dd class="mt-1 font-semibold">v2</dd>
    </div>
  </dl>
</article>

Tables

Tables keep stable headers and comparable numbers. On mobile, scroll the table frame, not the whole page. Use captions and header scopes.

Istoric apeluri · date ilustrative
ApelantDataDuratăRezultat
+40 700 000 10113 oct. 2026 · 09:4202:14Răspuns
+40 700 000 10213 oct. 2026 · 09:3800:48Mesaj vocal
+40 700 000 10313 oct. 2026 · 09:3100:12Fără răspuns
View HTML
<div class="ivr-table-frame">
  <table class="ivr-table">
    <caption>Istoric apeluri · date ilustrative</caption>
    <thead>
      <tr>
        <th scope="col">Apelant</th>
        <th scope="col">Data</th>
        <th scope="col">Durată</th>
        <th scope="col">Rezultat</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="whitespace-nowrap font-mono">+40 700 000 101</td>
        <td class="whitespace-nowrap">13 oct. 2026 · 09:42</td>
        <td class="tabular-nums">02:14</td>
        <td>
          <span class="ivr-badge">Răspuns</span>
        </td>
      </tr>
      <tr>
        <td class="whitespace-nowrap font-mono">+40 700 000 102</td>
        <td class="whitespace-nowrap">13 oct. 2026 · 09:38</td>
        <td class="tabular-nums">00:48</td>
        <td>
          <span class="ivr-badge ivr-badge-info">Mesaj vocal</span>
        </td>
      </tr>
      <tr>
        <td class="whitespace-nowrap font-mono">+40 700 000 103</td>
        <td class="whitespace-nowrap">13 oct. 2026 · 09:31</td>
        <td class="tabular-nums">00:12</td>
        <td>
          <span class="ivr-badge ivr-badge-warning">Fără răspuns</span>
        </td>
      </tr>
    </tbody>
  </table>
</div>

Empty states

Flux de apel

Încă nu ai adăugat pași.

Începe cu un mesaj de întâmpinare, apoi construiește traseul apelantului.

Vezi primul pas ↗
View HTML
<div class="ivr-empty">
  <p class="eyebrow">Flux de apel</p>
  <h3 class="mt-4 text-xl font-semibold">Încă nu ai adăugat pași.</h3>
  <p class="mt-3 text-sm text-muted">Începe cu un mesaj de întâmpinare, apoi construiește traseul apelantului.</p>
  <a class="ivr-btn mt-6" href="workspace.html#flow-editor">Vezi primul pas ↗</a>
</div>

Accordion

Use native details/summary for optional context. Keep necessary instructions visible outside the disclosure.

Ce se întâmplă la publicare?

Publicarea creează o versiune imuabilă a fluxului. Activarea acelei versiuni pe un număr este o acțiune separată.

Ce se întâmplă la activare?

Ruta telefonică folosește versiunea publicată selectată după confirmarea deployment-ului.

View HTML
<div class="space-y-3">
  <details name="version-accordion" class="rounded-control border border-control p-4" open>
    <summary class="font-semibold">Ce se întâmplă la publicare?</summary>
    <p class="mt-4 text-sm leading-relaxed">Publicarea creează o versiune imuabilă a fluxului. Activarea acelei versiuni pe un număr este o acțiune separată.</p>
  </details>
  <details name="version-accordion" class="rounded-control border border-control p-4">
    <summary class="font-semibold">Ce se întâmplă la activare?</summary>
    <p class="mt-4 text-sm leading-relaxed">Ruta telefonică folosește versiunea publicată selectată după confirmarea deployment-ului.</p>
  </details>
</div>

These native modal dialogs trap focus through the browser and close with Escape. A consuming app owns submission, error handling, focus restoration, and the actual authorization rules.

Exemplu de dialog

Acest control demonstrează stilul și comportamentul nativ. Nu salvează date în aplicație.

Ștergi acest contact?

Într-o aplicație, numește contactul și explică efectul. Aici nu este șters niciun contact.

View HTML
<button type="button" class="ivr-btn ivr-btn-secondary" data-dialog-open="save-demo">Deschide dialogul demonstrativ</button>
<dialog id="save-demo" class="m-auto w-[calc(100%_-_2rem)] max-w-md rounded-card border border-control bg-surface p-6 text-ink backdrop:bg-black/40" aria-labelledby="save-title">
  <div class="flex items-start justify-between gap-4">
    <h3 id="save-title" class="text-xl font-semibold">Exemplu de dialog</h3>
    <button type="button" class="ivr-close" data-dialog-close aria-label="Închide dialogul"></button>
  </div>
  <p class="mt-4 text-sm leading-relaxed text-muted">Acest control demonstrează stilul și comportamentul nativ. Nu salvează date în aplicație.</p>
  <button type="button" class="ivr-btn mt-6" data-dialog-close autofocus>Închide</button>
</dialog>
<dialog id="delete-demo" class="m-auto w-[calc(100%_-_2rem)] max-w-md rounded-card border border-control bg-surface p-6 text-ink backdrop:bg-black/40" aria-labelledby="delete-title">
  <div class="flex items-start justify-between gap-4">
    <h3 id="delete-title" class="text-xl font-semibold">Ștergi acest contact?</h3>
    <button type="button" class="ivr-close" data-dialog-close aria-label="Închide confirmarea"></button>
  </div>
  <p class="mt-4 text-sm leading-relaxed text-muted">Într-o aplicație, numește contactul și explică efectul. Aici nu este șters niciun contact.</p>
  <div class="mt-6 flex flex-wrap gap-3">
    <button type="button" class="ivr-btn ivr-btn-secondary" data-dialog-close autofocus>Anulează</button>
    <button type="button" class="ivr-btn ivr-btn-danger" data-dialog-close>Închide exemplul</button>
  </div>
</dialog>

Token reference

Click a value to copy it. Clipboard access may require HTTPS; the page displays a manual fallback when unavailable. These are fixed light identity values, not the adaptive dark-mode role values.

View HTML
<div class="grid gap-3 sm:grid-cols-2">
  <button class="ivr-btn ivr-btn-secondary justify-between" type="button" data-copy="#1F7558">
    Forest
    <span class="font-mono">#1F7558</span>
  </button>
  <button class="ivr-btn ivr-btn-secondary justify-between" type="button" data-copy="#14231F">
    Ink
    <span class="font-mono">#14231F</span>
  </button>
  <button class="ivr-btn ivr-btn-secondary justify-between" type="button" data-copy="#EDF6F1">
    Mint
    <span class="font-mono">#EDF6F1</span>
  </button>
  <button class="ivr-btn ivr-btn-secondary justify-between" type="button" data-copy="#FBFCFA">
    Canvas
    <span class="font-mono">#FBFCFA</span>
  </button>
</div>
<p id="copy-status" role="status" class="ivr-help min-h-5" aria-live="polite"></p>

Name the current object and preserve the account context. The last item is text, not a redundant self-link.

View HTML
<nav aria-label="Example breadcrumb">
  <ol class="flex flex-wrap gap-2 text-sm">
    <li>
      <a class="text-brand-link underline underline-offset-4" href="workspace.html">Fluxuri</a>
    </li>
    <li aria-hidden="true">/</li>
    <li aria-current="page">Asistență clienți</li>
  </ol>
</nav>

Button group

These toggle buttons demonstrate a single selected view. They do not filter application data.

View HTML
<div class="flex flex-wrap gap-2" role="group" aria-label="Example call view" data-toggle-group>
  <button type="button" class="ivr-btn ivr-btn-secondary" aria-pressed="true">Toate apelurile</button>
  <button type="button" class="ivr-btn ivr-btn-secondary" aria-pressed="false">Răspuns</button>
  <button type="button" class="ivr-btn ivr-btn-secondary" aria-pressed="false">Fără răspuns</button>
</div>

Use a carousel only when a sequential example helps. This one has manual controls and no autoplay. Essential product instructions should remain available outside a carousel.

01 / Ciornă

Construiește traseul apelantului.

Mesajele și rezultatele rămân editabile.

Pasul 1 din 3

View HTML
<section aria-label="Illustrative version lifecycle" aria-roledescription="carousel" data-carousel>
  <div class="ivr-card" data-slide role="group" aria-roledescription="slide" aria-label="1 of 3">
    <p class="eyebrow">01 / Ciornă</p>
    <h3 class="mt-3 text-xl font-semibold">Construiește traseul apelantului.</h3>
    <p class="mt-3 text-sm text-muted">Mesajele și rezultatele rămân editabile.</p>
  </div>
  <div class="ivr-card" data-slide role="group" aria-roledescription="slide" aria-label="2 of 3" hidden>
    <p class="eyebrow">02 / Publicare</p>
    <h3 class="mt-3 text-xl font-semibold">Creează o versiune imuabilă.</h3>
    <p class="mt-3 text-sm text-muted">Publicarea nu schimbă singură ruta telefonică.</p>
  </div>
  <div class="ivr-card" data-slide role="group" aria-roledescription="slide" aria-label="3 of 3" hidden>
    <p class="eyebrow">03 / Activare</p>
    <h3 class="mt-3 text-xl font-semibold">Alege ruta și versiunea.</h3>
    <p class="mt-3 text-sm text-muted">Confirmă starea reală după activare.</p>
  </div>
  <div class="mt-4 flex flex-wrap items-center justify-between gap-3">
    <button type="button" class="ivr-btn ivr-btn-secondary" data-slide-prev>← Înapoi</button>
    <p class="text-xs text-muted" role="status" data-slide-status>Pasul 1 din 3</p>
    <button type="button" class="ivr-btn ivr-btn-secondary" data-slide-next>Înainte →</button>
  </div>
</section>

Close button

Use a compact, icon-only control with an accessible name and visible focus. It has a 24px target and a 16px cross, without a border or filled button background. Closing a message returns focus to the section heading.

Mesaj demonstrativ care poate fi închis.

View HTML
<div class="ivr-alert flex items-center justify-between gap-3" data-dismissible>
  <p>Mesaj demonstrativ care poate fi închis.</p>
  <button type="button" class="ivr-close" data-dismiss aria-label="Închide mesajul"></button>
</div>

Collapse

A single native disclosure is enough for supplementary context. It works without JavaScript; do not hide necessary instructions inside it.

Vezi detaliile rutei
Rută demonstrativă
Linie principală
Versiune activă
v2
View HTML
<details class="rounded-control border border-control p-4">
  <summary class="font-semibold">Vezi detaliile rutei</summary>
  <dl class="mt-4 grid gap-4 sm:grid-cols-2 text-sm">
    <div>
      <dt class="text-muted">Rută demonstrativă</dt>
      <dd class="mt-1 font-semibold">Linie principală</dd>
    </div>
    <div>
      <dt class="text-muted">Versiune activă</dt>
      <dd class="mt-1 font-semibold">v2</dd>
    </div>
  </dl>
</details>

Use a disclosure with ordinary links for simple navigation. Keep menu roles for application menus that implement the corresponding keyboard behavior.

View HTML
<details class="relative max-w-xs">
  <summary class="ivr-btn ivr-btn-secondary">Resurse ↓</summary>
  <nav aria-label="Example resource menu" class="mt-2 rounded-card border border-control bg-surface p-2">
    <a class="block rounded-control p-3 text-sm text-brand-link hover:bg-tint" href="guide.html">Brand</a>
    <a class="block rounded-control p-3 text-sm text-brand-link hover:bg-tint" href="assets.html">Assets</a>
    <a class="block rounded-control p-3 text-sm text-brand-link hover:bg-tint" href="ui.html">Tailwind UI</a>
  </nav>
</details>

List group

View HTML
<nav aria-label="Example resources" class="overflow-hidden rounded-card border border-control">
  <a class="flex min-h-11 justify-between gap-4 bg-tint p-4 text-sm font-semibold text-brand-link" href="components.html" aria-current="page">
    Componente
    <span aria-hidden="true">→</span>
  </a>
  <a class="flex min-h-11 justify-between gap-4 border-t border-line p-4 text-sm hover:bg-tint" href="workspace.html">
    Exemplu de produs
    <span aria-hidden="true">→</span>
  </a>
  <a class="flex min-h-11 justify-between gap-4 border-t border-line p-4 text-sm hover:bg-tint" href="documents.html">
    Documente
    <span aria-hidden="true">→</span>
  </a>
</nav>

Use ordinary navigation links and a native disclosure on narrow screens. This example changes layout at Tailwind’s small breakpoint.

View HTML
<nav class="flex flex-wrap items-center justify-between gap-4" aria-label="Example navbar">
  <a href="index.html">
    <img class="logo-light" src="brand/assets/logos/ivr-cloud-primary.svg" width="146" height="36" alt="IVR Cloud home">
    <img class="logo-dark" src="brand/assets/logos/ivr-cloud-reversed.svg" width="146" height="36" alt="IVR Cloud home">
  </a>
  <div class="hidden gap-4 text-sm text-brand-link sm:flex">
    <a href="workspace.html">Produs</a>
    <a href="assets.html">Resurse</a>
  </div>
  <details class="w-full sm:hidden">
    <summary class="ivr-btn ivr-btn-secondary">Meniu ↓</summary>
    <div class="mt-3 grid gap-3 text-sm text-brand-link">
      <a class="min-h-11 p-3" href="workspace.html">Produs</a>
      <a class="min-h-11 p-3" href="assets.html">Resurse</a>
    </div>
  </details>
</nav>

Tabs switch local panels. Use Left/Right, Home/End, or click to select; Tab moves into the panel. Ordinary page navigation should remain links instead.

v4 / Ciornă. Mesajele și rezultatele pot fi editate.
View HTML
<div data-tabs>
  <div role="tablist" aria-label="Example version context" class="flex flex-wrap gap-2 border-b border-line pb-3">
    <button type="button" role="tab" id="draft-tab" aria-controls="draft-panel" aria-selected="true" tabindex="0" class="ivr-tab">Ciornă</button>
    <button type="button" role="tab" id="published-tab" aria-controls="published-panel" aria-selected="false" tabindex="-1" class="ivr-tab">Publicat</button>
    <button type="button" role="tab" id="route-tab" aria-controls="route-panel" aria-selected="false" tabindex="-1" class="ivr-tab">Activ pe rută</button>
  </div>
  <section class="pt-5 text-sm" id="draft-panel" role="tabpanel" aria-labelledby="draft-tab" tabindex="0">
    <strong>v4 / Ciornă.</strong>
    Mesajele și rezultatele pot fi editate.
  </section>
  <section class="pt-5 text-sm" id="published-panel" role="tabpanel" aria-labelledby="published-tab" tabindex="0" hidden>
    <strong>v3 / Publicat.</strong>
    Versiune imuabilă disponibilă pentru activare.
  </section>
  <section class="pt-5 text-sm" id="route-panel" role="tabpanel" aria-labelledby="route-tab" tabindex="0" hidden>
    <strong>v2 / Activ pe rută.</strong>
    Versiunea folosită de ruta demonstrativă.
  </section>
</div>

Offcanvas

A native dialog provides modal navigation with Escape and focus handling. A consuming application owns breakpoint behavior and routing.

IVR Cloud / Exemplu

View HTML
<button type="button" class="ivr-btn ivr-btn-secondary" data-dialog-open="navigation-drawer">Deschide navigarea</button>
<dialog id="navigation-drawer" aria-labelledby="drawer-title" class="m-0 min-h-dvh w-80 max-w-[calc(100%_-_2rem)] border-r border-control bg-canvas p-6 text-ink backdrop:bg-black/40">
  <div class="flex items-center justify-between gap-3">
    <h3 id="drawer-title" class="font-semibold">IVR Cloud / Exemplu</h3>
    <button type="button" class="ivr-close" data-dialog-close aria-label="Închide navigarea" autofocus></button>
  </div>
  <nav aria-label="Example drawer navigation" class="mt-6 grid gap-2 text-sm">
    <a class="rounded-control p-3 text-brand-link hover:bg-tint" href="workspace.html">Flux de apel</a>
    <a class="rounded-control p-3 text-brand-link hover:bg-tint" href="workspace.html#phone-route">Rută telefonică</a>
    <a class="rounded-control p-3 text-brand-link hover:bg-tint" href="workspace.html#call-history">Istoric apeluri</a>
  </nav>
</dialog>

Pagination

This specimen changes local example pages. A real application should provide working URLs, counts, and query-state preservation.

Pagina 1 · Apelurile demonstrative 1–10

Pagina 1 din 3

View HTML
<div data-pagination-demo>
  <p class="mb-5 text-sm" data-page-content="1">Pagina 1 · Apelurile demonstrative 1–10</p>
  <p class="mb-5 text-sm" data-page-content="2" hidden>Pagina 2 · Apelurile demonstrative 11–20</p>
  <p class="mb-5 text-sm" data-page-content="3" hidden>Pagina 3 · Apelurile demonstrative 21–30</p>
  <nav aria-label="Example pagination" class="flex gap-2">
    <button type="button" class="ivr-btn ivr-btn-secondary" data-page="1" aria-current="page" aria-label="Pagina 1">1</button>
    <button type="button" class="ivr-btn ivr-btn-secondary" data-page="2" aria-label="Pagina 2">2</button>
    <button type="button" class="ivr-btn ivr-btn-secondary" data-page="3" aria-label="Pagina 3">3</button>
  </nav>
  <p class="ivr-help" role="status" data-page-status>Pagina 1 din 3</p>
</div>

Placeholders

Placeholders communicate loading, not an empty result. Keep a written loading label and hide decorative shapes from assistive technology.

Se încarcă istoricul · specimen static

View HTML
<div class="ivr-card" aria-busy="true">
  <p class="mb-5 text-sm text-muted">Se încarcă istoricul · specimen static</p>
  <div class="space-y-3" aria-hidden="true">
    <div class="h-4 w-1/3 rounded bg-line"></div>
    <div class="h-4 w-full rounded bg-line"></div>
    <div class="h-4 w-2/3 rounded bg-line"></div>
  </div>
</div>

Popovers

Native popovers close with Escape or a click outside. Keep critical instructions in the main content. The trigger names the supplementary context.

Versiune imuabilă

Publicarea creează o versiune. Activarea pe un număr este o acțiune separată.

View HTML
<button type="button" class="ivr-btn ivr-btn-secondary" popovertarget="version-popover">Ce înseamnă „Publicat”?</button>
<div id="version-popover" popover class="m-auto max-w-sm rounded-card border border-control bg-surface p-5 text-ink shadow-lg">
  <h3 class="font-semibold">Versiune imuabilă</h3>
  <p class="mt-3 text-sm leading-relaxed">Publicarea creează o versiune. Activarea pe un număr este o acțiune separată.</p>
  <button type="button" class="ivr-btn ivr-btn-secondary mt-4" popovertarget="version-popover" popovertargetaction="hide">Închide</button>
</div>

Progress

Use an actual value when known; never fabricate a completion percentage. The value here is explicitly illustrative.

40%

Procent demonstrativ, fără operație în fundal.

View HTML
<label for="audio-progress" class="ivr-label">Generare audio · exemplu 40%</label>
<progress id="audio-progress" class="ivr-progress" value="40" max="100">40%</progress>
<p class="ivr-help">Procent demonstrativ, fără operație în fundal.</p>

Scrollspy

The links move within a bounded, keyboard-scrollable reading panel. JavaScript updates the active section label; the links still work without it.

Ciornă

Editează mesajele și rezultatele înainte de publicare.

Publicare

Creează o versiune imuabilă, fără a activa automat ruta.

Activare

Alege ruta și versiunea publicată. Confirmă starea reală.

View HTML
<div class="grid gap-5 sm:grid-cols-[150px_1fr]" data-scrollspy>
  <nav aria-label="Example section navigation" class="grid content-start gap-2 text-sm">
    <a class="ivr-spy-link" href="#spy-draft" aria-current="location">Ciornă</a>
    <a class="ivr-spy-link" href="#spy-publish">Publicare</a>
    <a class="ivr-spy-link" href="#spy-deploy">Activare</a>
  </nav>
  <div class="h-56 overflow-y-auto rounded-control border border-control p-5" tabindex="0" aria-label="Scrollable version context" data-spy-panel>
    <section id="spy-draft" class="min-h-48">
      <h3 class="font-semibold">Ciornă</h3>
      <p class="mt-3 text-sm leading-relaxed">Editează mesajele și rezultatele înainte de publicare.</p>
    </section>
    <section id="spy-publish" class="min-h-48">
      <h3 class="font-semibold">Publicare</h3>
      <p class="mt-3 text-sm leading-relaxed">Creează o versiune imuabilă, fără a activa automat ruta.</p>
    </section>
    <section id="spy-deploy" class="min-h-48">
      <h3 class="font-semibold">Activare</h3>
      <p class="mt-3 text-sm leading-relaxed">Alege ruta și versiunea publicată. Confirmă starea reală.</p>
    </section>
  </div>
</div>

Spinners

Pair motion with text. Reduced-motion settings stop the decorative animation while the written state remains.

Se încarcă · specimen static
View HTML
<div class="flex items-center gap-3 text-sm">
  <span class="inline-block size-6 animate-spin rounded-full border-2 border-line border-t-brand" aria-hidden="true"></span>
  <span>Se încarcă · specimen static</span>
</div>

Toasts

Toasts supplement persistent feedback. Do not make an important error discoverable only through a transient notification. This specimen stays visible until dismissed.

View HTML
<div data-toast-demo>
  <button type="button" class="ivr-btn ivr-btn-secondary" data-toast-show>Arată notificarea demonstrativă</button>
  <div class="ivr-card mt-5" data-toast hidden>
    <div class="flex items-center justify-between gap-4">
      <p role="status" aria-live="polite" data-toast-message></p>
      <button type="button" class="ivr-close" data-toast-hide aria-label="Închide notificarea"></button>
    </div>
  </div>
</div>

Tooltips

Tooltips contain supplementary information, never an input’s only label. This specimen appears on hover/focus and can be dismissed with Escape.

Creează o versiune; activarea rutei este separată.
View HTML
<span class="group relative inline-block" data-tooltip>
  <button type="button" class="ivr-btn ivr-btn-secondary" aria-describedby="publication-tooltip">Publicare ⓘ</button>
  <span id="publication-tooltip" role="tooltip" class="ivr-tooltip">Creează o versiune; activarea rutei este separată.</span>
</span>

JavaScript initialization

Native details, popovers, progress, and links provide their own semantics. Demo JavaScript handles tabs with keyboard navigation, manual carousel controls, page selection, toggle buttons, scrollspy, toasts, and dialog triggers. In an application, implement those interactions through its normal controllers. The guide’s JavaScript is not a product dependency.