UI SDK vs Base UI vs Radix: Welche Headless-Bibliothek für Komponenten im shadcn-Stil?
Vercels UI SDK, Base UI und Radix im Vergleich für shadcn-Komponenten: Modell, Frameworks, Umfang, Styling, Animation, Beta-Status, Lizenz und Agenten.
Preet Suthar · · 9 Min. Lesezeit
- React
- UI SDK
- Base UI
- Radix
Bis diese Woche hieß die Wahl der Primitive-Schicht unter einer Komponentenbibliothek im shadcn/ui-Stil, zwischen zwei Optionen zu wählen: Radix und Base UI. Am 12. November 2026 hat Vercel Labs eine dritte veröffentlicht, UI SDK, als 0.1.0-beta.1. Sie ist headless wie die anderen beiden, folgt aber einer anderen Idee und bringt etwas mit, das keine der beiden hat: eine Bridge, über die KI-Agenten die Komponenten lesen und bedienen können.
Vor dem Vergleich ein Hinweis in eigener Sache. Die Komponenten von HextaUI basieren heute auf Base UI, und ich baue daneben eine separate UI-SDK-Variante. Ich habe Gründe, beide zu mögen, also habe ich versucht, fair zu bleiben, und jede Aussage unten stammt aus der Doku der Bibliotheken, ihren npm-Metadaten oder einer Test-App, in der ich dieselbe Komponente dreimal gebaut habe.
Wenn du die Migration von Radix zu Base UI im Detail willst, mit jeder API-Änderung im shadcn/ui-Code, lies zuerst shadcn/ui ist zu Base UI gewechselt. Dieser Post wiederholt das nicht. Er nimmt UI SDK dazu und fragt, mit welcher du anfangen solltest.
Die kurze Antwort
- Nimm Radix, wenn du eine funktionierende Radix-Codebasis hast, dein Team sie kennt und du keine Komponente brauchst, die fehlt. Es ist stabil, nur für React und MIT.
- Nimm Base UI für ein neues React-Designsystem, das du in diesem Quartal auf stabilen APIs ausliefern willst. Es ist der Standard unter neuen shadcn/ui-Projekten, deckt mehr Komponenten ab als Radix und nutzt das Attributmodell, zu dem sich der Großteil des Ökosystems bewegt.
- Nimm UI SDK, wenn du mehr als React brauchst, Komponenten wie Color Picker, Date Picker oder Tree ohne zweite Bibliothek willst oder möchtest, dass KI-Agenten deine UI über strukturierte Tools bedienen. Akzeptiere, dass es eine Beta ist.
Der Rest des Posts liefert die Belege.
Die drei im Überblick
| Radix | Base UI | UI SDK | |
|---|---|---|---|
| Paket | radix-ui 1.8.1 | @base-ui/react 1.9.0 | @ui-sdk/react 0.1.0-beta.1 |
| Lizenz | MIT | MIT | Apache-2.0 |
| Status | Stabil | Stabil | Beta |
| Frameworks | React | React | React, Vue, Svelte, Solid, Web Components |
| Offen-Zustand | data-state="open" | data-open | data-open |
| Enter und Exit | Keyframes auf data-state | data-starting-style, data-ending-style | data-starting-style, data-ending-style |
data-slot an Parts | Nein | Nein | Ja |
| Popup-Parts | Portal, Content | Portal, Positioner, Popup | Content im Top Layer |
| Agent-Bridge | Nein | Nein | Ja, mit WebMCP |
Alle drei sind ungestylt und kümmern sich für dich um Fokus, Tastatur und ARIA. Verglichen werden die neuesten Versionen auf npm am 13. November 2026: radix-ui 1.8.1 (veröffentlicht am 12. Oktober 2026), @base-ui/react 1.9.0 (9. Oktober 2026) und @ui-sdk/react 0.1.0-beta.1 (12. November 2026).
Drei unterschiedliche Modelle
Radix liefert ein Primitive pro Komponente. Ein Dialog-Paket gibt dir Root, Trigger, Portal, Overlay, Content, Title, Description und Close, und das ist die Einheit, mit der du arbeitest. Die Behaviors darin, etwa Focus Trapping und Schließen, sind intern. Das Paket radix-ui bündelt sie alle.
Base UI hat dieselbe Form: eine Komponente, mehrere Parts. Es bietet mehr öffentliche Utilities drumherum, etwa useRender und mergeProps, damit du eigene Parts schreiben kannst, die sich wie die eingebauten verhalten. Es ist nur für React und wird von Leuten gebaut, die an Radix, Material UI und Floating UI gearbeitet haben.
UI SDK teilt die Schichten anders auf. @ui-sdk/core ist eine TypeScript-Bibliothek aus Behaviors: Roving Focus, Typeahead, Popups, Drag and Drop, Ansagen und vieles mehr. Ein Primitive verbindet über definePrimitive Behaviors mit State und benannten Slots. Die Komponenten, die du aus @ui-sdk/react importierst, sind Primitives, die der React-Adapter rendert, und dieselben Primitives rendern über ihre Adapter in Vue, Svelte, Solid und Web Components. Die Doku richtet das an Agenten: Gib einem Agenten getestete Behaviors, und er kann eine Komponente bauen, die die Bibliothek nicht mitliefert, etwa einen Icon-Picker oder ein Kanban-Board.
Der praktische Unterschied: Bei Radix und Base UI ist eine Komponente, die du brauchst und die sie nicht haben, dein Problem, von Grund auf. Bei UI SDK baust du sie aus denselben Behaviors, die auch die eingebauten Komponenten nutzen, und sie kann sich der Agent-Bridge anschließen.
Dasselbe Popover, drei Anatomien
Ich habe ein Popover dreimal in einer Vite-App mit denselben Tailwind-Klassen gebaut. Hier sind die Bäume, gekürzt auf die Parts, die sich unterscheiden:
trigger und panel sind gemeinsame Klassen-Strings, und die Radix-Version nutzt zwei kleine @keyframes-Regeln für Enter und Exit. Das Ergebnis sieht in allen dreien gleich aus:

Radix
- Popover.Root
- Popover.Trigger
- Popover.Portal
- Popover.Content
Base UI
- Popover.Root
- Popover.Trigger
- Popover.Portal
- Popover.Positioner
- Popover.Popup
UI SDK
- Popover
- PopoverTrigger
- PopoverContentAn Ort und Stelle gerendert, im Top Layer
Ein Part, der nur dazu da ist, das Popup zu verschieben oder zu platzieren
Unterschiedlich ist, wo der Content lebt. In meinem Test haben Radix und Base UI den offenen Content beide über ihr Portal ans Ende von <body> verschoben. UI SDK ließ ihn in der eigenen Komponente, mit popover="manual", und der Browser hob ihn in den Top Layer. Das hat Folgen:
- Keine Stacking-Kämpfe. Content im Top Layer liegt über der Seite, egal welchen
z-indexein Sticky Header oder ein transformiertes Elternelement hat. - Events bubbeln durch deinen Baum. Die UI-SDK-Doku warnt, dass ein Klick-Handler oder ein Link um ein Popup herum auch die Klicks darin abbekommt. Halte Popups aus klickbaren Karten heraus.
- Weniger Wrapper-Parts. Platzierungs-Props wie
side,alignundsideOffsetkommen auf den Content, nicht auf einen Positioner.
Radix und Base UI gehen seit Jahren gut mit Portals um, also ist der erste Punkt weniger eine Korrektur als eine Vereinfachung. Der zweite Punkt ist neues Verhalten, das du kennen musst.
Styling-Hooks
Alle drei legen den Zustand in Data-Attributen ab, aber die Namen unterscheiden sich, und nur eine benennt jeden Part.
| Hook | Radix | Base UI | UI SDK |
|---|---|---|---|
| Offen-Zustand | data-state="open" | data-open | data-open |
| Part-Name | keine | keine | data-slot an jedem Part |
| Transform-Origin | --radix-popover-content-transform-origin | --transform-origin | --transform-origin |
| Anker-Breite | --radix-popover-trigger-width | --anchor-width | --anchor-width |
| Zustand in `className` | nein | Funktion des Zustands | Funktion des Zustands |
Die Zeile zu data-slot ist wichtiger, als sie aussieht. shadcn/ui fügt in seinen Wrapper-Dateien eigene data-slot-Attribute hinzu, weil Radix und Base UI keins ausgeben. In meiner Test-App trug das Base-UI-Popup data-open, data-side und data-align, aber kein data-slot. UI SDK setzt es selbst an jedem Part, etwa data-slot="popover-content", und die Doku behandelt es als verwaltetes Attribut, das deine Props nicht überschreiben können. Damit haben globales CSS und Agenten einen stabilen Namen für jeden Part.
Wenn du mit Tailwind stylst, heißt der Wechsel von Base UI zu UI SDK vor allem, Wrapper zu löschen, weil die Attributnamen für Popups gleich sind. Der Wechsel von Radix heißt, data-[state=open]:-Varianten und Variablen mit Radix-Präfix zu ersetzen. Das Styling-Tutorial zu UI SDK geht vier Komponenten mit Tokens im shadcn-Stil durch.
Animation
Radix animiert Mount und Unmount mit CSS-Animationen auf data-state. Laut Doku hält es das Unmount an, während die Exit-Animation läuft. Für JavaScript-Animationsbibliotheken akzeptieren viele Parts forceMount, damit die Bibliothek entscheidet, wann Kinder mounten.
Base UI fügt data-starting-style und data-ending-style hinzu, sodass CSS-Transitions in beide Richtungen funktionieren, nicht nur Keyframes. Das Popup bleibt gemountet, bis die Animation endet, und wird dann entfernt oder versteckt, wenn das Portal keepMounted hat. Sein Animations-Guide behandelt Motion und sagt, dass es Motion-Animationen erkennt, die opacity enthalten.
UI SDK nutzt dieselben zwei Attribute mit derselben Bedeutung. Content bleibt gemountet, bis seine Exit-Transition oder -Animation fertig ist, keepMounted hält geschlossenen Content in der Seite, und onOpenChangeComplete läuft, wenn das Öffnen oder Schließen erledigt ist. Die UI-SDK-Doku hat noch keinen Guide für Motion, abgesehen von einem Hinweis, keepMounted zu nutzen, wenn eine Animationsbibliothek geschlossenen Content im DOM braucht.
Für reine CSS-Animation sind Base UI und UI SDK praktisch gleich. Für Oberflächen mit viel Motion hat Base UI heute dokumentierte Patterns, UI SDK nicht.
Komponentenumfang
Komponenten über Bibliotheken hinweg zu zählen ist ungenau, weil sie Dinge unterschiedlich aufteilen und benennen. Als Orientierung:
- Radix: 30 Primitive-Pakete in
radix-ui1.8.1, von Accordion bis Tooltip, plus Utilities wie Slot, Portal und Visually Hidden. - Base UI: 37 Komponenten in seinem Doku-Index, darunter Combobox, Autocomplete, Number Field, OTP Field, Drawer, Toast und Preview Card, die Radix nicht hat.
- UI SDK: 55 Komponenten und zwei Hooks in der Doku, die 0.1.0-beta.1 beiliegt.
Die meisten Base-UI-Komponenten haben ein Gegenstück in UI SDK, manchmal unter anderem Namen: Number Field heißt Number Input, Preview Card heißt Hover Card, OTP Field heißt OTP Input. UI SDK liefert außerdem Komponenten, die keine der beiden anderen hat, darunter Calendar, Date Picker, Date Input, Time Input, Color Picker, Rating, Tree, Command, Carousel, Resizable, Image Cropper, File Input, Token Input, Trigger Menu, Timeline und Waterfall.
Anzahl ist nicht Qualität. Hinter den Komponenten von Radix und Base UI stehen Jahre im Produktionseinsatz. Die Komponentenseiten von UI SDK listen ihre getesteten Behaviors Zeile für Zeile auf, was ein gutes Zeichen ist, aber ein Tag öffentliches Leben ist nicht dasselbe wie Jahre an Bug-Reports.
Die Agent-Bridge
Das ist der Teil, den nur UI SDK hat. createAgent() aus @ui-sdk/react/agent verbindet sich mit jeder UI-SDK-Komponente auf der Seite. snapshot() listet sie mit ihren Labels, ihrem Zustand und den verfügbaren Aktionen auf. act() ruft diese Aktionen über die API jeder Komponente auf, und deine Change-Callbacks sehen details.source === "agent". registerTools() bietet dieselben Tools über WebMCP einem Agenten an, der in den Browser eingebaut ist.
Radix und Base UI haben nichts Vergleichbares eingebaut. Ein Agent bedient sie wie jede andere Webseite: über Screenshots, das DOM oder den Accessibility Tree, mit Browser-Tools, die klicken und tippen.
Vercels Doku enthält einen Benchmark zu diesem Unterschied bei einer Aufgabe mit Projekteinstellungen. Laut ihren Zahlen, mit Sonnet über Claude Code und Medianen aus drei Läufen, senkte die Agent-Bridge die Tool-Aufrufe von 16 auf 5 und die Kosten von 0,073 $ auf 0,032 $. Das sind Vercels Zahlen für eine Aufgabe, nicht meine, aber die Richtung ergibt Sinn: Eine Liste von Komponenten mit ihrem Zustand zu lesen ist billiger, als eine Seite zu lesen. Eine funktionierende Demo der Bridge, mit Berechtigungen und einer eigenen Komponente, habe ich in Mach deine React-App für KI-Agenten bedienbar gebaut.
Wenn Agenten, die deine UI bedienen, nicht auf deiner Roadmap stehen, sollte dieser Abschnitt nichts entscheiden. Wenn doch, kommt nichts anderes in diesem Vergleich auch nur annähernd heran.
Reife und Lizenz
Radix und Base UI sind stabile 1.x-Bibliotheken. Ihre APIs ändern sich nach Semver, und shadcn/ui liefert jede Komponente für beide.
UI SDK sagt in README und Doku, dass es in der Beta ist und dass sich Framework, APIs, Dokumentation und Verhalten vor der allgemeinen Verfügbarkeit ändern können. Die Beta fällt unter Vercels öffentliche Beta-Vereinbarung. Einige APIs sind zusätzlich als experimentell markiert, darunter der agent-Key bei eigenen Primitives und die Helfer für Verlauf und Rückgängig. Das GitHub-Repository vercel-labs/ui wurde im Oktober 2026 angelegt, und der einzige Changelog-Eintrag ist „Introducing UI SDK“ vom 12. November 2026.
Auch die Lizenzen unterscheiden sich. Radix und Base UI sind MIT. UI SDK ist Apache-2.0, ebenfalls permissiv und mit einer ausdrücklichen Patentlizenz. Wenn du es weiterverteilst, verlangt Apache-2.0, dass du Lizenz und Hinweise beibehältst, also frag bei der Person nach, die sich in deiner Firma um Lizenzen kümmert, falls das relevant ist.
Frameworks
Radix und Base UI sind React-Bibliotheken. UI SDK veröffentlicht @ui-sdk/react, @ui-sdk/vue, @ui-sdk/svelte, @ui-sdk/solid und @ui-sdk/web in derselben Version, alle auf einem Core. Wenn deine Firma eine React-App und eine Vue-App betreibt oder einen Web-Components-Build für ein CMS will, ist UI SDK die einzige der drei, die alles mit einem Satz Behaviors und Attributnamen abdeckt.
Das React-Paket von UI SDK verlangt React 19 und React DOM 19 oder neuer, mit @types/react 19.2.10 oder neuer. Wenn du noch auf React 18 bist, ist die Sache damit vorerst entschieden.
Wann du welche nimmst
Bleib bei Radix, wenn die App funktioniert, das Team es kennt und dich nichts blockiert. Nichts hier zwingt dich zum Wechsel. Wenn du wechselst, dann zuerst zu Base UI: Das ist der kleinere Schritt, und das Attributmodell, das du lernst, lässt sich auf UI SDK übertragen.
Starte mit Base UI, wenn du eine React-Komponentenbibliothek oder eine Produkt-UI baust, die jetzt live gehen soll. Es ist stabil, es ist der Standard von shadcn/ui, und seine Patterns für Popups, Formulare und Animation sind gut dokumentiert.
Starte mit UI SDK, wenn eins davon zutrifft:
- mehrere Frameworks sich ein Komponentenmodell teilen sollen;
- du ihre zusätzlichen Komponenten brauchst und sonst Bibliotheken für Datumsangaben, Farben oder Bäume hinzufügen würdest;
- KI-Agenten, die deine UI bedienen, ein Produktziel sind und du Berechtigungen und Change-Sources eingebaut haben willst;
- du Prototypen baust und Breaking Changes während der Beta verkraften kannst.
Mischen ist möglich. UI-SDK-Komponenten brauchen keinen Provider, also kann eine Base-UI-App auf einem Screen einen UI-SDK-Color-Picker nutzen. Du trägst zwei Abhängigkeiten und zwei Sätze Attributnamen, also beschränk es auf die Komponenten, die du sonst nirgends bekommst.
Was HextaUI macht
Die Komponenten von HextaUI bleiben auf Base UI. Diese Variante ist heute auf der Seite, und sie verschwindet nicht. Ich baue außerdem eine separate UI-SDK-Variante mit demselben Look und denselben Theme-Tokens, für Projekte, die die Agent-Bridge oder die zusätzlichen Komponenten wollen. Sie ist noch nicht veröffentlicht. Wenn es so weit ist, wählst du eine Variante, statt zu migrieren.
