Skip to content

Commit

Permalink
feat: positioningDisabled + mobile example
Browse files Browse the repository at this point in the history
  • Loading branch information
Akryum committed Feb 1, 2022
1 parent 13dfd26 commit 433118a
Show file tree
Hide file tree
Showing 6 changed files with 251 additions and 39 deletions.
95 changes: 95 additions & 0 deletions packages/docs/src/.vuepress/components/DropdownMobileDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<script>
let count = 0
export default {
data () {
return {
isMobile: false,
}
},
methods: {
onShow () {
if (count === 0) {
document.body.classList.add('no-scroll')
}
count++
},
onHide () {
count--
if (count === 0) {
document.body.classList.remove('no-scroll')
}
},
},
}
</script>

<template>
<div class="example flex flex-col items-center justify-center space-y-6">
<label>
<input
v-model="isMobile"
type="checkbox"
>
Is mobile
</label>

<VDropdown
:positioning-disabled="isMobile"
@apply-show="isMobile && onShow()"
@apply-hide="isMobile && onHide()"
>
<button class="border border-gray-300 rounded px-4 py-2">
Click me
</button>

<template #popper="{ hide }">
<div class="p-6 space-y-6">
<div>This is awesome!</div>

<div v-if="isMobile">
<button
class="bg-gray-300 rounded px-4 py-2"
@click="hide()"
>
Cancel
</button>
</div>
</div>
</template>
</VDropdown>
</div>
</template>

<style>
body.no-scroll {
overflow: hidden;
}
.v-popper__popper--no-positioning {
position: fixed;
z-index: 9999;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0 0 0 / 90%);
pointer-events: none;
display: flex;
align-items: flex-end;
padding: 12px;
}
.v-popper__popper--no-positioning .v-popper__wrapper {
width: 100%;
pointer-events: auto;
transition: transform .15s ease-out;
}
.v-popper__popper--no-positioning.v-popper__popper--hidden .v-popper__wrapper {
transform: translateY(100%);
}
</style>
4 changes: 4 additions & 0 deletions packages/docs/src/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,10 @@ Hide the popper if clicked outside.

Boolean that disables the popper. If it was already open, it will be closed.

### `positioningDisabled`

Boolean that disables the automatic positioning of the popper. You can then style it manually. Useful for mobile version of the popper.

### `handleResize`

Boolean: Automatically update the popper position if its size changes.
Expand Down
126 changes: 110 additions & 16 deletions packages/docs/src/guide/component.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,22 +209,6 @@ To fix this, specify the `padding` option of the `arrow` modifier. In the follow

<ArrowPadding :padding="8" />

## Disable popper

Disabling a popper will prevent it from being shown.

```vue
<VDropdown :disabled="isDisabled"></VDropdown>
```

```js
data () {
return {
isDisabled: true,
}
}
```

## Hide from slot

Use the `hide` slot prop to close the popper:
Expand Down Expand Up @@ -281,3 +265,113 @@ Close all the poppers in the page with the `all` modifier:
```vue
<a v-close-popper.all>Close All</a>
```

## Disable popper

Disabling a popper will prevent it from being shown.

```vue
<VDropdown :disabled="isDisabled"></VDropdown>
```

```js
data () {
return {
isDisabled: true,
}
}
```

## Mobile

You can also just disable the positioning of the popper with `positioningDisabled`:

```vue
<VDropdown :positioning-disabled="isMobile"></VDropdown>
```

It can for example be useful on the mobile version of your app if you want to apply a fixed position to the popper with CSS.

<DropdownMobileDemo />

```vue
<script>
let count = 0
export default {
data () {
return {
isMobile: false,
}
},
methods: {
onShow () {
if (count === 0) {
document.body.classList.add('no-scroll')
}
count++
},
onHide () {
count--
if (count === 0) {
document.body.classList.remove('no-scroll')
}
},
},
}
</script>
<template>
<div class="example">
<label>
<input v-model="isMobile" type="checkbox">
Is mobile
</label>
<VDropdown
:positioning-disabled="isMobile"
@apply-show="isMobile && onShow()"
@apply-hide="isMobile && onHide()"
>
<button>Click me</button>
<template #popper="{ hide }">
<div>This is awesome!</div>
<button v-if="isMobile" @click="hide()">Cancel</button>
</template>
</VDropdown>
</div>
</template>
<style>
body.no-scroll {
overflow: hidden;
}
.v-popper__popper--no-positioning {
position: fixed;
z-index: 9999;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0 0 0 / 90%);
pointer-events: none;
display: flex;
align-items: flex-end;
padding: 12px;
}
.v-popper__popper--no-positioning .v-popper__wrapper {
width: 100%;
pointer-events: auto;
transition: transform .15s ease-out;
}
.v-popper__popper--no-positioning.v-popper__popper--hidden .v-popper__wrapper {
transform: translateY(100%);
}
</style>
```
2 changes: 2 additions & 0 deletions packages/docs/src/guide/css.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ HTML result:
'v-popper__popper--hidden',
'v-popper__popper--skip-transition',
'v-popper__popper--arrow-overflow',
'v-popper__popper--no-positioning',
'v-popper__popper--show-from',
'v-popper__popper--show-to',
'v-popper__popper--hide-from',
Expand Down Expand Up @@ -149,6 +150,7 @@ The `popper` element has several dynamic classes:
- `v-popper__popper--hidden`: the popper is hidden.
- `v-popper__popper--skip-transition`: the transition should be skipped.
- `v-popper__popper--arrow-overflow`: the arrow is overflowing past the reference, and should probably be hidden.
- `v-popper__popper--no-positioning`: positioning is disabled with `positioningDisabled` prop.


Full example style:
Expand Down
43 changes: 29 additions & 14 deletions packages/floating-vue/src/components/Popper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ export default () => ({
default: defaultPropFactory('disabled'),
},

positioningDisabled: {
type: Boolean,
default: defaultPropFactory('positioningDisabled'),
},

placement: {
type: String,
default: defaultPropFactory('placement'),
Expand Down Expand Up @@ -269,7 +274,7 @@ export default () => ({
...this.classes,
popperClass: this.popperClass,
},
result: this.result,
result: this.positioningDisabled ? null : this.result,
}
},
},
Expand All @@ -292,12 +297,13 @@ export default () => ({
}
},

triggers () {
if (!this.$_isDisposed) {
this.$_removeEventListeners()
this.$_addEventListeners()
}
},
...[
'triggers',
'positioningDisabled',
].reduce((acc, prop) => {
acc[prop] = '$_refreshListeners'
return acc
}, {}),

...[
'placement',
Expand Down Expand Up @@ -411,7 +417,7 @@ export default () => ({
},

async $_computePosition () {
if (this.$_isDisposed) return
if (this.$_isDisposed || this.positioningDisabled) return

const options: ComputePositionConfig = {
strategy: this.strategy,
Expand Down Expand Up @@ -764,12 +770,14 @@ export default () => ({
addEvents([this.$_popperNode], HIDE_EVENT_MAP, this.popperTriggers, this.popperHideTriggers, handleHide)

// Scroll
addListeners([
...getScrollParents(this.$_referenceNode),
...getScrollParents(this.$_popperNode),
], 'scroll', () => {
this.$_computePosition()
})
if (!this.positioningDisabled) {
addListeners([
...getScrollParents(this.$_referenceNode),
...getScrollParents(this.$_popperNode),
], 'scroll', () => {
this.$_computePosition()
})
}
},

$_removeEventListeners () {
Expand All @@ -779,6 +787,13 @@ export default () => ({
this.$_events = []
},

$_refreshListeners () {
if (!this.$_isDisposed) {
this.$_removeEventListeners()
this.$_addEventListeners()
}
},

$_handleGlobalClose (event, touch = false) {
if (this.$_showFrameLocked) return

Expand Down
20 changes: 11 additions & 9 deletions packages/floating-vue/src/components/PopperContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,24 @@
'v-popper__popper--hide-from': classes.hideFrom,
'v-popper__popper--hide-to': classes.hideTo,
'v-popper__popper--skip-transition': skipTransition,
'v-popper__popper--arrow-overflow': result.arrow.overflow,
'v-popper__popper--arrow-overflow': result && result.arrow.overflow,
'v-popper__popper--no-positioning': !result,
},
]"
:style="{
:style="result ? {
position: result.strategy,
transform: `translate3d(${Math.round(result.x)}px,${Math.round(result.y)}px,0)`,
}"
} : undefined"
:aria-hidden="shown ? 'false' : 'true'"
:tabindex="autoHide ? 0 : undefined"
:data-popper-placement="result.placement"
:data-popper-placement="result ? result.placement : undefined"
@keyup.esc="autoHide && $emit('hide')"
>
<div
class="v-popper__wrapper"
:style="{
:style="result ? {
transformOrigin: result.transformOrigin,
}"
} : undefined"
>
<div
ref="inner"
Expand All @@ -51,10 +52,10 @@
<div
ref="arrow"
class="v-popper__arrow-container"
:style="{
:style="result ? {
left: toPx(result.arrow.x),
top: toPx(result.arrow.y),
}"
} : undefined"
>
<div class="v-popper__arrow-outer" />
<div class="v-popper__arrow-inner" />
Expand Down Expand Up @@ -142,7 +143,8 @@ export default {
height: 10px;
}
.v-popper__popper--arrow-overflow .v-popper__arrow-container {
.v-popper__popper--arrow-overflow .v-popper__arrow-container,
.v-popper__popper--no-positioning .v-popper__arrow-container {
display: none;
}
Expand Down

0 comments on commit 433118a

Please sign in to comment.