Zum Inhalt springen
    WingoUI
    KomponentenVorlagenDokuPreiseKI-AgentenBlogChangelog
    1. Startseite
    2. Blog
    3. Praxis: Screens und Apps
    4. React Settings Page: Navigation, Save Bar und Danger Zone
    Read in English
    1. Blog
    2. Praxis: Screens und Apps
    3. React Settings Page: Navigation, Save Bar und Danger Zone
    Praxis: Screens und Apps
    Praxis: Screens und Apps

    React Settings Page: Navigation, Save Bar und Danger Zone

    SR
    Serban Rusu · Gründer von Wingo UI
    16. Okt. 2026 · 11 Min. Lesezeit

    Auf dieser Seite

    0%
    1. Was braucht eine gute Account Settings Page UI?
    2. Wie richtest du das Settings Layout in React ein?
    3. Wie bekommt jeder Bereich einer Next.js Settings Page seine URL?
    4. Wie sollen Switches auf einer Einstellungsseite speichern?
    5. Wie baust du eine Danger Zone, die man nicht aus Versehen klickt?
    6. Wie funktioniert die Einstellungsseite auf dem Smartphone?
    7. Was, wenn du nur die Einstellungsliste fürs Smartphone brauchst?
    8. Gibt es eine komplette Vorlage für eine React Settings Page?
    9. Wie geht es weiter?
    10. Häufige Fragen
      1. Soll eine Einstellungsseite automatisch speichern oder einen Speichern-Button haben?
      2. Wie warne ich vor ungespeicherten Änderungen auf einer Einstellungsseite?
      3. Wie sollte eine Einstellungsseite auf dem Smartphone aussehen?
      4. Was gehört in die Danger Zone einer Einstellungsseite?
      5. Gibt es eine fertige Vorlage für eine React Settings Page?

    Kurz gesagt

    Eine gute React Settings Page teilt die Einstellungen in Bereiche auf: links eine Navigation auf dem Desktop, auf dem Smartphone eine Liste wie in iOS, die jeden Bereich hereinschiebt. Textfelder sammeln sich in einem Entwurf, den eine Save Bar speichert oder verwirft, Switches speichern selbst und springen zurück, wenn die Anfrage scheitert, und destruktive Aktionen stehen ganz am Ende in einer Danger Zone hinter einer getippten Bestätigung. Mit dem Settings Layout von Wingo UI ist das eine Komponente plus deine eigenen Felder und Save-Handler.

    Veröffentlicht am 16. Okt. 2026

    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:

    bash
    npx wingo-ui@latest add settings-layout switch input alert-dialog

    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:

    tsx
    // app/(app)/settings/settings-view.tsx
    "use client"
    import { Bell, TriangleAlert, User } from "lucide-react"
    import { useState } from "react"
    import { Input } from "@/components/ui/input"
    import { SettingsLayout, SettingsRow, SettingsSection } from "@/components/ui/settings-layout"
    import { Switch } from "@/components/ui/switch"
    import { DangerZone } from "./danger-zone"
    export type AccountSettings = { name: string; title: string; digest: boolean; mentions: boolean }
    type Preference = "digest" | "mentions"
    export function SettingsView({ initial, section }: { initial: AccountSettings; section: string }) {
    const [saved, setSaved] = useState(initial)
    const [draft, setDraft] = useState(initial)
    const [prefError, setPrefError] = useState<Partial<Record<Preference, string>>>({})
    // nur Textfelder machen die Seite dirty; Switches speichern selbst
    const dirty = draft.name !== saved.name || draft.title !== saved.title
    const savePreference = async (key: Preference, value: boolean) => {
    setPrefError((e) => ({ ...e, [key]: undefined }))
    const res = await fetch("/api/settings/preferences", {
    method: "PATCH",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ [key]: value }),
    })
    if (!res.ok) {
    // die Zeile zeigt das an; die Ablehnung lässt den Switch zurückspringen
    setPrefError((e) => ({ ...e, [key]: "Speichern fehlgeschlagen. Versuch es noch mal." }))
    throw new Error("Einstellung nicht gespeichert")
    }
    setSaved((s) => ({ ...s, [key]: value }))
    setDraft((d) => ({ ...d, [key]: value }))
    }
    return (
    <SettingsLayout
    title="Einstellungen"
    description="Dein Profil und wie wir dich erreichen"
    defaultValue={section}
    onValueChange={(id) => {
    // andere Query-Parameter behalten, nur den Bereich tauschen
    const url = new URL(window.location.href)
    url.searchParams.set("section", id)
    window.history.replaceState(null, "", url)
    }}
    dirty={dirty}
    onSave={async () => {
    const res = await fetch("/api/settings/profile", {
    method: "PUT",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ name: draft.name, title: draft.title }),
    })
    if (!res.ok) throw new Error("Dein Profil konnte nicht gespeichert werden. Versuch es noch mal.")
    setSaved(draft)
    }}
    onDiscard={() => setDraft(saved)}
    sections={[
    {
    id: "profile",
    label: "Profil",
    group: "Konto",
    icon: <User />,
    tone: "info",
    description: draft.name,
    content: (
    <SettingsSection title="Öffentliches Profil" description="Für deine Teammitglieder sichtbar.">
    <SettingsRow label="Vollständiger Name" controlWidth="md">
    <Input value={draft.name} onValueChange={(name) => setDraft({ ...draft, name })} autoComplete="name" />
    </SettingsRow>
    <SettingsRow label="Position" controlWidth="md">
    <Input value={draft.title} onValueChange={(title) => setDraft({ ...draft, title })} />
    </SettingsRow>
    </SettingsSection>
    ),
    },
    {
    id: "notifications",
    label: "Benachrichtigungen",
    group: "Konto",
    icon: <Bell />,
    tone: "warning",
    description: "E-Mail-Zusammenfassung und Erwähnungen",
    content: (
    <SettingsSection title="E-Mail">
    <SettingsRow label="Tägliche Zusammenfassung" description="Neue Deals und überfällige Rechnungen, um 8 Uhr." error={prefError.digest}>
    <Switch checked={saved.digest} onCheckedChange={(v) => savePreference("digest", v)} />
    </SettingsRow>
    <SettingsRow label="Erwähnungen" description="Wenn dich jemand in einer Notiz markiert." error={prefError.mentions}>
    <Switch checked={saved.mentions} onCheckedChange={(v) => savePreference("mentions", v)} />
    </SettingsRow>
    </SettingsSection>
    ),
    },
    {
    id: "danger",
    label: "Danger Zone",
    icon: <TriangleAlert />,
    danger: true,
    description: "Konto löschen",
    content: <DangerZone />,
    },
    ]}
    />
    )
    }

    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.

    Tipp auf Profil, um den Bereich hereinzuschieben, ändere den Namen und sieh zu, wie die Save Bar mit Verwerfen und Speichern hochgleitet, dann tipp auf den Zurück-Button. In einem so schmalen Rahmen sind die Bereiche eine Liste wie in iOS; ab 768px zeigt dieselbe Komponente eine Sidebar
    $ npx wingo-ui@latest add settings-layout
    ProDoku: Settings Layout

    Wie 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:

    tsx
    // app/(app)/settings/page.tsx
    import { getAccountSettings } from "@/server/settings" // deine Datenschicht
    import { SettingsView } from "./settings-view"
    export default async function SettingsPage({
    searchParams,
    }: {
    searchParams: Promise<{ section?: string }>
    }) {
    const [{ section }, settings] = await Promise.all([searchParams, getAccountSettings()])
    return <SettingsView initial={settings} section={section ?? "profile"} />
    }

    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.

    Schalte New messages um, drück dann Simulate an error und schalte noch einmal: Der Switch schaltet sofort um, zeigt beim Speichern einen Spinner, springt dann zurück und zeigt den Grund
    $ npx wingo-ui@latest add switch
    FreeDoku: Switch

    Der 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:

    tsx
    // app/(app)/settings/danger-zone.tsx
    "use client"
    import { Trash2 } from "lucide-react"
    import { useState } from "react"
    import { AlertDialog } from "@/components/ui/alert-dialog"
    import { Button } from "@/components/ui/button"
    import { Input } from "@/components/ui/input"
    import { SettingsRow, SettingsSection } from "@/components/ui/settings-layout"
    export function DangerZone() {
    const [open, setOpen] = useState(false)
    const [typed, setTyped] = useState("")
    return (
    <>
    <SettingsSection title="Danger Zone" description="Aktionen, die sich nicht rückgängig machen lassen." danger>
    <SettingsRow label="Konto löschen" description="Entfernt dein Profil und jeden Workspace, der dir gehört." danger>
    <Button variant="soft" tone="danger" size="sm" leftIcon={<Trash2 />} onClick={() => setOpen(true)}>
    Konto löschen
    </Button>
    </SettingsRow>
    </SettingsSection>
    <AlertDialog
    open={open}
    onOpenChange={(next) => {
    setOpen(next)
    if (!next) setTyped("")
    }}
    tone="danger"
    icon={<Trash2 />}
    title="Dein Konto löschen?"
    description="Dein Profil, deine Workspaces und Rechnungen werden endgültig gelöscht."
    confirmLabel="Konto löschen"
    cancelLabel="Abbrechen"
    confirmDisabled={typed !== "DELETE"}
    onConfirm={async () => {
    const res = await fetch("/api/account", { method: "DELETE" })
    if (!res.ok) throw new Error("Das Konto konnte nicht gelöscht werden. Versuch es noch mal.")
    window.location.assign("/goodbye")
    }}
    >
    <Input label="Tippe DELETE zur Bestätigung" value={typed} onValueChange={setTyped} autoComplete="off" spellCheck={false} />
    </AlertDialog>
    </>
    )
    }

    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:

    tsx
    import { Bell, Globe, User } from "lucide-react"
    import { List, type ListGroupData } from "@/components/ui/list"
    import { Switch } from "@/components/ui/switch"
    const groups: ListGroupData[] = [
    {
    id: "account",
    label: "Konto",
    items: [
    { id: "profile", title: "Profil", description: "emma.carter@northwind.app", icon: <User />, href: "/settings/profile" },
    { id: "notifications", title: "Benachrichtigungen", icon: <Bell />, trailing: <Switch defaultChecked aria-label="Benachrichtigungen" /> },
    { id: "language", title: "Sprache", icon: <Globe />, value: "Deutsch", href: "/settings/language" },
    ],
    },
    ]
    export function MeTab() {
    return <List groups={groups} />
    }

    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.

    bash
    npx wingo-ui@latest add settings-page
    tsx
    "use client"
    import { SettingsPage } from "@/components/blocks/settings-page"
    export function SettingsRoute() {
    return (
    <SettingsPage
    sections={["profil", "notificari", "securitate", "pericol"]}
    onSave={async (section, values) => {
    const res = await fetch(`/api/settings/${section}`, { method: "PUT", body: JSON.stringify(values) })
    if (!res.ok) throw new Error("Speichern fehlgeschlagen. Bitte versuch es noch mal.")
    }}
    onPreferenceChange={async (preference, value) => {
    const res = await fetch("/api/settings/preferences", { method: "PATCH", body: JSON.stringify({ preference, value }) })
    if (!res.ok) throw new Error("Speichern fehlgeschlagen. Versuch es noch mal.")
    }}
    onDeleteAccount={async () => {
    const res = await fetch("/api/account", { method: "DELETE" })
    if (!res.ok) throw new Error("Das Konto konnte nicht gelöscht werden. Versuch es noch mal.")
    window.location.assign("/goodbye")
    }}
    />
    )
    }

    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.

    Öffne Delete account und tippe DELETE, um den Button freizuschalten, oder drück Export und sieh zu, wie der Export vorher in einem Toast hochzählt
    $ npx wingo-ui@latest add settings-page
    ProDoku: Settings Page

    Wie 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.

    Komponenten in diesem Artikel

    • Settings Layout

      A React settings page layout like macOS and iOS: a section nav, grouped label and control rows, and a save bar that slides up on changes.

      Pro
    • Settings Page

      A React account settings page for a back office: profile, account, notifications, billing, security and a danger zone, with a save bar.

      Pro
    • Switch

      A React toggle switch for settings that apply at once: a spring thumb that stretches and drags, thumb icons, and async saves that roll back.

      Free
    • List

      A React list for settings, contacts, inboxes and orders: iOS grouped panels, selection, row menus, swipe actions and drag to reorder.

      Pro
    • Alert Dialog

      A React alert dialog for confirmations: an async confirm that loads, fails inline and shakes, plus an await confirm() API.

      Pro
    • Input

      A React text input: icons and addons inside the box, a clear button, a loading spinner, a character counter and floating labels.

      Free

    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

    Teilen

    SR

    Über den Autor

    Serban Rusu

    Gründer von Wingo UI

    Serban Rusu hat Wingo UI gegründet. Er baut die Komponenten, die CLI und den MCP-Server und schreibt über React-UIs für Smartphones und KI-Agents.

    Mehr von Serban
    Weiterlesen

    Ähnliche Artikel

    Alle Artikel
    Praxis: Screens und Apps

    Nextjs Admin Dashboard: 5 Screens, fit fürs Smartphone

    Bau ein Nextjs Admin Dashboard mit dem App Router: App Shell, KPI-Startseite, serverseitige Datentabelle, Settings und Team, alles fit fürs Smartphone.

    SRSerban Rusu·9. Okt. 2026·21 Min. Lesezeit
    Mobile UI mit React

    React Action Sheet: wie unter iOS, async und responsive

    So baust du ein React Action Sheet wie unter iOS: rote Zeilen zum Löschen, Abbrechen in eigener Karte, show() mit await für async Aktionen, ab 768px ein Dialog.

    SRSerban Rusu·16. Okt. 2026·9 Min. Lesezeit
    Next.js und Tailwind CSS

    React Controllable State Hook: Code und 3 Fallstricke

    Bau einen React Controllable State Hook, der value oder defaultValue annimmt. Mit komplettem TypeScript-Code, drei echten Fallstricken und dem Radix-Vergleich.

    SRSerban Rusu·16. Okt. 2026·11 Min. Lesezeit
    Newsletter

    Neue Artikel per E-Mail

    Neue Guides, Tutorials und Vergleiche aus dem Wingo UI Blog, sobald sie erscheinen. Die meisten Artikel sind auf Englisch.

    Kein Spam. Du kannst dich jederzeit abmelden.

    WingoUI

    Animierte, konfigurierbare, mobile-first React-Komponenten und Blöcke. Kopier den Quellcode, pass ihn an und lass deinen Coding-Agenten damit bauen.

    Produkt

    • Komponenten
    • Vorlagen
    • Preise
    • KI-Agenten
    • Theme-Generator

    Ressourcen

    • Doku
    • Blog
    • Changelog
    • Changelog-RSS
    • llms.txt

    Rechtliches

    • AGB
    • Datenschutz
    • Rückerstattung
    • Lizenz
    • Impressum

    Komponenten-Kategorien

    • Buttons & Actions
    • Inputs
    • Forms
    • Navigation
    • Overlays
    • Feedback
    • Data Display
    • Tables & Lists
    • Charts & Stats
    • Layout
    • Media
    • AI Kit
    • Text & Effects
    • Mobile
    • Commerce
    • Marketing Sections
    • Blocks
    • Hooks & Utilities

    © 2026 Wingo UI

    Wingo UI