feat: custom themes logo size tuning

This commit is contained in:
3252a8
2026-05-15 13:54:47 +03:00
parent af7cee5014
commit a1725a6872
10 changed files with 175 additions and 20 deletions
@@ -134,6 +134,12 @@
return `#${hex}`;
}
function homeLogoScale(theme) {
const scale = Number(theme.tokens?.home_logo_scale || 100);
if (!Number.isFinite(scale)) return 100;
return Math.min(300, Math.max(50, Math.round(scale)));
}
function openThemeAccentPicker(theme) {
themesStore.setThemeAccent(theme.key, pickerHex(theme.tokens?.accent || "#00fe7a"));
}
@@ -216,6 +222,10 @@
themesStore.setThemeAccent(theme.key, value);
}
function setThemeHomeLogoScale(theme, value) {
themesStore.setThemeHomeLogoScale(theme.key, value);
}
function selectTheme(theme, event = null) {
if (event?.target?.closest?.("button,input,label")) return;
if (!themesSaving) themesStore.setCurrentTheme(theme.key);
@@ -472,6 +482,37 @@
/>
<span>{at("themes_use_in_admin", {}, "Использовать в админке")}</span>
</label>
<label class="admin-theme-card-option appearance-logo-scale-row">
<span
>{at(
"appearance_theme_home_logo_scale",
{},
"Логотип на главной и входе"
)}</span
>
<input
class="appearance-logo-scale-range"
type="range"
min="50"
max="300"
step="5"
value={homeLogoScale(theme)}
oninput={(event) => setThemeHomeLogoScale(theme, event.currentTarget.value)}
/>
<span class="appearance-logo-scale-value">
<input
class="input"
type="number"
min="50"
max="300"
step="5"
value={homeLogoScale(theme)}
oninput={(event) =>
setThemeHomeLogoScale(theme, event.currentTarget.value)}
/>
%
</span>
</label>
<div class="appearance-theme-actions">
<AdminButton
size="sm"
@@ -703,6 +744,31 @@
min-width: 0;
}
.appearance-logo-scale-row {
display: grid;
grid-template-columns: auto minmax(96px, 1fr) auto;
width: 100%;
}
.appearance-logo-scale-range {
width: 100%;
accent-color: var(--accent);
}
.appearance-logo-scale-value {
display: inline-flex;
align-items: center;
gap: 4px;
color: var(--admin-text);
}
.appearance-logo-scale-value .input {
width: 70px;
min-height: 32px;
padding: 4px 8px;
font-size: 12px;
}
.admin-color.is-empty {
opacity: 0.42;
filter: grayscale(1);
@@ -183,12 +183,38 @@ export function createThemesStore({ api, onThemesSaved, flash, at }) {
}));
}
function setThemeHomeLogoScale(key, scale) {
if (String(scale ?? "").trim() === "") scale = 100;
const numeric = Number(scale);
const nextScale = Number.isFinite(numeric)
? Math.min(300, Math.max(50, Math.round(numeric)))
: 100;
state.update((s) => ({
...s,
themesCatalog: {
...s.themesCatalog,
themes: (s.themesCatalog.themes || []).map((theme) =>
theme.key === key
? {
...theme,
tokens: {
...(theme.tokens || {}),
home_logo_scale: nextScale === 100 ? null : nextScale,
},
}
: theme
),
},
}));
}
return {
subscribe: state.subscribe,
loadThemes,
saveThemes,
setCurrentTheme,
setThemeAccent,
setThemeHomeLogoScale,
togglePrimaryAccent,
toggleAdminUse,
uploadLogoFile,
@@ -17,6 +17,7 @@ const TOKEN_TO_CSS_VAR = {
font_sans: "--font-sans",
font_logo: "--font-logo",
font_mono: "--font-mono",
home_logo_scale: "--home-logo-scale",
admin_bg: "--admin-bg",
admin_surface: "--admin-surface",
admin_surface_2: "--admin-surface-2",
@@ -38,6 +39,12 @@ export function themeTokensToInlineStyle(tokens, primaryFallback = "#00fe7a", op
if (key === "accent") continue;
const value = t[key];
if (value === undefined || value === null || value === "") continue;
if (key === "home_logo_scale") {
const scale = Number(value);
if (!Number.isFinite(scale) || scale <= 0) continue;
parts.push(`${cssVar}:${scale / 100}`);
continue;
}
parts.push(`${cssVar}:${String(value)}`);
}
return parts.join(";");
+25 -13
View File
@@ -30,12 +30,18 @@ a {
display: grid;
min-height: 100dvh;
place-items: center;
align-content: center;
align-content: safe center;
gap: 14px;
color: var(--muted);
font-weight: 800;
}
.loader .brand-mark.brand-mark-lg {
width: calc(4.125rem * var(--home-logo-scale, 1));
height: calc(4.125rem * var(--home-logo-scale, 1));
font-size: calc(2.875rem * var(--home-logo-scale, 1));
}
.app-header,
.preview-header,
.screen-head {
@@ -1530,17 +1536,29 @@ a {
.home-layout {
display: grid;
min-height: calc(100dvh - 34px);
grid-template-rows: minmax(0, 1fr) auto;
grid-template-rows: minmax(min-content, 1fr) auto;
gap: 18px;
padding-bottom: 86px;
animation: section-enter 0.24s ease-out both;
}
.home-brand {
align-self: center;
align-self: safe center;
padding-top: 0;
}
.home-brand .brand-mark.brand-mark-xl {
width: calc(6rem * var(--home-logo-scale, 1));
height: calc(6rem * var(--home-logo-scale, 1));
font-size: calc(4.375rem * var(--home-logo-scale, 1));
}
.login-brand-auth .brand-mark.brand-mark-xl {
width: calc(116px * var(--home-logo-scale, 1));
height: calc(116px * var(--home-logo-scale, 1));
font-size: calc(84px * var(--home-logo-scale, 1));
}
.home-bottom {
display: grid;
gap: 10px;
@@ -1549,7 +1567,7 @@ a {
.auth-screen {
display: grid;
align-content: center;
align-content: safe center;
}
.auth-card-wrap {
@@ -1568,12 +1586,6 @@ a {
gap: 5px;
}
.login-brand-auth .brand-mark.brand-mark-xl {
width: 116px;
height: 116px;
font-size: 84px;
}
.login-brand h1 {
margin: 0;
overflow-wrap: anywhere;
@@ -2129,9 +2141,9 @@ a {
.home-brand .brand-mark,
.home-brand .brand-mark-lg,
.home-brand .brand-mark-xl {
width: clamp(180px, 18vw, 260px);
height: clamp(180px, 18vw, 260px);
font-size: clamp(124px, 13vw, 184px);
width: calc(clamp(180px, 18vw, 260px) * var(--home-logo-scale, 1));
height: calc(clamp(180px, 18vw, 260px) * var(--home-logo-scale, 1));
font-size: calc(clamp(124px, 13vw, 184px) * var(--home-logo-scale, 1));
}
.home-bottom {
@@ -9,7 +9,7 @@
<link id="app-favicon" rel="icon" href="data:," sizes="any">
<title>/minishop</title>
<link rel="stylesheet" href="/subscription_webapp.css">
<link rel="preload" id="logo-preload" href="" as="image" fetchpriority="high" crossorigin="anonymous">
<link rel="preload" id="logo-preload" href="" as="image" fetchpriority="high">
</head>
<body>
+10 -1
View File
@@ -1,3 +1,5 @@
@import url("https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap&subset=cyrillic");
.theme-key-windows95 {
color-scheme: light;
image-rendering: pixelated;
@@ -15,7 +17,7 @@
--blue: #000080;
--radius: 0px;
--font-sans: "MS Sans Serif", Tahoma, "Segoe UI", sans-serif;
--font-logo: "MS Sans Serif", Tahoma, "Segoe UI", sans-serif;
--font-logo: "Press Start 2P", "Pixel Cyr", "MS Sans Serif", Tahoma, "Segoe UI", sans-serif;
--font-mono: Consolas, "Courier New", monospace;
--accent-contrast: #ffffff;
--surface-sheen: transparent;
@@ -89,6 +91,8 @@
.theme-key-windows95 svg.lucide-bitcoin,
.theme-key-windows95 svg.lucide-check,
.theme-key-windows95 svg.lucide-check-circle-2,
.theme-key-windows95 svg.lucide-circle-check,
.theme-key-windows95 svg.lucide-circle-check-big,
.theme-key-windows95 svg.lucide-chevrons-up-down,
.theme-key-windows95 svg.lucide-circle-x,
.theme-key-windows95 svg.lucide-coins,
@@ -142,6 +146,7 @@
background-repeat: no-repeat;
background-size: contain;
image-rendering: pixelated;
filter: none !important;
}
.theme-key-windows95 svg.lucide-arrow-left {
@@ -547,6 +552,10 @@
color: var(--accent);
}
.theme-key-windows95 .traffic-top strong {
color: var(--muted);
}
.theme-key-windows95 .btn-primary,
.theme-key-windows95 .bottom-nav button.active {
color: #ffffff;
+3 -3
View File
@@ -857,12 +857,12 @@ async def index_route(request: web.Request) -> web.Response:
brand_asset_url = _webapp_animated_emoji_asset_path(settings.WEBAPP_LOGO_EMOJI)
if brand_asset_url:
html = html.replace(
'<link rel="preload" id="logo-preload" href="" as="image" fetchpriority="high" crossorigin="anonymous">', # noqa: E501
f'<link rel="preload" href="{brand_asset_url}" as="image" fetchpriority="high" crossorigin="anonymous">', # noqa: E501
'<link rel="preload" id="logo-preload" href="" as="image" fetchpriority="high">',
f'<link rel="preload" href="{brand_asset_url}" as="image" fetchpriority="high">',
)
else:
html = html.replace(
'<link rel="preload" id="logo-preload" href="" as="image" fetchpriority="high" crossorigin="anonymous">', # noqa: E501
'<link rel="preload" id="logo-preload" href="" as="image" fetchpriority="high">',
"",
)
return web.Response(text=html, content_type="text/html", charset="utf-8")