@aidapt/tailwind-ui
v2.0.1
Published
La libreria di componenti React di AIDAPT, costruita su **React 19**, **TypeScript 5.9**, **Tailwind CSS 4**, **Vite 8** e **Radix UI**.
Readme
AIDAPT Tailwind UI
La libreria di componenti React di AIDAPT, costruita su React 19, TypeScript 5.9, Tailwind CSS 4, Vite 8 e Radix UI.
Compatibile con React 18 e 19 (vedi peerDependencies).
v2.0.0 contiene breaking change. Vedi MIGRATION.md.
Indice
Installazione
npm install @aidapt/tailwind-uiConfigurazione
La libreria usa Tailwind CSS 4, che non ha più tailwind.config.js: tema e
sorgenti si dichiarano dal CSS.
Nel index.css del progetto consumer:
@import 'tailwindcss';
/* Indica a Tailwind di scansionare anche la libreria, altrimenti le classi
dei componenti vengono eliminate dal tree-shaking del CSS. */
@source '../node_modules/@aidapt/tailwind-ui/dist';
/* Le scale di colore della libreria. La dark mode inverte le scale invece di
usare varianti `dark:`: ogni componente usa gli stessi token in entrambi i
temi. */
@custom-variant dark (&:where(.dark, .dark *));
@theme {
/* primary / gray / success / danger / warning, da 50 a 950 */
--color-primary-500: #5698ff;
/* … vedi src/index.css per la palette completa */
}
.dark {
/* le stesse variabili, con la scala invertita */
--color-primary-500: #5698ff;
--color-primary-50: #002660;
/* … */
}Il modo più rapido è copiare il blocco @theme e .dark da
src/index.css e adattare i valori al brand.
La dark mode si attiva aggiungendo la classe dark su <html>.
Direzione di lettura (RTL)
Per le lingue che si leggono da destra a sinistra, monta il provider una volta
sola vicino alla radice, allineato all'attributo dir di <html>:
<AiDirectionProvider dir={locale === 'ar' ? 'rtl' : 'ltr'}>
<App />
</AiDirectionProvider>Senza il provider i primitivi assumono LTR e il comportamento della tastiera contraddice quello che si vede a schermo.
Catalogo componenti
61 componenti, 251 export. I componenti composti si usano assemblando le loro parti, come in shadcn/ui.
Layout
| Componente | Descrizione |
|---|---|
| AiCard | Superficie che raggruppa contenuti correlati (+ Header, Title, Description, Action, Content, Footer) |
| AiSeparator | Riga divisoria, decorativa o semantica |
| AiAspectRatio | Vincola il contenuto a un rapporto fisso |
| AiCollapsible | Area espandibile singola |
| AiAccordion | Più sezioni espandibili coordinate |
| AiScrollArea | Area scrollabile con scrollbar personalizzata e raggiungibile da tastiera |
| AiResizable | Pannelli ridimensionabili (PanelGroup, Panel, Handle) |
Common
| Componente | Descrizione |
|---|---|
| AiButton | Bottone; 8 stili, 8 dimensioni, asChild, stato di caricamento |
| AiButtonGroup | Salda più bottoni in un'unica barra segmentata |
| AiChip | Etichetta compatta per stato, categoria o filtro attivo |
| AiAvatar | Avatar con fallback (+ Image, Fallback, Badge, Group, GroupCount) |
| AiSpinner | Indicatore di caricamento indeterminato |
| AiKbd | Tasto della tastiera (+ KbdGroup) |
| AiToggle | Bottone a due stati |
| AiToggleGroup | Insieme di toggle che si comportano come un controllo unico |
| AiItem | Riga con media, testo e azioni (+ 9 parti) |
| AiEmpty | Stato vuoto (+ Header, Media, Title, Description, Content) |
| AiAlert | Banner informativo o di errore |
| AiStatusIcon | Icona di stato con nome accessibile |
| AiTooltip | Suggerimento testuale su hover o focus |
| AiHoverCard | Anteprima ricca su hover o focus |
| AiPopover | Pannello fluttuante con contenuto ricco |
| AiContextMenu | Menu contestuale (tasto destro) |
| AiCarousel | Slide scorrevoli (Embla) |
| AiTabs | Pannelli a schede; API ad array o composta |
| AiPaginator | Navigazione tra pagine |
| AiDataDisplay | Riga di metriche principali |
| AiToast | Notifiche temporanee (openAiToast, AiToastContainer) |
Form
| Componente | Descrizione |
|---|---|
| AiTextField | Campo di testo a riga singola |
| AiTextArea | Campo multiriga con contatore caratteri |
| AiLabel | Etichetta accessibile per un controllo |
| AiField | Riga di form: etichetta, controllo, descrizione, errore (+ 9 parti) |
| AiForm | Binding React Hook Form con il wiring ARIA completo |
| AiInputGroup | Input con icone, bottoni o unità in un'unica superficie |
| AiCheckbox | Casella di selezione (input nativo, supporta lo stato indeterminato) |
| AiSwitch | Interruttore per un'impostazione che si applica subito |
| AiRadioGroup | Scelta singola tra opzioni mutuamente esclusive |
| AiCardSelect | Scelta singola tra card descrittive |
| AiNativeSelect | Select nativa — da preferire quando le opzioni sono testo semplice |
| AiListbox | Select stilizzata con rendering personalizzato |
| AiCombobox | Select con filtro, selezione multipla e creazione di opzioni |
| AiDropdown | Bottone che apre una lista di azioni |
| AiRange | Slider a uno o due cursori |
| AiColorPicker | Colore, tramite selettore visivo o campo esadecimale |
| AiDropzone | Caricamento file per trascinamento o click |
| AiTransferList | Due liste con spostamento e riordino |
Dialog
| Componente | Descrizione |
|---|---|
| AiDialog | Finestra modale per un'attività circoscritta |
| AiAlertDialog | Conferma di un'azione irreversibile |
| AiSheet | Pannello modale che entra da un bordo |
App shell
| Componente | Descrizione |
|---|---|
| AiNavbar | Barra superiore dell'applicazione |
| AiSidebar | Navigazione laterale collassabile |
| AiDrawer | Pannello a scomparsa (API a render prop) |
| AiNavigationMenu | Navigazione di sito con pannelli di link |
| AiMenubar | Barra di menu applicativi in stile desktop |
| AiBreadcrumb | Percorso di navigazione |
| AiFAB | Bottone di azione flottante |
Table
| Componente | Descrizione |
|---|---|
| AiTable | Tabella dati su TanStack Table v8, con API dichiarativa |
Skeleton
AiSkeleton, AiSkeletonAvatar, AiSkeletonHeader, AiSkeletonParagraph
Data
AiProgressBar
AI chat
| Componente | Descrizione |
|---|---|
| AiBubble | Fumetto di conversazione (+ Group, Content, Reactions) |
| AiMessage | Turno di conversazione (+ Avatar, Content, Header, Footer) |
| AiMarker | Annotazione in linea: separatore di data, nota di modifica |
| AiAttachment | File allegato con stato di caricamento (+ 8 parti) |
| AiMessageScroller | Viewport che segue i nuovi messaggi senza rubare il posto all'utente |
Utilities
AiPlaceholder, AiDirectionProvider
Utility e hook
import { cn, useIsMobile, useControllableState } from '@aidapt/tailwind-ui';cn(...)— unisce classi risolvendo i conflitti Tailwind a favore dell'ultimo valore. È l'helper che ogni componente usa, e garantisce che ilclassNamepassato dal consumer vinca sempre sulle classi di base.classNamesresta come alias deprecato.useIsMobile()—truesotto i 768px, viamatchMedia.useControllableState()— supporta API controllate e non controllate con un unico accessor, come i primitivi Radix.
Accessibilità
I componenti mirano a WCAG 2.1 livello AA. In pratica:
- ogni controllo interattivo è un elemento nativo (
button,a,input) o un primitivo Radix, quindi raggiungibile da tastiera e annunciato con il ruolo corretto; - i componenti composti implementano i pattern WAI-ARIA (menu, tabs, accordion, listbox, slider, dialog) con la navigazione da tastiera che ci si aspetta;
- il colore non è mai l'unico veicolo di un'informazione: stati ed errori sono sempre accompagnati da testo o da un attributo ARIA;
- le animazioni si disattivano sotto
prefers-reduced-motion; - il focus è sempre visibile, con un anello a due pixel sul colore primario.
Quello che resta al consumer: dare un nome ai controlli che mostrano solo
un'icona (aria-label), nominare i landmark quando la pagina ne ha più di uno,
e passare caption o label alle tabelle. Le JSDoc di ogni componente
indicano esattamente cosa serve, e le stories mostrano il pattern corretto.
Storybook include l'addon a11y (axe): il pannello Accessibility segnala le violazioni su ogni story.
Il rispetto di questi criteri è verificato automaticamente: axe-core viene
eseguito su tutte le 299 story a ogni giro di test, e le violazioni non
riconducibili al contrasto sono zero. Le violazioni di contrasto residue
riguardano token della palette esistente e sono elencate in
TESTING-REPORT.md §4, con le due soluzioni possibili.
Sviluppo
npm i # installa le dipendenze
npm run storybook # Storybook su :6005
npm run storybook:host # Storybook su 0.0.0.0 (accesso da LAN)
npm run build # type-check + build della libreria in dist/ + verify:dist
npm run verify:dist # importa dist/ come ESM: fallisce se il bundle non si valuta
npm run build-storybook
npm run format # Prettier
npm run lint # ESLint
npm run mcp:start # server MCP su :3001Struttura
src/
├── components/
│ ├── ai/ # primitivi per interfacce conversazionali
│ ├── appshell/ # navbar, sidebar, drawer, menubar, breadcrumb, FAB
│ ├── common/ # bottoni, chip, avatar, tooltip, popover, tabs…
│ ├── data/ # visualizzazione dati
│ ├── datepicker/ # calendario e selezione date
│ ├── dialog/ # dialog, alert dialog, sheet
│ ├── form/ # tutti i controlli di input
│ ├── layout/ # card, separator, accordion, scroll area, resizable
│ ├── skeleton/ # placeholder di caricamento
│ ├── table/ # tabella dati
│ └── utilities/ # placeholder, direction provider
├── consts/ # token e costanti di stile condivise
├── css/ # CSS specifico di alcuni componenti
├── hooks/ # hook riutilizzabili
├── icons/ # icone custom (non Lucide)
├── lib/ # cn() e helper
├── stories/ # una storia per componente, un caso d'uso per story
└── index.css # tema Tailwind, utility custom, keyframeConvenzioni
- Un componente per file, con il nome del file uguale a quello del componente.
- Ogni cartella ha un
index.tsche ri-esporta i simboli pubblici. - Le varianti visive si dichiarano con
cva, non con catene di ternari. - Ogni parte di un componente composto porta un attributo
data-slot, così i consumer possono agganciarsi allo stile dall'esterno. - Ogni prop pubblica ha una JSDoc che spiega quando usarla, non solo cosa fa.
Server MCP
La libreria espone i propri componenti a un LLM tramite un server Model Context Protocol, costruito sull'SDK TypeScript v2 (spec 2026-07-28):
npm run mcp:start # http://localhost:3001/mcpOtto strumenti: elenco e ricerca dei componenti, dettaglio delle prop, esempi
d'uso, sorgente, contratto di accessibilità e linee guida. Vedi
mcp-server/README.md.
