fix resizeable

This commit is contained in:
pa
2026-01-07 22:44:59 +09:00
committed by Natsumi
parent 69cdc584eb
commit 38a9325fac
7 changed files with 56 additions and 43 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
<span>{{ t('nav_menu.icon_picker.pick_icon') }}</span> <span>{{ t('nav_menu.icon_picker.pick_icon') }}</span>
</el-button> </el-button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent side="bottom" align="start" class="w-[620px]"> <PopoverContent side="bottom" align="start" class="w-155">
<div class="icon-picker"> <div class="icon-picker">
<el-input <el-input
v-model="search" v-model="search"
@@ -199,7 +199,7 @@
:class="{ 'x-user-badge-hidden': badge.hidden }" :class="{ 'x-user-badge-hidden': badge.hidden }"
loading="lazy" /> loading="lazy" />
</PopoverTrigger> </PopoverTrigger>
<PopoverContent side="bottom" class="w-[300px]"> <PopoverContent side="bottom" class="w-75">
<img <img
:src="badge.badgeImageUrl" :src="badge.badgeImageUrl"
:class="['x-link', 'x-popover-image']" :class="['x-link', 'x-popover-image']"
@@ -25,7 +25,7 @@
v-bind="forwarded" v-bind="forwarded"
:class=" :class="
cn( 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', '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.class props.class
) )
"> ">
+29 -30
View File
@@ -1,37 +1,36 @@
<script setup> <script setup>
import { reactiveOmit } from "@vueuse/core"; import { SelectIcon, SelectTrigger, useForwardProps } from 'reka-ui';
import { ChevronDown } from "lucide-vue-next"; import { ChevronDown } from 'lucide-vue-next';
import { SelectIcon, SelectTrigger, useForwardProps } from "reka-ui"; import { cn } from '@/lib/utils';
import { cn } from "@/lib/utils"; import { reactiveOmit } from '@vueuse/core';
const props = defineProps({ const props = defineProps({
disabled: { type: Boolean, required: false }, disabled: { type: Boolean, required: false },
reference: { type: null, required: false }, reference: { type: null, required: false },
asChild: { type: Boolean, required: false }, asChild: { type: Boolean, required: false },
as: { type: null, required: false }, as: { type: null, required: false },
class: { type: null, required: false }, class: { type: null, required: false },
size: { type: String, required: false, default: "default" }, size: { type: String, required: false, default: 'default' }
}); });
const delegatedProps = reactiveOmit(props, "class", "size"); const delegatedProps = reactiveOmit(props, 'class', 'size');
const forwardedProps = useForwardProps(delegatedProps); const forwardedProps = useForwardProps(delegatedProps);
</script> </script>
<template> <template>
<SelectTrigger <SelectTrigger
data-slot="select-trigger" data-slot="select-trigger"
:data-size="size" :data-size="size"
v-bind="forwardedProps" v-bind="forwardedProps"
:class=" :class="
cn( cn(
'border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*=\'text-\'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4', 'border-input data-placeholder:text-muted-foreground [&_svg:not([class*=\'text-\'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4',
props.class, props.class
) )
" ">
> <slot />
<slot /> <SelectIcon as-child>
<SelectIcon as-child> <ChevronDown class="size-4 opacity-50" />
<ChevronDown class="size-4 opacity-50" /> </SelectIcon>
</SelectIcon> </SelectTrigger>
</SelectTrigger>
</template> </template>
+1 -1
View File
@@ -34,7 +34,7 @@
data-slot="slider" data-slot="slider"
:class=" :class="
cn( cn(
'relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col', 'relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col',
props.class props.class
) )
" "
@@ -22,10 +22,10 @@ export function useAuthenticatedLayoutResizable() {
const panelGroupRef = ref(null); const panelGroupRef = ref(null);
const navPanelRef = ref(null); const navPanelRef = ref(null);
const asidePanelRef = ref(null);
const navExpandedSize = ref(null); const navExpandedSize = ref(null);
const groupWidth = ref(fallbackWidth); const groupWidth = ref(fallbackWidth);
let resizeObserver = null; let resizeObserver = null;
let windowResizeHandler = null;
const getGroupWidth = () => { const getGroupWidth = () => {
const element = panelGroupRef.value?.$el ?? panelGroupRef.value; const element = panelGroupRef.value?.$el ?? panelGroupRef.value;
@@ -111,11 +111,29 @@ export function useAuthenticatedLayoutResizable() {
const resizeNavPanel = (targetSize) => const resizeNavPanel = (targetSize) =>
navPanelRef.value?.resize?.(targetSize); navPanelRef.value?.resize?.(targetSize);
const resizeAsidePanel = (targetSize) =>
asidePanelRef.value?.resize?.(targetSize);
const updateGroupWidth = () => { const updateGroupWidth = () => {
groupWidth.value = getGroupWidth(); const width = getGroupWidth();
groupWidth.value = width;
if (isNavCollapsed.value) { if (isNavCollapsed.value) {
resizeNavPanel(navCollapsedSize.value); resizeNavPanel(navCollapsedSize.value);
} else {
const targetSize = pxToPercent(navExpandedPx.value, width);
navExpandedSize.value = targetSize;
resizeNavPanel(targetSize);
} }
if (!isSideBarTabShow.value) {
return;
}
const storedAsidePx = asideWidth.value;
const asideTargetSize =
storedAsidePx > 0 ? pxToPercent(storedAsidePx, width, 0) : 0;
resizeAsidePanel(asideTargetSize);
}; };
watch(isNavCollapsed, async (collapsed) => { watch(isNavCollapsed, async (collapsed) => {
@@ -144,9 +162,6 @@ export function useAuthenticatedLayoutResizable() {
if (element && typeof ResizeObserver !== 'undefined') { if (element && typeof ResizeObserver !== 'undefined') {
resizeObserver = new ResizeObserver(updateGroupWidth); resizeObserver = new ResizeObserver(updateGroupWidth);
resizeObserver.observe(element); resizeObserver.observe(element);
} else if (typeof window !== 'undefined') {
windowResizeHandler = updateGroupWidth;
window.addEventListener('resize', windowResizeHandler);
} }
}); });
@@ -155,15 +170,12 @@ export function useAuthenticatedLayoutResizable() {
resizeObserver.disconnect(); resizeObserver.disconnect();
resizeObserver = null; resizeObserver = null;
} }
if (windowResizeHandler && typeof window !== 'undefined') {
window.removeEventListener('resize', windowResizeHandler);
windowResizeHandler = null;
}
}); });
return { return {
panelGroupRef, panelGroupRef,
navPanelRef, navPanelRef,
asidePanelRef,
navDefaultSize, navDefaultSize,
navMinSize, navMinSize,
navMaxSize, navMaxSize,
+2
View File
@@ -26,6 +26,7 @@
'z-20 [&>div]:-translate-x-1/2' 'z-20 [&>div]:-translate-x-1/2'
]"></ResizableHandle> ]"></ResizableHandle>
<ResizablePanel <ResizablePanel
ref="asidePanelRef"
:default-size="asideDefaultSize" :default-size="asideDefaultSize"
:max-size="asideMaxSize" :max-size="asideMaxSize"
:collapsed-size="0" :collapsed-size="0"
@@ -110,6 +111,7 @@
const { const {
panelGroupRef, panelGroupRef,
navPanelRef, navPanelRef,
asidePanelRef,
navDefaultSize, navDefaultSize,
navMinSize, navMinSize,
navMaxSize, navMaxSize,