feat: refine theme customizer and horizontal navigation

This commit is contained in:
jxxghp
2026-06-02 17:56:41 +08:00
parent d02ece234c
commit b639737bd6
4 changed files with 283 additions and 45 deletions
+75 -4
View File
@@ -117,6 +117,7 @@ export default defineComponent({
// 👉 根据路由 meta 决定 footer 高度 // 👉 根据路由 meta 决定 footer 高度
const shouldShowFooter = !route.meta.hideFooter const shouldShowFooter = !route.meta.hideFooter
const isNavbarScrolled = scrollDistance.value > 5 || (isDialogOpen.value && wasScrolledBeforeDialog.value)
// 👉 Footer // 👉 Footer
const footer = h('footer', { class: 'layout-footer' }, [ const footer = h('footer', { class: 'layout-footer' }, [
@@ -146,8 +147,9 @@ export default defineComponent({
mdAndDown.value && 'layout-overlay-nav', mdAndDown.value && 'layout-overlay-nav',
isCollapsedLayout.value && 'layout-vertical-nav-collapsed', isCollapsedLayout.value && 'layout-vertical-nav-collapsed',
isHorizontalLayout.value && 'layout-horizontal-nav-active', isHorizontalLayout.value && 'layout-horizontal-nav-active',
isHorizontalLayout.value && isNavbarScrolled && 'layout-horizontal-nav-scrolled',
route.meta.layoutWrapperClasses, 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], [verticalNav, h('div', { class: 'layout-content-wrapper' }, [navbar, main, footer]), layoutOverlay],
@@ -340,11 +342,80 @@ export default defineComponent({
} }
@at-root { @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, html[data-theme='transparent'] .layout-wrapper.layout-horizontal-nav-active .layout-navbar,
.v-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)); backdrop-filter: none !important;
background-color: rgba(var(--v-theme-surface), var(--transparent-opacity-light, 0.2)); background: transparent !important;
border-block-end-color: rgba(var(--v-theme-on-surface), 0.06); 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'] html[data-theme='light'][data-theme-semi-dark-menu='true'][data-theme-layout='vertical']
+16 -1
View File
@@ -240,24 +240,39 @@ function handleLayoutChange(layout: ThemeCustomizerLayout) {
<style lang="scss"> <style lang="scss">
.theme-customizer-drawer { .theme-customizer-drawer {
position: fixed !important;
z-index: 12000 !important; z-index: 12000 !important;
border-inline-start: 1px solid rgba(var(--v-theme-on-surface), 0.08) !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; 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 { .v-navigation-drawer__content {
display: flex; display: flex;
overflow: hidden; overflow: hidden;
flex-direction: column; flex-direction: column;
block-size: 100%;
} }
} }
.theme-customizer-drawer .v-theme--transparent, .theme-customizer-drawer.v-theme--transparent,
.v-theme--transparent .theme-customizer-drawer, .v-theme--transparent .theme-customizer-drawer,
html[data-theme='transparent'] .theme-customizer-drawer { html[data-theme='transparent'] .theme-customizer-drawer {
backdrop-filter: blur(var(--transparent-blur-heavy, 16px)); backdrop-filter: blur(var(--transparent-blur-heavy, 16px));
background-color: rgba(var(--v-theme-surface), var(--transparent-opacity-heavy, 0.5)) !important; 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-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-color-option .theme-customizer-native-icon,
:is(html[data-theme='transparent'], .v-theme--transparent) .theme-customizer-header-icon { :is(html[data-theme='transparent'], .v-theme--transparent) .theme-customizer-header-icon {
+144 -19
View File
@@ -10,12 +10,20 @@ import UserProfile from '@/layouts/components/UserProfile.vue'
import QuickAccess from '@/layouts/components/QuickAccess.vue' import QuickAccess from '@/layouts/components/QuickAccess.vue'
import HeaderTab from '@/layouts/components/HeaderTab.vue' import HeaderTab from '@/layouts/components/HeaderTab.vue'
import { usePluginSidebarNavStore, useUserStore } from '@/stores' 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 { filterPluginSidebarNavEntries } from '@/utils/pluginSidebarNav'
import { NavMenu } from '@/@layouts/types' import { NavMenu } from '@/@layouts/types'
import { useDisplay } from 'vuetify' import { useDisplay } from 'vuetify'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useRoute } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { filterMenusByPermission } from '@/utils/permission' import { filterMenusByPermission } from '@/utils/permission'
import { onUnreadMessage } from '@/utils/badge' import { onUnreadMessage } from '@/utils/badge'
import { usePullDownGesture } from '@/composables/usePullDownGesture' import { usePullDownGesture } from '@/composables/usePullDownGesture'
@@ -34,6 +42,7 @@ const display = useDisplay()
const { appMode } = usePWA() const { appMode } = usePWA()
const { t } = useI18n() const { t } = useI18n()
const route = useRoute() const route = useRoute()
const router = useRouter()
const themeLayout = ref(readThemeCustomizerSettings().layout) const themeLayout = ref(readThemeCustomizerSettings().layout)
// 用户 Store // 用户 Store
@@ -133,6 +142,7 @@ interface DynamicHeaderTab {
// 提供动态标签页注册和获取的方法 // 提供动态标签页注册和获取的方法
const dynamicHeaderTab = ref<DynamicHeaderTab | null>(null) const dynamicHeaderTab = ref<DynamicHeaderTab | null>(null)
const openHorizontalNavGroup = ref<string | null>(null) const openHorizontalNavGroup = ref<string | null>(null)
const pendingHorizontalTab = ref<{ path: string; tab: string } | null>(null)
// 提供一个方法让其他组件注册动态标签页 // 提供一个方法让其他组件注册动态标签页
const registerDynamicHeaderTab = (tab: DynamicHeaderTab) => { const registerDynamicHeaderTab = (tab: DynamicHeaderTab) => {
@@ -140,6 +150,7 @@ const registerDynamicHeaderTab = (tab: DynamicHeaderTab) => {
tab.routePath = route.path tab.routePath = route.path
// 强制更新,确保响应式系统能检测到变化 // 强制更新,确保响应式系统能检测到变化
dynamicHeaderTab.value = { ...tab } dynamicHeaderTab.value = { ...tab }
applyPendingHorizontalTab()
} }
// 提供一个方法让其他组件取消注册动态标签页 // 提供一个方法让其他组件取消注册动态标签页
@@ -199,6 +210,20 @@ const visibleHorizontalHeaderButtons = computed(() => {
return (dynamicHeaderTab.value?.appendButtons ?? []).filter(button => resolveMaybeRefValue(button.show, true) !== false) 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(() => { onUnmounted(() => {
dynamicHeaderTab.value = null dynamicHeaderTab.value = null
@@ -269,10 +294,10 @@ function handleThemeCustomizerChange(event: Event) {
} }
function isHorizontalNavActive(item: NavMenu) { 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 = normalizeMenuPath(route.path)
const currentPath = route.path.replace(/\/$/, '')
return currentPath === targetPath || currentPath.startsWith(`${targetPath}/`) return currentPath === targetPath || currentPath.startsWith(`${targetPath}/`)
} }
@@ -282,15 +307,25 @@ function isHorizontalNavGroupActive(group: { items: NavMenu[] }) {
} }
function hasHorizontalDynamicTabs(item: NavMenu) { function hasHorizontalDynamicTabs(item: NavMenu) {
return showHorizontalThemeNav.value && hasDynamicHeaderTab.value && isHorizontalNavActive(item) return showHorizontalThemeNav.value && getHorizontalNavTabs(item).length > 0
} }
function isHorizontalDynamicTabActive(tab: DynamicHeaderTabItem) { function isHorizontalDynamicTabActive(tab: DynamicHeaderTabItem) {
return dynamicHeaderTab.value?.modelValue === tab.tab return dynamicHeaderTab.value?.modelValue === tab.tab
} }
function handleHorizontalDynamicTabSelect(tab: DynamicHeaderTabItem) { async function handleHorizontalDynamicTabSelect(item: NavMenu, tab: DynamicHeaderTabItem) {
handleTabChange(tab.tab) 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 openHorizontalNavGroup.value = null
} }
@@ -310,6 +345,57 @@ function resolveHeaderButtonLoading(button: DynamicHeaderTabButton) {
return resolveMaybeRefValue(button.loading, false) 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) { function handleUnreadMessage(count: number) {
if (superUser.value && count > 0) { if (superUser.value && count > 0) {
@@ -439,15 +525,22 @@ onMounted(async () => {
<VIcon icon="mdi-arrow-left" size="32" /> <VIcon icon="mdi-arrow-left" size="32" />
</IconBtn> </IconBtn>
<!-- 👉 Search Bar --> <!-- 👉 Search Bar -->
<SearchBar /> <SearchBar v-if="!showHorizontalThemeNav" />
<!-- 👉 Spacer --> <!-- 👉 Spacer -->
<VSpacer /> <VSpacer />
<!-- 👉 Shortcuts --> <div
<ShortcutBar v-if="superUser" ref="shortcutBarRef" /> class="theme-navbar-actions d-flex align-center"
<!-- 👉 Notification --> :class="{ 'theme-navbar-actions--horizontal': showHorizontalThemeNav }"
<UserNofification /> >
<!-- 👉 UserProfile --> <!-- 👉 Horizontal Search Icon -->
<UserProfile /> <SearchBar v-if="showHorizontalThemeNav" icon-only />
<!-- 👉 Shortcuts -->
<ShortcutBar v-if="superUser" ref="shortcutBarRef" />
<!-- 👉 Notification -->
<UserNofification />
<!-- 👉 UserProfile -->
<UserProfile />
</div>
</div> </div>
<div v-if="showHorizontalThemeNav" class="theme-horizontal-nav"> <div v-if="showHorizontalThemeNav" class="theme-horizontal-nav">
<VMenu <VMenu
@@ -479,6 +572,9 @@ onMounted(async () => {
v-if="hasHorizontalDynamicTabs(item)" v-if="hasHorizontalDynamicTabs(item)"
location="end top" location="end top"
offset="8" offset="8"
open-on-hover
:open-delay="0"
:close-delay="120"
:close-on-content-click="true" :close-on-content-click="true"
> >
<template #activator="{ props: subMenuProps }"> <template #activator="{ props: subMenuProps }">
@@ -495,13 +591,13 @@ onMounted(async () => {
<VList class="theme-horizontal-nav__submenu" min-width="12rem" density="comfortable"> <VList class="theme-horizontal-nav__submenu" min-width="12rem" density="comfortable">
<VListItem <VListItem
v-for="tab in dynamicHeaderTab!.items" v-for="tab in getHorizontalNavTabs(item)"
:key="`${item.to}-${tab.tab}`" :key="`${item.to}-${tab.tab}`"
:active="isHorizontalDynamicTabActive(tab)" :active="isHorizontalDynamicTabActive(tab)"
@click="handleHorizontalDynamicTabSelect(tab)" @click="handleHorizontalDynamicTabSelect(item, tab)"
> >
<template v-if="tab.icon" #prepend> <template #prepend>
<VIcon :icon="tab.icon" /> <VIcon :icon="getHorizontalTabIcon(tab)" />
</template> </template>
<VListItemTitle>{{ tab.title }}</VListItemTitle> <VListItemTitle>{{ tab.title }}</VListItemTitle>
</VListItem> </VListItem>
@@ -677,6 +773,35 @@ onMounted(async () => {
white-space: nowrap; 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 { .theme-horizontal-nav {
display: flex; display: flex;
overflow-x: auto; overflow-x: auto;
+48 -21
View File
@@ -5,6 +5,15 @@ import { openSharedDialog } from '@/composables/useSharedDialog'
import { useDisplay } from 'vuetify' import { useDisplay } from 'vuetify'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
const props = withDefaults(
defineProps<{
iconOnly?: boolean
}>(),
{
iconOnly: false,
},
)
const display = useDisplay() const display = useDisplay()
const { t } = useI18n() const { t } = useI18n()
@@ -23,17 +32,18 @@ function isMac() {
} }
// 计算属性:根据操作系统显示不同的按键提示 // 计算属性:根据操作系统显示不同的按键提示
const metaKey = computed(() => (isMac() ? '⌘+K' : 'Ctrl+K')) const metaKey = computed(() => (isMac() ? '⌘+K' : 'Ctrl+K'))
const showIconOnly = computed(() => props.iconOnly || !display.mdAndUp.value)
</script> </script>
<template> <template>
<!-- 小屏仅图标按钮 --> <!-- 小屏或水平导航右侧工具区仅显示搜索图标 -->
<IconBtn v-if="!display.mdAndUp.value" @click="openSearchDialog"> <IconBtn v-if="showIconOnly" class="search-icon-trigger" @click="openSearchDialog">
<VIcon icon="mdi-magnify" /> <VIcon class="search-icon-trigger__icon" icon="mdi-magnify" />
</IconBtn> </IconBtn>
<!-- 中屏及以上胶囊搜索触发栏 --> <!-- 中屏及以上胶囊搜索触发栏 -->
<div v-else class="search-trigger" @click="openSearchDialog"> <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> <span class="search-trigger-text">{{ t('common.search') }}</span>
<kbd class="search-trigger-kbd">{{ metaKey }}</kbd> <kbd class="search-trigger-kbd">{{ metaKey }}</kbd>
</div> </div>
@@ -43,12 +53,14 @@ const metaKey = computed(() => (isMac() ? '⌘+K' : 'Ctrl+K'))
.search-trigger { .search-trigger {
display: flex; display: flex;
align-items: center; align-items: center;
border: 1.5px solid rgba(var(--v-theme-primary), 0.6); border: 1px solid rgba(var(--v-theme-on-surface), 0.1);
border-radius: 22px; border-radius: 999px;
block-size: 36px; background: rgba(var(--v-theme-surface), 0.44);
block-size: 44px;
cursor: pointer; cursor: pointer;
gap: 8px; gap: 12px;
padding-inline: 12px; min-inline-size: 168px;
padding-inline: 18px 10px;
transition: transition:
border-color 0.2s ease, border-color 0.2s ease,
background-color 0.2s ease, background-color 0.2s ease,
@@ -57,34 +69,49 @@ const metaKey = computed(() => (isMac() ? '⌘+K' : 'Ctrl+K'))
} }
.search-trigger:hover { .search-trigger:hover {
border-color: rgb(var(--v-theme-primary)); border-color: rgba(var(--v-theme-on-surface), 0.18);
background-color: rgba(var(--v-theme-on-surface), 0.06); background-color: rgba(var(--v-theme-surface), 0.62);
box-shadow: 0 1px 4px rgba(0, 0, 0, 4%); box-shadow: 0 4px 14px rgba(0, 0, 0, 6%);
} }
.search-trigger-icon { .search-trigger-icon {
flex-shrink: 0; 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 { .search-trigger-text {
color: rgba(var(--v-theme-on-surface), 0.4); color: rgba(var(--v-theme-on-surface), 0.42);
font-size: 13.5px; font-size: 1rem;
line-height: 1; line-height: 1;
white-space: nowrap; white-space: nowrap;
} }
.search-trigger-kbd { .search-trigger-kbd {
border: 1px solid rgba(var(--v-theme-on-surface), 0.12); border: 1px solid rgba(var(--v-theme-on-surface), 0.12);
border-radius: 5px; border-radius: 8px;
background-color: rgba(var(--v-theme-on-surface), 0.04); background-color: rgba(var(--v-theme-surface), 0.5);
color: rgba(var(--v-theme-on-surface), 0.4); color: rgba(var(--v-theme-on-surface), 0.42);
font-family: inherit; font-family: inherit;
font-size: 11px; font-size: 0.875rem;
font-weight: 500; font-weight: 500;
line-height: 1; line-height: 1;
margin-inline-start: 4px; margin-inline-start: 4px;
padding-block: 3px; padding-block: 6px;
padding-inline: 5px; 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> </style>