React Settings Page: Navigation, Save Bar und Danger Zone

Jede App bekommt irgendwann eine Einstellungsseite, und meistens entsteht sie zuletzt und in Eile: ein langes Formular, ganz unten ein Speichern-Button, zu dem niemand scrollt, Switches, die gespeichert aussehen, es aber nicht sind, und ein Button „Konto löschen“ direkt neben „Passwort ändern“. Dieses Tutorial baut Schritt für Schritt eine React Settings Page, die all das vermeidet: eine Navigation auf dem Desktop, eine iOS-Liste mit Push-Navigation auf dem Smartphone, eine Save Bar, die nur bei Änderungen erscheint, Switches, die selbst speichern, und am Ende eine Danger Zone. Wir bauen Wingo UI, und der Code nutzt unser Settings Layout. Wir sind also nicht neutral; die Muster funktionieren mit jeder Bibliothek.
Was braucht eine gute Account Settings Page UI?
Eine gute Account Settings Page UI braucht fünf Dinge: Bereiche mit eigener Adresse, ein sichtbares Speichermodell, Umschalter, die sofort greifen, eine eigene Danger Zone und ein echtes Smartphone-Layout. Jedes davon stammt aus einem Produkt, das viele schon täglich nutzen:
- Bereiche mit eigener Adresse. Profil, Benachrichtigungen, Abrechnung, Sicherheit. Eine linke Spalte, wenn es viele sind, Tabs bei wenigen. Support-Links sollen im richtigen Bereich landen, also gehört der offene Bereich in die URL.
- Ein Speichermodell, das man sieht. Shopifys Save Bar API (opens in a new tab) zeigt Speichern und Verwerfen nur, solange ein Formular ungespeicherte Änderungen hat, und ihre Methode
leaveConfirmation()fragt den Händler, bevor die App wegnavigiert (Stand Oktober 2026). Das ist das Modell für Textfelder. - Umschalter, die sofort greifen. Ein Switch, der auf einen Speichern-Button wartet, lügt über seinen Zustand. Er soll sofort speichern und zurückspringen, wenn die Anfrage scheitert.
- Destruktive Aktionen zuletzt. Ein eigener Block mit rotem Rahmen, Buttons statt Switches und eine Bestätigung, die eine bewusste Handlung verlangt, etwa ein getipptes Wort.
- Ein Smartphone-Layout. Auf einem 390px breiten Bildschirm passt keine Sidebar. Die iOS-Einstellungen haben das längst gelöst: eine gruppierte Liste der Bereiche, und ein Tipp schiebt den Bereich herein.
Viele Vorlagen für eine React Einstellungsseite decken den ersten Punkt ab und hören dann auf. Die Settings Pages von Untitled UI (opens in a new tab) etwa listen 21 Layouts (Profil, Passwort, Team, Abrechnung, Benachrichtigungen, Integrationen), und Stand Oktober 2026 erwähnt die Seite weder ungespeicherte Änderungen noch eine Danger Zone oder ein Smartphone-Layout. Genau diese Teile kosten Zeit, deshalb bekommen sie hier den meisten Platz.
Wie richtest du das Settings Layout in React ein?
Du richtest ein einziges SettingsLayout ein, das deine Bereiche als Daten bekommt und Navigation und Save Bar selbst verwaltet. Installier es zusammen mit den Controls:
Die Settings Layout Komponente ist der Rahmen: Sie nimmt eine Liste von sections, rendert die Navigation, blendet die aktive Seite kurz über und verwaltet die Save Bar. Jeder Bereich ist ein Objekt mit id, label, optionalem icon, group (eine kleine Gruppenüberschrift in der Sidebar und eine eingerückte Gruppe auf dem Smartphone), description (der Untertitel in der Smartphone-Liste), tone (die Icon-Kachel auf dem Smartphone) und content. Innerhalb eines Bereichs kombinierst du SettingsSection (eine Gruppe von Zeilen mit Titel) und SettingsRow (Label, Beschreibung und rechts ein Control). Eine Zeile verbindet ihr Label selbst mit dem Control, ein Tipp auf den Label-Text schaltet also den Switch um.
Hier die Client-Ansicht mit drei Bereichen, einer Save Bar für die Textfelder und Switches, die selbst speichern:
Auf drei Details kommt es an. dirty vergleicht den Entwurf mit den zuletzt gespeicherten Werten: Tippst du einen Namen und löschst die Änderung wieder, verschwindet die Bar. onSave gibt ein Promise zurück: Solange es läuft, dreht sich der Button, ein aufgelöstes Promise blendet „Changes saved“ ein und schiebt die Bar weg, und ein geworfener Fehler lässt die Bar stehen, schüttelt sie und zeigt deine Meldung. onDiscard stellt die gespeicherten Werte wieder her, und das Layout ruft es auch auf, wenn jemand bestätigt, einen Bereich mit ungespeicherten Änderungen zu verlassen.
$ npx wingo-ui@latest add settings-layoutWie bekommt jeder Bereich einer Next.js Settings Page seine URL?
Lies den Bereich in der Server-Page aus dem Query-String und schreib ihn auf dem Client mit history.replaceState zurück. In Next.js 16 ist searchParams ein Promise, also brauchst du await:
Die Ansicht oben aktualisiert die Adresse mit window.history.replaceState in onValueChange. Next.js unterstützt die native History API (opens in a new tab) und hält usePathname und useSearchParams damit synchron. Der Aufruf schreibt die Adresse ohne Navigation um, ein Wechsel des Bereichs lädt die Einstellungen also nie neu und führt die Server-Page nicht erneut aus. Weil die URL aus window.location.href entsteht, bleiben andere Query-Parameter erhalten, die ein nackter ?section=-String verwerfen würde. Eine unbekannte ID in der URL fällt auf den ersten aktivierten Bereich zurück.
Einen Kompromiss auf dem Smartphone solltest du kennen. Ein Query-Parameter wählt den Bereich, aber auf dem Smartphone öffnet das Layout trotzdem die gruppierte Liste, so wie die iOS-Einstellungen. Wenn Deep Links auf dem Smartphone direkt den Bereich öffnen sollen, gib jedem Bereich ein href und mach ihn zu einer echten Route (/settings/notifications), wobei du value über den Pfad steuerst: Das Layout öffnet einen gerouteten Bereich dann schon hereingeschoben. Bereiche mit href rendern children statt content, und um ungespeicherte Änderungen über Routen hinweg muss sich dann dein Router kümmern.
Wie sollen Switches auf einer Einstellungsseite speichern?
Sofort, mit Rollback. Der Switch behandelt ein Promise aus onCheckedChange als Speichervorgang: Er schaltet sofort um, zeigt im Thumb einen kleinen Spinner, ignoriert Klicks, bis das Promise abgeschlossen ist, und springt zurück, wenn es abgelehnt wird. Deshalb wirft savePreference in der Ansicht bei einer gescheiterten Antwort und aktualisiert saved erst nach dem Erfolg. checked bleibt an den gespeicherten Wert gebunden: Während die Anfrage läuft, zeigt der Switch den ausstehenden Wert, danach folgt er wieder checked und behauptet nie einen Zustand, den der Server nicht hat.
Bei der Fehlermeldung stolpern viele. Ein Switch mit eigenem label zeigt seinen errorText nach einem gescheiterten Speichern unter dem Label an, aber in einer SettingsRow hat der Switch kein eigenes Label: Das liefert die Zeile. Ein nackter Switch schüttelt sich trotzdem, springt zurück und sagt errorText für Screenreader an, doch sichtbar erklärt nichts, warum. Deshalb führt die Ansicht eine prefError-Map und gibt sie an die Prop error der Zeile weiter. Die rendert die Meldung unter der Beschreibung und verknüpft sie per aria-describedby mit dem Switch. Lösch den Eintrag zu Beginn jedes Versuchs, damit ein erfolgreicher neuer Versuch die Meldung entfernt.
Wichtig ist, Switches aus dirty herauszuhalten. Würde ein Umschalter auch die Save Bar einblenden, sähen die Leute „You have unsaved changes“ für etwas, das schon gespeichert ist, und das nächste Verwerfen würde es scheinbar rückgängig machen. Eine Seite, zwei Speichermodelle, und jedes Control macht klar, welches es nutzt.
$ npx wingo-ui@latest add switchDer Switch ist kostenlos. In einer SettingsRow bekommt der nackte Track auf Touchscreens eine Trefferfläche von 44px, das Label der Zeile ist mit ihm verbunden, sodass auch ein Tipp auf „Tägliche Zusammenfassung“ ihn umschaltet, und ein vertikales Wischen über den Track scrollt weiterhin die Seite.
Wie baust du eine Danger Zone, die man nicht aus Versehen klickt?
Setz sie ans Ende, markier sie und mach den letzten Schritt bewusst. SettingsSection nimmt danger für einen roten Ring und Titel, SettingsRow nimmt danger für ein rotes Label, und der Bereich bekommt danger: true, damit ihn auch die Smartphone-Liste rot zeigt. Die Bestätigung ist ein Alert Dialog mit einem getippten Wort:
Beim Öffnen des Dialogs liegt der Fokus auf Abbrechen, ein Klick auf die abgedunkelte Seite tut nichts, und die Aktion bleibt gesperrt, bis das Wort stimmt. onConfirm gibt ein Promise zurück: Der Button dreht sich, solange die Anfrage läuft, und ein geworfener Fehler schüttelt die Karte und zeigt die Meldung über den Buttons, statt den Dialog zu schließen. Setz typed beim Schließen zurück, sonst ist der Dialog beim nächsten Öffnen schon scharf.
Wie funktioniert die Einstellungsseite auf dem Smartphone?
Das Settings Layout misst seine eigene Breite und wechselt unter 768px die Navigation. Der Standardwert mobileNav="list" ist das iOS-Muster: Der Seitentitel wird zum großen Titel über einer gruppierten Liste, jeder Bereich ist eine Zeile mit Icon-Kachel und Beschreibung, und ein Tipp auf die Zeile schiebt den Bereich herein. Zurück geht es mit dem Zurück-Button, mit Escape oder mit einem Wischen nach rechts. Für kürzere Seiten gibt es zwei Alternativen: "tabs" (fixierte, scrollbare Pill-Tabs) und "select" (ein Select, das ein Bottom Sheet mit denselben Gruppen öffnet).
Auch die Save Bar ändert sich. Auf dem Smartphone ist sie immer unten fixiert, sitzt über der Safe Area und über einer Bottom Tab Bar, die ihre Höhe als --bottom-bar-offset veröffentlicht, hebt sich über die Bildschirmtastatur, und das Layout gibt dem Inhalt unten genug Abstand, damit die Bar nie die letzte Zeile verdeckt. Falls du schon mit position: fixed auf iOS gekämpft hast: Unser Artikel über die Tastatur in iOS Safari und fixierte Leisten erklärt, warum der letzte Punkt Sorgfalt braucht, und der Guide zur Bottom Navigation Bar behandelt die Tab-Bar-Seite von --bottom-bar-offset.
Auf dem Desktop zeigt der Speichern-Button einen Tastenhinweis für saveShortcut (Standard mod+s: Cmd+S auf dem Mac, sonst Ctrl+S), auf Touchscreens ausgeblendet. Der Shortcut ist nur aktiv, solange es etwas zu speichern gibt, auch in einem Textfeld. Den Rest der Zeit funktioniert also das „Seite speichern“ des Browsers weiter. Mit saveShortcut="" schaltest du ihn ab.
Was, wenn du nur die Einstellungsliste fürs Smartphone brauchst?
Nimm die Komponente List, wenn ein ganzes Layout zu viel ist, etwa für einen Tab „Ich“ in einer Mobile-first-App mit ein paar Zeilen, die auf Seiten verlinken, einen aktuellen Wert zeigen oder etwas umschalten. Sie zeichnet das gruppierte iOS-Panel auch für sich allein:
Zeilen mit href enden mit einem Chevron, value zeigt rechts die aktuelle Auswahl, und trailing nimmt jedes beliebige Control. Hat eine Zeile sowohl ein href als auch einen Switch in trailing, bekommt sie eine gestreckte klickbare Fläche statt eines umschließenden Buttons, damit der Switch nie in einem Link steckt. Der komplette Block Settings Page nutzt dieselbe List für die angemeldeten Geräte.
Gibt es eine komplette Vorlage für eine React Settings Page?
Ja, wenn du lieber mit dem fertigen Screen anfängst. Der Block Settings Page baut auf dem Settings Layout auf und bringt sechs Bereiche mit: Profil (Foto-Upload mit Zuschnitt, Telefon, Zeitzone), Konto (E-Mail-Änderung mit 6-stelligem Code, Prüfung der Workspace-Adresse), Benachrichtigungen (ein Switch pro Ereignis und Kanal, Ruhezeiten, Zusammenfassung), Abrechnung (Plan, Nutzung, Rechnungen, die auf dem Smartphone zu Karten werden), Sicherheit (Passwort, eine Zwei-Faktor-Einrichtung in drei Schritten mit QR-Code und Backup-Codes, Sitzungen) und eine Danger Zone mit Export und getipptem Löschen. Seine Bereichs-IDs sind rumänische Schlüssel hinter englischen Labels: profil, cont, notificari, facturare, securitate, pericol.
onSave deckt die Textfelder des offenen Bereichs ab und onPreferenceChange die Switches, die selbst speichern, mit demselben Rollback wie oben (hier lässt eine Ablehnung den Switch mit einem Toast zurückspringen). Beide Handler müssen bei einer gescheiterten Antwort werfen: fetch lehnt nur bei einem Netzwerkfehler ab, also zählt ein 500, den du nicht in einen Throw verwandelst, als erfolgreiches Speichern. Die Schlüssel der Einstellungen sind Pfade wie notificari.quietHours oder securitate.loginAlerts. Jeder Text ist eine labels-Prop und alle Daten haben eine eigene Prop (profile, billing, sessions), so ersetzt du die Beispieldaten Stück für Stück. Unser Tutorial zum Next.js Admin Dashboard verbindet diesen Block in einem kompletten Backoffice mit Server Actions, und die übrigen Artikel der Kategorie Build behandeln weitere komplette Screens.
$ npx wingo-ui@latest add settings-pageWie geht es weiter?
Fang mit dem Layout und einem Bereich an, schließ dessen Speichern an und ergänze dann die Switches und die Danger Zone. Switch und Input sind kostenlos, Settings Layout, List, Alert Dialog und der Block Settings Page gehören zu Wingo UI Pro (Preise). Installier das Layout mit npx wingo-ui@latest add settings-layout und bau deinen ersten Bereich mit dem Code von oben.
Häufige Fragen
Soll eine Einstellungsseite automatisch speichern oder einen Speichern-Button haben?
Beides, jeweils für die passende Art von Control. Switches und andere einfache Umschalter speichern sofort und springen zurück, wenn die Anfrage scheitert. Textfelder sammeln sich in einem Entwurf, den eine Save Bar speichert, denn ein halb getippter Name soll nie beim Server ankommen.
Wie warne ich vor ungespeicherten Änderungen auf einer Einstellungsseite?
Berechne ein Dirty-Flag, indem du den Entwurf mit den zuletzt gespeicherten Werten vergleichst, zeig eine Save Bar, solange es true ist, frag vor dem Wechsel des Bereichs nach und registrier einen beforeunload-Handler, damit auch das Schließen des Tabs warnt. Das Settings Layout erledigt alle drei Punkte über seine Props dirty, confirmLeave und warnBeforeUnload.
Wie sollte eine Einstellungsseite auf dem Smartphone aussehen?
Mach aus der Navigation eine gruppierte Liste wie in den iOS-Einstellungen: Ein Tipp auf eine Zeile schiebt den Bereich mit Zurück-Button und Wischgeste herein. Pinn die Save Bar über die Tab Bar und die Safe Area, damit sie nie die letzte Zeile verdeckt oder hinter der Bildschirmtastatur verschwindet.
Was gehört in die Danger Zone einer Einstellungsseite?
Aktionen, die sich nicht rückgängig machen lassen, etwa das Konto löschen, die Inhaberschaft übertragen oder einen Workspace entfernen. Setz den Bereich ans Ende, gib ihm einen roten Rahmen und Titel, nimm einen Button statt eines Switches und verlang eine getippte Bestätigung, bevor die Aktion läuft.
Gibt es eine fertige Vorlage für eine React Settings Page?
Der Block Settings Page von Wingo UI bringt die Bereiche Profil, Konto, Benachrichtigungen, Abrechnung, Sicherheit und Danger Zone mit Save Bar und Smartphone-Layout mit und lässt sich mit npx wingo-ui@latest add settings-page installieren. Er gehört zu Wingo UI Pro; Switch und Input, die er nutzt, sind kostenlos.
- Einstellungen
- React
- Next.js
- Formulare
- Mobile UI


