React UI-componentbibliotheken vergeleken: shadcn/ui, Radix, Headless UI, daisyUI, Flowbite en MUI

shadcn/ui, Radix, Headless UI, daisyUI, Flowbite en MUI verschillen vooral in styling: Radix en Headless UI zijn ongestyled, daisyUI en Flowbite zijn vooraf gestyled met Tailwind, MUI is Material Design, en shadcn/ui kopieert gestylede code naar uw project. Hier staan dezelfde zes componenten in elke bibliotheek, plus welke u kiest.

De korte versie

Deze zes bibliotheken lossen verschillende problemen op, en daarom heeft de vraag "welke is de beste" geen eenduidig antwoord. Twee ervan (Radix Primitives en Headless UI) geven u gedrag en toegankelijkheid zonder styling. Twee (daisyUI en Flowbite) geven u een kant-en-klare Tailwind-look. MUI geeft u een compleet designsysteem met een eigen styling-engine. shadcn/ui is helemaal geen package: het kopieert gestylede componentcode naar uw project, gebouwd op een headless laag eronder.

Alle feiten hieronder (versies, licenties, vereisten) zijn in oktober 2026 gecontroleerd aan de hand van de officiële documentatie, de GitHub-repository en de npm-vermelding van elk project. Versies veranderen snel, dus beschouw de getallen als "op het moment van schrijven".

Vergelijkingstabel

shadcn/uiRadix PrimitivesHeadless UIdaisyUIFlowbite ReactMUI (Material UI)
Wat u installeerteen CLI die componentcode naar uw repo kopieertnpm-packages (radix-ui of één per component)@headlessui/reactdaisyui Tailwind-pluginflowbite-react@mui/material plus Emotion
StylingmodelTailwind-classes in code die van u is; thema via CSS-variabelenongestyled; u voegt classes toe, status via data-state-attributenongestyled; status via data-*-attributen, ontworpen voor TailwindCSS-componentclasses (btn, modal) en thema'svooraf gestylede Tailwind-componenten, aan te passen via thema'sMaterial Design, CSS-in-JS (sx-prop, thema-object)
Versie (okt 2026)CLI shadcn 4.x (geen runtime-package)radix-ui 1.8; losse packages 1.x en 2.x2.25.x0.12 (vóór 1.0)9.x
LicentieMITMITMITMITMITMIT (betaalde MUI X Pro/Premium staan los)
React nodigja16.8 tot 1918 of 19nee (gewone HTML en CSS)18 of 1917, 18 of 19
Tailwind nodigja (v4 in de huidige documentatie)neenee, maar wel bedoeld ervoorja, Tailwind 4 voor daisyUI 5ja, Tailwind 3 of 4nee
Aanpak van toegankelijkheidneemt die over van de onderliggende primitive-laag (Base UI of Radix)volgt de WAI-ARIA Authoring Practices; toetsenbord en focus ingebouwdomschreven als "volledig toegankelijk"; toetsenbord en focus ingebouwdleunt op native elementen (<dialog>, <details>); ARIA en gedrag voegt u zelf toeReact-componenten met positionering via Floating UI; test het toetsenbordgebruik zelfARIA en toetsenbordafhandeling per component, per component gedocumenteerd
Heeft een toastja, via Sonnerja (Toast)neeja (alleen een layout-class)ja (Toast)ja (Snackbar)

De bundlegrootte hebben we bewust uit de tabel gelaten. De getallen hangen sterk af van welke componenten u importeert, of uw bundler ze tree-shaket en (bij daisyUI) hoeveel CSS Tailwind genereert voor de classes die u gebruikt. Eén "kB"-getal per bibliotheek zou meer misleiden dan helpen. Meet uw eigen build: draai de analyzer van uw bundler vóór en na het toevoegen van de componenten die u echt nodig hebt.

Elke bibliotheek in detail

shadcn/ui

Wat het is. shadcn/ui omschrijft zichzelf als "geen componentbibliotheek" maar als "de manier waarop u uw componentbibliotheek bouwt". U draait de CLI (npx shadcn init, daarna npx shadcn add button) en die schrijft de componentcode in uw project. Vanaf dat moment is de code van u om te bewerken; er is geen shadcn-runtimepackage om te upgraden.

Styling. Tailwind CSS-classes in de gekopieerde bestanden, met kleuren en radii als CSS-variabelen, zodat u op één plek een ander thema kunt instellen. Varianten worden meestal gedefinieerd met class-variance-authority.

Onder de motorkap. De interactieve onderdelen draaien op een headless bibliotheek. Volgens de changelog van shadcn/ui gebruiken nieuwe projecten sinds juli 2026 standaard Base UI, en wordt Radix "niet uitgefaseerd": beide worden ondersteund. De toast is gebouwd op Sonner, een apart opensource-toastpackage.

Licentie en versie. MIT (GitHub-repository shadcn-ui/ui). Het CLI-package shadcn stond op het moment van schrijven op 4.x op npm.

Let op. Omdat de code van u is, is het onderhoud dat ook. Fixes upstream komen niet automatisch in uw kopieën terecht, en verschillende projecten groeien na verloop van tijd uit elkaar.

Radix Primitives

Wat het is. Een set ongestylede, toegankelijke React-componenten (dialog, dropdownmenu, tabs, switch, toast, tooltip, popover en meer). U kunt alles installeren via het ene package radix-ui (1.8 op het moment van schrijven) of één package per component, zoals @radix-ui/react-dialog.

Styling. Standaard geen. Elk onderdeel rendert een gewoon element dat u met elke methode kunt stylen. De status wordt beschikbaar gemaakt als data-attributen, bijvoorbeeld data-state="open" of data-highlighted, die goed samengaan met de data-[state=open]:-varianten van Tailwind.

Toegankelijkheid. Volgens de documentatie van Radix volgen de primitives de WAI-ARIA Authoring Practices, bieden ze toetsenbordondersteuning en beheren ze de focus (bijvoorbeeld door de focus binnen een open dialoog vast te houden en die bij het sluiten terug te geven).

Licentie en vereisten. MIT. Het bereik van de npm-peer-dependency dekt React 16.8 tot en met 19.

Let op. Elke stijl schrijft u zelf. Radix levert geen Button-primitive: gebruik een native <button>, of de utility Slot om props samen te voegen in uw eigen element.

Headless UI

Wat het is. Ongestylede componenten van het Tailwind CSS-team. Het React-package, @headlessui/react (2.2 op het moment van schrijven), bevat Button, Checkbox, Combobox, Dialog, Disclosure, Fieldset, Input, Listbox, Menu (dropdown), Popover, Radio Group, Select, Switch, Tabs, Textarea en Transition.

Styling. Ongestyled. Componenten maken hun status beschikbaar via data-attributen (data-open, data-checked, data-selected, data-focus), dus u stylet ze met Tailwind-varianten zoals data-checked:bg-blue-600 (syntaxis van Tailwind 4) of data-[checked]:bg-blue-600 (Tailwind 3).

Toegankelijkheid. De site omschrijft de componenten als "volledig ongestyled, volledig toegankelijk". Toetsenbordnavigatie, het vasthouden van de focus in dialogen en de ARIA-koppelingen zijn ingebouwd.

Licentie en vereisten. MIT. React 18 of 19 (npm-peer-dependency).

Let op. De set is kleiner dan die van Radix: er is geen toast, tooltip of slider, dus daarvoor hebt u een ander package nodig.

daisyUI

Wat het is. Een Tailwind CSS-plugin die componentclassnamen toevoegt zoals btn, modal, dropdown, tabs, toggle en toast, plus een set kleurthema's. Het levert CSS, geen React-componenten, dus het werkt met elk framework of zonder framework.

Styling. Semantische classes met modifiers (btn btn-primary btn-sm) die u nog steeds kunt combineren met gewone Tailwind-utilities. Thema's wisselen via CSS-variabelen.

Vereisten. daisyUI 5 (voor het eerst uitgebracht in februari 2025, 5.x op het moment van schrijven) is gericht op Tailwind CSS 4; de upgradegids laat u eerst Tailwind bijwerken. U installeert het met één regel @plugin "daisyui"; in uw CSS.

Toegankelijkheid. Omdat het alleen CSS is, komt het gedrag uit native HTML: de modal gebruikt het <dialog>-element (Escape sluit hem en de browser regelt de focus), dropdowns gebruiken <details> of de popover-API. Alles daarbuiten (ARIA voor tabs, toasts aankondigen) is uw taak.

Licentie. MIT.

Let op. In React koppelt u de status zelf (bijvoorbeeld door showModal() via een ref aan te roepen). Er is geen afhandeling van pijltjestoetsen voor menu's of tabs, tenzij u die toevoegt.

Flowbite React

Wat het is. React-componenten (flowbite-react) gestyled met Tailwind, van het Flowbite-project. Het bevat Button, Modal, Dropdown, Tabs, ToggleSwitch, Toast, Navbar, Sidebar, Datepicker en meer.

Styling. Vooraf gestyled met Tailwind-classes, aan te passen via een thema-object en een theme-prop op elke component.

Vereisten en versie. Versie 0.12 op het moment van schrijven: het heeft 1.0 nog niet bereikt, dus reken op breaking changes tussen minor-versies. De npm-peer-dependencies zijn React 18 of 19 en Tailwind CSS 3 of 4. Het gebruikt Floating UI voor de positionering van dropdowns en tooltips.

Toegankelijkheid. Componenten renderen de verwachte rollen voor gangbare patronen, maar we vonden geen gepubliceerde toegankelijkheidsverklaring die vergelijkbaar is met die van Radix. Test het gedrag met toetsenbord en schermlezer voor de componenten waarop u vertrouwt.

Licentie. MIT (de opensource-bibliotheek; Flowbite verkoopt daarnaast aparte Pro-blokken en ontwerpbestanden).

MUI (Material UI)

Wat het is. In eigen woorden "een opensource React-componentbibliotheek die Material Design van Google implementeert." Het is de grootste set in deze vergelijking, met componenten voor dataweergave, invoer, navigatie, layout en feedback.

Styling. CSS-in-JS. Standaard gebruikt het Emotion (@emotion/react en @emotion/styled zijn peer-dependencies van @mui/material 9). U stelt het thema in met createTheme en stylet losse gevallen met de sx-prop. Het kan naast Tailwind bestaan, maar de twee themasystemen delen geen tokens, tenzij u ze koppelt.

Versie en licentie. Versie 9 (9.0.0 verscheen in april 2026). De kernbibliotheek is MIT. Geavanceerde functies voor datagrids, datums en grafieken in MUI X Pro en Premium vallen onder commerciële licenties.

Toegankelijkheid. Componenten worden geleverd met ARIA-attributen en toetsenbordafhandeling, en de componentpagina's in de documentatie van MUI beschrijven het toegankelijkheidsgedrag per component.

Let op. Afstappen van de Material-look kost echt werk aan het thema, en CSS-in-JS vraagt extra configuratie met React Server Components.

Dezelfde zes componenten in elke bibliotheek

Hieronder zijn dezelfde knop, dialoog, dropdownmenu, tabs, switch en toast zes keer geschreven, één keer in de gedocumenteerde API van elke bibliotheek. Elk fragment is originele code die voor deze pagina is geschreven (niet gekopieerd uit de documentatie van de bibliotheken), gebruikt de huidige hoofdversie van elke bibliotheek en is ingekort tot de delen die verschillen. Live, klikbare versies worden alleen voor Radix Primitives getoond, omdat Radix de bibliotheek is die op deze site is geïnstalleerd. Ze zijn gestyled met onze eigen Tailwind-classes, omdat Radix geen stijlen meelevert. Van de andere vijf bibliotheken tonen we geen live versies, zodat niets hier hun look nabootst.

Knop

De meeste bibliotheken leveren een knop met varianten. Merk op dat Radix en Headless UI de look aan u overlaten, terwijl daisyUI varianten als classes uitdrukt en de rest als props.

Knop: shadcn/ui

// after: npx shadcn add button
import { Button } from "@/components/ui/button";

<Button>Save changes</Button>
<Button variant="outline" size="sm">Cancel</Button>
<Button variant="destructive" disabled>Delete</Button>
<Button asChild><a href="/pricing">See pricing</a></Button>

Knop: Radix Primitives

// Radix has no Button primitive. Use a native button,
// or Slot to pass props onto your own element.
import { Slot } from "radix-ui";

function Button({ asChild, className, ...props }) {
  const Comp = asChild ? Slot.Root : "button";
  return <Comp className={"rounded-lg bg-black px-4 py-2 text-white " + className} {...props} />;
}

Knop: Headless UI

import { Button } from "@headlessui/react";

<Button className="rounded-lg bg-black px-4 py-2 text-white
  data-hover:bg-black/80 data-active:bg-black/70
  data-disabled:opacity-50">
  Save changes
</Button>

Knop: daisyUI

<button className="btn btn-primary">Save changes</button>
<button className="btn btn-outline btn-sm">Cancel</button>
<button className="btn btn-error" disabled>Delete</button>
<a className="btn btn-link" href="/pricing">See pricing</a>

Knop: Flowbite React

import { Button } from "flowbite-react";

<Button>Save changes</Button>
<Button color="alternative" size="sm">Cancel</Button>
<Button color="red" disabled>Delete</Button>
<Button href="/pricing">See pricing</Button>

Knop: MUI

import Button from "@mui/material/Button";

<Button variant="contained">Save changes</Button>
<Button variant="outlined" size="small">Cancel</Button>
<Button variant="contained" color="error" disabled>Delete</Button>
<Button href="/pricing">See pricing</Button>

Dialoog (modal)

In een dialoog zit het verborgen toegankelijkheidswerk: de focus vasthouden, sluiten met Escape, de focus teruggeven aan de trigger, labels. De headless bibliotheken en MUI doen dit in JavaScript; daisyUI leunt op het native <dialog>-element, dat Escape en focus in de browser afhandelt.

Dialoog (modal): shadcn/ui

import {
  Dialog, DialogContent, DialogDescription, DialogFooter,
  DialogHeader, DialogTitle, DialogTrigger, DialogClose,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";

<Dialog>
  <DialogTrigger asChild><Button>Edit profile</Button></DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Edit profile</DialogTitle>
      <DialogDescription>Update your display name.</DialogDescription>
    </DialogHeader>
    {/* form fields */}
    <DialogFooter>
      <DialogClose asChild><Button variant="outline">Cancel</Button></DialogClose>
      <Button type="submit">Save</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>

Dialoog (modal): Radix Primitives

import { Dialog } from "radix-ui";

<Dialog.Root>
  <Dialog.Trigger className="btn-dark">Edit profile</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay className="fixed inset-0 bg-black/40" />
    <Dialog.Content className="fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-xl bg-white p-5">
      <Dialog.Title>Edit profile</Dialog.Title>
      <Dialog.Description>Update your display name.</Dialog.Description>
      {/* form fields */}
      <Dialog.Close>Cancel</Dialog.Close>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

Dialoog (modal): Headless UI

import { Dialog, DialogPanel, DialogTitle, DialogBackdrop } from "@headlessui/react";
import { useState } from "react";

const [open, setOpen] = useState(false);

<button onClick={() => setOpen(true)}>Edit profile</button>
<Dialog open={open} onClose={setOpen} className="relative z-50">
  <DialogBackdrop className="fixed inset-0 bg-black/40" />
  <div className="fixed inset-0 flex items-center justify-center p-4">
    <DialogPanel className="max-w-md rounded-xl bg-white p-5">
      <DialogTitle className="font-semibold">Edit profile</DialogTitle>
      {/* form fields */}
      <button onClick={() => setOpen(false)}>Cancel</button>
    </DialogPanel>
  </div>
</Dialog>

Dialoog (modal): daisyUI

import { useRef } from "react";

const ref = useRef<HTMLDialogElement>(null);

<button className="btn" onClick={() => ref.current?.showModal()}>Edit profile</button>
<dialog ref={ref} className="modal">
  <div className="modal-box">
    <h3 className="text-lg font-bold">Edit profile</h3>
    {/* form fields */}
    <div className="modal-action">
      <form method="dialog"><button className="btn">Cancel</button></form>
    </div>
  </div>
  <form method="dialog" className="modal-backdrop"><button>close</button></form>
</dialog>

Dialoog (modal): Flowbite React

import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from "flowbite-react";
import { useState } from "react";

const [open, setOpen] = useState(false);

<Button onClick={() => setOpen(true)}>Edit profile</Button>
<Modal show={open} onClose={() => setOpen(false)} size="md">
  <ModalHeader>Edit profile</ModalHeader>
  <ModalBody>{/* form fields */}</ModalBody>
  <ModalFooter>
    <Button color="alternative" onClick={() => setOpen(false)}>Cancel</Button>
    <Button onClick={() => setOpen(false)}>Save</Button>
  </ModalFooter>
</Modal>

Dialoog (modal): MUI

import Button from "@mui/material/Button";
import Dialog from "@mui/material/Dialog";
import DialogTitle from "@mui/material/DialogTitle";
import DialogContent from "@mui/material/DialogContent";
import DialogActions from "@mui/material/DialogActions";
import { useState } from "react";

const [open, setOpen] = useState(false);

<Button variant="contained" onClick={() => setOpen(true)}>Edit profile</Button>
<Dialog open={open} onClose={() => setOpen(false)}>
  <DialogTitle>Edit profile</DialogTitle>
  <DialogContent>{/* form fields */}</DialogContent>
  <DialogActions>
    <Button onClick={() => setOpen(false)}>Cancel</Button>
    <Button variant="contained" onClick={() => setOpen(false)}>Save</Button>
  </DialogActions>
</Dialog>

Dropdownmenu

Menu's hebben navigatie met pijltjestoetsen, type-ahead en de juiste rollen nodig. Radix, Headless UI, shadcn/ui en MUI regelen dat; de <details>-versie van daisyUI opent en sluit zonder JavaScript, maar voegt geen navigatie met pijltjestoetsen toe.

Dropdownmenu: shadcn/ui

import {
  DropdownMenu, DropdownMenuContent, DropdownMenuItem,
  DropdownMenuSeparator, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

<DropdownMenu>
  <DropdownMenuTrigger asChild><Button variant="outline">Options</Button></DropdownMenuTrigger>
  <DropdownMenuContent align="start">
    <DropdownMenuItem onSelect={rename}>Rename</DropdownMenuItem>
    <DropdownMenuItem onSelect={duplicate}>Duplicate</DropdownMenuItem>
    <DropdownMenuSeparator />
    <DropdownMenuItem variant="destructive">Delete</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

Dropdownmenu: Radix Primitives

import { DropdownMenu } from "radix-ui";

<DropdownMenu.Root>
  <DropdownMenu.Trigger>Options</DropdownMenu.Trigger>
  <DropdownMenu.Portal>
    <DropdownMenu.Content sideOffset={6} className="rounded-lg bg-white p-1 shadow-lg">
      <DropdownMenu.Item onSelect={rename} className="data-[highlighted]:bg-black/5">Rename</DropdownMenu.Item>
      <DropdownMenu.Item onSelect={duplicate}>Duplicate</DropdownMenu.Item>
      <DropdownMenu.Separator className="my-1 h-px bg-black/10" />
      <DropdownMenu.Item disabled>Move</DropdownMenu.Item>
    </DropdownMenu.Content>
  </DropdownMenu.Portal>
</DropdownMenu.Root>

Dropdownmenu: Headless UI

import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";

<Menu>
  <MenuButton>Options</MenuButton>
  <MenuItems anchor="bottom start" className="rounded-lg bg-white p-1 shadow-lg">
    <MenuItem>
      <button onClick={rename} className="block w-full data-focus:bg-black/5">Rename</button>
    </MenuItem>
    <MenuItem>
      <button onClick={duplicate} className="block w-full data-focus:bg-black/5">Duplicate</button>
    </MenuItem>
  </MenuItems>
</Menu>

Dropdownmenu: daisyUI

<details className="dropdown">
  <summary className="btn">Options</summary>
  <ul className="menu dropdown-content z-1 w-52 rounded-box bg-base-100 p-2 shadow-sm">
    <li><button onClick={rename}>Rename</button></li>
    <li><button onClick={duplicate}>Duplicate</button></li>
  </ul>
</details>

Dropdownmenu: Flowbite React

import { Dropdown, DropdownDivider, DropdownItem } from "flowbite-react";

<Dropdown label="Options" dismissOnClick>
  <DropdownItem onClick={rename}>Rename</DropdownItem>
  <DropdownItem onClick={duplicate}>Duplicate</DropdownItem>
  <DropdownDivider />
  <DropdownItem>Delete</DropdownItem>
</Dropdown>

Dropdownmenu: MUI

import Button from "@mui/material/Button";
import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import { useState } from "react";

const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
const close = () => setAnchorEl(null);

<Button onClick={(e) => setAnchorEl(e.currentTarget)}>Options</Button>
<Menu anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={close}>
  <MenuItem onClick={() => { rename(); close(); }}>Rename</MenuItem>
  <MenuItem onClick={() => { duplicate(); close(); }}>Duplicate</MenuItem>
</Menu>

Tabs

Correcte tabs hebben role="tablist", role="tab", aria-selected en verplaatsing met pijltjestoetsen tussen tabs nodig. In daisyUI en MUI koppelt u panelen en ID's zelf; de andere doen dat voor u.

Tabs: shadcn/ui

import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";

<Tabs defaultValue="account">
  <TabsList>
    <TabsTrigger value="account">Account</TabsTrigger>
    <TabsTrigger value="billing">Billing</TabsTrigger>
  </TabsList>
  <TabsContent value="account">Account settings</TabsContent>
  <TabsContent value="billing">Billing settings</TabsContent>
</Tabs>

Tabs: Radix Primitives

import { Tabs } from "radix-ui";

<Tabs.Root defaultValue="account">
  <Tabs.List aria-label="Settings">
    <Tabs.Trigger value="account" className="data-[state=active]:font-semibold">Account</Tabs.Trigger>
    <Tabs.Trigger value="billing" className="data-[state=active]:font-semibold">Billing</Tabs.Trigger>
  </Tabs.List>
  <Tabs.Content value="account">Account settings</Tabs.Content>
  <Tabs.Content value="billing">Billing settings</Tabs.Content>
</Tabs.Root>

Tabs: Headless UI

import { Tab, TabGroup, TabList, TabPanel, TabPanels } from "@headlessui/react";

<TabGroup>
  <TabList>
    <Tab className="data-selected:font-semibold">Account</Tab>
    <Tab className="data-selected:font-semibold">Billing</Tab>
  </TabList>
  <TabPanels>
    <TabPanel>Account settings</TabPanel>
    <TabPanel>Billing settings</TabPanel>
  </TabPanels>
</TabGroup>

Tabs: daisyUI

const [tab, setTab] = useState("account");

<div role="tablist" className="tabs tabs-box">
  <button role="tab" aria-selected={tab === "account"}
    className={"tab " + (tab === "account" ? "tab-active" : "")}
    onClick={() => setTab("account")}>Account</button>
  <button role="tab" aria-selected={tab === "billing"}
    className={"tab " + (tab === "billing" ? "tab-active" : "")}
    onClick={() => setTab("billing")}>Billing</button>
</div>
<div role="tabpanel">{tab === "account" ? "Account settings" : "Billing settings"}</div>

Tabs: Flowbite React

import { TabItem, Tabs } from "flowbite-react";

<Tabs aria-label="Settings" variant="underline" onActiveTabChange={(i) => console.log(i)}>
  <TabItem active title="Account">Account settings</TabItem>
  <TabItem title="Billing">Billing settings</TabItem>
</Tabs>

Tabs: MUI

import Tabs from "@mui/material/Tabs";
import Tab from "@mui/material/Tab";
import { useState } from "react";

const [tab, setTab] = useState(0);

<Tabs value={tab} onChange={(_, next) => setTab(next)} aria-label="Settings">
  <Tab label="Account" id="tab-0" aria-controls="panel-0" />
  <Tab label="Billing" id="tab-1" aria-controls="panel-1" />
</Tabs>
<div role="tabpanel" id={`panel-${tab}`} aria-labelledby={`tab-${tab}`}>
  {tab === 0 ? "Account settings" : "Billing settings"}
</div>

Switch (schakelaar)

Een switch is een aan/uit-bediening die wordt aangekondigd als role="switch". daisyUI stylet een echte checkbox, waardoor het native formuliergedrag behouden blijft; de andere renderen een knop met de switch-rol.

Switch (schakelaar): shadcn/ui

import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";

<div className="flex items-center gap-2">
  <Switch id="email-alerts" checked={on} onCheckedChange={setOn} />
  <Label htmlFor="email-alerts">Email notifications</Label>
</div>

Switch (schakelaar): Radix Primitives

import { Switch } from "radix-ui";

<Switch.Root id="email-alerts" checked={on} onCheckedChange={setOn}
  className="h-6 w-11 rounded-full bg-black/20 data-[state=checked]:bg-blue-500">
  <Switch.Thumb className="block h-5 w-5 rounded-full bg-white transition-transform data-[state=checked]:translate-x-5" />
</Switch.Root>
<label htmlFor="email-alerts">Email notifications</label>

Switch (schakelaar): Headless UI

import { Field, Label, Switch } from "@headlessui/react";

<Field className="flex items-center gap-2">
  <Switch checked={on} onChange={setOn}
    className="group h-6 w-11 rounded-full bg-black/20 data-checked:bg-blue-500">
    <span className="block h-5 w-5 rounded-full bg-white transition group-data-checked:translate-x-5" />
  </Switch>
  <Label>Email notifications</Label>
</Field>

Switch (schakelaar): daisyUI

<label className="flex items-center gap-2">
  <input type="checkbox" className="toggle toggle-primary"
    checked={on} onChange={(e) => setOn(e.target.checked)} />
  Email notifications
</label>

Switch (schakelaar): Flowbite React

import { ToggleSwitch } from "flowbite-react";

<ToggleSwitch checked={on} onChange={setOn} label="Email notifications" />

Switch (schakelaar): MUI

import FormControlLabel from "@mui/material/FormControlLabel";
import Switch from "@mui/material/Switch";

<FormControlLabel
  control={<Switch checked={on} onChange={(e) => setOn(e.target.checked)} />}
  label="Email notifications"
/>

Toast (melding)

Bij toasts verschillen de bibliotheken het meest. Sommige geven u een component die u met state bestuurt, andere een functie die u overal kunt aanroepen, en Headless UI laat het helemaal weg.

Toast (melding): shadcn/ui

// after: npx shadcn add sonner
import { Toaster } from "@/components/ui/sonner";
import { toast } from "sonner";

// once, near the root of your app
<Toaster />

// anywhere
<Button onClick={() => toast("Changes saved", {
  description: "Your profile is up to date.",
  action: { label: "Undo", onClick: undo },
})}>
  Save
</Button>

Toast (melding): Radix Primitives

import { Toast } from "radix-ui";

<Toast.Provider duration={4000}>
  <button onClick={() => setOpen(true)}>Save</button>
  <Toast.Root open={open} onOpenChange={setOpen} className="rounded-lg bg-white p-3 shadow-lg">
    <Toast.Title>Changes saved</Toast.Title>
    <Toast.Description>Your profile is up to date.</Toast.Description>
    <Toast.Action altText="Undo the save" onClick={undo}>Undo</Toast.Action>
  </Toast.Root>
  <Toast.Viewport className="fixed bottom-4 right-4 w-80" />
</Toast.Provider>

Toast (melding): Headless UI

// Headless UI has no toast component. Common choices:
// pair it with a small toast package, or build one from
// Transition plus an aria-live region:
import { Transition } from "@headlessui/react";

<div aria-live="polite" className="fixed bottom-4 right-4">
  <Transition show={open}>
    <div className="rounded-lg bg-white p-3 shadow-lg transition data-closed:opacity-0">
      Changes saved
    </div>
  </Transition>
</div>

Toast (melding): daisyUI

{/* daisyUI positions and stacks; showing and hiding is your state */}
{open && (
  <div className="toast toast-end toast-bottom" role="status">
    <div className="alert alert-success">
      <span>Changes saved</span>
    </div>
  </div>
)}

Toast (melding): Flowbite React

import { Toast, ToastToggle } from "flowbite-react";

{open && (
  <Toast className="fixed bottom-4 right-4">
    <div className="text-sm font-normal">Changes saved</div>
    <ToastToggle onDismiss={() => setOpen(false)} />
  </Toast>
)}

Toast (melding): MUI

import Snackbar from "@mui/material/Snackbar";
import Button from "@mui/material/Button";

<Snackbar
  open={open}
  autoHideDuration={4000}
  onClose={() => setOpen(false)}
  message="Changes saved"
  action={<Button size="small" onClick={undo}>Undo</Button>}
/>

Welke kiezen per type project

ProjectPast goedWaarom
Marketingsite of landingspagina in TailwinddaisyUI, of gewoon TailwindGrotendeels statische pagina's hebben knoppen, kaarten en een menu nodig, geen JavaScript-componentlaag. De classes van daisyUI werken ook op pagina's zonder React.
SaaS-product met een eigen merkshadcn/ui, of Radix / Headless UI door u gestyledU krijgt toegankelijk gedrag zonder de look van een ander product over te nemen, en u kunt uw designsysteem precies volgen.
Uw eigen designsysteem of componentbibliotheek bouwenRadix Primitives (of Base UI), Headless UIOngestylede primitives zijn precies de laag waarop u zelf de stijlen wilt bepalen. shadcn/ui is zelf een voorbeeld van deze aanpak.
Interne tool, adminpaneel, dashboardMUI, of shadcn/uiDe breedte van MUI (tabellen, datumkiezers via MUI X, formulieren) bespaart de meeste tijd als de look minder belangrijk is dan opleveren. shadcn/ui als u al met Tailwind werkt.
Prototype of hackathon met TailwindFlowbite React of daisyUIAfgewerkt ogende componenten met heel weinig stylingwerk. Plan een herziening als het prototype een product wordt.
Team dat al Material Design gebruikt (of een UI in Android-stijl)MUIHet implementeert Material Design direct, dus ontwerpers en ontwikkelaars delen één vocabulaire.
Strenge toegankelijkheidseisen (overheid, enterprise)Radix Primitives, Headless UI, MUI, of shadcn/ui daarbovenopToetsenbord- en focusgedrag zijn ingebouwd en gedocumenteerd. Wat u ook kiest, test toch met een toetsenbord en een schermlezer; geen enkele bibliotheek maakt een pagina uit zichzelf toegankelijk.

Vragen om te beantwoorden voordat u kiest

Voor de hooks waarop deze componenten zijn gebouwd, zie de React hooks cheat sheet. Voor de utility-classes die in de fragmenten worden gebruikt, zie de Tailwind cheat sheet, en voor de hover-, focus- en disabled-statussen die elke knop nodig heeft, CSS-knopstatussen. U kunt in onze componentengalerij ook kant-en-klare React- en Tailwind-modals, knoppen en navigatie bekijken.

Bronnen

Gecontroleerd in oktober 2026: de documentatie en changelog van shadcn/ui (ui.shadcn.com), de GitHub-repository shadcn-ui/ui; de documentatie van Radix Primitives, inclusief het toegankelijkheidsoverzicht (radix-ui.com/primitives); Headless UI (headlessui.com); de installatie-, upgrade- en componentpagina's van daisyUI (daisyui.com); de documentatie van MUI Material UI (mui.com); en de vermeldingen in het npm-register voor shadcn, radix-ui, @headlessui/react, daisyui, flowbite-react en @mui/material voor versies, licenties en peer-dependencies.

Veelgestelde vragen

Is shadcn/ui een componentbibliotheek?

Niet in de gebruikelijke zin. Volgens de eigen documentatie is het geen componentbibliotheek maar een manier om uw eigen bibliotheek te bouwen: een CLI kopieert de componentcode naar uw project, en u bewerkt en onderhoudt die code. De interactieve onderdelen zijn gebouwd op een headless bibliotheek, sinds juli 2026 standaard Base UI voor nieuwe projecten, waarbij Radix nog steeds wordt ondersteund.

Wat is het verschil tussen Radix en Headless UI?

Beide zijn ongestylede, toegankelijke React-componenten. Radix Primitives heeft een grotere set, met onder meer toast, tooltip, slider en toolbar, en ondersteunt React 16.8 tot 19. Headless UI komt van het Tailwind CSS-team, heeft een kleinere set zonder toast of tooltip en vereist React 18 of 19.

Werkt daisyUI met React?

Ja. daisyUI is een Tailwind CSS-plugin die classnamen toevoegt zoals btn, modal en tabs, dus u gebruikt die classes in JSX zoals elke andere Tailwind-class. Het levert geen React-componenten, dus state zoals het openen van een modal of het wisselen van tabs regelt u in uw eigen React-code.

Zijn deze bibliotheken gratis voor commercieel gebruik?

Ja. shadcn/ui, Radix Primitives, Headless UI, daisyUI, flowbite-react en het kernpackage Material UI van MUI hebben op het moment van schrijven (oktober 2026) allemaal een MIT-licentie. De componenten van MUI X Pro en Premium en de Pro-blokken van Flowbite zijn aparte commerciële producten.

Welke React UI-bibliotheek is het best voor toegankelijkheid?

Radix Primitives, Headless UI en MUI bouwen toetsenbordnavigatie en focusbeheer in hun componenten in, en shadcn/ui neemt dat over van de onderliggende primitive-laag. daisyUI leunt op native HTML-elementen, dus ARIA en toetsenbordgedrag voegt u zelf toe. Wat u ook gebruikt, test met een toetsenbord en een schermlezer.

Kan ik MUI gebruiken met Tailwind CSS?

Dat kan, maar ze stylen op een andere manier: MUI gebruikt Emotion en een JavaScript-thema, Tailwind gebruikt utility-classes. Ze werken naast elkaar, maar u moet kleuren en spacing tussen de twee thema's zelf gelijk houden. Teams die alles in Tailwind willen, kiezen meestal shadcn/ui of een headless bibliotheek.

Live: Radix Primitives {title} (ongestylede bibliotheek, onze Tailwind-classes)

Profiel bewerken

Druk op Tab: de focus blijft binnen. Druk op Escape of klik erbuiten om te sluiten.

Weergavenaam

Annuleren

Opslaan

Sluiten

nog niets

Opties

Naam wijzigen

Dupliceren

Verplaatsen (uitgeschakeld)

Verborgen bestanden tonen

Probeer de pijltjestoetsen en type-ahead. Laatst gekozen: {last}

Instellingen

Account

Facturering

Team

Paneel met accountinstellingen. Gebruik de pijltjes Links en Rechts op de tabs.

Factureringspaneel.

Teampaneel.

E-mailmeldingen: aan

E-mailmeldingen: uit

Wijzigingen opslaan

Wijzigingen opgeslagen

{n} keer opgeslagen in deze demo.

{n} keer opgeslagen in deze demo.

Het opslaan ongedaan maken

Ongedaan maken

Gratis beginnen · Geen creditcard nodig

Gerelateerd: Gidsen

Product

Voor wie

Functies

Bronnen

Bedrijf

Sitemap