perf: reorganize the icons and reduce the volume

This commit is contained in:
vince
2024-07-17 22:25:27 +08:00
parent cb161eab89
commit 910a3553ac
54 changed files with 341 additions and 404 deletions

View File

@@ -4,12 +4,7 @@ import type { Preferences } from './types';
import { markRaw, reactive, readonly, watch } from 'vue';
import {
StorageManager,
generatorColorVariables,
merge,
updateCSSVariables,
} from '@vben-core/toolkit';
import { StorageManager, merge } from '@vben-core/toolkit';
import {
breakpointsTailwind,
@@ -18,7 +13,7 @@ import {
} from '@vueuse/core';
import { defaultPreferences } from './config';
import { BUILT_IN_THEME_PRESETS } from './constants';
import { updateCSSVariables } from './update-css-variables';
const STORAGE_KEY = 'preferences';
const STORAGE_KEY_LOCALE = `${STORAGE_KEY}-locale`;
@@ -48,11 +43,10 @@ class PreferenceManager {
});
constructor() {
this.cache = new StorageManager();
// this.flattenedState = reactive(flattenObject(this.state));
this.savePreferences = useDebounceFn(
(preference: Preferences) => this._savePreferences(preference),
100,
200,
);
}
@@ -76,7 +70,7 @@ class PreferenceManager {
const themeUpdates = updates.theme || {};
const appUpdates = updates.app || {};
if (themeUpdates && Object.keys(themeUpdates).length > 0) {
this.updateTheme(this.state);
updateCSSVariables(this.state);
}
if (
@@ -130,7 +124,7 @@ class PreferenceManager {
this.updatePreferences({
theme: { mode: isDark ? 'dark' : 'light' },
});
this.updateTheme(this.state);
updateCSSVariables(this.state);
});
}
@@ -153,101 +147,6 @@ class PreferenceManager {
}
}
/**
* 更新 CSS 变量
* @param preference - 当前偏好设置对象,它的颜色值将被转换成 HSL 格式并设置为 CSS 变量。
*/
private updateMainColors(preference: Preferences) {
if (!preference.theme) {
return;
}
const { colorDestructive, colorPrimary, colorSuccess, colorWarning } =
preference.theme;
const colorVariables = generatorColorVariables([
{ color: colorPrimary, name: 'primary' },
{ alias: 'warning', color: colorWarning, name: 'yellow' },
{ alias: 'success', color: colorSuccess, name: 'green' },
{ alias: 'destructive', color: colorDestructive, name: 'red' },
]);
if (colorPrimary) {
document.documentElement.style.setProperty(
'--primary',
colorVariables['--primary-500'],
);
}
if (colorVariables['--green-500']) {
colorVariables['--success'] = colorVariables['--green-500'];
}
if (colorVariables['--yellow-500']) {
colorVariables['--warning'] = colorVariables['--yellow-500'];
}
if (colorVariables['--red-500']) {
colorVariables['--destructive'] = colorVariables['--red-500'];
}
updateCSSVariables(colorVariables);
}
/**
* 更新主题
* @param preferences - 当前偏好设置对象,它的主题值将被用来设置文档的主题。
*/
private updateTheme(preferences: Preferences) {
// 当修改到颜色变量时,更新 css 变量
const root = document.documentElement;
if (!root) {
return;
}
const theme = preferences?.theme ?? {};
const { builtinType, colorPrimary, mode, radius } = theme;
if (Reflect.has(theme, 'mode')) {
const dark = isDarkTheme(mode);
root.classList.toggle('dark', dark);
}
if (Reflect.has(theme, 'builtinType')) {
const rootTheme = root.dataset.theme;
if (rootTheme !== builtinType) {
root.dataset.theme = builtinType;
}
}
const currentBuiltType = BUILT_IN_THEME_PRESETS.find(
(item) => item.type === builtinType,
);
let builtinTypeColorPrimary: string | undefined = '';
if (currentBuiltType) {
const isDark = isDarkTheme(this.state.theme.mode);
const color = isDark
? currentBuiltType.darkPrimaryColor || currentBuiltType.primaryColor
: currentBuiltType.primaryColor;
builtinTypeColorPrimary = color || currentBuiltType.color;
}
if (
builtinTypeColorPrimary ||
Reflect.has(theme, 'colorPrimary') ||
Reflect.has(theme, 'colorDestructive') ||
Reflect.has(theme, 'colorSuccess') ||
Reflect.has(theme, 'colorWarning')
) {
preferences.theme.colorPrimary = builtinTypeColorPrimary || colorPrimary;
this.updateMainColors(preferences);
}
if (Reflect.has(theme, 'radius')) {
document.documentElement.style.setProperty('--radius', `${radius}rem`);
}
}
clearCache() {
[STORAGE_KEY, STORAGE_KEY_LOCALE, STORAGE_KEY_THEME].forEach((key) => {
this.cache?.removeItem(key);

View File

@@ -0,0 +1,118 @@
import type { Preferences } from './types';
import {
updateCSSVariables as executeUpdateCSSVariables,
generatorColorVariables,
} from '@vben-core/toolkit';
import { BUILT_IN_THEME_PRESETS } from './constants';
/**
* 更新主题的 CSS 变量以及其他 CSS 变量
* @param preferences - 当前偏好设置对象,它的主题值将被用来设置文档的主题。
*/
function updateCSSVariables(preferences: Preferences) {
// 当修改到颜色变量时,更新 css 变量
const root = document.documentElement;
if (!root) {
return;
}
const theme = preferences?.theme ?? {};
const { builtinType, colorPrimary, mode, radius } = theme;
// html 设置 dark 类
if (Reflect.has(theme, 'mode')) {
const dark = isDarkTheme(mode);
root.classList.toggle('dark', dark);
}
// html 设置 data-theme=[builtinType]
if (Reflect.has(theme, 'builtinType')) {
const rootTheme = root.dataset.theme;
if (rootTheme !== builtinType) {
root.dataset.theme = builtinType;
}
}
// 获取当前的内置主题
const currentBuiltType = BUILT_IN_THEME_PRESETS.find(
(item) => item.type === builtinType,
);
let builtinTypeColorPrimary: string | undefined = '';
if (currentBuiltType) {
const isDark = isDarkTheme(preferences.theme.mode);
// 设置不同主题的主要颜色
const color = isDark
? currentBuiltType.darkPrimaryColor || currentBuiltType.primaryColor
: currentBuiltType.primaryColor;
builtinTypeColorPrimary = color || currentBuiltType.color;
}
// 如果内置主题颜色和自定义颜色都不存在,则不更新主题颜色
if (
builtinTypeColorPrimary ||
Reflect.has(theme, 'colorPrimary') ||
Reflect.has(theme, 'colorDestructive') ||
Reflect.has(theme, 'colorSuccess') ||
Reflect.has(theme, 'colorWarning')
) {
preferences.theme.colorPrimary = builtinTypeColorPrimary || colorPrimary;
updateMainColorVariables(preferences);
}
// 更新圆角
if (Reflect.has(theme, 'radius')) {
document.documentElement.style.setProperty('--radius', `${radius}rem`);
}
}
/**
* 更新主要的 CSS 变量
* @param preference - 当前偏好设置对象,它的颜色值将被转换成 HSL 格式并设置为 CSS 变量。
*/
function updateMainColorVariables(preference: Preferences) {
if (!preference.theme) {
return;
}
const { colorDestructive, colorPrimary, colorSuccess, colorWarning } =
preference.theme;
const colorVariables = generatorColorVariables([
{ color: colorPrimary, name: 'primary' },
{ alias: 'warning', color: colorWarning, name: 'yellow' },
{ alias: 'success', color: colorSuccess, name: 'green' },
{ alias: 'destructive', color: colorDestructive, name: 'red' },
]);
if (colorPrimary) {
document.documentElement.style.setProperty(
'--primary',
colorVariables['--primary-500'],
);
}
if (colorVariables['--green-500']) {
colorVariables['--success'] = colorVariables['--green-500'];
}
if (colorVariables['--yellow-500']) {
colorVariables['--warning'] = colorVariables['--yellow-500'];
}
if (colorVariables['--red-500']) {
colorVariables['--destructive'] = colorVariables['--red-500'];
}
executeUpdateCSSVariables(colorVariables);
}
function isDarkTheme(theme: string) {
let dark = theme === 'dark';
if (theme === 'auto') {
dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
}
return dark;
}
export { updateCSSVariables };

View File

@@ -27,6 +27,10 @@ function usePreferences() {
return isDarkTheme(preferences.theme.mode);
});
const isMobile = computed(() => {
return appPreferences.value.isMobile;
});
const theme = computed(() => {
return isDark.value ? 'dark' : 'light';
});
@@ -35,7 +39,7 @@ function usePreferences() {
* @zh_CN 布局方式
*/
const layout = computed(() =>
appPreferences.value.isMobile ? 'sidebar-nav' : appPreferences.value.layout,
isMobile.value ? 'sidebar-nav' : appPreferences.value.layout,
);
/**
@@ -109,6 +113,16 @@ function usePreferences() {
return appPreferences.value.authPageLayout === 'panel-center';
});
/**
* @zh_CN 内容是否已经最大化
* 排除 full-content模式
*/
const contentIsMaximize = computed(() => {
const headerIsHidden = preferences.header.hidden;
const sidebarIsHidden = preferences.sidebar.hidden;
return headerIsHidden && sidebarIsHidden && !isFullContent.value;
});
/**
* @zh_CN 是否启用全局搜索快捷键
*/
@@ -138,17 +152,6 @@ function usePreferences() {
return enable && globalPreferences;
});
/**
* @zh_CN 内容是否已经最大化
* 排除 full-content模式
*/
const contentIsMaximize = computed(() => {
const headerIsHidden = preferences.header.hidden;
const sidebarIsHidden = preferences.sidebar.hidden;
return headerIsHidden && sidebarIsHidden && !isFullContent.value;
});
return {
authPanelCenter,
authPanelLeft,
@@ -163,6 +166,7 @@ function usePreferences() {
isFullContent,
isHeaderNav,
isMixedNav,
isMobile,
isSideMixedNav,
isSideMode,
isSideNav,

View File

@@ -15,7 +15,7 @@
--card-foreground: 210 40% 98%;
/* Background color for popovers such as <DropdownMenu />, <HoverCard />, <Popover /> */
--popover: 222.82deg 8.43% 16.27%;
--popover: 222.82deg 8.43% 12.27%;
--popover-foreground: 210 40% 98%;
/* Muted backgrounds such as <TabsList />, <Skeleton /> and <Switch /> */

View File

@@ -36,6 +36,7 @@
},
"dependencies": {
"@iconify/vue": "^4.1.2",
"lucide-vue-next": "^0.408.0",
"vue": "^3.4.32"
}
}

View File

@@ -1,5 +1,5 @@
export * from './create-icon';
export * from './material';
export * from './mdi';
export * from './lucide';
export * from './mdi';
export * from '@iconify/vue';

View File

@@ -0,0 +1,46 @@
export {
ArrowDown,
ArrowLeft,
ArrowLeftToLine,
ArrowRightLeft,
ArrowRightToLine,
ArrowUp,
ArrowUpToLine,
Bell,
BookOpenText,
ChevronDown,
ChevronRight,
CircleHelp,
Copy,
CornerDownLeft,
Disc3 as IconDefault,
Ellipsis,
ExternalLink,
Eye,
EyeOff,
FoldHorizontal,
Fullscreen,
Github,
InspectionPanel,
Languages,
LoaderCircle,
LockKeyhole,
LogOut,
MailCheck,
Maximize,
Menu,
Minimize,
Minimize2,
MoonStar,
Palette,
PanelLeft,
PanelRight,
RotateCw,
Search,
SearchX,
Sun,
SunMoon,
SwatchBook,
UserRoundPen,
X,
} from 'lucide-vue-next';

View File

@@ -1,88 +0,0 @@
import { createIconifyIcon } from './create-icon';
export const IconDefault = createIconifyIcon('ic:round-auto-awesome');
export const IcRoundKeyboardArrowDown = createIconifyIcon(
'ic:round-keyboard-arrow-down',
);
export const IcRoundChevronRight = createIconifyIcon('ic:round-chevron-right');
export const IcRoundMenu = createIconifyIcon('ic:round-menu');
export const IcRoundMoreHoriz = createIconifyIcon('ic:round-more-horiz');
export const IcRoundFitScreen = createIconifyIcon('ic:round-fit-screen');
export const IcTwotoneFitScreen = createIconifyIcon('ic:twotone-fit-screen');
export const IcRoundColorLens = createIconifyIcon('ic:round-color-lens');
export const IcRoundMoreVert = createIconifyIcon('ic:round-more-vert');
export const IcRoundFullscreen = createIconifyIcon('ic:round-fullscreen');
export const IcRoundFullscreenExit = createIconifyIcon(
'ic:round-fullscreen-exit',
);
export const IcRoundClose = createIconifyIcon('ic:round-close');
export const IcRoundRestartAlt = createIconifyIcon('ic:round-restart-alt');
export const IcRoundLogout = createIconifyIcon('ic:round-logout');
export const IcOutlineVisibility = createIconifyIcon('ic:outline-visibility');
export const IcOutlineVisibilityOff = createIconifyIcon(
'ic:outline-visibility-off',
);
export const IcRoundSearch = createIconifyIcon('ic:round-search');
export const IcRoundFolderCopy = createIconifyIcon('ic:round-folder-copy');
export const IcRoundSubdirectoryArrowLeft = createIconifyIcon(
'ic:round-subdirectory-arrow-left',
);
export const IcRoundArrowUpward = createIconifyIcon('ic:round-arrow-upward');
export const IcRoundArrowDownward = createIconifyIcon(
'ic:round-arrow-downward',
);
export const IcBaselineLanguage = createIconifyIcon('ic:baseline-language');
export const IcRoundSearchOff = createIconifyIcon('ic:round-search-off');
export const IcRoundNotificationsNone = createIconifyIcon(
'ic:round-notifications-none',
);
export const IcRoundMarkEmailRead = createIconifyIcon(
'ic:round-mark-email-read',
);
export const IcRoundWbSunny = createIconifyIcon('ic:round-wb-sunny');
export const IcRoundMotionPhotosAuto = createIconifyIcon(
'ic:round-motion-photos-auto',
);
export const IcRoundSettingsSuggest = createIconifyIcon(
'ic:round-settings-suggest',
);
export const IcRoundArrowBackIosNew = createIconifyIcon(
'ic:round-arrow-back-ios-new',
);
export const IcRoundMultipleStop = createIconifyIcon('ic:round-multiple-stop');
export const IcRoundTableView = createIconifyIcon('ic:round-table-view');
export const IcRoundRefresh = createIconifyIcon('ic:round-refresh');
export const IcRoundCreditScore = createIconifyIcon('ic:round-credit-score');
export const IcRoundLock = createIconifyIcon('ic:round-lock');

View File

@@ -2,8 +2,6 @@ import { createIconifyIcon } from './create-icon';
export const MdiKeyboardEsc = createIconifyIcon('mdi:keyboard-esc');
export const MdiLoading = createIconifyIcon('mdi:loading');
export const MdiWechat = createIconifyIcon('mdi:wechat');
export const MdiGithub = createIconifyIcon('mdi:github');
@@ -16,34 +14,6 @@ export const MdiPin = createIconifyIcon('mdi:pin');
export const MdiPinOff = createIconifyIcon('mdi:pin-off');
export const MdiFormatHorizontalAlignLeft = createIconifyIcon(
'mdi:format-horizontal-align-left',
);
export const MdiFormatHorizontalAlignRight = createIconifyIcon(
'mdi:format-horizontal-align-right',
);
export const MdiArrowExpandHorizontal = createIconifyIcon(
'mdi:arrow-expand-horizontal',
);
export const MdiMenuClose = createIconifyIcon('mdi:menu-close');
export const MdiMenuOpen = createIconifyIcon('mdi:menu-open');
export const MdiDockLeft = createIconifyIcon('mdi:dock-left');
export const MdiDockRight = createIconifyIcon('mdi:dock-right');
export const MdiDockBottom = createIconifyIcon('mdi:dock-bottom');
export const MdiDriveDocument = createIconifyIcon('mdi:drive-document');
export const MdiMoonAndStars = createIconifyIcon('mdi:moon-and-stars');
export const MdiEditBoxOutline = createIconifyIcon('mdi:edit-box-outline');
export const MdiQuestionMarkCircleOutline = createIconifyIcon(
'mdi:question-mark-circle-outline',
);

View File

@@ -2,7 +2,7 @@
import type { CSSProperties } from 'vue';
import { computed, useSlots } from 'vue';
import { IcRoundMenu } from '@vben-core/icons';
import { Menu } from '@vben-core/icons';
import { VbenIconButton } from '@vben-core/shadcn-ui';
interface Props {
@@ -108,7 +108,7 @@ function handleToggleMenu() {
class="my-0 ml-2 mr-1 rounded"
@click="handleToggleMenu"
>
<IcRoundMenu class="size-5" />
<Menu class="size-4" />
</VbenIconButton>
<slot></slot>
</header>

View File

@@ -12,7 +12,7 @@ interface Props {
const props = withDefaults(defineProps<Props>(), {
fixed: true,
height: 30,
height: 38,
});
const style = computed((): CSSProperties => {

View File

@@ -13,7 +13,7 @@ function handleCollapsed() {
class="flex-center hover:text-foreground text-foreground/60 hover:bg-accent-hover bg-accent absolute bottom-2 left-3 z-10 cursor-pointer rounded-sm p-1 transition-all duration-300"
@click.stop="handleCollapsed"
>
<MdiMenuClose v-if="collapsed" />
<MdiMenuOpen v-else />
<MdiMenuClose v-if="collapsed" class="size-4" />
<MdiMenuOpen v-else class="size-4" />
</div>
</template>

View File

@@ -19,7 +19,7 @@ import {
} from 'vue';
import { useNamespace } from '@vben-core/hooks';
import { IcRoundMoreHoriz } from '@vben-core/icons';
import { Ellipsis } from '@vben-core/icons';
import { isHttpUrl } from '@vben-core/toolkit';
import { UseResizeObserverReturn, useResizeObserver } from '@vueuse/core';
@@ -338,7 +338,7 @@ function removeMenuItem(item: MenuItemRegistered) {
</template>
<SubMenu is-sub-menu-more path="sub-menu-more">
<template #title>
<IcRoundMoreHoriz />
<Ellipsis class="size-4" />
</template>
<template v-for="item in getSlot.slotMore" :key="item.key">
<component :is="item" />
@@ -852,9 +852,9 @@ $namespace: vben;
cursor: pointer;
background: var(--menu-submenu-hover-background-color) !important;
svg {
fill: var(--menu-submenu-hover-color);
}
// svg {
// fill: var(--menu-submenu-hover-color);
// }
}
}
</style>

View File

@@ -4,10 +4,7 @@ import type { MenuItemProps } from '../interface';
import { computed } from 'vue';
import { useNamespace } from '@vben-core/hooks';
import {
IcRoundChevronRight,
IcRoundKeyboardArrowDown,
} from '@vben-core/icons';
import { ChevronDown, ChevronRight } from '@vben-core/icons';
import { VbenIcon } from '@vben-core/shadcn-ui';
import { useMenuContext } from '../hooks';
@@ -67,8 +64,8 @@ const hiddenTitle = computed(() => {
const iconComp = computed(() => {
return (mode.value === 'horizontal' && !isFirstLevel.value) ||
(mode.value === 'vertical' && collapse.value)
? IcRoundChevronRight
: IcRoundKeyboardArrowDown;
? ChevronRight
: ChevronDown;
});
const iconArrowStyle = computed(() => {
@@ -102,6 +99,7 @@ const iconArrowStyle = computed(() => {
v-show="showArrowIcon"
:class="[e('icon-arrow')]"
:style="iconArrowStyle"
class="size-4"
/>
</div>
</template>

View File

@@ -3,7 +3,7 @@ import type { BacktopProps } from './backtop';
import { computed } from 'vue';
import { IcRoundArrowUpward } from '@vben-core/icons';
import { ArrowUpToLine } from '@vben-core/icons';
import { VbenButton } from '../button';
import { useBackTop } from './use-backtop';
@@ -37,7 +37,7 @@ const { handleClick, visible } = useBackTop(props);
variant="icon"
@click="handleClick"
>
<IcRoundArrowUpward />
<ArrowUpToLine class="size-4" />
</VbenButton>
</transition>
</template>

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { IBreadcrumb } from './interface';
import { IcRoundKeyboardArrowDown } from '@vben-core/icons';
import { ChevronDown } from '@vben-core/icons';
import {
Breadcrumb,
BreadcrumbItem,
@@ -56,7 +56,7 @@ function handleClick(path?: string) {
class="size-5"
/>
{{ item.title }}
<IcRoundKeyboardArrowDown class="size-5" />
<ChevronDown class="size-4" />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<template

View File

@@ -2,7 +2,7 @@
import type { HTMLAttributes } from 'vue';
import { computed } from 'vue';
import { MdiLoading } from '@vben-core/icons';
import { LoaderCircle } from '@vben-core/icons';
import {
type ButtonVariants,
buttonVariants,
@@ -40,9 +40,9 @@ const isDisabled = computed(() => {
:class="cn(buttonVariants({ variant, size }), props.class)"
:disabled="isDisabled"
>
<MdiLoading
<LoaderCircle
v-if="loading"
class="text-md mr-2 flex-shrink-0 animate-spin"
class="text-md mr-2 size-4 flex-shrink-0 animate-spin"
/>
<slot></slot>
</Primitive>

View File

@@ -81,7 +81,7 @@ function handleClick(menu: IContextMenuItem) {
<component
:is="menu.icon"
v-if="menu.icon"
class="mr-1 w-6 text-lg"
class="mr-2 size-4 text-lg"
/>
{{ menu.text }}

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { IcRoundFullscreen, IcRoundFullscreenExit } from '@vben-core/icons';
import { Maximize, Minimize } from '@vben-core/icons';
import { useFullscreen } from '@vueuse/core';
@@ -22,7 +22,7 @@ isFullscreen.value = !!(
</script>
<template>
<VbenIconButton @click="toggle">
<IcRoundFullscreenExit v-if="isFullscreen" class="size-6" />
<IcRoundFullscreen v-else class="size-6" />
<Minimize v-if="isFullscreen" class="size-4" />
<Maximize v-else class="size-4" />
</VbenIconButton>
</template>

View File

@@ -2,12 +2,12 @@
import { type Component, computed } from 'vue';
import { Icon, IconDefault } from '@vben-core/icons';
import { isHttpUrl, isObject, isString } from '@vben-core/toolkit';
import { isFunction, isHttpUrl, isObject, isString } from '@vben-core/toolkit';
const props = defineProps<{
// 没有是否显示默认图标
fallback?: boolean;
icon?: Component | string;
icon?: Component | Function | string;
}>();
const isRemoteIcon = computed(() => {
@@ -15,7 +15,8 @@ const isRemoteIcon = computed(() => {
});
const isComponent = computed(() => {
return !isString(props.icon) && isObject(props.icon);
const { icon } = props;
return !isString(icon) && (isObject(icon) || isFunction(icon));
});
</script>

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { ref, useSlots } from 'vue';
import { IcOutlineVisibility, IcOutlineVisibilityOff } from '@vben-core/icons';
import { Eye, EyeOff } from '@vben-core/icons';
import {
type InputProps,
VbenInput,
@@ -48,8 +48,8 @@ const show = ref(false);
class="hover:text-foreground text-foreground/60 absolute inset-y-0 right-0 top-3 flex cursor-pointer pr-3 text-lg leading-5"
@click="show = !show"
>
<IcOutlineVisibility v-if="show" />
<IcOutlineVisibilityOff v-else />
<Eye v-if="show" class="size-4" />
<EyeOff v-else class="size-4" />
</div>
</form>
</template>

View File

@@ -42,7 +42,7 @@ function handleScroll(event: Event) {
<div
v-if="shadow"
:class="{
'opacity-100': !isAtTop,
'border-border border-t opacity-100': !isAtTop,
}"
class="scrollbar-top-shadow pointer-events-none absolute top-0 z-10 h-12 w-full opacity-0 transition-opacity duration-300 ease-in-out will-change-[opacity]"
></div>
@@ -50,7 +50,7 @@ function handleScroll(event: Event) {
<div
v-if="shadow"
:class="{
'opacity-100': !isAtTop && !isAtBottom,
'border-border border-b opacity-100': !isAtTop && !isAtBottom,
}"
class="scrollbar-bottom-shadow pointer-events-none absolute bottom-0 z-10 h-12 w-full opacity-0 transition-opacity duration-300 ease-in-out will-change-[opacity]"
></div>

View File

@@ -17,7 +17,7 @@ import {
SheetTrigger,
} from '@vben-core/shadcn-ui/components/ui/sheet';
import { Cross2Icon } from '@radix-icons/vue';
import { X } from 'lucide-vue-next';
interface Props {
cancelText?: string;
@@ -87,12 +87,12 @@ function handlerSubmit() {
class="data-[state=open]:bg-secondary cursor-pointer rounded-full opacity-80 transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none"
>
<VbenIconButton>
<Cross2Icon class="size-4" />
<X class="size-4" />
</VbenIconButton>
</SheetClose>
</SheetHeader>
<div class="h-full pb-16">
<VbenScrollbar class="h-full">
<VbenScrollbar class="h-full" shadow>
<slot></slot>
</VbenScrollbar>
</div>

View File

@@ -5,7 +5,7 @@ import type { TabConfig, TabsProps } from '../../types';
import { computed, ref, watch } from 'vue';
import { IcRoundClose, MdiPin } from '@vben-core/icons';
import { MdiPin, X } from '@vben-core/icons';
import { VbenContextMenu, VbenIcon, VbenScrollbar } from '@vben-core/shadcn-ui';
interface Props extends TabsProps {}
@@ -146,7 +146,7 @@ function scrollIntoView() {
class="tabs-chrome__extra absolute right-[calc(var(--gap)*2)] top-1/2 z-[3] size-4 translate-y-[-50%] opacity-0 transition-opacity group-hover:opacity-100"
> -->
<!-- close-icon -->
<IcRoundClose
<X
v-show="
!tab.affixTab && tabsView.length > 1 && tab.closable
"

View File

@@ -3,7 +3,7 @@ import type { TabConfig, TabsProps } from '../../types';
import { computed, watch } from 'vue';
import { IcRoundClose, MdiPin } from '@vben-core/icons';
import { MdiPin, X } from '@vben-core/icons';
import { VbenContextMenu, VbenIcon, VbenScrollbar } from '@vben-core/shadcn-ui';
import { TabDefinition } from '@vben-core/typings';
@@ -115,7 +115,7 @@ function scrollIntoView() {
class="absolute right-1.5 top-1/2 z-[3] translate-y-[-50%] overflow-hidden opacity-0 transition-opacity group-hover:opacity-100 group-[.is-active]:opacity-100"
> -->
<!-- close-icon -->
<IcRoundClose
<X
v-show="
!tab.affixTab && tabsView.length > 1 && tab.closable
"

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { DropdownMenuProps } from '@vben-core/shadcn-ui';
import { IcRoundKeyboardArrowDown } from '@vben-core/icons';
import { ChevronDown } from '@vben-core/icons';
import { VbenDropdownMenu } from '@vben-core/shadcn-ui';
defineProps<DropdownMenuProps>();
@@ -10,9 +10,9 @@ defineProps<DropdownMenuProps>();
<template>
<VbenDropdownMenu :menus="menus" :modal="false">
<div
class="flex-center hover:bg-muted hover:text-foreground text-muted-foreground border-border h-full cursor-pointer border-l px-1.5 text-lg font-semibold"
class="flex-center hover:bg-muted hover:text-foreground text-muted-foreground border-border h-full cursor-pointer border-l px-2 text-lg font-semibold"
>
<IcRoundKeyboardArrowDown class="size-5" />
<ChevronDown class="size-4" />
</div>
</VbenDropdownMenu>
</template>

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { IcRoundFitScreen, IcTwotoneFitScreen } from '@vben-core/icons';
import { Fullscreen, Minimize2 } from '@vben-core/icons';
const screen = defineModel<boolean>('screen');
@@ -13,7 +13,7 @@ function toggleScreen() {
class="flex-center hover:bg-muted hover:text-foreground text-muted-foreground border-border h-full cursor-pointer border-l px-2 text-lg font-semibold"
@click="toggleScreen"
>
<IcTwotoneFitScreen v-if="screen" />
<IcRoundFitScreen v-else />
<Minimize2 v-if="screen" class="size-4" />
<Fullscreen v-else class="size-4" />
</div>
</template>