Добавлены настройки темы по умолчанию
This commit is contained in:
+4
-1
@@ -7,4 +7,7 @@ VITE_BANNER_SLOGAN=— qr-код без излишеств
|
||||
VITE_BANNER_URL=https://github.com/IliaMiheev/iQR
|
||||
|
||||
# Акцентный цвет (hex, rgb или css-имя)
|
||||
VITE_ACCENT_COLOR=#ff4500
|
||||
VITE_ACCENT_COLOR="#ff4500"
|
||||
|
||||
# Тема по умолчанию: dark или light (если пользователь ещё не переключал)
|
||||
VITE_DEFAULT_THEME=light
|
||||
|
||||
@@ -26,6 +26,7 @@ npm run dev
|
||||
| `VITE_BANNER_SLOGAN` | Слоган в плашке | `— qr-код без излишеств` |
|
||||
| `VITE_BANNER_URL` | Ссылка плашки | репозиторий iQR |
|
||||
| `VITE_ACCENT_COLOR` | Акцентный цвет | `#ff4500` |
|
||||
| `VITE_DEFAULT_THEME` | Тема по умолчанию (`dark` / `light`) | `dark` |
|
||||
|
||||
После изменения `.env` перезапустите `npm run dev`.
|
||||
|
||||
@@ -46,6 +47,7 @@ environment:
|
||||
BANNER_SLOGAN: "— быстрые qr-коды"
|
||||
BANNER_URL: "https://example.com"
|
||||
ACCENT_COLOR: "#7c3aed"
|
||||
DEFAULT_THEME: "light"
|
||||
```
|
||||
|
||||
При старте контейнера генерируется `config.json`, поэтому пересборка образа для смены текстов не нужна.
|
||||
|
||||
@@ -9,4 +9,5 @@ services:
|
||||
BANNER_SLOGAN: "— qr-код без излишеств"
|
||||
BANNER_URL: "https://github.com/IliaMiheev/iQR"
|
||||
ACCENT_COLOR: "#ff4500"
|
||||
DEFAULT_THEME: "dark"
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -6,6 +6,7 @@ BANNER_BRAND="${BANNER_BRAND:-iQR}"
|
||||
BANNER_SLOGAN="${BANNER_SLOGAN:-— qr-код без излишеств}"
|
||||
BANNER_URL="${BANNER_URL:-https://github.com/IliaMiheev/iQR}"
|
||||
ACCENT_COLOR="${ACCENT_COLOR:-#ff4500}"
|
||||
DEFAULT_THEME="${DEFAULT_THEME:-dark}"
|
||||
|
||||
cat > /usr/share/nginx/html/config.json <<EOF
|
||||
{
|
||||
@@ -13,7 +14,8 @@ cat > /usr/share/nginx/html/config.json <<EOF
|
||||
"bannerBrand": "$(printf '%s' "$BANNER_BRAND" | sed 's/"/\\"/g')",
|
||||
"bannerSlogan": "$(printf '%s' "$BANNER_SLOGAN" | sed 's/"/\\"/g')",
|
||||
"bannerUrl": "$(printf '%s' "$BANNER_URL" | sed 's/"/\\"/g')",
|
||||
"accentColor": "$(printf '%s' "$ACCENT_COLOR" | sed 's/"/\\"/g')"
|
||||
"accentColor": "$(printf '%s' "$ACCENT_COLOR" | sed 's/"/\\"/g')",
|
||||
"defaultTheme": "$(printf '%s' "$DEFAULT_THEME" | sed 's/"/\\"/g')"
|
||||
}
|
||||
EOF
|
||||
|
||||
|
||||
+2
-2
@@ -134,7 +134,7 @@ onUnmounted(() => {
|
||||
<div class="qr-modal__backdrop" @click="closeQrModal" />
|
||||
|
||||
<aside class="qr-modal__toolbar" aria-label="Инструменты" @click.stop>
|
||||
<button type="button" title="Увеличить" @click="zoomIn">+</button>
|
||||
<button type="button" title="Уменьшить" @click="zoomOut">−</button>
|
||||
<button
|
||||
type="button"
|
||||
class="qr-modal__tool-btn"
|
||||
@@ -153,7 +153,7 @@ onUnmounted(() => {
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button type="button" title="Уменьшить" @click="zoomOut">−</button>
|
||||
<button type="button" title="Увеличить" @click="zoomIn">+</button>
|
||||
</aside>
|
||||
|
||||
<div class="qr-modal__dialog" @click.stop>
|
||||
|
||||
+13
-11
@@ -474,8 +474,9 @@ html.light .qr-modal__backdrop {
|
||||
border: 1px solid var(--surface-border);
|
||||
border-radius: 50%;
|
||||
background: var(--surface-solid);
|
||||
color: var(--text);
|
||||
color: var(--accent);
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -486,7 +487,8 @@ html.light .qr-modal__backdrop {
|
||||
}
|
||||
|
||||
.qr-modal__close:hover {
|
||||
border-color: var(--accent);
|
||||
background: var(--surface-hover);
|
||||
border-color: var(--surface-border);
|
||||
color: var(--accent);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
@@ -511,7 +513,7 @@ html.light .qr-modal__backdrop {
|
||||
padding: 6px;
|
||||
border-radius: 12px;
|
||||
background: var(--surface-solid);
|
||||
border: 1px solid var(--surface-border);
|
||||
border: none;
|
||||
box-shadow: var(--shadow-sm);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
@@ -531,11 +533,18 @@ html.light .qr-modal__backdrop {
|
||||
border: 1px solid transparent;
|
||||
border-radius: 8px;
|
||||
box-shadow: none;
|
||||
transition:
|
||||
color 0.2s ease,
|
||||
border-color 0.2s ease,
|
||||
background-color 0.2s ease,
|
||||
box-shadow 0.2s ease,
|
||||
transform 0.15s ease;
|
||||
}
|
||||
|
||||
.qr-modal__toolbar button:hover {
|
||||
background: var(--surface-hover);
|
||||
border-color: var(--surface-border);
|
||||
color: var(--accent);
|
||||
border-color: var(--accent);
|
||||
transform: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
@@ -551,11 +560,6 @@ html.light .qr-modal__backdrop {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.qr-modal__tool-btn:hover {
|
||||
color: var(--accent);
|
||||
border-color: var(--accent) !important;
|
||||
}
|
||||
|
||||
.qr-modal__status-slot {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -617,7 +621,6 @@ html.light .qr-modal__backdrop {
|
||||
|
||||
#qr-code {
|
||||
display: inline-flex;
|
||||
padding: 16px;
|
||||
border-radius: 16px;
|
||||
background: var(--surface-solid);
|
||||
border: 1px solid var(--surface-border);
|
||||
@@ -643,7 +646,6 @@ canvas {
|
||||
display: block;
|
||||
border-radius: 8px;
|
||||
background: var(--canvas-bg);
|
||||
border: 1px solid var(--canvas-border);
|
||||
image-rendering: pixelated;
|
||||
transition: border-color 0.35s ease;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { inject, ref, computed } from 'vue'
|
||||
import { resolveTheme } from '../config/applyTheme'
|
||||
|
||||
export function useTheme() {
|
||||
const theme = ref('dark')
|
||||
const config = inject('appConfig')
|
||||
const theme = ref(resolveTheme(config))
|
||||
|
||||
const isLightTheme = computed(() => theme.value === 'light')
|
||||
|
||||
@@ -15,16 +17,5 @@ export function useTheme() {
|
||||
applyTheme(theme.value === 'dark' ? 'light' : 'dark')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const saved = localStorage.getItem('theme')
|
||||
if (saved === 'dark' || saved === 'light') {
|
||||
applyTheme(saved)
|
||||
return
|
||||
}
|
||||
|
||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
applyTheme(prefersDark ? 'dark' : 'light')
|
||||
})
|
||||
|
||||
return { theme, isLightTheme, toggleTheme }
|
||||
}
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
import { normalizeTheme } from './defaults'
|
||||
|
||||
export function resolveTheme(config) {
|
||||
const saved = localStorage.getItem('theme')
|
||||
if (saved === 'dark' || saved === 'light') {
|
||||
return saved
|
||||
}
|
||||
|
||||
return normalizeTheme(config.defaultTheme)
|
||||
}
|
||||
|
||||
export function applyAppConfig(config) {
|
||||
const root = document.documentElement
|
||||
|
||||
root.style.setProperty('--accent', config.accentColor)
|
||||
root.className = resolveTheme(config)
|
||||
|
||||
const themeMeta = document.querySelector('meta[name="theme-color"]')
|
||||
if (themeMeta) {
|
||||
|
||||
@@ -4,4 +4,10 @@ export const defaultConfig = {
|
||||
bannerSlogan: '— qr-код без излишеств',
|
||||
bannerUrl: 'https://github.com/IliaMiheev/iQR',
|
||||
accentColor: '#ff4500',
|
||||
defaultTheme: 'dark',
|
||||
}
|
||||
|
||||
export function normalizeTheme(value) {
|
||||
const normalized = String(value ?? '').trim().toLowerCase()
|
||||
return normalized === 'light' ? 'light' : 'dark'
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defaultConfig } from './defaults'
|
||||
import { defaultConfig, normalizeTheme } from './defaults'
|
||||
|
||||
function fromBuildEnv() {
|
||||
const env = import.meta.env
|
||||
@@ -9,6 +9,7 @@ function fromBuildEnv() {
|
||||
bannerSlogan: env.VITE_BANNER_SLOGAN,
|
||||
bannerUrl: env.VITE_BANNER_URL,
|
||||
accentColor: env.VITE_ACCENT_COLOR,
|
||||
defaultTheme: env.VITE_DEFAULT_THEME,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -44,5 +45,7 @@ export async function loadConfig() {
|
||||
}
|
||||
}
|
||||
|
||||
config.defaultTheme = normalizeTheme(config.defaultTheme)
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user