This commit is contained in:
pa
2026-01-16 23:43:12 +09:00
committed by Natsumi
parent d55ee08a05
commit 043765dc8f
29 changed files with 721 additions and 315 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
<template>
<div @click="confirm" class="cursor-pointer w-fit align-top">
<span v-if="avatarType" :class="color" class="mr-2">
<div @click="confirm" class="cursor-pointer w-fit align-top flex items-center">
<span v-if="avatarType" :class="color" class="mr-1.5">
<Lock v-if="avatarType === '(own)'" class="h-4 w-4" />
<Unlock v-else-if="avatarType === '(public)'" class="h-4 w-4" />
</span>
+65 -91
View File
@@ -128,7 +128,7 @@
<span v-show="!isCollapsed">{{ t('nav_tooltip.manage') }}</span>
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent side="right" align="start" class="w-64">
<DropdownMenuContent side="right" align="start" class="w-54">
<div class="flex items-center gap-2 px-2 py-1.5">
<img class="h-6 w-6 cursor-pointer" :src="vrcxLogo" alt="VRCX" @click="openGithub" />
<div class="flex min-w-0 flex-col">
@@ -145,23 +145,20 @@
<DropdownMenuItem @click="handleSettingsClick">
<span>{{ t('nav_tooltip.settings') }}</span>
</DropdownMenuItem>
<DropdownMenuItem @click="handleOpenCustomNavDialog">
<span>{{ t('nav_menu.custom_nav.header') }}</span>
</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<span>{{ t('view.settings.appearance.appearance.theme_mode') }}</span>
</DropdownMenuSubTrigger>
<DropdownMenuSubContent side="right" align="start" class="w-72">
<DropdownMenuItem
<DropdownMenuSubContent side="right" align="start" class="w-54">
<DropdownMenuCheckboxItem
v-for="theme in themes"
:key="theme"
:class="themeMode === theme ? 'font-medium' : undefined"
@click="handleThemeSelect(theme)">
<span class="flex-1">{{ themeDisplayName(theme) }}</span>
<span v-if="themeMode === theme" class="text-muted-foreground">✓</span>
</DropdownMenuItem>
:model-value="themeMode === theme"
indicator-position="right"
@select="handleThemeSelect(theme)">
<span>{{ themeDisplayName(theme) }}</span>
</DropdownMenuCheckboxItem>
<DropdownMenuSeparator />
<DropdownMenuSub>
@@ -171,27 +168,36 @@
<DropdownMenuSubContent
side="right"
align="start"
class="w-72 max-h-80 overflow-auto">
<DropdownMenuItem
v-for="color in colorFamilies"
:key="color.name"
:disabled="isApplyingPrimaryColor"
@click="handleThemeColorSelect(color)">
class="w-54 max-h-80 overflow-auto">
<DropdownMenuCheckboxItem
v-for="theme in themeColors"
:key="theme.key"
:model-value="currentThemeColor === theme.key"
:disabled="isApplyingThemeColor"
indicator-position="right"
@select="handleThemeColorSelect(theme)">
<span class="flex items-center gap-2 min-w-0 flex-1">
<span
class="h-3 w-3 shrink-0 rounded-sm"
:style="{ backgroundColor: color.base }" />
<span class="truncate">{{ color.name }}</span>
:style="{ backgroundColor: theme.swatch }" />
<span class="truncate">{{ theme.label }}</span>
</span>
<span v-if="currentPrimary === color.base" class="text-muted-foreground"
>✓</span
>
</DropdownMenuItem>
</DropdownMenuCheckboxItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
</DropdownMenuSubContent>
</DropdownMenuSub>
<DropdownMenuCheckboxItem
:model-value="compactTableMode"
indicator-position="right"
@update:modelValue="handleCompactModeToggle">
<span>{{ t('view.settings.appearance.appearance.compact_table_mode') }}</span>
</DropdownMenuCheckboxItem>
<DropdownMenuItem @click="handleOpenCustomNavDialog">
<span>{{ t('nav_menu.custom_nav.header') }}</span>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive" @click="handleLogoutClick">
<span>{{ t('dialog.user.actions.logout') }}</span>
@@ -200,6 +206,15 @@
</DropdownMenu>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton :tooltip="t('nav_tooltip.toggle_theme')" @click="handleThemeToggle">
<i
:class="currentThemeIsDark ? 'ri-moon-line' : 'ri-sun-line'"
class="inline-flex size-6 items-center justify-center text-[19px]" />
<span v-show="!isCollapsed">{{ t('nav_tooltip.toggle_theme') }}</span>
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
:tooltip="isCollapsed ? t('nav_tooltip.expand_menu') : t('nav_tooltip.collapse_menu')"
@@ -238,6 +253,7 @@
} from '@/components/ui/sidebar';
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
@@ -253,6 +269,7 @@
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import { useThemeColor } from '@/shared/utils/base/ui';
import dayjs from 'dayjs';
@@ -307,15 +324,19 @@
const DEFAULT_FOLDER_ICON = 'ri-menu-fold-line';
const VRCXUpdaterStore = useVRCXUpdaterStore();
const { pendingVRCXUpdate, pendingVRCXInstall, updateInProgress, updateProgress, branch, appVersion } =
storeToRefs(VRCXUpdaterStore);
const { showVRCXUpdateDialog, updateProgressText, showChangeLogDialog } = VRCXUpdaterStore;
const { pendingVRCXUpdate, pendingVRCXInstall, appVersion } = storeToRefs(VRCXUpdaterStore);
const { showVRCXUpdateDialog, showChangeLogDialog } = VRCXUpdaterStore;
const uiStore = useUiStore();
const { notifiedMenus } = storeToRefs(uiStore);
const { directAccessPaste } = useSearchStore();
const { logout } = useAuthStore();
const appearanceSettingsStore = useAppearanceSettingsStore();
const { themeMode, isNavCollapsed: isCollapsed } = storeToRefs(appearanceSettingsStore);
const {
themeMode,
compactTableMode,
isDarkMode,
isNavCollapsed: isCollapsed
} = storeToRefs(appearanceSettingsStore);
const navLayout = ref([]);
const navLayoutReady = ref(false);
@@ -394,15 +415,8 @@
const vrcxLogo = new URL('../../images/VRCX.png', import.meta.url).href;
const themes = computed(() => Object.keys(THEME_CONFIG));
// const {
// currentPrimary,
// isApplying: isApplyingPrimaryColor,
// applyCustomPrimaryColor,
// initPrimaryColor,
// colorFamilies,
// selectPaletteColor
// } = useThemePrimaryColor();
const { themeColors, currentThemeColor, isApplyingThemeColor, applyThemeColor, initThemeColor } = useThemeColor();
const currentThemeIsDark = computed(() => isDarkMode.value);
watch(
() => locale.value,
@@ -502,9 +516,20 @@
appearanceSettingsStore.setThemeMode(theme);
};
// const handleThemeColorSelect = async (colorFamily) => {
// await selectPaletteColor(colorFamily);
// };
const handleThemeToggle = () => {
appearanceSettingsStore.setThemeMode(isDarkMode.value ? 'light' : 'dark');
};
const handleCompactModeToggle = () => {
appearanceSettingsStore.setCompactTableMode();
};
const handleThemeColorSelect = async (theme) => {
if (!theme) {
return;
}
await applyThemeColor(theme.key);
};
const openGithub = () => {
openExternalLink('https://github.com/vrcx-team/VRCX');
@@ -687,63 +712,12 @@
};
onMounted(async () => {
// await initPrimaryColor();
await initThemeColor();
await loadNavMenuConfig();
});
</script>
<style scoped>
.nav-menu-container {
position: relative;
width: 100%;
min-width: 64px;
height: 100%;
display: flex;
.nav-menu-theme__label--swatch {
display: inline-flex;
align-items: center;
gap: 8px;
min-width: 0;
}
.nav-menu-theme__label-text {
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-transform: capitalize;
}
.nav-menu-theme__swatch {
inline-size: 14px;
block-size: 14px;
border-radius: 4px;
flex: none;
}
.nav-menu-theme__custom {
display: flex;
align-items: center;
justify-content: space-between;
padding: 6px 10px;
border-radius: 6px;
}
.nav-menu-theme__custom-label {
font-size: 13px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding-right: 10px;
}
}
.nav-menu-theme--colors {
max-height: 360px;
overflow: hidden auto;
}
.notify::after {
position: absolute;
top: 45%;
@@ -271,6 +271,7 @@
const meta = columnDef?.meta ?? {};
const pinned = getPinnedState(cell?.column);
return joinClasses(
'py-1.5',
pinned && 'sticky bg-background z-20',
isSpacer(cell.column) && 'p-0',
resolveClassValue(meta.class, cell?.getContext?.()),
+1 -1
View File
@@ -19,7 +19,7 @@
v-bind="delegatedProps"
:class="
cn(
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80',
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/40 backdrop-blur-xs',
props.class
)
">
@@ -10,11 +10,12 @@
textValue: { type: String, required: false },
asChild: { type: Boolean, required: false },
as: { type: null, required: false },
class: { type: null, required: false }
class: { type: null, required: false },
indicatorPosition: { type: String, required: false, default: 'left' }
});
const emits = defineEmits(['select', 'update:modelValue']);
const delegatedProps = reactiveOmit(props, 'class');
const delegatedProps = reactiveOmit(props, 'class', 'indicatorPosition');
const forwarded = useForwardPropsEmits(delegatedProps, emits);
</script>
@@ -26,10 +27,16 @@
:class="
cn(
'focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4',
props.indicatorPosition === 'right' ? 'pr-8 pl-2' : undefined,
props.class
)
">
<span class="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
<span
:class="
props.indicatorPosition === 'right'
? 'pointer-events-none absolute right-2 flex size-3.5 items-center justify-center'
: 'pointer-events-none absolute left-2 flex size-3.5 items-center justify-center'
">
<DropdownMenuItemIndicator>
<slot name="indicator-icon">
<Check class="size-4" />
+1 -1
View File
@@ -11,7 +11,7 @@
data-slot="table-cell"
:class="
cn(
'p-2 align-middle whitespace-nowrap in-[.is-compact-table]:py-1! in-[.is-compact-table]:px-2.5! [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-0.5',
'p-2 align-middle whitespace-nowrap in-[.is-compact-table]:py-1! [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-0.5',
props.class
)
">