feat(FloatingBubble): allow gap xy to be set separately (#13297) (#13429)

Co-authored-by: neverland <jait.chen@foxmail.com>
This commit is contained in:
Wei-Liang Liou
2025-04-13 17:20:59 +08:00
committed by GitHub
co-authored by neverland
parent 5a7042c182
commit d739f678b4
5 changed files with 55 additions and 11 deletions
@@ -20,7 +20,7 @@ import {
addUnit,
closest,
createNamespace,
makeNumberProp,
isObject,
makeStringProp,
windowWidth,
windowHeight,
@@ -38,11 +38,15 @@ import {
FloatingBubbleAxis,
FloatingBubbleMagnetic,
FloatingBubbleOffset,
FloatingBubbleGap,
FloatingBubbleBoundary,
} from './types';
export const floatingBubbleProps = {
gap: makeNumberProp(24),
gap: {
type: [Number, Object] as unknown as PropType<FloatingBubbleGap>,
default: 24,
},
icon: String,
axis: makeStringProp<FloatingBubbleAxis>('y'),
magnetic: String as PropType<FloatingBubbleMagnetic>,
@@ -79,11 +83,17 @@ export default defineComponent({
height: 0,
});
const gapX = computed(() =>
isObject(props.gap) ? props.gap.x : props.gap,
);
const gapY = computed(() =>
isObject(props.gap) ? props.gap.y : props.gap,
);
const boundary = computed<FloatingBubbleBoundary>(() => ({
top: props.gap,
right: windowWidth.value - state.value.width - props.gap,
bottom: windowHeight.value - state.value.height - props.gap,
left: props.gap,
top: gapY.value,
right: windowWidth.value - state.value.width - gapX.value,
bottom: windowHeight.value - state.value.height - gapY.value,
left: gapX.value,
}));
const dragging = ref(false);
@@ -110,8 +120,8 @@ export default defineComponent({
const { width, height } = useRect(rootRef.value!);
const { offset } = props;
state.value = {
x: offset.x > -1 ? offset.x : windowWidth.value - width - props.gap,
y: offset.y > -1 ? offset.y : windowHeight.value - height - props.gap,
x: offset.x > -1 ? offset.x : windowWidth.value - width - gapX.value,
y: offset.y > -1 ? offset.y : windowHeight.value - height - gapY.value,
width,
height,
};
@@ -203,7 +213,7 @@ export default defineComponent({
});
watch(
[windowWidth, windowHeight, () => props.gap, () => props.offset],
[windowWidth, windowHeight, gapX, gapY, () => props.offset],
updateState,
{ deep: true },
);
+1 -1
View File
@@ -94,7 +94,7 @@ export default {
| axis | Drag direction, `xy` stands for free drag, `lock` stands for disable drag | _'x' \| 'y' \| 'xy' \| 'lock'_ | `y` |
| magnetic | Direction of automatic magnetic absorption | _'x' \| 'y'_ | - |
| icon | Bubble icon | _string_ | - |
| gap | Minimum gap between the bubble and the window, unit `px` | _number_ | `24` |
| gap | Minimum gap between the bubble and the window, unit `px` | _number \| { x: number, y: number }_ | `24` |
| teleport | Specifies a target element where BackTop will be mounted | _string \| Element_ | `body` |
### Events
@@ -94,7 +94,7 @@ export default {
| axis | 拖拽的方向,`xy` 代表自由拖拽,`lock` 代表禁止拖拽 | _'x' \| 'y' \| 'xy' \| 'lock'_ | `y` |
| magnetic | 自动磁吸的方向 | _'x' \| 'y'_ | - |
| icon | 气泡图标名称或图片链接,等同于 Icon 组件的 [name 属性](#/zh-CN/icon#props) | _string_ | - |
| gap | 气泡与窗口的最小间距,单位为 `px` | _number_ | `24` |
| gap | 气泡与窗口的最小间距,单位为 `px` | _number \| { x: number, y: number }_ | `24` |
| teleport | 指定挂载的节点,等同于 Teleport 组件的 [to 属性](https://cn.vuejs.org/api/built-in-components.html#teleport) | _string \| Element_ | `body` |
### Events
@@ -62,6 +62,33 @@ test('should render correctly when all props set', async () => {
restore();
});
test('should render with xy gaps', async () => {
useWindowSize();
const restore = mockGetBoundingClientRect({ width: 48, height: 48 });
const root = document.createElement('div');
mount(FloatingBubble, {
props: {
teleport: root,
gap: { x: 50, y: 27 },
},
});
const floatingBubbleEl = root.querySelector<HTMLDivElement>(
'.van-floating-bubble',
)!;
await later();
expect(floatingBubbleEl.style.transform).toEqual(
`translate3d(${window.innerWidth - 48 - 50}px, ${
window.innerHeight - 48 - 27
}px, 0)`,
);
restore();
});
test('should only y axis direction move when axis is default', async () => {
const restore = mockGetBoundingClientRect({ width: 48, height: 48 });
@@ -16,6 +16,13 @@ export type FloatingBubbleOffset = {
y: number;
};
export type FloatingBubbleGap =
| number
| {
x: number;
y: number;
};
export type FloatingBubbleBoundary = {
top: number;
right: number;