fix: cover admin controls in css themes
This commit is contained in:
@@ -318,6 +318,70 @@
|
||||
box-shadow: inset 0 0 0 1px #ffffff;
|
||||
}
|
||||
|
||||
/* ---------- Admin controls: range sliders and sortable rows ---------- */
|
||||
|
||||
.theme-key-ascii .ui-range-input {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.theme-key-ascii .ui-range-input::before {
|
||||
height: 8px;
|
||||
border: 1px solid #ffffff;
|
||||
background: #000000;
|
||||
}
|
||||
|
||||
.theme-key-ascii .ui-range-input__range {
|
||||
height: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.theme-key-ascii .ui-range-input__thumb {
|
||||
width: 16px;
|
||||
height: 18px;
|
||||
border: 1px solid #ffffff;
|
||||
border-radius: 0;
|
||||
background: #000000;
|
||||
box-shadow: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.theme-key-ascii .ui-range-input__thumb:hover,
|
||||
.theme-key-ascii .ui-range-input__thumb:focus-visible {
|
||||
background: #ffffff;
|
||||
color: #000000;
|
||||
box-shadow: 0 0 0 1px #000000;
|
||||
}
|
||||
|
||||
.theme-key-ascii .ui-sortable {
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.theme-key-ascii .ui-sortable-item.is-dragging {
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.theme-key-ascii .ui-sortable-item.is-drop-target {
|
||||
outline: 1px dashed #ffffff;
|
||||
outline-offset: 2px;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.theme-key-ascii .ui-sortable-handle {
|
||||
align-self: center;
|
||||
height: 28px;
|
||||
border: 1px solid #ffffff;
|
||||
background: #000000;
|
||||
color: #ffffff;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.theme-key-ascii .ui-sortable-handle:hover,
|
||||
.theme-key-ascii .ui-sortable-handle:focus-visible,
|
||||
.theme-key-ascii .ui-sortable-handle:active {
|
||||
background: #ffffff;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
/* ---------- New webapp surfaces: support, purchase info, password login ---------- */
|
||||
|
||||
.theme-key-ascii .trial-offer-card,
|
||||
@@ -1104,6 +1168,7 @@ body:has(.theme-key-ascii) .install-platform-item[data-selected] svg {
|
||||
.admin-cn-card-skeleton--tall,
|
||||
.admin-input, .admin-textarea, .admin-btn, .admin-chip,
|
||||
.admin-tabs-trigger, .admin-tabs-list,
|
||||
.ui-range-input__thumb, .ui-sortable-item, .ui-sortable-handle,
|
||||
.admin-nav-item, .admin-revenue-period-btn, .admin-mobile-toggle,
|
||||
.admin-header, .admin-sidebar, .admin-sidebar-brand,
|
||||
.admin-dialog,
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"use_primary_accent": false,
|
||||
"use_in_admin": true,
|
||||
"css_file": "style.css",
|
||||
"assets_version": 5,
|
||||
"assets_version": 6,
|
||||
"tokens": {
|
||||
"color_scheme": "dark",
|
||||
"style_preset": "ascii"
|
||||
|
||||
@@ -205,6 +205,42 @@ body:has(.theme-key-light) .install-platform-item[data-selected] {
|
||||
color: color-mix(in srgb, var(--accent) 55%, #000000);
|
||||
}
|
||||
|
||||
/* Admin controls: range sliders and sortable rows */
|
||||
|
||||
.theme-key-light .ui-range-input::before {
|
||||
background: rgba(15, 23, 42, 0.12);
|
||||
}
|
||||
|
||||
.theme-key-light .ui-range-input__range {
|
||||
background: color-mix(in srgb, var(--accent) 70%, #0f172a);
|
||||
}
|
||||
|
||||
.theme-key-light .ui-range-input__thumb {
|
||||
border-color: color-mix(in srgb, var(--accent) 68%, #0f172a);
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 8px rgba(15, 23, 42, 0.18);
|
||||
}
|
||||
|
||||
.theme-key-light .ui-range-input__thumb:focus-visible {
|
||||
box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent);
|
||||
}
|
||||
|
||||
.theme-key-light .ui-sortable-handle {
|
||||
border-radius: 6px;
|
||||
color: color-mix(in srgb, var(--admin-muted) 82%, var(--admin-text));
|
||||
}
|
||||
|
||||
.theme-key-light .ui-sortable-handle:hover,
|
||||
.theme-key-light .ui-sortable-handle:focus-visible {
|
||||
background: rgba(15, 23, 42, 0.055);
|
||||
color: color-mix(in srgb, var(--accent) 58%, #0f172a);
|
||||
}
|
||||
|
||||
.theme-key-light .ui-sortable-item.is-drop-target {
|
||||
outline-color: color-mix(in srgb, var(--accent) 48%, #0f172a);
|
||||
background: color-mix(in srgb, var(--accent) 8%, #ffffff);
|
||||
}
|
||||
|
||||
/* Telegram notifications banner: keep the warm warning tint but swap the
|
||||
* dark-theme inset bevel for the soft drop shadow the other light cards use. */
|
||||
.theme-key-light .telegram-notifications-card {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"use_primary_accent": true,
|
||||
"use_in_admin": true,
|
||||
"css_file": "style.css",
|
||||
"assets_version": 4,
|
||||
"assets_version": 5,
|
||||
"tokens": {
|
||||
"color_scheme": "light"
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@
|
||||
.theme-key-windows95 svg.lucide-file-text,
|
||||
.theme-key-windows95 svg.lucide-gift,
|
||||
.theme-key-windows95 svg.lucide-globe-2,
|
||||
.theme-key-windows95 svg.lucide-grip-vertical,
|
||||
.theme-key-windows95 svg.lucide-home,
|
||||
.theme-key-windows95 svg.lucide-house,
|
||||
.theme-key-windows95 svg.lucide-info,
|
||||
@@ -232,6 +233,10 @@
|
||||
--win95-button-icon: var(--win95-icon-globe);
|
||||
}
|
||||
|
||||
.theme-key-windows95 svg.lucide-grip-vertical {
|
||||
--win95-button-icon: var(--win95-icon-sliders);
|
||||
}
|
||||
|
||||
.theme-key-windows95 svg.lucide-file-text {
|
||||
--win95-button-icon: var(--win95-icon-file-text);
|
||||
}
|
||||
@@ -375,6 +380,7 @@
|
||||
svg.lucide-file-text,
|
||||
svg.lucide-gift,
|
||||
svg.lucide-globe-2,
|
||||
svg.lucide-grip-vertical,
|
||||
svg.lucide-home,
|
||||
svg.lucide-house,
|
||||
svg.lucide-info,
|
||||
@@ -1171,6 +1177,86 @@ body:has(.theme-key-windows95) .install-platform-item[data-selected] {
|
||||
opacity: 0.52;
|
||||
}
|
||||
|
||||
/* Admin controls: range sliders and sortable rows */
|
||||
|
||||
.theme-key-windows95 .ui-range-input {
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.theme-key-windows95 .ui-range-input::before {
|
||||
height: 8px;
|
||||
border: 2px solid;
|
||||
border-color: #404040 #ffffff #ffffff #404040;
|
||||
border-radius: 0 !important;
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
inset 1px 1px 0 #808080,
|
||||
inset -1px -1px 0 #dfdfdf;
|
||||
}
|
||||
|
||||
.theme-key-windows95 .ui-range-input__range {
|
||||
height: 8px;
|
||||
border-radius: 0 !important;
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.theme-key-windows95 .ui-range-input__thumb {
|
||||
width: 14px;
|
||||
height: 20px;
|
||||
border: 2px solid;
|
||||
border-color: #ffffff #404040 #404040 #ffffff;
|
||||
border-radius: 0 !important;
|
||||
background: #c0c0c0;
|
||||
box-shadow:
|
||||
inset 1px 1px 0 #dfdfdf,
|
||||
inset -1px -1px 0 #808080;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.theme-key-windows95 .ui-range-input__thumb:hover,
|
||||
.theme-key-windows95 .ui-range-input__thumb:focus-visible {
|
||||
background: #dfdfdf;
|
||||
}
|
||||
|
||||
.theme-key-windows95 .ui-range-input__thumb[data-active] {
|
||||
border-color: #404040 #ffffff #ffffff #404040;
|
||||
box-shadow:
|
||||
inset 1px 1px 0 #808080,
|
||||
inset -1px -1px 0 #dfdfdf;
|
||||
}
|
||||
|
||||
.theme-key-windows95 .ui-sortable-item.is-drop-target {
|
||||
outline: 1px dotted #000000;
|
||||
outline-offset: 3px;
|
||||
background: color-mix(in srgb, var(--accent) 12%, var(--admin-surface));
|
||||
}
|
||||
|
||||
.theme-key-windows95 .ui-sortable-handle {
|
||||
align-self: center;
|
||||
width: 24px;
|
||||
height: 28px;
|
||||
border: 2px solid;
|
||||
border-color: #ffffff #404040 #404040 #ffffff;
|
||||
background: #c0c0c0;
|
||||
color: #000000;
|
||||
box-shadow:
|
||||
inset 1px 1px 0 #dfdfdf,
|
||||
inset -1px -1px 0 #808080;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.theme-key-windows95 .ui-sortable-handle:hover,
|
||||
.theme-key-windows95 .ui-sortable-handle:focus-visible {
|
||||
background: #dfdfdf;
|
||||
}
|
||||
|
||||
.theme-key-windows95 .ui-sortable-handle:active {
|
||||
border-color: #404040 #ffffff #ffffff #404040;
|
||||
box-shadow:
|
||||
inset 1px 1px 0 #808080,
|
||||
inset -1px -1px 0 #dfdfdf;
|
||||
}
|
||||
|
||||
.theme-key-windows95 input::placeholder,
|
||||
.theme-key-windows95 textarea::placeholder,
|
||||
.theme-key-windows95 .input::placeholder,
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"use_primary_accent": false,
|
||||
"use_in_admin": true,
|
||||
"css_file": "style.css",
|
||||
"assets_version": 12,
|
||||
"assets_version": 13,
|
||||
"tokens": {
|
||||
"color_scheme": "light",
|
||||
"style_preset": "win95"
|
||||
|
||||
@@ -371,6 +371,7 @@ def _builtin_theme_assets_need_refresh(key: str, target_dir: Path) -> bool:
|
||||
"--success-text" not in style
|
||||
or ".theme-key-light.app-shell" not in style
|
||||
or "Install guide theme surfaces" not in style
|
||||
or "Admin controls: range sliders and sortable rows" not in style
|
||||
)
|
||||
if key == "ascii":
|
||||
return (
|
||||
@@ -381,6 +382,7 @@ def _builtin_theme_assets_need_refresh(key: str, target_dir: Path) -> bool:
|
||||
or "Console-style tables" not in style
|
||||
or "New webapp surfaces: support, purchase info, password login" not in style
|
||||
or "Install guide theme surfaces" not in style
|
||||
or "Admin controls: range sliders and sortable rows" not in style
|
||||
)
|
||||
if key != "windows95":
|
||||
return False
|
||||
@@ -404,6 +406,7 @@ def _builtin_theme_assets_need_refresh(key: str, target_dir: Path) -> bool:
|
||||
or "lucide-qr-code" not in style
|
||||
or "New webapp surfaces: support, purchase info, password login" not in style
|
||||
or "Install guide theme surfaces" not in style
|
||||
or "Admin controls: range sliders and sortable rows" not in style
|
||||
or any(not (target_dir / "icons" / icon).exists() for icon in required_icons)
|
||||
)
|
||||
|
||||
|
||||
@@ -568,6 +568,24 @@ class WebAppAssetTests(unittest.IsolatedAsyncioTestCase):
|
||||
self.assertIn("--home-logo-scale-mobile", base_css)
|
||||
self.assertIn("--home-logo-scale-desktop", base_css)
|
||||
|
||||
def test_builtin_css_themes_cover_admin_range_and_sortable_controls(self):
|
||||
theme_root = Path("backend/bot/app/web/themes")
|
||||
required_selectors = (
|
||||
"ui-range-input",
|
||||
"ui-range-input__thumb",
|
||||
"ui-sortable-item",
|
||||
"ui-sortable-handle",
|
||||
"is-drop-target",
|
||||
)
|
||||
|
||||
for key in ("light", "ascii", "windows95"):
|
||||
css = (theme_root / key / "style.css").read_text(encoding="utf-8")
|
||||
for selector in required_selectors:
|
||||
self.assertIn(selector, css, f"{key} theme must style {selector}")
|
||||
|
||||
windows95_css = (theme_root / "windows95" / "style.css").read_text(encoding="utf-8")
|
||||
self.assertIn("lucide-grip-vertical", windows95_css)
|
||||
|
||||
def test_prune_unused_appearance_assets_keeps_only_referenced_logo_and_favicons(self):
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
root = Path(tmpdir)
|
||||
|
||||
@@ -33,14 +33,14 @@ class WebappThemesConfigTests(unittest.TestCase):
|
||||
self.assertEqual(win95.tokens.style_preset, "win95")
|
||||
self.assertFalse(win95.use_primary_accent)
|
||||
self.assertTrue(win95.use_in_admin)
|
||||
self.assertEqual(win95.assets_version, 12)
|
||||
self.assertEqual(cfg.theme_by_key("light").assets_version, 4)
|
||||
self.assertEqual(win95.assets_version, 13)
|
||||
self.assertEqual(cfg.theme_by_key("light").assets_version, 5)
|
||||
ascii_theme = cfg.theme_by_key("ascii")
|
||||
self.assertIsNotNone(ascii_theme)
|
||||
self.assertEqual(ascii_theme.css_file, "style.css")
|
||||
self.assertFalse(ascii_theme.use_primary_accent)
|
||||
self.assertTrue(ascii_theme.use_in_admin)
|
||||
self.assertEqual(ascii_theme.assets_version, 5)
|
||||
self.assertEqual(ascii_theme.assets_version, 6)
|
||||
|
||||
def test_env_override_default_theme(self):
|
||||
cfg = builtin_webapp_themes_config("#00fe7a")
|
||||
@@ -391,7 +391,7 @@ class WebappThemesConfigTests(unittest.TestCase):
|
||||
descriptor["assets_version"],
|
||||
cfg.theme_by_key("windows95").assets_version,
|
||||
)
|
||||
self.assertEqual(descriptor["assets_version"], 12)
|
||||
self.assertEqual(descriptor["assets_version"], 13)
|
||||
self.assertIn("lucide-house", css)
|
||||
self.assertIn("lucide-earth", css)
|
||||
self.assertIn("lucide-circle-check", css)
|
||||
@@ -404,6 +404,7 @@ class WebappThemesConfigTests(unittest.TestCase):
|
||||
self.assertIn("lucide-qr-code", css)
|
||||
self.assertIn("New webapp surfaces: support, purchase info, password login", css)
|
||||
self.assertIn("Install guide theme surfaces", css)
|
||||
self.assertIn("Admin controls: range sliders and sortable rows", css)
|
||||
self.assertIn(
|
||||
(
|
||||
".theme-key-windows95 .support-list-card {\n"
|
||||
@@ -445,6 +446,7 @@ class WebappThemesConfigTests(unittest.TestCase):
|
||||
css = (stale_theme_dir / "style.css").read_text(encoding="utf-8")
|
||||
self.assertIn(".theme-key-light.app-shell", css)
|
||||
self.assertIn("Install guide theme surfaces", css)
|
||||
self.assertIn("Admin controls: range sliders and sortable rows", css)
|
||||
|
||||
def test_resolved_refreshes_stale_builtin_ascii_assets(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
@@ -477,6 +479,7 @@ class WebappThemesConfigTests(unittest.TestCase):
|
||||
descriptor = json.loads((stale_theme_dir / "theme.json").read_text(encoding="utf-8"))
|
||||
css = (stale_theme_dir / "style.css").read_text(encoding="utf-8")
|
||||
self.assertEqual(descriptor["assets_version"], cfg.theme_by_key("ascii").assets_version)
|
||||
self.assertEqual(descriptor["assets_version"], 5)
|
||||
self.assertEqual(descriptor["assets_version"], 6)
|
||||
self.assertIn("Console-style tables", css)
|
||||
self.assertIn("Install guide theme surfaces", css)
|
||||
self.assertIn("Admin controls: range sliders and sortable rows", css)
|
||||
|
||||
Reference in New Issue
Block a user