summaryrefslogtreecommitdiff
path: root/Biz/PodcastItLater/Web.py
diff options
context:
space:
mode:
Diffstat (limited to 'Biz/PodcastItLater/Web.py')
-rw-r--r--Biz/PodcastItLater/Web.py181
1 files changed, 63 insertions, 118 deletions
diff --git a/Biz/PodcastItLater/Web.py b/Biz/PodcastItLater/Web.py
index 39e2240..d91587a 100644
--- a/Biz/PodcastItLater/Web.py
+++ b/Biz/PodcastItLater/Web.py
@@ -53,55 +53,34 @@ from typing import override
logger = Log.setup()
-def create_theme_switcher_script() -> html.script:
- """Create JavaScript for theme switching with localStorage persistence."""
- return html.script(
+def create_auto_dark_mode_style() -> html.style:
+ """Create CSS for automatic dark mode based on prefers-color-scheme."""
+ return html.style(
"""
- // Theme switcher with localStorage persistence
- (function() {
- const getStoredTheme = () => localStorage.getItem('theme');
- const setStoredTheme = (theme) => {
- localStorage.setItem('theme', theme);
- };
- const getPreferredTheme = () => {
- const storedTheme = getStoredTheme();
- if (storedTheme) {
- return storedTheme;
- }
- return window.matchMedia('(prefers-color-scheme: dark)').matches
- ? 'dark' : 'light';
- };
-
- const setTheme = theme => {
- document.documentElement.setAttribute('data-bs-theme', theme);
- const icon = document.getElementById('theme-icon');
- if (icon) {
- icon.className = theme === 'dark'
- ? 'bi bi-sun-fill'
- : 'bi bi-moon-fill';
- }
- };
-
- // Set theme on page load
- setTheme(getPreferredTheme());
-
- // Theme toggle button handler
- window.toggleTheme = () => {
- const currentTheme = document.documentElement
- .getAttribute('data-bs-theme');
- const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
- setTheme(newTheme);
- setStoredTheme(newTheme);
- };
-
- // Listen for system theme changes
- window.matchMedia('(prefers-color-scheme: dark)')
- .addEventListener('change', e => {
- if (!getStoredTheme()) {
- setTheme(e.matches ? 'dark' : 'light');
- }
- });
- })();
+ /* Auto dark mode - sets Bootstrap theme based on system preference */
+ @media (prefers-color-scheme: dark) {
+ :root {
+ color-scheme: dark;
+ }
+ html {
+ --bs-body-color: #dee2e6;
+ --bs-body-bg: #212529;
+ --bs-emphasis-color: #fff;
+ --bs-border-color: #495057;
+ --bs-link-color: #6ea8fe;
+ --bs-link-hover-color: #8bb9fe;
+ --bs-code-color: #e685b5;
+ }
+ body {
+ color: var(--bs-body-color);
+ background-color: var(--bs-body-bg);
+ }
+ }
+ @media (prefers-color-scheme: light) {
+ :root {
+ color-scheme: light;
+ }
+ }
""",
)
@@ -687,6 +666,10 @@ class BillingPage(Component[AnyChildren, BillingPageAttrs]):
name="viewport",
content="width=device-width, initial-scale=1",
),
+ html.meta(
+ name="color-scheme",
+ content="light dark",
+ ),
html.title("Billing - PodcastItLater"),
html.script(
src="https://unpkg.com/htmx.org@1.9.10",
@@ -701,51 +684,32 @@ class BillingPage(Component[AnyChildren, BillingPageAttrs]):
"@import url('https://cdn.jsdelivr.net/npm/bootstrap-icons"
"@1.11.3/font/bootstrap-icons.min.css');",
),
+ # Auto dark mode CSS (must come after Bootstrap)
+ create_auto_dark_mode_style(),
html.div(
html.div(
+ html.h1(
+ html.i(
+ classes=["bi", "bi-credit-card", "me-2"],
+ ),
+ "Billing & Usage",
+ classes=["mb-4"],
+ ),
html.div(
- html.h1(
+ html.a(
html.i(
- classes=["bi", "bi-credit-card", "me-2"],
- ),
- "Billing & Usage",
- classes=["mb-4"],
- ),
- html.div(
- html.a(
- html.i(
- classes=["bi", "bi-arrow-left", "me-1"],
- ),
- "Back to Dashboard",
- href="/",
- classes=[
- "btn",
- "btn-outline-secondary",
- "mb-4",
- ],
+ classes=["bi", "bi-arrow-left", "me-1"],
),
+ "Back to Dashboard",
+ href="/",
+ classes=[
+ "btn",
+ "btn-outline-secondary",
+ "mb-4",
+ ],
),
- classes=["flex-grow-1"],
- ),
- html.button(
- html.i(
- id="theme-icon",
- classes=["bi", "bi-moon-fill"],
- ),
- on_click="toggleTheme()",
- classes=[
- "btn",
- "btn-outline-secondary",
- "position-absolute",
- "top-0",
- "end-0",
- "mt-3",
- "me-3",
- ],
- title="Toggle dark mode",
- type="button",
),
- classes=["position-relative", "mb-4"],
+ classes=["mb-4"],
),
# Success/Error alerts
html.div(
@@ -882,8 +846,6 @@ class BillingPage(Component[AnyChildren, BillingPageAttrs]):
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL",
crossorigin="anonymous",
),
- # Theme switcher script
- create_theme_switcher_script(),
),
)
@@ -999,6 +961,10 @@ class HomePage(Component[AnyChildren, HomePageAttrs]):
name="viewport",
content="width=device-width, initial-scale=1",
),
+ html.meta(
+ name="color-scheme",
+ content="light dark",
+ ),
html.title("PodcastItLater"),
html.script(
src="https://unpkg.com/htmx.org@1.9.10",
@@ -1013,40 +979,21 @@ class HomePage(Component[AnyChildren, HomePageAttrs]):
"@import url('https://cdn.jsdelivr.net/npm/bootstrap-icons"
"@1.11.3/font/bootstrap-icons.min.css');",
),
+ # Auto dark mode CSS (must come after Bootstrap)
+ create_auto_dark_mode_style(),
# Bootstrap container
html.div(
# Header
html.div(
- html.div(
- html.h1(
- "PodcastItLater",
- classes=["display-4", "mb-2"],
- ),
- html.p(
- "Convert web articles to podcast episodes",
- classes=["lead", "text-muted"],
- ),
- classes=["text-center", "flex-grow-1"],
+ html.h1(
+ "PodcastItLater",
+ classes=["display-4", "mb-2"],
),
- html.button(
- html.i(
- id="theme-icon",
- classes=["bi", "bi-moon-fill"],
- ),
- on_click="toggleTheme()",
- classes=[
- "btn",
- "btn-outline-secondary",
- "position-absolute",
- "top-0",
- "end-0",
- "mt-3",
- "me-3",
- ],
- title="Toggle dark mode",
- type="button",
+ html.p(
+ "Convert web articles to podcast episodes",
+ classes=["lead", "text-muted"],
),
- classes=["position-relative", "mb-4", "pt-4"],
+ classes=["text-center", "mb-4", "pt-4"],
),
# Error alert
html.div(
@@ -1180,8 +1127,6 @@ class HomePage(Component[AnyChildren, HomePageAttrs]):
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL",
crossorigin="anonymous",
),
- # Theme switcher script
- create_theme_switcher_script(),
),
)