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.
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.
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.
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
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.
| Apelant | Data | Durată | Rezultat |
|---|---|---|---|
| +40 700 000 101 | 13 oct. 2026 · 09:42 | 02:14 | Răspuns |
| +40 700 000 102 | 13 oct. 2026 · 09:38 | 00:48 | Mesaj vocal |
| +40 700 000 103 | 13 oct. 2026 · 09:31 | 00:12 | Fă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>Modal
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.
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>Breadcrumb
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>Carousel
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.
02 / Publicare
Creează o versiune imuabilă.
Publicarea nu schimbă singură ruta telefonică.
03 / Activare
Alege ruta și versiunea.
Confirmă starea reală după activare.
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>Dropdowns
Use a disclosure with ordinary links for simple navigation. Keep menu roles for application menus that implement the corresponding keyboard behavior.
Resurse ↓
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>Navbar
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>Navs and tabs
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.
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.
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 2 · Apelurile demonstrative 11–20
Pagina 3 · Apelurile demonstrative 21–30
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.
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.
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.
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.