Skip to content

Commit

Permalink
fix: improve the dialog and drawer scrollbar experience, fix internal…
Browse files Browse the repository at this point in the history
… click failure problems and warnings (#4391)

* fix: improve the dialog and drawer scrollbar experience, fix internal click failure problems and warnings

* chore: remove test code
  • Loading branch information
anncwb committed Sep 13, 2024
1 parent bd6b724 commit d27e5ee
Show file tree
Hide file tree
Showing 20 changed files with 186 additions and 42 deletions.
4 changes: 2 additions & 2 deletions packages/@core/base/design/src/css/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
}

body {
@apply !pointer-events-auto;

min-height: 100vh;

/* pointer-events: auto !important; */

/* overflow: overlay; */

/* -webkit-font-smoothing: antialiased; */
Expand Down
19 changes: 19 additions & 0 deletions packages/@core/base/shared/src/utils/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,22 @@ export function getElementVisibleRect(
width: Math.max(0, right - left),
};
}

export function getScrollbarWidth() {
const scrollDiv = document.createElement('div');

scrollDiv.style.visibility = 'hidden';
scrollDiv.style.overflow = 'scroll';
scrollDiv.style.position = 'absolute';
scrollDiv.style.top = '-9999px';

document.body.append(scrollDiv);

const innerDiv = document.createElement('div');
scrollDiv.append(innerDiv);

const scrollbarWidth = scrollDiv.offsetWidth - innerDiv.offsetWidth;

scrollDiv.remove();
return scrollbarWidth;
}
1 change: 1 addition & 0 deletions packages/@core/composables/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './use-content-style';
export * from './use-is-mobile';
export * from './use-namespace';
export * from './use-priority-value';
export * from './use-scroll-lock';
export * from './use-simple-locale';
export * from './use-sortable';
export {
Expand Down
48 changes: 48 additions & 0 deletions packages/@core/composables/src/use-scroll-lock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { getScrollbarWidth } from '@vben-core/shared/utils';

import {
useScrollLock as _useScrollLock,
tryOnBeforeMount,
tryOnBeforeUnmount,
} from '@vueuse/core';

export const SCROLL_FIXED_CLASS = `_scroll__fixed_`;

export function useScrollLock() {
const isLocked = _useScrollLock(document.body);
const scrollbarWidth = getScrollbarWidth();

tryOnBeforeMount(() => {
document.body.style.paddingRight = `${scrollbarWidth}px`;

const layoutFixedNodes = document.querySelectorAll<HTMLElement>(
`.${SCROLL_FIXED_CLASS}`,
);
const nodes = [...layoutFixedNodes];
if (nodes.length > 0) {
nodes.forEach((node) => {
node.dataset.transition = node.style.transition;
node.style.transition = 'none';
node.style.paddingRight = `${scrollbarWidth}px`;
});
}
isLocked.value = true;
});

tryOnBeforeUnmount(() => {
isLocked.value = false;
const layoutFixedNodes = document.querySelectorAll<HTMLElement>(
`.${SCROLL_FIXED_CLASS}`,
);
const nodes = [...layoutFixedNodes];
if (nodes.length > 0) {
nodes.forEach((node) => {
node.style.paddingRight = '';
requestAnimationFrame(() => {
node.style.transition = node.dataset.transition || '';
});
});
}
document.body.style.paddingRight = '';
});
}
10 changes: 7 additions & 3 deletions packages/@core/ui-kit/layout-ui/src/vben-layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { VbenLayoutProps } from './vben-layout';
import type { CSSProperties } from 'vue';
import { computed, ref, watch } from 'vue';
import { SCROLL_FIXED_CLASS } from '@vben-core/composables';
import { Menu } from '@vben-core/icons';
import { VbenIconButton } from '@vben-core/shadcn-ui';
Expand Down Expand Up @@ -478,9 +479,12 @@ function handleHeaderToggle() {
class="flex flex-1 flex-col overflow-hidden transition-all duration-300 ease-in"
>
<div
:class="{
'shadow-[0_16px_24px_hsl(var(--background))]': scrollY > 20,
}"
:class="[
{
'shadow-[0_16px_24px_hsl(var(--background))]': scrollY > 20,
},
SCROLL_FIXED_CLASS,
]"
:style="headerWrapperStyle"
class="overflow-hidden transition-all duration-200"
>
Expand Down
1 change: 1 addition & 0 deletions packages/@core/ui-kit/popup-ui/src/drawer/drawer-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export class DrawerApi {
isOpen: false,
loading: false,
modal: true,
openAutoFocus: false,
showCancelButton: true,
showConfirmButton: true,
title: '',
Expand Down
4 changes: 4 additions & 0 deletions packages/@core/ui-kit/popup-ui/src/drawer/drawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ export interface DrawerProps {
* @default true
*/
modal?: boolean;
/**
* 是否自动聚焦
*/
openAutoFocus?: boolean;
/**
* 是否显示取消按钮
* @default true
Expand Down
19 changes: 18 additions & 1 deletion packages/@core/ui-kit/popup-ui/src/drawer/drawer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const {
footer: showFooter,
loading: showLoading,
modal,
openAutoFocus,
showCancelButton,
showConfirmButton,
title,
Expand Down Expand Up @@ -87,10 +88,21 @@ function pointerDownOutside(e: Event) {
e.preventDefault();
}
}
function handerOpenAutoFocus(e: Event) {
if (!openAutoFocus.value) {
e?.preventDefault();
}
}
function handleFocusOutside(e: Event) {
e.preventDefault();
e.stopPropagation();
}
</script>
<template>
<Sheet
:modal="modal"
:modal="false"
:open="state?.isOpen"
@update:open="() => drawerApi?.close()"
>
Expand All @@ -100,8 +112,13 @@ function pointerDownOutside(e: Event) {
'!w-full': isMobile,
})
"
:modal="modal"
:open="state?.isOpen"
@close-auto-focus="handleFocusOutside"
@escape-key-down="escapeKeyDown"
@focus-outside="handleFocusOutside"
@interact-outside="interactOutside"
@open-auto-focus="handerOpenAutoFocus"
@pointer-down-outside="pointerDownOutside"
>
<SheetHeader
Expand Down
2 changes: 1 addition & 1 deletion packages/@core/ui-kit/popup-ui/src/drawer/use-drawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ async function checkProps(api: ExtendedDrawerApi, attrs: Record<string, any>) {
const stateKeys = new Set(Object.keys(state));

for (const attr of Object.keys(attrs)) {
if (stateKeys.has(attr)) {
if (stateKeys.has(attr) && !['class'].includes(attr)) {
// connectedComponent存在时,不要传入Drawer的props,会造成复杂度提升,如果你需要修改Drawer的props,请使用 useVbenDrawer 或者api
console.warn(
`[Vben Drawer]: When 'connectedComponent' exists, do not set props or slots '${attr}', which will increase complexity. If you need to modify the props of Drawer, please use useVbenDrawer or api.`,
Expand Down
13 changes: 12 additions & 1 deletion packages/@core/ui-kit/popup-ui/src/modal/modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ function handleFullscreen() {
function interactOutside(e: Event) {
if (!closeOnClickModal.value) {
e.preventDefault();
e.stopPropagation();
}
}
function escapeKeyDown(e: KeyboardEvent) {
Expand All @@ -143,12 +144,18 @@ function pointerDownOutside(e: Event) {
const isDismissableModal = !!target?.dataset.dismissableModal;
if (!closeOnClickModal.value || !isDismissableModal) {
e.preventDefault();
e.stopPropagation();
}
}
function handleFocusOutside(e: Event) {
e.preventDefault();
e.stopPropagation();
}
</script>
<template>
<Dialog
:modal="modal"
:modal="false"
:open="state?.isOpen"
@update:open="() => modalApi?.close()"
>
Expand All @@ -166,9 +173,13 @@ function pointerDownOutside(e: Event) {
},
)
"
:modal="modal"
:open="state?.isOpen"
:show-close="closable"
close-class="top-3"
@close-auto-focus="handleFocusOutside"
@escape-key-down="escapeKeyDown"
@focus-outside="handleFocusOutside"
@interact-outside="interactOutside"
@open-auto-focus="handerOpenAutoFocus"
@pointer-down-outside="pointerDownOutside"
Expand Down
2 changes: 1 addition & 1 deletion packages/@core/ui-kit/popup-ui/src/modal/use-modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ async function checkProps(api: ExtendedModalApi, attrs: Record<string, any>) {
const stateKeys = new Set(Object.keys(state));

for (const attr of Object.keys(attrs)) {
if (stateKeys.has(attr)) {
if (stateKeys.has(attr) && !['class'].includes(attr)) {
// connectedComponent存在时,不要传入Modal的props,会造成复杂度提升,如果你需要修改Modal的props,请使用 useModal 或者api
console.warn(
`[Vben Modal]: When 'connectedComponent' exists, do not set props or slots '${attr}', which will increase complexity. If you need to modify the props of Modal, please use useVbenModal or api.`,
Expand Down
1 change: 1 addition & 0 deletions packages/@core/ui-kit/shadcn-ui/build.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default defineBuildConfig({
{
builder: 'mkdist',
input: './src',

pattern: ['**/*'],
},
{
Expand Down
1 change: 1 addition & 0 deletions packages/@core/ui-kit/shadcn-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
},
"dependencies": {
"@radix-icons/vue": "^1.0.0",
"@vben-core/composables": "workspace:*",
"@vben-core/icons": "workspace:*",
"@vben-core/shared": "workspace:*",
"@vben-core/typings": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@ import {
DialogContent,
type DialogContentEmits,
type DialogContentProps,
DialogOverlay,
DialogPortal,
useForwardPropsEmits,
} from 'radix-vue';
import DialogOverlay from './DialogOverlay.vue';
const props = withDefaults(
defineProps<
{
class?: any;
closeClass?: any;
modal?: boolean;
open?: boolean;
showClose?: boolean;
} & DialogContentProps
>(),
Expand All @@ -27,7 +30,13 @@ const props = withDefaults(
const emits = defineEmits<{ close: [] } & DialogContentEmits>();
const delegatedProps = computed(() => {
const { class: _, showClose: __, ...delegated } = props;
const {
class: _,
modal: _modal,
open: _open,
showClose: __,
...delegated
} = props;
return delegated;
});
Expand All @@ -43,11 +52,7 @@ defineExpose({

<template>
<DialogPortal>
<DialogOverlay
class="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 bg-overlay fixed inset-0 z-[1000]"
data-dismissable-modal="true"
@click="() => emits('close')"
/>
<DialogOverlay v-if="open && modal" @click="() => emits('close')" />
<DialogContent
ref="contentRef"
v-bind="forwarded"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { useScrollLock } from '@vben-core/composables';
useScrollLock();
</script>
<template>
<div
class="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 bg-overlay fixed inset-0 z-[1000]"
data-dismissable-modal="true"
></div>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@ import {
DialogContent,
type DialogContentEmits,
type DialogContentProps,
DialogOverlay,
DialogPortal,
useForwardPropsEmits,
} from 'radix-vue';
import { type SheetVariants, sheetVariants } from './sheet';
import SheetOverlay from './SheetOverlay.vue';
interface SheetContentProps extends DialogContentProps {
class?: any;
modal?: boolean;
open?: boolean;
side?: SheetVariants['side'];
}
Expand All @@ -28,7 +30,13 @@ const props = defineProps<SheetContentProps>();
const emits = defineEmits<DialogContentEmits>();
const delegatedProps = computed(() => {
const { class: _, side: _side, ...delegated } = props;
const {
class: _,
modal: _modal,
open: _open,
side: _side,
...delegated
} = props;
return delegated;
});
Expand All @@ -38,10 +46,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);

<template>
<DialogPortal>
<DialogOverlay
class="bg-overlay 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-[1000]"
data-dismissable-modal="true"
/>
<SheetOverlay v-if="open && modal" />
<DialogContent
:class="cn(sheetVariants({ side }), 'z-[1000]', props.class)"
v-bind="{ ...forwarded, ...$attrs }"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { useScrollLock } from '@vben-core/composables';
useScrollLock();
</script>
<template>
<div
class="bg-overlay 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-[1000]"
data-dismissable-modal="true"
></div>
</template>
4 changes: 2 additions & 2 deletions packages/effects/layouts/src/basic/tabbar/tabbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ defineProps<{ showIcon?: boolean; theme?: string }>();
const route = useRoute();
const tabbarStore = useTabbarStore();
const { toggleMaximize } = useContentMaximize();
const { contentIsMaximize, toggleMaximize } = useContentMaximize();
const { refreshTab, unpinTab } = useTabs();
const {
Expand Down Expand Up @@ -73,7 +73,7 @@ if (!preferences.tabbar.persist) {
<TabsToolMore v-if="preferences.tabbar.showMore" :menus="menus" />
<TabsToolScreen
v-if="preferences.tabbar.showMaximize"
:screen="preferences.sidebar.hidden"
:screen="contentIsMaximize"
@change="toggleMaximize"
@update:screen="toggleMaximize"
/>
Expand Down
Loading

0 comments on commit d27e5ee

Please sign in to comment.