Headless-Komponentensystem · Neue Ressource

Headless UI-Designsystem.

Headless UI stellt ungestaltete React-Interaktionskomponenten für Dialoge, Listenfelder und Umschalter bereit. Diese Anleitung zeigt, wie sich deren integriertes Fokus-, Auswahl- und Popup-Verhalten mit gewöhnlichem CSS kombinieren lässt. Als Beispiel dient ein Ablauf zum Teilen von Dokumenten.

OpenDesign-Leitfaden9 Kapitel27 ReferenzeinträgeOriginaler Anwendungsleitfaden
01

Vorschau der Headless UI-Designsystem-Oberfläche

Öffnen Sie den Dialog zum Teilen, prüfen Sie eine E-Mail-Adresse, wählen Sie mit der Tastatur eine Berechtigung aus, fügen Sie eine lokale Einladung hinzu und schalten Sie den Status des öffentlichen Links um.

Dokumente teilen mit nativen Headless-PrimitivenVollständiges Beispiel öffnen
Natives @headlessui/react 2.2.10 mit React 19. Alle Farben, Schriftarten, Abstände und Layouts sind eigens für dieses Beispiel erstellte CSS und keine offiziellen Headless UI-Design-Tokens. · Implementierungsreferenz
02

Designreferenz für das Headless UI-Designsystem

Headless UI verfügt über keine offizielle visuelle Design-Tokens-Skala. Alle nachfolgenden Zahlen- und Farbwerte gehören zu diesem OpenDesign-Beispiel; die verlinkte Dokumentation beschreibt Verhalten und Zustands-APIs. Getestetes Paket: @headlessui/react 2.2.10.

Eigene CSS-Farbrollen

Quelle
Name / RegelWert / KonfigurationVerwendung
--canvas#f5f5f4 Dokumentenarbeitsbereich.
--surface#ffffff Papierfläche, Zugriffsbereich und Dialog.
--ink#1c1917 Primärer Text.
--muted#57534e Sekundärer Text.
--line#d6d3d1 Rahmen von Bereichen und Eingabefeldern.
--accent#4338ca Primäre Aktion und Fokusumrandung.
--accent-soft#eef2ff Hintergrund für ausgewählte Option und Avatar.
--error#b91c1c Text und Rahmen für ungültige E-Mail-Adressen.

Eigene Abstände und Geometrie

Quelle
Name / RegelWert / KonfigurationVerwendung
--space-1 / --space-24px / 8pxKleine Abstände.
--space-3 / --space-412px / 16pxAbstände zwischen Steuerelementen und Innenabstand auf Mobilgeräten.
--space-6 / --space-824px / 32pxInnenabstand von Bereichen und größere Abstände.
--radius-control8pxSchaltflächen und Eingabefelder.
--radius-panel16pxPapierfläche und Dialog.
.dialog-panel widthmin(100%, 460px)Begrenztes Overlay auf schmalen Bildschirmen.
.dialog-panel max-heightcalc(100% - 16px)Lässt innerhalb des Containers für die feste Positionierung Platz.

Eigene Schrift- und Responsive-Einstellungen

Quelle
Name / RegelWert / KonfigurationVerwendung
Body16px / 1.5 system-uiKeine externe Schriftart erforderlich.
Screen title28px / 1.25Dokumentenidentität.
Document headline32px; 26px below 700pxHierarchie redaktioneller Inhalte.
Dialog heading20px / 1.3Benennt die Aufgabe zum Teilen.
Labels and helper copy14pxKontext des Eingabefelds.
Error and access description13pxDauerhafte Rückmeldung.
Breakpoint700pxDokument- und Zugriffsbereiche werden untereinander angeordnet.

Verträge nativer Interaktionen

Quelle
Name / RegelWert / KonfigurationVerwendung
Dialog open / onCloseControlled boolean / dismissal callbackEscape-Taste und Klick außerhalb lösen das Schließen aus; sie speichern nichts.
DialogPanelContent boundaryBackdrop und Positionierungs-Wrapper befinden sich außerhalb dieser Begrenzung.
Listbox value / onChangeControlled permission stringDie Tastaturnavigation aktualisiert die ausgewählte Berechtigung.
data-focus / data-selectedNative state attributesCSS unterscheidet den Tastaturfokus von der bestätigten Auswahl.
Switch checked / onChangeControlled booleandata-checked legt den visuellen Zustand fest.
03

Vollständiger Leitfaden zum Headless UI-Designsystem

Ein praktischer Leitfaden zur Auswahl, Anwendung und Überprüfung dieses Systems für ein echtes Interface.

DESIGN-headless-ui.md

Umfassende Anleitung, Einstieg in die Implementierung und Links zu den Quellen.

Leitfaden herunterladen

Headless UI-Designsystem: Verhalten zusammenstellen, bevor der Bildschirm gestaltet wird

Verhalten zusammenstellen, bevor der Bildschirm gestaltet wird

Dialog, Listbox und Switch bilden jeweils eine andere Interaktion ab. Der Dialog steuert eine klar begrenzte Aufgabe und ihren Fokuskontext; die Listbox stellt eine bestätigte Auswahl dar; der Switch bildet eine unabhängige boolesche Einstellung ab. Sie lassen sich kombinieren, ohne ihren Zustand zusammenzuführen: Der Einladungsentwurf, die ausgewählte Berechtigung und die Einstellung für den öffentlichen Link bleiben getrennt.

Aus diesem OpenDesign-Leitfaden

Das Beispiel verwendet die Komponente API aus React mit direkten Imports wie DialogPanel und ListboxButton. Der Dialog enthält eine Listbox. Daher müssen Positionierung und Schließen des Pop-ups auch innerhalb eines bereits geöffneten Overlays funktionieren. Beginnen Sie mit dieser Zusammensetzung, bevor Sie den Dokumentbereich und die Zugriffsübersicht ergänzen. Das bereitgestellte CSS zeigt eine vollständige Gestaltung dieser nativen Elemente.

Anatomie von Dialog, Listbox und Switch im Headless UI-Designsystem

Grenzen des Overlays bewusst festlegen

DialogBackdrop ist ein Geschwisterelement des Containers für die feste Positionierung. DialogPanel ist der begrenzte weiße Bereich innerhalb dieses Containers und füllt nicht den gesamten Viewport aus. DialogTitle benennt die Aufgabe, und Description erklärt, was beim Schließen geschieht. Das native Eingabefeld hat data-autofocus; Headless UI verwaltet das Fokusverhalten des umgebenden Dialogs.

Unterstützende Spezifikation lesen

Eine Listbox wählt einen Wert aus; ein Switch ändert einen booleschen Wert

ListboxButton zeigt die ausgewählte Rolle an. ListboxOptions verwendet anchor="bottom" und eine Breite, die sich an --button-width orientiert, damit das Pop-up bündig mit seinem Auslöser abschließt. Jede ListboxOption hat einen stabilen Zeichenfolgenwert. Die nativen Attribute data-focus und data-selected steuern zwei unterschiedliche CSS-Darstellungen.

Der Switch für den öffentlichen Link befindet sich in Field mit Label und nicht in einem unbeschrifteten, eingefärbten Feld. Sein aktivierter Zustand ändert sowohl das barrierefreie Steuerelement als auch den sichtbaren Erklärungssatz. Die lokale Einladung ist unabhängig von der Einstellung für den öffentlichen Link.

Unterstützende Spezifikation lesen

Headless UI-Designsystem: Auswahl, Schließen und lokale Bestätigung getrennt behandeln

Das hier verwendete Zustandsmodell

Beim Öffnen werden ein neuer Empfängerentwurf und die Rolle „Darf ansehen“ initialisiert. Abbrechen, Escape und ein Klick außerhalb schließen den Dialog; keine dieser Aktionen fügt einen Empfänger hinzu. Beim Absenden wird die E-Mail-Adresse geprüft und eine bereits vorhandene Adresse abgewiesen. Anschließend wird die Einladung im Arbeitsspeicher hinzugefügt und der Dialog geschlossen. Die Bestätigung weist ausdrücklich darauf hin, dass keine E-Mail versendet wurde.

Die Listbox für Berechtigungen ändert die Rolle im Entwurf, nicht den Zugriff eines bestehenden Empfängers. Der Zustand des öffentlichen Links ändert einen separaten booleschen Wert. So wird der häufige Fehler vermieden, jedes Schließen des Dialogs als Speicherung von Berechtigungen zu behandeln.

  • Ungültige Eingabe: Dialog geöffnet lassen und den Fehler mit der E-Mail-Adresse verknüpfen.
  • Doppelter Empfänger: Bestehende Zugriffsliste unverändert lassen.
  • Lokale Einladung angenommen: Liste aktualisieren und das Ergebnis der Vorschau ansagen.

Headless UI-Designsystem: Auswahl und Tastaturfokus unabhängig voneinander gestalten

Auswahl und Tastaturfokus unabhängig voneinander gestalten

ListboxOption stellt data-focus und data-selected für unterschiedliche Zustände bereit. Die fokussierte Option erhält die dezente Akzentgestaltung, während die bestätigte Berechtigung mit einem Häkchen markiert wird. So können Tastaturnutzende durch die Alternativen navigieren, ohne die bestehende Auswahl aus dem Blick zu verlieren.

Dieselbe Unterscheidung gilt außerhalb des Pop-ups: Die Fehlerrolle gehört zum ungültigen Empfängerfeld, während das aktivierte Erscheinungsbild von Switch den Zugriff über den öffentlichen Link kennzeichnet. Beschränken Sie CSS auf den Komponentenstatus, den es beschreibt. Ein breit gefasster Selektor, der alle fokussierten oder aktivierten Elemente identisch einfärbt, würde diese unterschiedlichen Bedeutungen verwischen.

css
:root { --accent: #4338ca; --accent-soft: #eef2ff; --error: #b91c1c; }
.role-option[data-focus] { background: var(--accent-soft); }
.role-option[data-selected] .selected { visibility: visible; }

Code-Referenz

Headless UI-Designsystem: Dokumentidentität und Berechtigungen verständlich darstellen

Reproduzierbare typografische Einstellungen

Der Dokumenttitel hat eine Schriftgröße von 28px und einen Zeilenabstand von 1.25, der Dialogtitel eine Schriftgröße von 20px und einen Zeilenabstand von 1.3. Der Fließtext verwendet die Systemschrift der Plattform mit 16px/1.5. Feldbeschriftungen und Hilfetexte sind 14px groß. Diese exakten Werte stehen in style.css; sie müssen nicht aus einem Screenshot abgeleitet werden.

Für die E-Mail-Adresse in der Zugriffsliste wird overflow-wrap:anywhere verwendet, damit sie die Spalte nicht verbreitert. Die Berechtigung wird in einer separaten Zeile angezeigt. Im Dialog sind der vollständige Dokumenttitel und die ausgewählte Berechtigung sichtbar, sobald die Einladung hinzugefügt wird.

Headless UI-Designsystem: vollständige Overlay-Positionierung und responsives CSS

Das Layout ist nicht hinter einer Voraussetzung verborgen

Das bereitgestellte Stylesheet enthält das vollständige Overlay: feste Positionierung mit Insets, Deckkraft des Backdrops, z-index, maximale Breite, vertikales Scrollen und Innenabstand. Unter 700px werden die Dokumentbereiche untereinander angeordnet und der Innenabstand des Dialogs verringert. Ein Tailwind-Build wird nicht vorausgesetzt.

Halten Sie den Positionierungscontainer und DialogPanel voneinander getrennt. Der Container erstreckt sich über den verfügbaren Viewport und sorgt für einen Randabstand; das Panel stellt die in der Breite begrenzte Inhaltsfläche bereit. Geben Sie längeren Dialoginhalten einen scrollbaren Bereich, damit Empfängerfeld, Berechtigungsauswahl und Schließen-Aktionen auch bei schmalen Ansichten erreichbar bleiben.

css
.dialog-position { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; padding: 16px; overflow-y: auto; }
.dialog-panel { width: min(100%, 460px); max-height: calc(100% - 16px); overflow-y: auto; }

Code-Referenz

Headless UI-Designsystem: nativen Status und Fokusverhalten nutzen

Tastaturbedienung überprüfen

Öffnen Sie den Dialog und prüfen Sie, ob der Fokus zunächst auf dem Empfänger liegt. Navigieren Sie mit der Tabulatortaste zum Berechtigungstrigger und wählen Sie mit den Pfeiltasten und Enter eine Rolle aus. Escape schließt das aktive Pop-up oder den Dialog entsprechend dem aktuellen Fokuskontext der nativen Komponente. Nach dem Schließen des Dialogs sollte der Fokus zum Freigabe-Trigger zurückkehren.

Die E-Mail-Adresse verwendet aria-invalid und aria-describedby für ihren benutzerdefinierten Fehler. Das Häkchen in einer Option ist dekorativ, da Listbox die Auswahlsemantik bereitstellt. Das Steuerelement für den öffentlichen Link hat ein sichtbares Label, und der erklärende Satz bleibt nach dem Umschalten erhalten. Die Einstellung für reduzierte Bewegung CSS entfernt den dekorativen Übergang des Switch-Daumens.

Unterstützende Spezifikation lesen

Headless UI-Designsystem: eine React-API-Generation durchgängig verwenden

Eine React-API-Generation durchgängig verwenden

Der vollständige React-Eintrag bindet App ein; dessen Stylesheet liefert die Geometrie des Overlays und die Selektoren für die Zustände. DialogPanel, DialogBackdrop, ListboxButton und ListboxOptions werden im geprüften Beispiel mit Version 2.2.10 direkt importiert. Ältere Schreibweisen für zusammengesetzte Komponenten sollten gezielt migriert und nicht mit dieser Zusammensetzung vermischt werden.

ListboxOptions verwendet anchor="bottom" und die native Variable --button-width, um die Optionen am Trigger auszurichten. Diese Details sind Teil der Integration und keine optionale Dekoration: Wird der Positionierungscontainer entfernt oder die Breite durch einen unabhängigen festen Wert ersetzt, kann ein verschachteltes Pop-up fehlerhaft dargestellt werden, obwohl das geschlossene Feld weiterhin korrekt aussieht.

  1. Installieren Sie @headlessui/react im React-Projekt.
  2. Speichern Sie App.jsx und style.css aus den Beispielen und ersetzen Sie anschließend main.jsx wie gezeigt.
  3. Starten Sie den Entwicklungsserver und testen Sie das Schließen des Dialogs, die Berechtigungsauswahl und die Behandlung doppelter E-Mail-Adressen.

Headless UI-Designsystem: eine echte Berechtigungsinteraktion prüfen

Abnahmekriterien

Eine aussagekräftige Prüfung beginnt mit einem Dokument und einem bestehenden Empfänger, nicht mit einer leeren Komponentengalerie. Fügen Sie eine gültige Einladung mit der Berechtigung „Darf kommentieren“ hinzu und öffnen Sie den Dialog erneut, um dieselbe E-Mail-Adresse einzugeben. Prüfen Sie, ob der ursprüngliche Eintrag erhalten bleibt und für das Duplikat eine konkrete Fehlermeldung erscheint. Aktivieren Sie den öffentlichen Link und prüfen Sie die dazugehörige, unabhängige Erklärung.

Das Beispiel demonstriert ausschließlich den lokalen UI-Status. Es bietet weder eine Empfängersuche noch ein Backend für die Freigabe. Für die Anbindung eines echten Dienstes sind ein Statusmodell für ausstehende und fehlgeschlagene Anfragen sowie eine explizite Richtlinie für gleichzeitige Berechtigungsänderungen erforderlich; die nativen Primitives legen keine Autorisierungsregeln fest.

Headless UI-Designsystem: Komponentenbeispiele

App.jsx — native Freigabezusammensetzung

Vollständig kontrollierter Dialog, Berechtigungs-Listbox, beschrifteter Switch und lokale Validierung.

jsx
import React, { useState } from 'react';
import { Dialog, DialogBackdrop, DialogPanel, DialogTitle, Description, Listbox, ListboxButton, ListboxOptions, ListboxOption, Switch, Field, Label } from '@headlessui/react';
import './style.css';
const roles = ['Can view', 'Can comment', 'Can edit'];
export default function App() {
 const [open,setOpen]=useState(false),[role,setRole]=useState(roles[0]),[publicLink,setPublicLink]=useState(false),[email,setEmail]=useState(''),[error,setError]=useState(''),[notice,setNotice]=useState('');
 const [people,setPeople]=useState([{email:'[email protected]',role:'Can edit'}]);
 const start=()=>{setEmail('');setError('');setRole(roles[0]);setOpen(true)};
 const submit=e=>{e.preventDefault();if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)){setError('Enter a complete email address.');return;}if(people.some(p=>p.email===email)){setError('This person already appears in the access list.');return;}setPeople([...people,{email,role}]);setOpen(false);setNotice('Invitation added to this local example only. No email was sent.');};
 return <main className='sharing-shell'>
  <header><div><span className='eyebrow'>HEADLESS UI / CUSTOM SURFACE</span><h1>Quarterly brief</h1><p className='muted'>Research · Updated today</p></div><button className='primary' onClick={start}>Share document</button></header>
  <div className='document-grid'><article className='paper'><span className='tag'>WORKING DOCUMENT</span><h2>Make the next decision clearer.</h2><p>Three research priorities for the coming quarter, shared with the people who need to review them.</p><div className='rule'/><h3>01 / Understand the handoff</h3><p>Compare where context is lost between research notes and the next product decision.</p><h3>02 / Review access deliberately</h3><p>Keep editing rights separate from the ability to read a document.</p></article>
  <aside className='access'><h2>People with access</h2><p className='muted'>The list below is local demonstration state.</p>{people.map((p,i)=><div className='person' key={p.email}><span className='avatar'>{i===0?'AK':'+'}</span><div><strong>{p.email}</strong><small>{p.role}</small></div></div>)}<Field className='link-setting'><Label>Public link</Label><Switch checked={publicLink} onChange={setPublicLink} className='switch'><span /></Switch></Field><p className='link-detail'>{publicLink?'Anyone with the example link could view this document. This changes only the local preview.':'Restricted to the named people in this example.'}</p><p role='status' className='notice'>{notice}</p></aside></div>
  <Dialog open={open} onClose={()=>setOpen(false)} className='dialog-root'><DialogBackdrop className='backdrop'/><div className='dialog-position'><DialogPanel className='dialog-panel'><DialogTitle as='h2'>Share quarterly brief</DialogTitle><Description className='muted'>Choose one recipient and a permission. Closing discards this invitation draft.</Description><form noValidate onSubmit={submit}><label className='field-label' htmlFor='recipient'>Recipient email</label><input id='recipient' data-autofocus type='email' value={email} onChange={e=>{setEmail(e.target.value);setError('')}} aria-invalid={!!error} aria-describedby={error?'email-error':undefined} placeholder='[email protected]'/>{error&&<p id='email-error' role='alert' className='error'>{error}</p>}<Listbox value={role} onChange={setRole}><Label className='field-label'>Permission</Label><ListboxButton className='role-button'>{role}<span aria-hidden='true'>⌄</span></ListboxButton><ListboxOptions anchor='bottom' className='role-options'>{roles.map(value=><ListboxOption key={value} value={value} className='role-option'><span>{value}</span><span className='selected' aria-hidden='true'>✓</span></ListboxOption>)}</ListboxOptions></Listbox><p className='muted permission-help'>{role==='Can edit'?'May change document content in this example.':role==='Can comment'?'May add comments without editing content.':'May read the document without changing it.'}</p><div className='dialog-actions'><button type='button' onClick={()=>setOpen(false)}>Cancel</button><button className='primary' type='submit'>Add invitation</button></div></form></DialogPanel></div></Dialog>
  <footer>Native Dialog, Listbox, and Switch behavior. Original CSS below supplies all visual values; Headless UI does not ship this palette.</footer>
 </main>;
}

Code-Referenz

  • Es werden weder E-Mails versendet noch Anfragen gesendet.
  • Escape und Abbrechen verwerfen die nicht gespeicherte Einladung.

style.css — vollständiges originales visuelles System

Alle visuellen Designwerte, Zustandsselektoren, die Positionierung des Overlays und die responsiven Regeln, die App.jsx benötigt. Dies sind Entscheidungen für das Beispiel, keine offiziellen Headless UI-Standardwerte.

css
:root{--canvas:#f5f5f4;--surface:#fff;--ink:#1c1917;--muted:#57534e;--line:#d6d3d1;--accent:#4338ca;--accent-soft:#eef2ff;--error:#b91c1c;--space-1:4px;--space-2:8px;--space-3:12px;--space-4:16px;--space-6:24px;--space-8:32px;--radius-control:8px;--radius-panel:16px;font:16px/1.5 system-ui,sans-serif;color:var(--ink);background:var(--canvas)}*{box-sizing:border-box}body{margin:0}button,input{font:inherit}button{cursor:pointer;border:1px solid var(--line);border-radius:var(--radius-control);padding:10px 16px;background:var(--surface);color:var(--ink);font-weight:600}button:focus-visible,input:focus-visible{outline:2px solid var(--accent);outline-offset:3px}.primary{background:var(--accent);color:white;border-color:var(--accent)}.sharing-shell{max-width:1120px;margin:auto;padding:32px}.sharing-shell>header{display:flex;align-items:center;justify-content:space-between;gap:24px;margin-bottom:32px}.eyebrow{font-size:11px;letter-spacing:.1em;color:var(--accent);font-weight:700}h1{font-size:28px;line-height:1.25;margin:8px 0}h2{font-size:20px;line-height:1.3;margin:0 0 12px}h3{font-size:16px;margin:24px 0 8px}p{margin:0 0 16px}.muted{color:var(--muted);font-size:14px}.document-grid{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(260px,1fr);gap:24px}.paper,.access{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-panel);padding:32px}.paper h2{font-size:32px;max-width:15ch;margin-top:24px}.paper p{max-width:48ch}.tag{font-size:11px;font-weight:600;border:1px solid var(--line);padding:4px 8px;border-radius:4px}.rule{height:1px;background:var(--line);margin:24px 0}.person{display:flex;gap:12px;padding:16px 0;border-bottom:1px solid var(--line)}.person strong{display:block;font-size:14px;overflow-wrap:anywhere}.person small{color:var(--muted)}.avatar{flex:none;width:32px;height:32px;border-radius:50%;background:var(--accent-soft);color:var(--accent);display:grid;place-items:center;font-size:12px}.link-setting{display:flex;align-items:center;justify-content:space-between;margin-top:24px;font-weight:600}.switch{padding:3px;width:44px;height:26px;border:0;border-radius:999px;background:#a8a29e}.switch span{display:block;width:20px;height:20px;border-radius:50%;background:white;transition:transform .15s}.switch[data-checked]{background:var(--accent)}.switch[data-checked] span{transform:translateX(18px)}.link-detail{margin-top:12px;font-size:13px;color:var(--muted)}.notice{font-size:13px;color:var(--accent)}footer{font-size:12px;color:var(--muted);margin-top:24px}.dialog-root{position:fixed;inset:0;z-index:20}.backdrop{position:fixed;inset:0;background:rgb(28 25 23/.45)}.dialog-position{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;padding:16px;overflow-y:auto}.dialog-panel{width:min(100%,460px);max-height:calc(100% - 16px);overflow-y:auto;background:var(--surface);padding:32px;border-radius:var(--radius-panel);box-shadow:0 24px 64px rgb(0 0 0/.22)}.field-label{display:block;font-size:14px;font-weight:600;margin:20px 0 8px}input[type=email]{display:block;width:100%;padding:10px 12px;border:1px solid var(--line);border-radius:var(--radius-control);background:white;color:var(--ink)}input[aria-invalid=true]{border-color:var(--error)}.error{font-size:13px;color:var(--error);margin:8px 0}.role-button{display:flex;justify-content:space-between;width:100%;text-align:left}.role-options{z-index:30;width:var(--button-width);--anchor-gap:4px;background:var(--surface);border:1px solid var(--line);padding:4px;border-radius:8px;box-shadow:0 8px 24px rgb(0 0 0/.12);outline:none}.role-option{display:flex;justify-content:space-between;padding:10px;border-radius:4px;cursor:pointer;font-size:14px}.role-option[data-focus]{background:var(--accent-soft)}.role-option .selected{visibility:hidden;color:var(--accent)}.role-option[data-selected] .selected{visibility:visible}.permission-help{margin-top:12px}.dialog-actions{display:flex;justify-content:flex-end;gap:12px;margin-top:24px}@media(max-width:700px){.sharing-shell{padding:20px}.sharing-shell>header{align-items:flex-start;flex-direction:column}.document-grid{grid-template-columns:1fr}.paper,.access{padding:24px}.paper h2{font-size:26px}.dialog-panel{padding:24px}}@media(prefers-reduced-motion:reduce){.switch span{transition:none}}

Code-Referenz

  • data-focus und data-selected getrennt behandeln.
  • Tailwind wird nicht vorausgesetzt.
04

Headless UI-Designsystem: Agenten-Setup

Ausgangspunkt für die Implementierung

Die vollständigen Style- und Komponentendateien sind oben enthalten. Erfordert eine Node-Version, die von der ausgewählten Vite-Version unterstützt wird. Die Demo bündelt dasselbe native Komponentenpaket lokal.

text
# Terminal
npm create vite@latest sharing-demo -- --template react
cd sharing-demo
npm install
npm install @headlessui/[email protected]

# Save the complete examples as src/App.jsx and src/style.css.
# Replace src/main.jsx with:
import React from 'react';
import {createRoot} from 'react-dom/client';
import App from './App';
createRoot(document.getElementById('root')).render(<App/>);

# Terminal
npm run dev

Ein Prompt für dein Projekt

Agenten-Prompt
Verwenden Sie das bereitgestellte Headless UI App.jsx und style.css. Behalten Sie die native Zusammensetzung aus Dialog, Listbox und Switch bei, trennen Sie Berechtigungsentwürfe von bestätigten Zugriffsrechten und behalten Sie alle Selektoren für Fokus- und Auswahlzustände bei. Ersetzen Sie das lokale Hinzufügen von Einladungen durch unsere autorisierte API, einschließlich Status für ausstehende und fehlgeschlagene Anfragen; speichern Sie niemals in onClose. Bezeichnen Sie die benutzerdefinierte CSS-Farbpalette nicht als offizielles Headless UI-Theme.
05

Headless UI-Designsystem: Quellen und Geltungsbereich

Originale visuelle Konfiguration von OpenDesign und React-Beispiel mit dem nativen Verhalten von Headless UI 2.2.10. Die Werte von CSS sind ausdrücklich Entscheidungen auf Anwendungsebene; Headless UI stellt dieses Theme nicht bereit. Einladungen und Berechtigungsänderungen sind nur im lokalen Vorschauzustand vorhanden.