feat(ui): add dark mode support with system preference detection and localStorage persistence

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-25 13:59:49 +00:00
parent 9cbffc4acb
commit c428a7ec00
9 changed files with 416 additions and 1 deletions
+10
View File
@@ -382,6 +382,16 @@ class Settings(BaseSettings):
),
)
# UI / Appearance
ui_default_color_scheme: str = Field(
default="system",
description=(
"Default color scheme for the web interface. "
"Options: 'system' (follow OS preference), 'light', 'dark'. "
"Individual users can override this with the in-app toggle; their choice is persisted in localStorage."
),
)
# Rate Limiting Configuration (see SECURITY_AUDIT.md and docs/API.md)
# Protects against DoS attacks and API abuse
rate_limiting_enabled: bool = Field(
+14
View File
@@ -1153,6 +1153,20 @@ SETTING_METADATA = {
"required": False,
"restart_required": False,
},
# UI / Appearance
"ui_default_color_scheme": {
"category": "UI",
"description": (
"Default color scheme for the web interface. "
"Options: 'system' (follow OS preference), 'light', 'dark'. "
"Individual users can override this with the in-app toggle; their choice is persisted in localStorage."
),
"type": "string",
"sensitive": False,
"required": False,
"restart_required": False,
"options": ["system", "light", "dark"],
},
}
+4
View File
@@ -34,11 +34,15 @@ def template_response_with_version(*args, **kwargs):
req = args[1].get("request")
if req is not None and hasattr(req.state, "csrf_token"):
args[1].setdefault("csrf_token", req.state.csrf_token)
# Inject default color scheme for dark-mode initialisation
args[1].setdefault("ui_default_color_scheme", getattr(settings, "ui_default_color_scheme", "system"))
elif "context" in kwargs and isinstance(kwargs["context"], dict):
kwargs["context"].setdefault("version", settings.version)
req = kwargs["context"].get("request")
if req is not None and hasattr(req.state, "csrf_token"):
kwargs["context"].setdefault("csrf_token", req.state.csrf_token)
# Inject default color scheme for dark-mode initialisation
kwargs["context"].setdefault("ui_default_color_scheme", getattr(settings, "ui_default_color_scheme", "system"))
return original_template_response(*args, **kwargs)