Erscheinungsbild

Der Bereich „Erscheinungsbild“ in den Einstellungen eines KI-Produkts: Theme, Akzent, Hintergrundtönung, Dichte, Chat-Schrift, Textgrößen und Barrierefreiheitsoptionen, alles als Entwurf gehalten, bis gespeichert wird.

Appearance bündelt alles zum Aussehen der App in einem Bereich. Theme-Karten zeigen ein kleines Fenster in jedem Theme, gezeichnet im gewählten Akzent, sodass die Wahl vor dem Speichern klar ist.

System folgt dem Gerät und sagt, welches Theme gerade aktiv ist. Hoher Kontrast verstärkt Kanten und Text und hält Hintergründe neutral, deshalb ist der Tönungsregler deaktiviert, solange er gewählt ist.

Der Akzentfarbton ist eine echte Farbleiste mit acht Schnellwahlen darunter, und die Anzeige nennt die Farbe, etwa Blue 250°. Die Hintergrundtönung mischt diesen Akzent in die Flächen. Karten für Dichte und Chat-Schrift zeigen je ein Beispiel jeder Option, und die zwei Textgrößen sind Stepper mit Grenzen.

Reduce motion und Reduce transparency sagen, wenn das Gerät bereits eines davon verlangt.

Alles ist ein Entwurf, bis es gespeichert wird. Die Speicherleiste aus Settings erscheint, sobald sich etwas unterscheidet, Discard bringt das gespeicherte Aussehen zurück, und Reset setzt jede Option als Entwurf auf den Standard zurück, den du weiterhin verwerfen kannst.

  1. Die Pro-Registry zu components.json hinzufügen

    components.json
    {
      "registries": {
        "@hextaui-pro": {
          "url": "https://hextaui.com/r/pro/{name}.json",
          "headers": {
            "Authorization": "Bearer ${HEXTAUI_PRO_TOKEN}"
          }
        }
      }
    }
  2. Token hinzufügen

    Erstelle auf deiner Kontoseite einen Token und trage ihn in .env.local als HEXTAUI_PRO_TOKEN ein.

  3. Den Block hinzufügen

    pnpm dlx shadcn@latest add @hextaui-pro/appearance

In deiner API speichern

Übergib die gespeicherten Werte und ein asynchrones onSave. Es wird nichts gesendet, bis jemand in der Leiste auf Save drückt. Wirf einen Fehler, um deine Meldung in der Leiste zu zeigen und die Auswahl zu behalten.

"use client"

import { IconPalette } from "@tabler/icons-react"

import { SettingsSection, SettingsShell } from "../settings/settings"
import { AppearanceSettings, type AppearanceValues } from "@/components/blocks/appearance/appearance"

export function AppearancePage({ appearance }: { appearance: AppearanceValues }) {
  return (
    <SettingsShell
      sections={[{ id: "appearance", label: "Appearance", icon: <IconPalette /> }]}
      className="h-svh"
    >
      <SettingsSection id="appearance">
        <AppearanceSettings
          values={appearance}
          onSave={async (values) => {
            const response = await fetch("/api/appearance", {
              method: "PUT",
              body: JSON.stringify(values),
            })
            if (!response.ok) throw new Error("Check your connection and try again.")
          }}
        />
      </SettingsSection>
    </SettingsShell>
  )
}

Das gespeicherte Aussehen anwenden

Wende die Werte nach dem Speichern an, wie auch immer deine App ihr Theme umsetzt. normalizeAppearance repariert alles, was eine ältere Version gespeichert hat, sodass ein fehlerhafter Wert nie die Seite zerstört.

"use client"

import * as React from "react"

import { AppearanceSettings, normalizeAppearance, type AppearanceValues } from "@/components/blocks/appearance/appearance"

function applyAppearance(values: AppearanceValues) {
  const root = document.documentElement
  const systemDark = window.matchMedia("(prefers-color-scheme: dark)").matches
  const dark = values.theme === "dark" || values.theme === "contrast" || (values.theme === "system" && systemDark)
  root.classList.toggle("dark", dark)
  root.dataset.contrast = values.theme === "contrast" ? "more" : "normal"
  root.dataset.density = values.density
  root.dataset.chatFont = values.chatFont
  root.dataset.motion = values.reduceMotion ? "reduce" : "full"
  root.dataset.transparency = values.reduceTransparency ? "reduce" : "full"
  root.style.setProperty("--accent-hue", String(values.hue))
  root.style.setProperty("--accent-tint", `${values.intensity}%`)
  root.style.setProperty("--text-interface", `${values.interfaceSize}px`)
  root.style.setProperty("--text-code", `${values.codeSize}px`)
}

export function AppearanceForm({ stored }: { stored: Partial<AppearanceValues> | null }) {
  const [saved, setSaved] = React.useState(() => normalizeAppearance(stored))

  React.useEffect(() => applyAppearance(saved), [saved])

  return (
    <AppearanceSettings
      values={saved}
      onSave={async (values) => {
        const response = await fetch("/api/appearance", {
          method: "PUT",
          body: JSON.stringify(values),
        })
        if (!response.ok) throw new Error("Check your connection and try again.")
        setSaved(values)
      }}
    />
  )
}

Aufbau

Die Teile, die du zusammensetzt, von außen nach innen.

PartBeschreibung
AppearanceSettingsDer Inhalt des Bereichs: die Optionsgruppen, verbunden mit der Speicherleiste der Shell.
normalizeAppearanceMacht aus gespeicherten oder unvollständigen Werten gültige: begrenzt Größen, lässt den Farbton umlaufen und greift bei unbekannten Namen auf Standards zurück.
appearanceDefaultsDie Werte, auf die Reset zurückgeht, wenn du keine eigenen übergibst.

AppearanceSettings

Verwende es in einer SettingsSection. Akzeptiert auch alle div-Props.

PropTypStandard
valuesWas jetzt gespeichert ist: { theme, hue, intensity, density, chatFont, interfaceSize, codeSize, reduceMotion, reduceTransparency }. Ungültige Werte werden repariert, und die Reparatur zählt nicht als ungespeicherte Änderung.
AppearanceValues–
onSaveSpeichert den Entwurf. Wirf einen Fehler, um die Meldung in der Speicherleiste zu zeigen und den Entwurf zu behalten.
(values) => void | errors | Promise<void | errors>–
defaultsWas Reset zurücksetzt.
AppearanceValuesappearanceDefaults
PropTypStandard
themeSystem folgt prefers-color-scheme.
"system" | "light" | "dark" | "contrast""system"
hueDer OKLCH-Farbton des Akzents, 0 bis 359.
number250
intensityWie stark der Akzent Hintergründe tönt, 0 bis 100.
number30
densityAbstand zwischen und innerhalb von Nachrichten.
"compact" | "comfortable""comfortable"
chatFontDie Schrift für Nachrichten.
"sans" | "serif" | "mono""sans"
interfaceSizeTextgröße in Pixeln, 12 bis 18.
number14
codeSizeCodegröße in Pixeln, 11 bis 20.
number13
reduceMotionStoppt Spinner und gleitende Panels.
booleanfalse
reduceTransparencyDeckende Hintergründe statt unscharfer.
booleanfalse
TasteAktion
←→Wählt in den Karten für Theme, Dichte oder Schrift die vorherige oder nächste Karte. Bewegt auf der Farbtonleiste um ein Grad.
Shift→Bewegt auf der Farbtonleiste um 15 Grad. Bild auf und Bild ab tun dasselbe.
HomeEndSpringt auf der Farbtonleiste zu einem der Enden.
↑↓Ändert in einem Textgrößenfeld die Größe um einen Pixel.
⌘SSpeichert, solange etwas ungespeichert ist. Strg+S unter Windows und Linux.
  • Jede Kartengruppe ist eine Radio-Gruppe, benannt nach ihrer Zeile, und jede Karte trägt ihr eigenes Label, sodass Screenreader „Dunkel, Radio, 3 von 4“ vorlesen.
  • Die Farbtonleiste liest ihre Farbe mit Namen vor, etwa „Blau, 250 Grad“, und die Schnellwahlen sind Toggle-Buttons, benannt nach der Farbe.
  • Reset behält nach der Ausführung den Fokus und sagt an, dass die Standards zurück sind und gespeichert werden müssen.

Gebaut mit

Die kostenlosen HextaUI-Komponenten, aus denen Appearance besteht. Jede lässt sich einzeln installieren.

Code

2 Dateien, hinzugefügt zu components/blocks/appearance.