mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-07 00:36:41 +08:00
feat(theme): 添加阴影级别支持并优化主题定制器的阴影设置
This commit is contained in:
+139
-149
@@ -1,6 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
themeCustomizerPrimaryColors,
|
themeCustomizerPrimaryColors,
|
||||||
|
themeCustomizerShadowLevels,
|
||||||
useThemeCustomizer,
|
useThemeCustomizer,
|
||||||
type ThemeCustomizerLayout,
|
type ThemeCustomizerLayout,
|
||||||
type ThemeCustomizerRadius,
|
type ThemeCustomizerRadius,
|
||||||
@@ -86,62 +87,35 @@ const skinOptions = computed<Array<{ title: string; value: ThemeCustomizerSkin }
|
|||||||
{ title: t('theme.customizer.skinBordered'), value: 'bordered' },
|
{ title: t('theme.customizer.skinBordered'), value: 'bordered' },
|
||||||
])
|
])
|
||||||
|
|
||||||
const shadowOptions = computed<
|
// 当前阴影滑杆数值,界面使用 number,主题设置继续存储 Vuetify elevation 字符串档位。
|
||||||
Array<{
|
const shadowSliderValue = computed(() => Number(settings.value.shadow))
|
||||||
title: string
|
|
||||||
value: ThemeCustomizerShadow
|
|
||||||
}>
|
|
||||||
>(() => [
|
|
||||||
{
|
|
||||||
title: t('theme.customizer.shadowNone'),
|
|
||||||
value: 'none',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('theme.customizer.shadowLow'),
|
|
||||||
value: 'low',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('theme.customizer.shadowMedium'),
|
|
||||||
value: 'medium',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('theme.customizer.shadowHigh'),
|
|
||||||
value: 'high',
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
const radiusOptions = computed<
|
const radiusOptions = computed<
|
||||||
Array<{
|
Array<{
|
||||||
previewRadius: string
|
|
||||||
title: string
|
title: string
|
||||||
value: ThemeCustomizerRadius
|
value: ThemeCustomizerRadius
|
||||||
}>
|
}>
|
||||||
>(() => [
|
>(() => [
|
||||||
{
|
{
|
||||||
previewRadius: '4px',
|
title: t('theme.customizer.radiusNone'),
|
||||||
|
value: 'none',
|
||||||
|
},
|
||||||
|
{
|
||||||
title: t('theme.customizer.radiusSmall'),
|
title: t('theme.customizer.radiusSmall'),
|
||||||
value: 'small',
|
value: 'small',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
previewRadius: '8px',
|
|
||||||
title: t('theme.customizer.radiusDefault'),
|
title: t('theme.customizer.radiusDefault'),
|
||||||
value: 'default',
|
value: 'default',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
previewRadius: '12px',
|
|
||||||
title: t('theme.customizer.radiusLarge'),
|
title: t('theme.customizer.radiusLarge'),
|
||||||
value: 'large',
|
value: 'large',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
previewRadius: '16px',
|
|
||||||
title: t('theme.customizer.radiusExtra'),
|
title: t('theme.customizer.radiusExtra'),
|
||||||
value: 'extra',
|
value: 'extra',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
previewRadius: '24px',
|
|
||||||
title: t('theme.customizer.radiusHuge'),
|
|
||||||
value: 'huge',
|
|
||||||
},
|
|
||||||
])
|
])
|
||||||
|
|
||||||
const layoutOptions = computed<Array<{ icon: string; title: string; value: ThemeCustomizerLayout }>>(() => [
|
const layoutOptions = computed<Array<{ icon: string; title: string; value: ThemeCustomizerLayout }>>(() => [
|
||||||
@@ -156,7 +130,7 @@ const hasAppModeCustomization = computed(() => {
|
|||||||
return (
|
return (
|
||||||
settings.value.primaryColor !== defaultPrimaryColor ||
|
settings.value.primaryColor !== defaultPrimaryColor ||
|
||||||
settings.value.radius !== 'default' ||
|
settings.value.radius !== 'default' ||
|
||||||
settings.value.shadow !== 'none' ||
|
settings.value.shadow !== '0' ||
|
||||||
settings.value.skin !== 'default' ||
|
settings.value.skin !== 'default' ||
|
||||||
settings.value.theme !== 'auto'
|
settings.value.theme !== 'auto'
|
||||||
)
|
)
|
||||||
@@ -189,6 +163,19 @@ function handleLayoutChange(layout: ThemeCustomizerLayout) {
|
|||||||
setLayout(layout)
|
setLayout(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将 Vuetify 滑杆的数字步进写回字符串型 elevation 档位。
|
||||||
|
function handleShadowSliderChange(value: unknown) {
|
||||||
|
const rawValue = Array.isArray(value) ? value[0] : value
|
||||||
|
const numericValue = Number(rawValue)
|
||||||
|
|
||||||
|
if (!Number.isFinite(numericValue)) return
|
||||||
|
|
||||||
|
const clampedValue = Math.min(24, Math.max(0, Math.round(numericValue)))
|
||||||
|
const shadow = String(clampedValue) as ThemeCustomizerShadow
|
||||||
|
|
||||||
|
if (themeCustomizerShadowLevels.includes(shadow)) setShadow(shadow)
|
||||||
|
}
|
||||||
|
|
||||||
async function handleResetSettings() {
|
async function handleResetSettings() {
|
||||||
if (!appMode.value) {
|
if (!appMode.value) {
|
||||||
await resetSettings()
|
await resetSettings()
|
||||||
@@ -199,7 +186,7 @@ async function handleResetSettings() {
|
|||||||
// App 模式共享定制器,但保留桌面导航相关偏好,只重置 App 侧可调整的外观设置。
|
// App 模式共享定制器,但保留桌面导航相关偏好,只重置 App 侧可调整的外观设置。
|
||||||
await setPrimaryColor(defaultPrimaryColor)
|
await setPrimaryColor(defaultPrimaryColor)
|
||||||
await setRadius('default')
|
await setRadius('default')
|
||||||
await setShadow('none')
|
await setShadow('0')
|
||||||
await setSkin('default')
|
await setSkin('default')
|
||||||
await setTheme('auto')
|
await setTheme('auto')
|
||||||
}
|
}
|
||||||
@@ -320,7 +307,7 @@ async function handleResetSettings() {
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="theme-customizer-radius-scene"
|
class="theme-customizer-radius-scene"
|
||||||
:style="{ '--theme-customizer-radius-preview': radius.previewRadius }"
|
:class="`theme-customizer-radius-scene--${radius.value}`"
|
||||||
>
|
>
|
||||||
<span class="theme-customizer-radius-scene__card">
|
<span class="theme-customizer-radius-scene__card">
|
||||||
<span class="theme-customizer-radius-scene__badge" />
|
<span class="theme-customizer-radius-scene__badge" />
|
||||||
@@ -335,29 +322,41 @@ async function handleResetSettings() {
|
|||||||
<VDivider class="mt-7" />
|
<VDivider class="mt-7" />
|
||||||
|
|
||||||
<h3 class="theme-customizer-section-title">{{ t('theme.customizer.shadow') }}</h3>
|
<h3 class="theme-customizer-section-title">{{ t('theme.customizer.shadow') }}</h3>
|
||||||
<div class="theme-customizer-preview-grid theme-customizer-preview-grid--shadow">
|
<div class="theme-customizer-shadow-slider">
|
||||||
<div
|
<div class="theme-customizer-shadow-slider__header">
|
||||||
v-for="shadow in shadowOptions"
|
<span>{{ t('theme.customizer.shadowLevel', { level: settings.shadow }) }}</span>
|
||||||
:key="shadow.value"
|
<span>0 - 24</span>
|
||||||
class="theme-customizer-preview-option"
|
</div>
|
||||||
:class="{ 'is-active': settings.shadow === shadow.value }"
|
<div class="theme-customizer-shadow-slider__control">
|
||||||
@click="setShadow(shadow.value)"
|
<span
|
||||||
>
|
class="theme-customizer-shadow-slider__sample"
|
||||||
<span class="theme-customizer-shadow-scene" :class="`theme-customizer-shadow-scene--${shadow.value}`">
|
:style="{ boxShadow: `var(--app-elevation-${settings.shadow})` }"
|
||||||
<span class="theme-customizer-shadow-scene__panel">
|
>
|
||||||
<span class="theme-customizer-shadow-scene__panel-line" />
|
<span class="theme-customizer-shadow-slider__sample-accent" />
|
||||||
<span
|
<span class="theme-customizer-shadow-slider__sample-line" />
|
||||||
class="theme-customizer-shadow-scene__panel-line theme-customizer-shadow-scene__panel-line--short"
|
<span class="theme-customizer-shadow-slider__sample-line theme-customizer-shadow-slider__sample-line--short" />
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="theme-customizer-shadow-scene__card">
|
|
||||||
<span class="theme-customizer-shadow-scene__badge" />
|
|
||||||
<span class="theme-customizer-shadow-scene__line theme-customizer-shadow-scene__line--short" />
|
|
||||||
<span class="theme-customizer-shadow-scene__line" />
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
<span>{{ shadow.title }}</span>
|
<VSlider
|
||||||
|
:model-value="shadowSliderValue"
|
||||||
|
:aria-label="t('theme.customizer.shadow')"
|
||||||
|
:max="24"
|
||||||
|
:min="0"
|
||||||
|
:step="1"
|
||||||
|
color="primary"
|
||||||
|
density="comfortable"
|
||||||
|
hide-details
|
||||||
|
show-ticks="always"
|
||||||
|
thumb-label
|
||||||
|
tick-size="2"
|
||||||
|
@update:model-value="handleShadowSliderChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="theme-customizer-shadow-slider__scale"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<span>0</span>
|
||||||
|
<span>24</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -626,10 +625,6 @@ async function handleResetSettings() {
|
|||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-preview-grid--shadow {
|
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-customizer-preview-grid--radius {
|
.theme-customizer-preview-grid--radius {
|
||||||
grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
|
||||||
}
|
}
|
||||||
@@ -646,8 +641,7 @@ async function handleResetSettings() {
|
|||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
|
|
||||||
.theme-customizer-mini-layout,
|
.theme-customizer-mini-layout,
|
||||||
.theme-customizer-radius-scene,
|
.theme-customizer-radius-scene {
|
||||||
.theme-customizer-shadow-scene {
|
|
||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
border-color: rgb(var(--v-theme-primary));
|
border-color: rgb(var(--v-theme-primary));
|
||||||
background: rgba(var(--v-theme-primary), 0.04);
|
background: rgba(var(--v-theme-primary), 0.04);
|
||||||
@@ -747,6 +741,24 @@ async function handleResetSettings() {
|
|||||||
block-size: 90px;
|
block-size: 90px;
|
||||||
inline-size: 100%;
|
inline-size: 100%;
|
||||||
min-inline-size: 0;
|
min-inline-size: 0;
|
||||||
|
|
||||||
|
--theme-customizer-preview-radius: var(--app-vuetify-rounded);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-customizer-radius-scene--none {
|
||||||
|
--theme-customizer-preview-radius: var(--app-vuetify-rounded-0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-customizer-radius-scene--small {
|
||||||
|
--theme-customizer-preview-radius: var(--app-vuetify-rounded-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-customizer-radius-scene--large {
|
||||||
|
--theme-customizer-preview-radius: var(--app-vuetify-rounded-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-customizer-radius-scene--extra {
|
||||||
|
--theme-customizer-preview-radius: var(--app-vuetify-rounded-xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-radius-scene__card {
|
.theme-customizer-radius-scene__card {
|
||||||
@@ -754,7 +766,7 @@ async function handleResetSettings() {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border: 1px solid rgba(var(--v-theme-on-surface), 0.08);
|
border: 1px solid rgba(var(--v-theme-on-surface), 0.08);
|
||||||
border-radius: var(--theme-customizer-radius-preview);
|
border-radius: var(--theme-customizer-preview-radius);
|
||||||
background: rgb(var(--v-theme-surface));
|
background: rgb(var(--v-theme-surface));
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
inset: 16px;
|
inset: 16px;
|
||||||
@@ -765,17 +777,18 @@ async function handleResetSettings() {
|
|||||||
.theme-customizer-radius-scene__badge,
|
.theme-customizer-radius-scene__badge,
|
||||||
.theme-customizer-radius-scene__line {
|
.theme-customizer-radius-scene__line {
|
||||||
display: block;
|
display: block;
|
||||||
border-radius: 999px;
|
|
||||||
background: rgba(var(--v-theme-on-surface), 0.1);
|
background: rgba(var(--v-theme-on-surface), 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-radius-scene__badge {
|
.theme-customizer-radius-scene__badge {
|
||||||
|
border-radius: var(--theme-customizer-preview-radius);
|
||||||
block-size: 8px;
|
block-size: 8px;
|
||||||
inline-size: 42%;
|
inline-size: 42%;
|
||||||
min-inline-size: 28px;
|
min-inline-size: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-radius-scene__line {
|
.theme-customizer-radius-scene__line {
|
||||||
|
border-radius: var(--theme-customizer-preview-radius);
|
||||||
block-size: 7px;
|
block-size: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -783,112 +796,89 @@ async function handleResetSettings() {
|
|||||||
inline-size: 66%;
|
inline-size: 66%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-shadow-scene {
|
.theme-customizer-shadow-slider {
|
||||||
position: relative;
|
padding: 16px 18px 12px;
|
||||||
display: block;
|
|
||||||
overflow: hidden;
|
|
||||||
border: 1px solid rgba(var(--v-theme-on-surface), 0.12);
|
border: 1px solid rgba(var(--v-theme-on-surface), 0.12);
|
||||||
border-radius: 10px;
|
border-radius: var(--app-vuetify-rounded-lg);
|
||||||
background:
|
background: rgba(var(--v-theme-surface), 0.72);
|
||||||
linear-gradient(180deg, rgba(var(--v-theme-on-surface), 0.02), rgba(var(--v-theme-on-surface), 0.06)),
|
|
||||||
rgb(var(--v-theme-surface));
|
|
||||||
block-size: 110px;
|
|
||||||
inline-size: 100%;
|
|
||||||
min-inline-size: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-shadow-scene__panel,
|
.theme-customizer-shadow-slider__header,
|
||||||
.theme-customizer-shadow-scene__card {
|
.theme-customizer-shadow-slider__scale {
|
||||||
position: absolute;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-customizer-shadow-slider__header {
|
||||||
|
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.3;
|
||||||
|
margin-block-end: 14px;
|
||||||
|
|
||||||
|
> span:first-child {
|
||||||
|
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity));
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-customizer-shadow-slider__control {
|
||||||
|
display: grid;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
grid-template-columns: 56px minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-customizer-shadow-slider__sample {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: var(--app-vuetify-rounded);
|
||||||
border: 1px solid rgba(var(--v-theme-on-surface), 0.08);
|
border: 1px solid rgba(var(--v-theme-on-surface), 0.08);
|
||||||
background: rgb(var(--v-theme-surface));
|
background: rgb(var(--v-theme-surface));
|
||||||
box-shadow: none;
|
block-size: 42px;
|
||||||
transition: box-shadow 0.18s ease;
|
gap: 5px;
|
||||||
|
inline-size: 42px;
|
||||||
|
padding-block: 8px;
|
||||||
|
padding-inline: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-shadow-scene__panel {
|
.theme-customizer-shadow-slider__sample-accent,
|
||||||
padding: 12px;
|
.theme-customizer-shadow-slider__sample-line {
|
||||||
gap: 8px;
|
|
||||||
inset-block-start: 16px;
|
|
||||||
inset-inline: 14px;
|
|
||||||
min-block-size: 54px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-customizer-shadow-scene__card {
|
|
||||||
gap: 8px;
|
|
||||||
inset-block-end: 12px;
|
|
||||||
inset-inline: 20px 16px;
|
|
||||||
min-block-size: 46px;
|
|
||||||
padding-block: 10px;
|
|
||||||
padding-inline: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-customizer-shadow-scene__panel-line,
|
|
||||||
.theme-customizer-shadow-scene__line,
|
|
||||||
.theme-customizer-shadow-scene__badge {
|
|
||||||
display: block;
|
display: block;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: rgba(var(--v-theme-on-surface), 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-shadow-scene__badge {
|
.theme-customizer-shadow-slider__sample-accent {
|
||||||
block-size: 6px;
|
background: rgba(var(--v-theme-primary), 0.48);
|
||||||
inline-size: 34%;
|
block-size: 5px;
|
||||||
min-inline-size: 28px;
|
inline-size: 44%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-shadow-scene__panel-line,
|
.theme-customizer-shadow-slider__sample-line {
|
||||||
.theme-customizer-shadow-scene__line {
|
background: rgba(var(--v-theme-on-surface), 0.12);
|
||||||
block-size: 7px;
|
block-size: 4px;
|
||||||
|
inline-size: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-shadow-scene__panel-line--short,
|
.theme-customizer-shadow-slider__sample-line--short {
|
||||||
.theme-customizer-shadow-scene__line--short {
|
inline-size: 68%;
|
||||||
inline-size: 62%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-shadow-scene--low {
|
.theme-customizer-shadow-slider__scale {
|
||||||
.theme-customizer-shadow-scene__panel {
|
color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
|
||||||
box-shadow:
|
font-size: 0.75rem;
|
||||||
0 8px 18px rgba(var(--v-theme-on-surface), 0.08),
|
line-height: 1;
|
||||||
0 2px 6px rgba(var(--v-theme-on-surface), 0.05);
|
margin-block-start: 2px;
|
||||||
}
|
margin-inline-start: 72px;
|
||||||
|
|
||||||
.theme-customizer-shadow-scene__card {
|
|
||||||
box-shadow:
|
|
||||||
0 10px 22px rgba(var(--v-theme-on-surface), 0.1),
|
|
||||||
0 4px 10px rgba(var(--v-theme-on-surface), 0.06);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-shadow-scene--medium {
|
.theme-customizer-shadow-slider :deep(.v-slider.v-input) {
|
||||||
.theme-customizer-shadow-scene__panel {
|
margin: 0;
|
||||||
box-shadow:
|
|
||||||
0 12px 28px rgba(var(--v-theme-on-surface), 0.12),
|
|
||||||
0 4px 12px rgba(var(--v-theme-on-surface), 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-customizer-shadow-scene__card {
|
|
||||||
box-shadow:
|
|
||||||
0 16px 34px rgba(var(--v-theme-on-surface), 0.14),
|
|
||||||
0 6px 16px rgba(var(--v-theme-on-surface), 0.09);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-shadow-scene--high {
|
.theme-customizer-shadow-slider :deep(.v-slider-track__tick) {
|
||||||
.theme-customizer-shadow-scene__panel {
|
opacity: 0.5;
|
||||||
box-shadow:
|
|
||||||
0 16px 38px rgba(var(--v-theme-on-surface), 0.16),
|
|
||||||
0 6px 18px rgba(var(--v-theme-on-surface), 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-customizer-shadow-scene__card {
|
|
||||||
box-shadow:
|
|
||||||
0 22px 48px rgba(var(--v-theme-on-surface), 0.18),
|
|
||||||
0 8px 22px rgba(var(--v-theme-on-surface), 0.12);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (width <= 600px) {
|
@media (width <= 600px) {
|
||||||
|
|||||||
@@ -24,9 +24,37 @@ export const themeCustomizerPrimaryColors = [
|
|||||||
{ name: 'Slate', value: '#607D8B' },
|
{ name: 'Slate', value: '#607D8B' },
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
|
export const themeCustomizerShadowLevels = [
|
||||||
|
'0',
|
||||||
|
'1',
|
||||||
|
'2',
|
||||||
|
'3',
|
||||||
|
'4',
|
||||||
|
'5',
|
||||||
|
'6',
|
||||||
|
'7',
|
||||||
|
'8',
|
||||||
|
'9',
|
||||||
|
'10',
|
||||||
|
'11',
|
||||||
|
'12',
|
||||||
|
'13',
|
||||||
|
'14',
|
||||||
|
'15',
|
||||||
|
'16',
|
||||||
|
'17',
|
||||||
|
'18',
|
||||||
|
'19',
|
||||||
|
'20',
|
||||||
|
'21',
|
||||||
|
'22',
|
||||||
|
'23',
|
||||||
|
'24',
|
||||||
|
] as const
|
||||||
|
|
||||||
export type ThemeCustomizerLayout = 'collapsed' | 'horizontal' | 'vertical'
|
export type ThemeCustomizerLayout = 'collapsed' | 'horizontal' | 'vertical'
|
||||||
export type ThemeCustomizerRadius = 'default' | 'extra' | 'huge' | 'large' | 'small'
|
export type ThemeCustomizerRadius = 'default' | 'extra' | 'large' | 'none' | 'small'
|
||||||
export type ThemeCustomizerShadow = 'none' | 'low' | 'medium' | 'high'
|
export type ThemeCustomizerShadow = (typeof themeCustomizerShadowLevels)[number]
|
||||||
export type ThemeCustomizerSkin = 'bordered' | 'default'
|
export type ThemeCustomizerSkin = 'bordered' | 'default'
|
||||||
export type ThemeCustomizerTheme = 'auto' | 'dark' | 'light' | 'purple' | 'transparent'
|
export type ThemeCustomizerTheme = 'auto' | 'dark' | 'light' | 'purple' | 'transparent'
|
||||||
|
|
||||||
@@ -44,10 +72,16 @@ type VuetifyThemeApi = ReturnType<typeof useTheme>
|
|||||||
|
|
||||||
const defaultPrimaryColor = themeCustomizerPrimaryColors[0].value
|
const defaultPrimaryColor = themeCustomizerPrimaryColors[0].value
|
||||||
const validLayouts: ThemeCustomizerLayout[] = ['vertical', 'collapsed', 'horizontal']
|
const validLayouts: ThemeCustomizerLayout[] = ['vertical', 'collapsed', 'horizontal']
|
||||||
const validRadii: ThemeCustomizerRadius[] = ['small', 'default', 'large', 'extra', 'huge']
|
const validRadii: ThemeCustomizerRadius[] = ['none', 'small', 'default', 'large', 'extra']
|
||||||
const validShadows: ThemeCustomizerShadow[] = ['none', 'low', 'medium', 'high']
|
const validShadows: readonly ThemeCustomizerShadow[] = themeCustomizerShadowLevels
|
||||||
const validSkins: ThemeCustomizerSkin[] = ['default', 'bordered']
|
const validSkins: ThemeCustomizerSkin[] = ['default', 'bordered']
|
||||||
const validThemes: ThemeCustomizerTheme[] = ['auto', 'light', 'dark', 'purple', 'transparent']
|
const validThemes: ThemeCustomizerTheme[] = ['auto', 'light', 'dark', 'purple', 'transparent']
|
||||||
|
const legacyShadowMap: Record<string, ThemeCustomizerShadow> = {
|
||||||
|
high: '24',
|
||||||
|
low: '6',
|
||||||
|
medium: '12',
|
||||||
|
none: '0',
|
||||||
|
}
|
||||||
|
|
||||||
let themeApplyVersion = 0
|
let themeApplyVersion = 0
|
||||||
|
|
||||||
@@ -73,27 +107,35 @@ function getDefaultThemeCustomizerSettings(): ThemeCustomizerSettings {
|
|||||||
primaryColor: defaultPrimaryColor,
|
primaryColor: defaultPrimaryColor,
|
||||||
radius: 'default',
|
radius: 'default',
|
||||||
semiDarkMenu: false,
|
semiDarkMenu: false,
|
||||||
shadow: 'none',
|
shadow: '0',
|
||||||
skin: 'default',
|
skin: 'default',
|
||||||
theme: readStoredThemePreference(),
|
theme: readStoredThemePreference(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 将旧版语义阴影档位迁移到 Vuetify elevation 数值档位。 */
|
||||||
|
function normalizeThemeCustomizerShadow(shadow: unknown): ThemeCustomizerShadow {
|
||||||
|
if (validShadows.includes(shadow as ThemeCustomizerShadow)) return shadow as ThemeCustomizerShadow
|
||||||
|
if (typeof shadow === 'string' && legacyShadowMap[shadow]) return legacyShadowMap[shadow]
|
||||||
|
|
||||||
|
return getDefaultThemeCustomizerSettings().shadow
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeThemeCustomizerSettings(settings: Partial<ThemeCustomizerSettings>): ThemeCustomizerSettings {
|
function normalizeThemeCustomizerSettings(settings: Partial<ThemeCustomizerSettings>): ThemeCustomizerSettings {
|
||||||
const fallback = getDefaultThemeCustomizerSettings()
|
const fallback = getDefaultThemeCustomizerSettings()
|
||||||
|
const storedRadius = settings.radius as string | undefined
|
||||||
|
const radius = storedRadius === 'huge' ? 'extra' : storedRadius
|
||||||
|
|
||||||
return {
|
return {
|
||||||
layout: validLayouts.includes(settings.layout as ThemeCustomizerLayout)
|
layout: validLayouts.includes(settings.layout as ThemeCustomizerLayout)
|
||||||
? (settings.layout as ThemeCustomizerLayout)
|
? (settings.layout as ThemeCustomizerLayout)
|
||||||
: fallback.layout,
|
: fallback.layout,
|
||||||
primaryColor: isHexColor(settings.primaryColor) ? settings.primaryColor.toUpperCase() : fallback.primaryColor,
|
primaryColor: isHexColor(settings.primaryColor) ? settings.primaryColor.toUpperCase() : fallback.primaryColor,
|
||||||
radius: validRadii.includes(settings.radius as ThemeCustomizerRadius)
|
radius: validRadii.includes(radius as ThemeCustomizerRadius)
|
||||||
? (settings.radius as ThemeCustomizerRadius)
|
? (radius as ThemeCustomizerRadius)
|
||||||
: fallback.radius,
|
: fallback.radius,
|
||||||
semiDarkMenu: typeof settings.semiDarkMenu === 'boolean' ? settings.semiDarkMenu : fallback.semiDarkMenu,
|
semiDarkMenu: typeof settings.semiDarkMenu === 'boolean' ? settings.semiDarkMenu : fallback.semiDarkMenu,
|
||||||
shadow: validShadows.includes(settings.shadow as ThemeCustomizerShadow)
|
shadow: normalizeThemeCustomizerShadow(settings.shadow),
|
||||||
? (settings.shadow as ThemeCustomizerShadow)
|
|
||||||
: fallback.shadow,
|
|
||||||
skin: validSkins.includes(settings.skin as ThemeCustomizerSkin)
|
skin: validSkins.includes(settings.skin as ThemeCustomizerSkin)
|
||||||
? (settings.skin as ThemeCustomizerSkin)
|
? (settings.skin as ThemeCustomizerSkin)
|
||||||
: fallback.skin,
|
: fallback.skin,
|
||||||
@@ -247,7 +289,7 @@ export function isDefaultThemeCustomizerSettings(settings: ThemeCustomizerSettin
|
|||||||
primaryColor: defaultPrimaryColor,
|
primaryColor: defaultPrimaryColor,
|
||||||
radius: 'default',
|
radius: 'default',
|
||||||
semiDarkMenu: false,
|
semiDarkMenu: false,
|
||||||
shadow: 'none',
|
shadow: '0',
|
||||||
skin: 'default',
|
skin: 'default',
|
||||||
theme: 'auto',
|
theme: 'auto',
|
||||||
})
|
})
|
||||||
@@ -324,7 +366,7 @@ export function useThemeCustomizer() {
|
|||||||
primaryColor: defaultPrimaryColor,
|
primaryColor: defaultPrimaryColor,
|
||||||
radius: 'default',
|
radius: 'default',
|
||||||
semiDarkMenu: false,
|
semiDarkMenu: false,
|
||||||
shadow: 'none',
|
shadow: '0',
|
||||||
skin: 'default',
|
skin: 'default',
|
||||||
theme: 'auto',
|
theme: 'auto',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ function handleDynamicMenuItemClick(item: DynamicButtonMenuItem) {
|
|||||||
<VCardText class="footer-card-content">
|
<VCardText class="footer-card-content">
|
||||||
<!-- 添加指示器 -->
|
<!-- 添加指示器 -->
|
||||||
<div ref="indicator" class="nav-indicator"></div>
|
<div ref="indicator" class="nav-indicator"></div>
|
||||||
<VBtnToggle class="footer-btn-group" :mandatory="true" v-model="currentMenu">
|
<VBtnToggle class="footer-btn-group" :mandatory="true" variant="plain" v-model="currentMenu">
|
||||||
<!-- 遍历底部菜单项 -->
|
<!-- 遍历底部菜单项 -->
|
||||||
<VBtn
|
<VBtn
|
||||||
v-for="menu in footerMenus"
|
v-for="menu in footerMenus"
|
||||||
@@ -343,6 +343,9 @@ function handleDynamicMenuItemClick(item: DynamicButtonMenuItem) {
|
|||||||
transition: all 0.5s cubic-bezier(0.25, 1, 0.5, 1);
|
transition: all 0.5s cubic-bezier(0.25, 1, 0.5, 1);
|
||||||
will-change: transform, max-inline-size, opacity;
|
will-change: transform, max-inline-size, opacity;
|
||||||
|
|
||||||
|
--app-control-radius: var(--app-vuetify-rounded-pill);
|
||||||
|
--app-surface-radius: var(--app-vuetify-rounded-pill);
|
||||||
|
|
||||||
// 透明主题下的特殊样式
|
// 透明主题下的特殊样式
|
||||||
.v-theme--transparent & {
|
.v-theme--transparent & {
|
||||||
backdrop-filter: blur(var(--transparent-blur-heavy, 16px));
|
backdrop-filter: blur(var(--transparent-blur-heavy, 16px));
|
||||||
@@ -361,13 +364,19 @@ function handleDynamicMenuItemClick(item: DynamicButtonMenuItem) {
|
|||||||
padding-inline: 6px;
|
padding-inline: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-btn-group {
|
.footer-nav-card .footer-btn-group.v-btn-group {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
border: none;
|
border: none;
|
||||||
|
border-radius: 9999px !important;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
box-shadow: none !important;
|
||||||
inline-size: 100%;
|
inline-size: 100%;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-nav-btn {
|
.footer-nav-btn {
|
||||||
@@ -377,12 +386,15 @@ function handleDynamicMenuItemClick(item: DynamicButtonMenuItem) {
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
border-radius: 9999px !important;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
block-size: 48px;
|
block-size: 48px;
|
||||||
|
box-shadow: none !important;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
&.v-btn--active {
|
&.v-btn--active {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
box-shadow: none;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-content {
|
.btn-content {
|
||||||
|
|||||||
@@ -170,16 +170,13 @@ export default {
|
|||||||
skinDefault: 'Default',
|
skinDefault: 'Default',
|
||||||
skinBordered: 'Bordered',
|
skinBordered: 'Bordered',
|
||||||
radius: 'Corners',
|
radius: 'Corners',
|
||||||
|
radiusNone: 'Square',
|
||||||
radiusSmall: 'Small',
|
radiusSmall: 'Small',
|
||||||
radiusDefault: 'Default',
|
radiusDefault: 'Default',
|
||||||
radiusLarge: 'Large',
|
radiusLarge: 'Large',
|
||||||
radiusExtra: 'Larger',
|
radiusExtra: 'Larger',
|
||||||
radiusHuge: 'Extra Large',
|
|
||||||
shadow: 'Shadows',
|
shadow: 'Shadows',
|
||||||
shadowNone: 'Flat',
|
shadowLevel: 'Level {level}',
|
||||||
shadowLow: 'Soft',
|
|
||||||
shadowMedium: 'Balanced',
|
|
||||||
shadowHigh: 'Bold',
|
|
||||||
semiDarkMenu: 'Semi Dark Menu',
|
semiDarkMenu: 'Semi Dark Menu',
|
||||||
layout: 'Layout',
|
layout: 'Layout',
|
||||||
layoutVertical: 'Vertical',
|
layoutVertical: 'Vertical',
|
||||||
|
|||||||
@@ -170,16 +170,13 @@ export default {
|
|||||||
skinDefault: '默认',
|
skinDefault: '默认',
|
||||||
skinBordered: '边框',
|
skinBordered: '边框',
|
||||||
radius: '圆角',
|
radius: '圆角',
|
||||||
|
radiusNone: '无圆角',
|
||||||
radiusSmall: '小圆角',
|
radiusSmall: '小圆角',
|
||||||
radiusDefault: '默认',
|
radiusDefault: '默认',
|
||||||
radiusLarge: '大圆角',
|
radiusLarge: '大圆角',
|
||||||
radiusExtra: '更大圆角',
|
radiusExtra: '更大圆角',
|
||||||
radiusHuge: '超大圆角',
|
|
||||||
shadow: '阴影',
|
shadow: '阴影',
|
||||||
shadowNone: '无阴影',
|
shadowLevel: '层级 {level}',
|
||||||
shadowLow: '柔和',
|
|
||||||
shadowMedium: '标准',
|
|
||||||
shadowHigh: '强烈',
|
|
||||||
semiDarkMenu: '半暗菜单',
|
semiDarkMenu: '半暗菜单',
|
||||||
layout: '布局',
|
layout: '布局',
|
||||||
layoutVertical: '垂直',
|
layoutVertical: '垂直',
|
||||||
|
|||||||
@@ -170,16 +170,13 @@ export default {
|
|||||||
skinDefault: '默認',
|
skinDefault: '默認',
|
||||||
skinBordered: '邊框',
|
skinBordered: '邊框',
|
||||||
radius: '圓角',
|
radius: '圓角',
|
||||||
|
radiusNone: '無圓角',
|
||||||
radiusSmall: '小圓角',
|
radiusSmall: '小圓角',
|
||||||
radiusDefault: '默認',
|
radiusDefault: '默認',
|
||||||
radiusLarge: '大圓角',
|
radiusLarge: '大圓角',
|
||||||
radiusExtra: '更大圓角',
|
radiusExtra: '更大圓角',
|
||||||
radiusHuge: '超大圓角',
|
|
||||||
shadow: '陰影',
|
shadow: '陰影',
|
||||||
shadowNone: '無陰影',
|
shadowLevel: '層級 {level}',
|
||||||
shadowLow: '柔和',
|
|
||||||
shadowMedium: '標準',
|
|
||||||
shadowHigh: '強烈',
|
|
||||||
semiDarkMenu: '半暗菜單',
|
semiDarkMenu: '半暗菜單',
|
||||||
layout: '佈局',
|
layout: '佈局',
|
||||||
layoutVertical: '垂直',
|
layoutVertical: '垂直',
|
||||||
|
|||||||
+90
-71
@@ -1,6 +1,30 @@
|
|||||||
|
/* stylelint-disable custom-property-pattern */
|
||||||
/* stylelint-disable no-duplicate-selectors */
|
/* stylelint-disable no-duplicate-selectors */
|
||||||
/* stylelint-disable scss/at-rule-no-unknown */
|
/* stylelint-disable scss/at-rule-no-unknown */
|
||||||
/* stylelint-disable no-descending-specificity */
|
/* stylelint-disable no-descending-specificity */
|
||||||
|
@use 'sass:map';
|
||||||
|
@use 'vuetify/settings' as vuetify-settings;
|
||||||
|
|
||||||
|
// 返回 Vuetify 指定 elevation 的完整三层 box-shadow,供主题定制器映射全局阴影档位。
|
||||||
|
@function app-vuetify-elevation($level) {
|
||||||
|
@return map.get(vuetify-settings.$shadow-key-umbra, $level),
|
||||||
|
map.get(vuetify-settings.$shadow-key-penumbra, $level),
|
||||||
|
map.get(vuetify-settings.$shadow-key-ambient, $level);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将相对阴影层级限制在 Vuetify elevation 的 0 到 24 档范围内。
|
||||||
|
@function app-clamp-elevation($level) {
|
||||||
|
@if $level < 0 {
|
||||||
|
@return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@if $level > 24 {
|
||||||
|
@return 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
@return $level;
|
||||||
|
}
|
||||||
|
|
||||||
// 公共样式 - 所有主题都需要
|
// 公共样式 - 所有主题都需要
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@@ -38,24 +62,36 @@ html.quick-access-scroll-locked body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 全局卡片外观 token:圆角和阴影在主题定制器中即时切换。
|
// 全局外观 token:圆角和阴影复用 Vuetify 的 rounded / elevation 分级。
|
||||||
html {
|
html {
|
||||||
--app-theme-surface-radius: 8px;
|
--app-vuetify-rounded-0: #{map.get(vuetify-settings.$rounded, 0)};
|
||||||
|
--app-vuetify-rounded-sm: #{map.get(vuetify-settings.$rounded, 'sm')};
|
||||||
|
--app-vuetify-rounded: #{map.get(vuetify-settings.$rounded, null)};
|
||||||
|
--app-vuetify-rounded-lg: #{map.get(vuetify-settings.$rounded, 'lg')};
|
||||||
|
--app-vuetify-rounded-xl: #{map.get(vuetify-settings.$rounded, 'xl')};
|
||||||
|
--app-vuetify-rounded-pill: #{map.get(vuetify-settings.$rounded, 'pill')};
|
||||||
|
|
||||||
|
@for $level from 0 through 24 {
|
||||||
|
--app-elevation-#{$level}: #{app-vuetify-elevation($level)};
|
||||||
|
}
|
||||||
|
|
||||||
|
--app-theme-surface-radius: var(--app-vuetify-rounded);
|
||||||
--app-surface-radius: var(--app-theme-surface-radius);
|
--app-surface-radius: var(--app-theme-surface-radius);
|
||||||
--app-field-radius: var(--app-theme-surface-radius);
|
--app-field-radius: var(--app-vuetify-rounded);
|
||||||
|
--app-control-radius: var(--app-vuetify-rounded);
|
||||||
|
--app-overlay-radius: var(--app-vuetify-rounded);
|
||||||
--app-surface-border-opacity: 0.06;
|
--app-surface-border-opacity: 0.06;
|
||||||
--app-surface-border: 1px solid rgba(var(--v-theme-on-surface), var(--app-surface-border-opacity));
|
--app-surface-border: 1px solid rgba(var(--v-theme-on-surface), var(--app-surface-border-opacity));
|
||||||
--app-shadow-rgb: 15, 23, 42;
|
--app-card-rest-shadow: var(--app-elevation-0);
|
||||||
--app-card-rest-shadow: none;
|
--app-card-hover-shadow: var(--app-elevation-0);
|
||||||
--app-card-hover-shadow: none;
|
--app-fab-shadow: var(--app-elevation-0);
|
||||||
--app-fab-shadow: none;
|
--app-fab-shadow-strong: var(--app-elevation-0);
|
||||||
--app-fab-shadow-strong: none;
|
--app-fab-shadow-hover: var(--app-elevation-0);
|
||||||
--app-fab-shadow-hover: none;
|
--app-fab-shadow-strong-hover: var(--app-elevation-0);
|
||||||
--app-fab-shadow-strong-hover: none;
|
--app-fab-shadow-active: var(--app-elevation-0);
|
||||||
--app-fab-shadow-active: none;
|
--app-overlay-shadow: var(--app-elevation-0);
|
||||||
--app-overlay-shadow: none;
|
--app-surface-shadow: var(--app-elevation-0);
|
||||||
--app-surface-shadow: none;
|
--app-surface-hover-shadow: var(--app-elevation-0);
|
||||||
--app-surface-hover-shadow: none;
|
|
||||||
--mp-motion-duration-page: 180ms;
|
--mp-motion-duration-page: 180ms;
|
||||||
--mp-motion-duration-overlay: 160ms;
|
--mp-motion-duration-overlay: 160ms;
|
||||||
--mp-motion-ease-standard: cubic-bezier(0.2, 0.8, 0.2, 1);
|
--mp-motion-ease-standard: cubic-bezier(0.2, 0.8, 0.2, 1);
|
||||||
@@ -66,65 +102,47 @@ html[data-theme-skin='bordered'] {
|
|||||||
--app-surface-border-opacity: 0.1;
|
--app-surface-border-opacity: 0.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html[data-theme-radius='none'] {
|
||||||
|
--app-theme-surface-radius: var(--app-vuetify-rounded-0);
|
||||||
|
--app-field-radius: var(--app-vuetify-rounded-0);
|
||||||
|
--app-control-radius: var(--app-vuetify-rounded-0);
|
||||||
|
--app-overlay-radius: var(--app-vuetify-rounded-0);
|
||||||
|
}
|
||||||
|
|
||||||
html[data-theme-radius='small'] {
|
html[data-theme-radius='small'] {
|
||||||
--app-theme-surface-radius: 4px;
|
--app-theme-surface-radius: var(--app-vuetify-rounded-sm);
|
||||||
|
--app-field-radius: var(--app-vuetify-rounded-sm);
|
||||||
|
--app-control-radius: var(--app-vuetify-rounded-sm);
|
||||||
|
--app-overlay-radius: var(--app-vuetify-rounded-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme-radius='large'] {
|
html[data-theme-radius='large'] {
|
||||||
--app-theme-surface-radius: 12px;
|
--app-theme-surface-radius: var(--app-vuetify-rounded-lg);
|
||||||
|
--app-field-radius: var(--app-vuetify-rounded-lg);
|
||||||
|
--app-control-radius: var(--app-vuetify-rounded-lg);
|
||||||
|
--app-overlay-radius: var(--app-vuetify-rounded-lg);
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme-radius='extra'] {
|
html[data-theme-radius='extra'] {
|
||||||
--app-theme-surface-radius: 16px;
|
--app-theme-surface-radius: var(--app-vuetify-rounded-xl);
|
||||||
|
--app-field-radius: var(--app-vuetify-rounded-xl);
|
||||||
|
--app-control-radius: var(--app-vuetify-rounded-xl);
|
||||||
|
--app-overlay-radius: var(--app-vuetify-rounded-xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-theme-radius='huge'] {
|
@for $level from 1 through 24 {
|
||||||
--app-theme-surface-radius: 24px;
|
html[data-theme-shadow='#{$level}'] {
|
||||||
}
|
--app-card-rest-shadow: var(--app-elevation-#{app-clamp-elevation($level - 1)});
|
||||||
|
--app-card-hover-shadow: var(--app-elevation-#{app-clamp-elevation($level + 1)});
|
||||||
html[data-theme='dark'],
|
--app-fab-shadow: var(--app-elevation-#{$level});
|
||||||
html[data-theme='purple'],
|
--app-fab-shadow-active: var(--app-elevation-#{app-clamp-elevation($level - 2)});
|
||||||
html[data-theme='transparent'] {
|
--app-fab-shadow-hover: var(--app-elevation-#{app-clamp-elevation($level + 3)});
|
||||||
--app-shadow-rgb: 0, 0, 0;
|
--app-fab-shadow-strong: var(--app-elevation-#{app-clamp-elevation($level + 2)});
|
||||||
}
|
--app-fab-shadow-strong-hover: var(--app-elevation-#{app-clamp-elevation($level + 4)});
|
||||||
|
--app-overlay-shadow: var(--app-elevation-#{app-clamp-elevation($level + 6)});
|
||||||
html[data-theme-shadow='low'] {
|
--app-surface-shadow: var(--app-elevation-#{$level});
|
||||||
--app-card-rest-shadow: 0 10px 24px rgba(var(--app-shadow-rgb), 0.06), 0 2px 8px rgba(var(--app-shadow-rgb), 0.04);
|
--app-surface-hover-shadow: var(--app-elevation-#{app-clamp-elevation($level + 2)});
|
||||||
--app-card-hover-shadow: 0 14px 30px rgba(var(--app-shadow-rgb), 0.08), 0 4px 12px rgba(var(--app-shadow-rgb), 0.05);
|
}
|
||||||
--app-fab-shadow: 0 16px 34px rgba(var(--app-shadow-rgb), 0.16), 0 6px 16px rgba(var(--app-shadow-rgb), 0.1);
|
|
||||||
--app-fab-shadow-strong: 0 20px 40px rgba(var(--app-shadow-rgb), 0.2), 0 8px 18px rgba(var(--app-shadow-rgb), 0.12);
|
|
||||||
--app-fab-shadow-hover: 0 22px 42px rgba(var(--app-shadow-rgb), 0.22), 0 8px 18px rgba(var(--app-shadow-rgb), 0.12);
|
|
||||||
--app-fab-shadow-strong-hover: 0 26px 46px rgba(var(--app-shadow-rgb), 0.24), 0 10px 22px rgba(var(--app-shadow-rgb), 0.14);
|
|
||||||
--app-fab-shadow-active: 0 10px 22px rgba(var(--app-shadow-rgb), 0.16), 0 3px 8px rgba(var(--app-shadow-rgb), 0.1);
|
|
||||||
--app-overlay-shadow: 0 18px 42px rgba(var(--app-shadow-rgb), 0.14), 0 6px 18px rgba(var(--app-shadow-rgb), 0.08);
|
|
||||||
--app-surface-shadow: 0 10px 24px rgba(var(--app-shadow-rgb), 0.07), 0 2px 8px rgba(var(--app-shadow-rgb), 0.05);
|
|
||||||
--app-surface-hover-shadow: 0 14px 30px rgba(var(--app-shadow-rgb), 0.09), 0 4px 12px rgba(var(--app-shadow-rgb), 0.06);
|
|
||||||
}
|
|
||||||
|
|
||||||
html[data-theme-shadow='medium'] {
|
|
||||||
--app-card-rest-shadow: 0 14px 32px rgba(var(--app-shadow-rgb), 0.09), 0 4px 12px rgba(var(--app-shadow-rgb), 0.06);
|
|
||||||
--app-card-hover-shadow: 0 18px 40px rgba(var(--app-shadow-rgb), 0.11), 0 6px 16px rgba(var(--app-shadow-rgb), 0.07);
|
|
||||||
--app-fab-shadow: 0 18px 40px rgba(var(--app-shadow-rgb), 0.2), 0 7px 18px rgba(var(--app-shadow-rgb), 0.12);
|
|
||||||
--app-fab-shadow-strong: 0 24px 48px rgba(var(--app-shadow-rgb), 0.24), 0 10px 24px rgba(var(--app-shadow-rgb), 0.14);
|
|
||||||
--app-fab-shadow-hover: 0 24px 46px rgba(var(--app-shadow-rgb), 0.24), 0 10px 22px rgba(var(--app-shadow-rgb), 0.14);
|
|
||||||
--app-fab-shadow-strong-hover: 0 30px 54px rgba(var(--app-shadow-rgb), 0.28), 0 12px 28px rgba(var(--app-shadow-rgb), 0.16);
|
|
||||||
--app-fab-shadow-active: 0 12px 26px rgba(var(--app-shadow-rgb), 0.18), 0 4px 10px rgba(var(--app-shadow-rgb), 0.12);
|
|
||||||
--app-overlay-shadow: 0 24px 56px rgba(var(--app-shadow-rgb), 0.18), 0 10px 24px rgba(var(--app-shadow-rgb), 0.1);
|
|
||||||
--app-surface-shadow: 0 14px 32px rgba(var(--app-shadow-rgb), 0.1), 0 4px 12px rgba(var(--app-shadow-rgb), 0.07);
|
|
||||||
--app-surface-hover-shadow: 0 18px 40px rgba(var(--app-shadow-rgb), 0.12), 0 6px 16px rgba(var(--app-shadow-rgb), 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
html[data-theme-shadow='high'] {
|
|
||||||
--app-card-rest-shadow: 0 18px 40px rgba(var(--app-shadow-rgb), 0.12), 0 6px 18px rgba(var(--app-shadow-rgb), 0.08);
|
|
||||||
--app-card-hover-shadow: 0 22px 50px rgba(var(--app-shadow-rgb), 0.15), 0 8px 22px rgba(var(--app-shadow-rgb), 0.1);
|
|
||||||
--app-fab-shadow: 0 22px 48px rgba(var(--app-shadow-rgb), 0.24), 0 10px 24px rgba(var(--app-shadow-rgb), 0.14);
|
|
||||||
--app-fab-shadow-strong: 0 28px 58px rgba(var(--app-shadow-rgb), 0.3), 0 12px 30px rgba(var(--app-shadow-rgb), 0.18);
|
|
||||||
--app-fab-shadow-hover: 0 28px 56px rgba(var(--app-shadow-rgb), 0.28), 0 12px 28px rgba(var(--app-shadow-rgb), 0.17);
|
|
||||||
--app-fab-shadow-strong-hover: 0 34px 64px rgba(var(--app-shadow-rgb), 0.34), 0 14px 32px rgba(var(--app-shadow-rgb), 0.2);
|
|
||||||
--app-fab-shadow-active: 0 14px 30px rgba(var(--app-shadow-rgb), 0.22), 0 5px 12px rgba(var(--app-shadow-rgb), 0.14);
|
|
||||||
--app-overlay-shadow: 0 30px 70px rgba(var(--app-shadow-rgb), 0.22), 0 14px 30px rgba(var(--app-shadow-rgb), 0.12);
|
|
||||||
--app-surface-shadow: 0 18px 40px rgba(var(--app-shadow-rgb), 0.13), 0 6px 18px rgba(var(--app-shadow-rgb), 0.09);
|
|
||||||
--app-surface-hover-shadow: 0 22px 50px rgba(var(--app-shadow-rgb), 0.16), 0 8px 22px rgba(var(--app-shadow-rgb), 0.11);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 进度条样式
|
// 进度条样式
|
||||||
@@ -421,12 +439,12 @@ html[data-theme-shadow='high'] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.v-btn:not(.v-btn--rounded, .v-btn--flat, .v-btn--icon, [class^='rounded-'], [class*=' rounded-']) {
|
.v-btn:not(.v-btn--rounded, .v-btn--flat, .v-btn--icon, [class^='rounded-'], [class*=' rounded-']) {
|
||||||
border-radius: var(--app-surface-radius);
|
border-radius: var(--app-control-radius);
|
||||||
transition: border-radius 0.2s ease;
|
transition: border-radius 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-btn-group:not(.v-btn-group--variant-plain, .v-btn-group--variant-text) {
|
.v-btn-group:not(.v-btn-group--variant-plain, .v-btn-group--variant-text) {
|
||||||
border-radius: var(--app-surface-radius);
|
border-radius: var(--app-control-radius);
|
||||||
box-shadow: var(--app-surface-shadow) !important;
|
box-shadow: var(--app-surface-shadow) !important;
|
||||||
transition: box-shadow 0.2s ease, border-radius 0.2s ease;
|
transition: box-shadow 0.2s ease, border-radius 0.2s ease;
|
||||||
}
|
}
|
||||||
@@ -703,7 +721,7 @@ html[data-theme="transparent"] .app-card-colorful,
|
|||||||
}
|
}
|
||||||
|
|
||||||
.Vue-Toastification__toast {
|
.Vue-Toastification__toast {
|
||||||
border-radius: var(--app-surface-radius);
|
border-radius: var(--app-overlay-radius);
|
||||||
box-shadow: var(--app-overlay-shadow);
|
box-shadow: var(--app-overlay-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1175,6 +1193,7 @@ html[data-theme="transparent"] .app-card-colorful,
|
|||||||
.v-bottom-sheet > .v-bottom-sheet__content.v-overlay__content > .v-card,
|
.v-bottom-sheet > .v-bottom-sheet__content.v-overlay__content > .v-card,
|
||||||
.v-menu > .v-overlay__content > .v-card,
|
.v-menu > .v-overlay__content > .v-card,
|
||||||
.v-menu > .v-overlay__content > .v-list {
|
.v-menu > .v-overlay__content > .v-list {
|
||||||
|
border-radius: var(--app-overlay-radius) !important;
|
||||||
box-shadow: var(--app-overlay-shadow) !important;
|
box-shadow: var(--app-overlay-shadow) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1191,8 +1210,8 @@ html[data-theme="transparent"] .app-card-colorful,
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-end-end-radius: 0 !important;
|
border-end-end-radius: 0 !important;
|
||||||
border-end-start-radius: 0 !important;
|
border-end-start-radius: 0 !important;
|
||||||
border-start-end-radius: var(--app-theme-surface-radius) !important;
|
border-start-end-radius: var(--app-overlay-radius) !important;
|
||||||
border-start-start-radius: var(--app-theme-surface-radius) !important;
|
border-start-start-radius: var(--app-overlay-radius) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-dialog--fullscreen > .v-overlay__content > .v-card,
|
.v-dialog--fullscreen > .v-overlay__content > .v-card,
|
||||||
@@ -1201,8 +1220,8 @@ html[data-theme="transparent"] .app-card-colorful,
|
|||||||
.v-dialog--fullscreen > .v-overlay__content > form > .v-sheet {
|
.v-dialog--fullscreen > .v-overlay__content > form > .v-sheet {
|
||||||
border-end-end-radius: 0 !important;
|
border-end-end-radius: 0 !important;
|
||||||
border-end-start-radius: 0 !important;
|
border-end-start-radius: 0 !important;
|
||||||
border-start-end-radius: var(--app-theme-surface-radius) !important;
|
border-start-end-radius: var(--app-overlay-radius) !important;
|
||||||
border-start-start-radius: var(--app-theme-surface-radius) !important;
|
border-start-start-radius: var(--app-overlay-radius) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user