mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-06-22 08:03:45 +08:00
feat: refine theme customizer and horizontal navigation
This commit is contained in:
@@ -117,6 +117,7 @@ export default defineComponent({
|
||||
|
||||
// 👉 根据路由 meta 决定 footer 高度
|
||||
const shouldShowFooter = !route.meta.hideFooter
|
||||
const isNavbarScrolled = scrollDistance.value > 5 || (isDialogOpen.value && wasScrolledBeforeDialog.value)
|
||||
|
||||
// 👉 Footer
|
||||
const footer = h('footer', { class: 'layout-footer' }, [
|
||||
@@ -146,8 +147,9 @@ export default defineComponent({
|
||||
mdAndDown.value && 'layout-overlay-nav',
|
||||
isCollapsedLayout.value && 'layout-vertical-nav-collapsed',
|
||||
isHorizontalLayout.value && 'layout-horizontal-nav-active',
|
||||
isHorizontalLayout.value && isNavbarScrolled && 'layout-horizontal-nav-scrolled',
|
||||
route.meta.layoutWrapperClasses,
|
||||
(scrollDistance.value > 5 || (isDialogOpen.value && wasScrolledBeforeDialog.value)) && 'window-scrolled',
|
||||
!isHorizontalLayout.value && isNavbarScrolled && 'window-scrolled',
|
||||
],
|
||||
},
|
||||
[verticalNav, h('div', { class: 'layout-content-wrapper' }, [navbar, main, footer]), layoutOverlay],
|
||||
@@ -340,11 +342,80 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
@at-root {
|
||||
.layout-wrapper.layout-horizontal-nav-active.layout-horizontal-nav-scrolled.layout-navbar-fixed .layout-navbar {
|
||||
backdrop-filter: blur(12px) saturate(1.2);
|
||||
background: rgb(var(--v-theme-surface)) !important;
|
||||
box-shadow: 0 4px 8px -4px rgb(94 86 105 / 42%);
|
||||
}
|
||||
|
||||
.layout-wrapper.layout-horizontal-nav-active.layout-horizontal-nav-scrolled.layout-navbar-fixed
|
||||
.navbar-content-container {
|
||||
backdrop-filter: none !important;
|
||||
background: transparent !important;
|
||||
background-color: transparent !important;
|
||||
box-shadow: none !important;
|
||||
filter: none !important;
|
||||
padding-inline: 1.5rem !important;
|
||||
|
||||
&::before {
|
||||
display: none !important;
|
||||
backdrop-filter: none !important;
|
||||
background: transparent !important;
|
||||
background-color: transparent !important;
|
||||
content: none !important;
|
||||
filter: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme='transparent'] .layout-wrapper.layout-horizontal-nav-active .layout-navbar,
|
||||
.v-theme--transparent .layout-wrapper.layout-horizontal-nav-active .layout-navbar {
|
||||
backdrop-filter: blur(var(--transparent-blur-heavy, 16px));
|
||||
background-color: rgba(var(--v-theme-surface), var(--transparent-opacity-light, 0.2));
|
||||
border-block-end-color: rgba(var(--v-theme-on-surface), 0.06);
|
||||
backdrop-filter: none !important;
|
||||
background: transparent !important;
|
||||
box-shadow: none !important;
|
||||
border-block-end-color: rgba(var(--v-theme-on-surface), 0.04);
|
||||
}
|
||||
|
||||
html[data-theme='transparent'] .layout-wrapper.layout-horizontal-nav-active .navbar-content-container,
|
||||
.v-theme--transparent .layout-wrapper.layout-horizontal-nav-active .navbar-content-container {
|
||||
backdrop-filter: none !important;
|
||||
background: transparent !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
// 透明主题的水平导航不叠加滚动磨砂层,避免中间区域出现一块更深的背景。
|
||||
html[data-theme='transparent']
|
||||
.layout-wrapper.layout-horizontal-nav-active.layout-horizontal-nav-scrolled.layout-navbar-fixed
|
||||
.layout-navbar,
|
||||
.v-theme--transparent
|
||||
.layout-wrapper.layout-horizontal-nav-active.layout-horizontal-nav-scrolled.layout-navbar-fixed
|
||||
.layout-navbar {
|
||||
backdrop-filter: blur(var(--transparent-blur-light, 6px)) !important;
|
||||
background: rgba(var(--v-theme-surface), var(--transparent-opacity-light, 0.2)) !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
// 透明主题滚动时只让外层导航栏承载整屏背景,避免内部最大宽度容器单独变深。
|
||||
html[data-theme='transparent']
|
||||
.layout-wrapper.layout-horizontal-nav-active.layout-horizontal-nav-scrolled.layout-navbar-fixed
|
||||
.navbar-content-container,
|
||||
.v-theme--transparent
|
||||
.layout-wrapper.layout-horizontal-nav-active.layout-horizontal-nav-scrolled.layout-navbar-fixed
|
||||
.navbar-content-container {
|
||||
backdrop-filter: none !important;
|
||||
background: transparent !important;
|
||||
background-color: transparent !important;
|
||||
box-shadow: none !important;
|
||||
filter: none !important;
|
||||
padding-inline: 1.5rem !important;
|
||||
|
||||
&::before {
|
||||
display: none !important;
|
||||
backdrop-filter: none !important;
|
||||
background: transparent !important;
|
||||
background-color: transparent !important;
|
||||
content: none !important;
|
||||
filter: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme='light'][data-theme-semi-dark-menu='true'][data-theme-layout='vertical']
|
||||
|
||||
@@ -240,24 +240,39 @@ function handleLayoutChange(layout: ThemeCustomizerLayout) {
|
||||
|
||||
<style lang="scss">
|
||||
.theme-customizer-drawer {
|
||||
position: fixed !important;
|
||||
z-index: 12000 !important;
|
||||
border-inline-start: 1px solid rgba(var(--v-theme-on-surface), 0.08) !important;
|
||||
block-size: 100dvh !important;
|
||||
box-shadow: -2px 0 6px rgba(0, 0, 0, 10%) !important;
|
||||
inset-block: 0 !important;
|
||||
inset-inline-end: 0 !important;
|
||||
max-block-size: 100dvh !important;
|
||||
|
||||
.v-navigation-drawer__content {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
block-size: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-customizer-drawer .v-theme--transparent,
|
||||
.theme-customizer-drawer.v-theme--transparent,
|
||||
.v-theme--transparent .theme-customizer-drawer,
|
||||
html[data-theme='transparent'] .theme-customizer-drawer {
|
||||
backdrop-filter: blur(var(--transparent-blur-heavy, 16px));
|
||||
background-color: rgba(var(--v-theme-surface), var(--transparent-opacity-heavy, 0.5)) !important;
|
||||
}
|
||||
|
||||
// 透明主题的全局 overlay 毛玻璃会影响临时抽屉绘制,主题定制器改由 drawer 自身承担背景。
|
||||
html[data-theme='transparent'] .v-overlay__content:has(.theme-customizer-drawer),
|
||||
.v-theme--transparent .v-overlay__content:has(.theme-customizer-drawer) {
|
||||
border-radius: 0 !important;
|
||||
backdrop-filter: none !important;
|
||||
background: transparent !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
:is(html[data-theme='transparent'], .v-theme--transparent) .theme-customizer-card-option .theme-customizer-theme-icon,
|
||||
:is(html[data-theme='transparent'], .v-theme--transparent) .theme-customizer-color-option .theme-customizer-native-icon,
|
||||
:is(html[data-theme='transparent'], .v-theme--transparent) .theme-customizer-header-icon {
|
||||
|
||||
@@ -10,12 +10,20 @@ import UserProfile from '@/layouts/components/UserProfile.vue'
|
||||
import QuickAccess from '@/layouts/components/QuickAccess.vue'
|
||||
import HeaderTab from '@/layouts/components/HeaderTab.vue'
|
||||
import { usePluginSidebarNavStore, useUserStore } from '@/stores'
|
||||
import { getNavMenus } from '@/router/i18n-menu'
|
||||
import {
|
||||
getDiscoverTabs,
|
||||
getNavMenus,
|
||||
getPluginTabs,
|
||||
getSettingTabs,
|
||||
getSubscribeMovieTabs,
|
||||
getSubscribeTvTabs,
|
||||
getWorkflowTabs,
|
||||
} from '@/router/i18n-menu'
|
||||
import { filterPluginSidebarNavEntries } from '@/utils/pluginSidebarNav'
|
||||
import { NavMenu } from '@/@layouts/types'
|
||||
import { useDisplay } from 'vuetify'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { filterMenusByPermission } from '@/utils/permission'
|
||||
import { onUnreadMessage } from '@/utils/badge'
|
||||
import { usePullDownGesture } from '@/composables/usePullDownGesture'
|
||||
@@ -34,6 +42,7 @@ const display = useDisplay()
|
||||
const { appMode } = usePWA()
|
||||
const { t } = useI18n()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const themeLayout = ref(readThemeCustomizerSettings().layout)
|
||||
|
||||
// 用户 Store
|
||||
@@ -133,6 +142,7 @@ interface DynamicHeaderTab {
|
||||
// 提供动态标签页注册和获取的方法
|
||||
const dynamicHeaderTab = ref<DynamicHeaderTab | null>(null)
|
||||
const openHorizontalNavGroup = ref<string | null>(null)
|
||||
const pendingHorizontalTab = ref<{ path: string; tab: string } | null>(null)
|
||||
|
||||
// 提供一个方法让其他组件注册动态标签页
|
||||
const registerDynamicHeaderTab = (tab: DynamicHeaderTab) => {
|
||||
@@ -140,6 +150,7 @@ const registerDynamicHeaderTab = (tab: DynamicHeaderTab) => {
|
||||
tab.routePath = route.path
|
||||
// 强制更新,确保响应式系统能检测到变化
|
||||
dynamicHeaderTab.value = { ...tab }
|
||||
applyPendingHorizontalTab()
|
||||
}
|
||||
|
||||
// 提供一个方法让其他组件取消注册动态标签页
|
||||
@@ -199,6 +210,20 @@ const visibleHorizontalHeaderButtons = computed(() => {
|
||||
return (dynamicHeaderTab.value?.appendButtons ?? []).filter(button => resolveMaybeRefValue(button.show, true) !== false)
|
||||
})
|
||||
|
||||
const staticHorizontalNavTabs = computed<Record<string, DynamicHeaderTabItem[]>>(() => ({
|
||||
'/recommend': getRecommendTabs(),
|
||||
'/discover': getDiscoverTabs(t).map(tab => ({
|
||||
title: tab.name,
|
||||
icon: tab.icon,
|
||||
tab: tab.tab,
|
||||
})),
|
||||
'/subscribe/movie': getSubscribeMovieTabs(t),
|
||||
'/subscribe/tv': getSubscribeTvTabs(t),
|
||||
'/workflow': getWorkflowTabs(t),
|
||||
'/plugins': getPluginTabs(t),
|
||||
'/setting': getSettingTabs(t),
|
||||
}))
|
||||
|
||||
// 在组件销毁时清理
|
||||
onUnmounted(() => {
|
||||
dynamicHeaderTab.value = null
|
||||
@@ -269,10 +294,10 @@ function handleThemeCustomizerChange(event: Event) {
|
||||
}
|
||||
|
||||
function isHorizontalNavActive(item: NavMenu) {
|
||||
if (typeof item.to !== 'string') return false
|
||||
const targetPath = normalizeMenuPath(item.to)
|
||||
if (!targetPath) return false
|
||||
|
||||
const targetPath = item.to.replace(/\/$/, '')
|
||||
const currentPath = route.path.replace(/\/$/, '')
|
||||
const currentPath = normalizeMenuPath(route.path)
|
||||
|
||||
return currentPath === targetPath || currentPath.startsWith(`${targetPath}/`)
|
||||
}
|
||||
@@ -282,15 +307,25 @@ function isHorizontalNavGroupActive(group: { items: NavMenu[] }) {
|
||||
}
|
||||
|
||||
function hasHorizontalDynamicTabs(item: NavMenu) {
|
||||
return showHorizontalThemeNav.value && hasDynamicHeaderTab.value && isHorizontalNavActive(item)
|
||||
return showHorizontalThemeNav.value && getHorizontalNavTabs(item).length > 0
|
||||
}
|
||||
|
||||
function isHorizontalDynamicTabActive(tab: DynamicHeaderTabItem) {
|
||||
return dynamicHeaderTab.value?.modelValue === tab.tab
|
||||
}
|
||||
|
||||
function handleHorizontalDynamicTabSelect(tab: DynamicHeaderTabItem) {
|
||||
handleTabChange(tab.tab)
|
||||
async function handleHorizontalDynamicTabSelect(item: NavMenu, tab: DynamicHeaderTabItem) {
|
||||
const targetPath = normalizeMenuPath(item.to)
|
||||
const currentPath = normalizeMenuPath(route.path)
|
||||
|
||||
if (targetPath && currentPath !== targetPath) {
|
||||
// 三级菜单可能在目标页面挂载前点击,先记录待切换 tab,页面注册动态 tab 后再应用。
|
||||
pendingHorizontalTab.value = { path: targetPath, tab: tab.tab }
|
||||
await router.push(targetPath)
|
||||
} else {
|
||||
handleTabChange(tab.tab)
|
||||
}
|
||||
|
||||
openHorizontalNavGroup.value = null
|
||||
}
|
||||
|
||||
@@ -310,6 +345,57 @@ function resolveHeaderButtonLoading(button: DynamicHeaderTabButton) {
|
||||
return resolveMaybeRefValue(button.loading, false)
|
||||
}
|
||||
|
||||
function getHorizontalTabIcon(tab: DynamicHeaderTabItem) {
|
||||
const icon = tab.icon?.trim()
|
||||
|
||||
// 部分页面会把业务来源标识(如 themoviedb/douban/bangumi)放进 icon 字段,
|
||||
// 这些值不是菜单里的可渲染图标,三级菜单统一回退到默认图标。
|
||||
if (!icon || (!icon.startsWith('mdi-') && !icon.startsWith('tabler-') && !icon.includes(':'))) {
|
||||
return 'mdi-circle-medium'
|
||||
}
|
||||
|
||||
return icon
|
||||
}
|
||||
|
||||
function normalizeMenuPath(value: unknown) {
|
||||
if (typeof value !== 'string') return ''
|
||||
|
||||
return value.replace(/\/$/, '') || '/'
|
||||
}
|
||||
|
||||
function getHorizontalNavTabs(item: NavMenu): DynamicHeaderTabItem[] {
|
||||
const targetPath = normalizeMenuPath(item.to)
|
||||
|
||||
if (targetPath && isHorizontalNavActive(item) && hasDynamicHeaderTab.value) {
|
||||
return dynamicHeaderTab.value?.items ?? []
|
||||
}
|
||||
|
||||
return staticHorizontalNavTabs.value[targetPath] ?? []
|
||||
}
|
||||
|
||||
function getRecommendTabs(): DynamicHeaderTabItem[] {
|
||||
return [
|
||||
{ title: t('recommend.all'), icon: 'mdi-filmstrip-box-multiple', tab: t('recommend.all') },
|
||||
{ title: t('recommend.categoryMovie'), icon: 'mdi-movie', tab: t('recommend.categoryMovie') },
|
||||
{ title: t('recommend.categoryTV'), icon: 'mdi-television-classic', tab: t('recommend.categoryTV') },
|
||||
{ title: t('recommend.categoryAnime'), icon: 'mdi-animation', tab: t('recommend.categoryAnime') },
|
||||
{ title: t('recommend.categoryRankings'), icon: 'mdi-trophy', tab: t('recommend.categoryRankings') },
|
||||
]
|
||||
}
|
||||
|
||||
function applyPendingHorizontalTab() {
|
||||
if (!pendingHorizontalTab.value || !hasDynamicHeaderTab.value) return
|
||||
|
||||
const pending = pendingHorizontalTab.value
|
||||
if (normalizeMenuPath(route.path) !== pending.path) return
|
||||
|
||||
const tabExists = dynamicHeaderTab.value?.items.some(item => item.tab === pending.tab)
|
||||
if (!tabExists) return
|
||||
|
||||
handleTabChange(pending.tab)
|
||||
pendingHorizontalTab.value = null
|
||||
}
|
||||
|
||||
// 处理未读消息事件
|
||||
function handleUnreadMessage(count: number) {
|
||||
if (superUser.value && count > 0) {
|
||||
@@ -439,15 +525,22 @@ onMounted(async () => {
|
||||
<VIcon icon="mdi-arrow-left" size="32" />
|
||||
</IconBtn>
|
||||
<!-- 👉 Search Bar -->
|
||||
<SearchBar />
|
||||
<SearchBar v-if="!showHorizontalThemeNav" />
|
||||
<!-- 👉 Spacer -->
|
||||
<VSpacer />
|
||||
<!-- 👉 Shortcuts -->
|
||||
<ShortcutBar v-if="superUser" ref="shortcutBarRef" />
|
||||
<!-- 👉 Notification -->
|
||||
<UserNofification />
|
||||
<!-- 👉 UserProfile -->
|
||||
<UserProfile />
|
||||
<div
|
||||
class="theme-navbar-actions d-flex align-center"
|
||||
:class="{ 'theme-navbar-actions--horizontal': showHorizontalThemeNav }"
|
||||
>
|
||||
<!-- 👉 Horizontal Search Icon -->
|
||||
<SearchBar v-if="showHorizontalThemeNav" icon-only />
|
||||
<!-- 👉 Shortcuts -->
|
||||
<ShortcutBar v-if="superUser" ref="shortcutBarRef" />
|
||||
<!-- 👉 Notification -->
|
||||
<UserNofification />
|
||||
<!-- 👉 UserProfile -->
|
||||
<UserProfile />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showHorizontalThemeNav" class="theme-horizontal-nav">
|
||||
<VMenu
|
||||
@@ -479,6 +572,9 @@ onMounted(async () => {
|
||||
v-if="hasHorizontalDynamicTabs(item)"
|
||||
location="end top"
|
||||
offset="8"
|
||||
open-on-hover
|
||||
:open-delay="0"
|
||||
:close-delay="120"
|
||||
:close-on-content-click="true"
|
||||
>
|
||||
<template #activator="{ props: subMenuProps }">
|
||||
@@ -495,13 +591,13 @@ onMounted(async () => {
|
||||
|
||||
<VList class="theme-horizontal-nav__submenu" min-width="12rem" density="comfortable">
|
||||
<VListItem
|
||||
v-for="tab in dynamicHeaderTab!.items"
|
||||
v-for="tab in getHorizontalNavTabs(item)"
|
||||
:key="`${item.to}-${tab.tab}`"
|
||||
:active="isHorizontalDynamicTabActive(tab)"
|
||||
@click="handleHorizontalDynamicTabSelect(tab)"
|
||||
@click="handleHorizontalDynamicTabSelect(item, tab)"
|
||||
>
|
||||
<template v-if="tab.icon" #prepend>
|
||||
<VIcon :icon="tab.icon" />
|
||||
<template #prepend>
|
||||
<VIcon :icon="getHorizontalTabIcon(tab)" />
|
||||
</template>
|
||||
<VListItemTitle>{{ tab.title }}</VListItemTitle>
|
||||
</VListItem>
|
||||
@@ -677,6 +773,35 @@ onMounted(async () => {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.theme-navbar-actions--horizontal {
|
||||
gap: 0.85rem;
|
||||
|
||||
:deep(.ms-2),
|
||||
:deep(.ms-3) {
|
||||
margin-inline-start: 0 !important;
|
||||
}
|
||||
|
||||
:deep(.v-btn.v-btn--icon) {
|
||||
flex: 0 0 auto;
|
||||
border-radius: 12px;
|
||||
block-size: 2.75rem;
|
||||
color: rgba(var(--v-theme-on-surface), 0.78);
|
||||
inline-size: 2.75rem;
|
||||
}
|
||||
|
||||
:deep(.v-btn.v-btn--icon .v-icon) {
|
||||
font-size: 1.75rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
:deep(.v-avatar.cursor-pointer) {
|
||||
flex: 0 0 auto;
|
||||
block-size: 2.75rem !important;
|
||||
inline-size: 2.75rem !important;
|
||||
margin-inline-start: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-horizontal-nav {
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
|
||||
@@ -5,6 +5,15 @@ import { openSharedDialog } from '@/composables/useSharedDialog'
|
||||
import { useDisplay } from 'vuetify'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
iconOnly?: boolean
|
||||
}>(),
|
||||
{
|
||||
iconOnly: false,
|
||||
},
|
||||
)
|
||||
|
||||
const display = useDisplay()
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -23,17 +32,18 @@ function isMac() {
|
||||
}
|
||||
// 计算属性:根据操作系统显示不同的按键提示
|
||||
const metaKey = computed(() => (isMac() ? '⌘+K' : 'Ctrl+K'))
|
||||
const showIconOnly = computed(() => props.iconOnly || !display.mdAndUp.value)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 小屏:仅图标按钮 -->
|
||||
<IconBtn v-if="!display.mdAndUp.value" @click="openSearchDialog">
|
||||
<VIcon icon="mdi-magnify" />
|
||||
<!-- 小屏或水平导航右侧工具区:仅显示搜索图标。 -->
|
||||
<IconBtn v-if="showIconOnly" class="search-icon-trigger" @click="openSearchDialog">
|
||||
<VIcon class="search-icon-trigger__icon" icon="mdi-magnify" />
|
||||
</IconBtn>
|
||||
|
||||
<!-- 中屏及以上:胶囊搜索触发栏 -->
|
||||
<div v-else class="search-trigger" @click="openSearchDialog">
|
||||
<VIcon icon="mdi-magnify" size="18" class="search-trigger-icon" />
|
||||
<VIcon icon="mdi-magnify" size="30" class="search-trigger-icon" />
|
||||
<span class="search-trigger-text">{{ t('common.search') }}</span>
|
||||
<kbd class="search-trigger-kbd">{{ metaKey }}</kbd>
|
||||
</div>
|
||||
@@ -43,12 +53,14 @@ const metaKey = computed(() => (isMac() ? '⌘+K' : 'Ctrl+K'))
|
||||
.search-trigger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1.5px solid rgba(var(--v-theme-primary), 0.6);
|
||||
border-radius: 22px;
|
||||
block-size: 36px;
|
||||
border: 1px solid rgba(var(--v-theme-on-surface), 0.1);
|
||||
border-radius: 999px;
|
||||
background: rgba(var(--v-theme-surface), 0.44);
|
||||
block-size: 44px;
|
||||
cursor: pointer;
|
||||
gap: 8px;
|
||||
padding-inline: 12px;
|
||||
gap: 12px;
|
||||
min-inline-size: 168px;
|
||||
padding-inline: 18px 10px;
|
||||
transition:
|
||||
border-color 0.2s ease,
|
||||
background-color 0.2s ease,
|
||||
@@ -57,34 +69,49 @@ const metaKey = computed(() => (isMac() ? '⌘+K' : 'Ctrl+K'))
|
||||
}
|
||||
|
||||
.search-trigger:hover {
|
||||
border-color: rgb(var(--v-theme-primary));
|
||||
background-color: rgba(var(--v-theme-on-surface), 0.06);
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 4%);
|
||||
border-color: rgba(var(--v-theme-on-surface), 0.18);
|
||||
background-color: rgba(var(--v-theme-surface), 0.62);
|
||||
box-shadow: 0 4px 14px rgba(0, 0, 0, 6%);
|
||||
}
|
||||
|
||||
.search-trigger-icon {
|
||||
flex-shrink: 0;
|
||||
color: rgba(var(--v-theme-on-surface), 0.4);
|
||||
color: rgba(var(--v-theme-on-surface), 0.72);
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.search-trigger-text {
|
||||
color: rgba(var(--v-theme-on-surface), 0.4);
|
||||
font-size: 13.5px;
|
||||
color: rgba(var(--v-theme-on-surface), 0.42);
|
||||
font-size: 1rem;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.search-trigger-kbd {
|
||||
border: 1px solid rgba(var(--v-theme-on-surface), 0.12);
|
||||
border-radius: 5px;
|
||||
background-color: rgba(var(--v-theme-on-surface), 0.04);
|
||||
color: rgba(var(--v-theme-on-surface), 0.4);
|
||||
border-radius: 8px;
|
||||
background-color: rgba(var(--v-theme-surface), 0.5);
|
||||
color: rgba(var(--v-theme-on-surface), 0.42);
|
||||
font-family: inherit;
|
||||
font-size: 11px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
margin-inline-start: 4px;
|
||||
padding-block: 3px;
|
||||
padding-inline: 5px;
|
||||
padding-block: 6px;
|
||||
padding-inline: 8px;
|
||||
}
|
||||
|
||||
html[data-theme='transparent'] .search-trigger,
|
||||
.v-theme--transparent .search-trigger {
|
||||
backdrop-filter: none;
|
||||
background: rgba(var(--v-theme-surface), var(--transparent-opacity-light, 0.2));
|
||||
}
|
||||
|
||||
.search-icon-trigger {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.search-icon-trigger__icon {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user