mirror of
https://github.com/youzan/vant.git
synced 2026-05-06 01:00:26 +08:00
feat(FloatingPanel): add draggable prop (#13773)
Co-authored-by: Junwei Wang <junwei.wang@algento.com>
This commit is contained in:
@@ -29,6 +29,7 @@ export const floatingPanelProps = {
|
||||
anchors: makeArrayProp<number>(),
|
||||
duration: makeNumericProp(0.3),
|
||||
magnetic: truthProp,
|
||||
draggable: truthProp,
|
||||
contentDraggable: truthProp,
|
||||
lockScroll: Boolean,
|
||||
safeAreaInsetBottom: truthProp,
|
||||
@@ -97,6 +98,8 @@ export default defineComponent({
|
||||
const touch = useTouch();
|
||||
|
||||
const onTouchstart = (e: TouchEvent) => {
|
||||
if (!props.draggable) return;
|
||||
|
||||
touch.start(e);
|
||||
dragging.value = true;
|
||||
startY = -height.value;
|
||||
@@ -104,6 +107,8 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
const onTouchmove = (e: TouchEvent) => {
|
||||
if (!props.draggable) return;
|
||||
|
||||
touch.move(e);
|
||||
|
||||
const target = e.target as Element;
|
||||
@@ -130,8 +135,17 @@ export default defineComponent({
|
||||
|
||||
const onTouchend = () => {
|
||||
maxScroll = -1;
|
||||
|
||||
if (!dragging.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
dragging.value = false;
|
||||
|
||||
if (!props.draggable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.magnetic) {
|
||||
height.value = closest(anchors.value, height.value);
|
||||
} else {
|
||||
@@ -162,6 +176,10 @@ export default defineComponent({
|
||||
return slots.header();
|
||||
}
|
||||
|
||||
if (!props.draggable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div class={bem('header')}>
|
||||
<div class={bem('header-bar')} />
|
||||
|
||||
@@ -93,6 +93,18 @@ When `magnetic` is set to `false`, the panel will not automatically snap to anch
|
||||
</van-floating-panel>
|
||||
```
|
||||
|
||||
### Disable Dragging
|
||||
|
||||
You can disable the dragging functionality of the panel through the `draggable` attribute. When set to `false`, the panel will not be draggable, and the header drag bar will be hidden.
|
||||
|
||||
```html
|
||||
<van-floating-panel :draggable="false">
|
||||
<div style="text-align: center; padding: 15px">
|
||||
<p>This panel cannot be dragged</p>
|
||||
</div>
|
||||
</van-floating-panel>
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
@@ -104,6 +116,7 @@ When `magnetic` is set to `false`, the panel will not automatically snap to anch
|
||||
| duration | Transition duration, unit second | _number \| string_ | `0.3` |
|
||||
| magnetic | Whether to enable magnetic adsorption to anchors. When disabled, panel can stop at any position within the anchor boundaries | _boolean_ | `true` |
|
||||
| content-draggable | Allow dragging content | _boolean_ | `true` |
|
||||
| draggable | Whether to allow dragging the panel. When disabled, the header drag bar will be hidden | _boolean_ | `true` |
|
||||
| lock-scroll `v4.6.4` | When not dragging, Whether to lock background scroll | _boolean_ | `false` |
|
||||
| safe-area-inset-bottom | Whether to enable bottom safe area adaptation | _boolean_ | `true` |
|
||||
|
||||
|
||||
@@ -93,6 +93,18 @@ export default {
|
||||
</van-floating-panel>
|
||||
```
|
||||
|
||||
### 禁用拖拽
|
||||
|
||||
你可以通过 `draggable` 属性来禁用面板的拖拽功能。当设置为 `false` 时,面板将不可拖拽,同时头部拖拽栏也会被隐藏。
|
||||
|
||||
```html
|
||||
<van-floating-panel :draggable="false">
|
||||
<div style="text-align: center; padding: 15px">
|
||||
<p>该面板不可拖拽</p>
|
||||
</div>
|
||||
</van-floating-panel>
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
@@ -104,6 +116,7 @@ export default {
|
||||
| duration | 动画时长,单位秒,设置为 0 可以禁用动画 | _number \| string_ | `0.3` |
|
||||
| magnetic | 是否启用磁力吸附到锚点。禁用后面板可在锚点边界范围内任意位置停留 | _boolean_ | `true` |
|
||||
| content-draggable | 允许拖拽内容容器 | _boolean_ | `true` |
|
||||
| draggable | 是否允许拖拽面板。禁用后头部拖拽栏会被隐藏 | _boolean_ | `true` |
|
||||
| lock-scroll `v4.6.4` | 当不拖拽时,是否锁定背景滚动 | _boolean_ | `false` |
|
||||
| safe-area-inset-bottom | 是否开启[底部安全区适配](#/zh-CN/advanced-usage#di-bu-an-quan-qu-gua-pei) | _boolean_ | `true` |
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ const t = useTranslate({
|
||||
customAnchors: '自定义锚点',
|
||||
headDragOnly: '仅头部拖拽',
|
||||
disableMagnetic: '禁用吸附',
|
||||
disableDragging: '禁用拖拽',
|
||||
panelUnDrag: '该面板不可拖拽',
|
||||
panelShowHeight: '面板显示高度',
|
||||
contentUnDrag: '内容不可拖拽',
|
||||
magneticDisabled: '已禁用磁力吸附,可在边界内任意停留',
|
||||
@@ -23,6 +25,8 @@ const t = useTranslate({
|
||||
customAnchors: 'Custom Anchors',
|
||||
headDragOnly: 'Head Drag Only',
|
||||
disableMagnetic: 'Disable Magnetic',
|
||||
disableDragging: 'Disable Dragging',
|
||||
panelUnDrag: 'This panel cannot be dragged',
|
||||
panelShowHeight: 'Panel Show Height',
|
||||
contentUnDrag: 'Content cannot be dragged',
|
||||
magneticDisabled: 'Magnetic disabled, free positioning within boundaries',
|
||||
@@ -76,5 +80,13 @@ const height = ref(anchors[0]);
|
||||
</div>
|
||||
</van-floating-panel>
|
||||
</van-tab>
|
||||
|
||||
<van-tab :title="t('disableDragging')">
|
||||
<van-floating-panel :draggable="false">
|
||||
<div style="text-align: center; padding: 15px">
|
||||
<p>{{ t('panelUnDrag') }}</p>
|
||||
</div>
|
||||
</van-floating-panel>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</template>
|
||||
|
||||
@@ -56,6 +56,16 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
style="display:none;"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
id="van-tab"
|
||||
role="tabpanel"
|
||||
class="van-tab__panel"
|
||||
tabindex="-1"
|
||||
aria-labelledby="van-tabs-4"
|
||||
data-allow-mismatch="attribute"
|
||||
style="display:none;"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -60,6 +60,19 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
Disable Magnetic
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
id="van-tabs-4"
|
||||
role="tab"
|
||||
class="van-tab van-tab--line van-tab--grow"
|
||||
tabindex="-1"
|
||||
aria-selected="false"
|
||||
aria-controls="van-tab"
|
||||
data-allow-mismatch="attribute"
|
||||
>
|
||||
<span class="van-tab__text">
|
||||
Disable Dragging
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="van-tabs__line"
|
||||
style="transform: translateX(50px) translateX(-50%);"
|
||||
@@ -306,6 +319,16 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
style="display: none;"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
id="van-tab"
|
||||
role="tabpanel"
|
||||
class="van-tab__panel"
|
||||
tabindex="-1"
|
||||
aria-labelledby="van-tabs-4"
|
||||
data-allow-mismatch="attribute"
|
||||
style="display: none;"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -189,3 +189,38 @@ test('should add padding bottom to content when panel is not fully expanded', as
|
||||
await wrapper.setProps({ height: 400 });
|
||||
expect(content.style.paddingBottom).toBe('0px');
|
||||
});
|
||||
|
||||
test('should not allow dragging when draggable is false', async () => {
|
||||
const wrapper = mount({
|
||||
render() {
|
||||
return (
|
||||
<FloatingPanel
|
||||
anchors={[100, 200, 400]}
|
||||
draggable={false}
|
||||
onHeightChange={(h) => this.$emit('change', h)}
|
||||
>
|
||||
Content
|
||||
</FloatingPanel>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.find('.van-floating-panel__header').exists()).toBe(false);
|
||||
|
||||
await triggerDrag(wrapper.find('.van-floating-panel__content'), 0, -199);
|
||||
await later();
|
||||
expect(wrapper.emitted('change')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('should render header slot even when draggable is false', () => {
|
||||
const wrapper = mount(FloatingPanel, {
|
||||
props: {
|
||||
draggable: false,
|
||||
},
|
||||
slots: {
|
||||
header: () => 'Custom Header',
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.html()).toContain('Custom Header');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user