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
@@ -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);
@@ -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 };
@@ -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,
@@ -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 /> */
+1
View File
@@ -36,6 +36,7 @@
},
"dependencies": {
"@iconify/vue": "^4.1.2",
"lucide-vue-next": "^0.408.0",
"vue": "^3.4.32"
}
}
+2 -2
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';
+46
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';
@@ -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');
-30
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',
);
@@ -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>
@@ -12,7 +12,7 @@ interface Props {
const props = withDefaults(defineProps<Props>(), {
fixed: true,
height: 30,
height: 38,
});
const style = computed((): CSSProperties => {
@@ -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>
@@ -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>
@@ -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>
@@ -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>
@@ -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
@@ -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>
@@ -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 }}
@@ -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>
@@ -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>
@@ -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>
@@ -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>
@@ -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>
@@ -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
"
@@ -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
"
@@ -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>
@@ -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>