Skip to content

Commit

Permalink
feat(popper): arrow option & docs consistency across components (#875)
Browse files Browse the repository at this point in the history
  • Loading branch information
connerblanton committed Oct 27, 2023
1 parent 4ce2374 commit f785ecd
Show file tree
Hide file tree
Showing 22 changed files with 412 additions and 101 deletions.
35 changes: 35 additions & 0 deletions docs/components/content/examples/ContextMenuExampleArrow.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script setup>
const { x, y } = useMouse()
const { y: windowY } = useWindowScroll()
const isOpen = ref(false)
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
function onContextMenu () {
const top = unref(y) - unref(windowY)
const left = unref(x)
virtualElement.value.getBoundingClientRect = () => ({
width: 0,
height: 0,
top,
left
})
isOpen.value = true
}
</script>

<template>
<div class="w-full" @contextmenu.prevent="onContextMenu">
<Placeholder class="h-96 select-none w-full flex items-center justify-center">
Right click here
</Placeholder>

<UContextMenu v-model="isOpen" :virtual-element="virtualElement" :popper="{ arrow: true, placement: 'right' }">
<div class="p-4">
Menu
</div>
</UContextMenu>
</div>
</template>
35 changes: 35 additions & 0 deletions docs/components/content/examples/ContextMenuExampleOffset.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script setup>
const { x, y } = useMouse()
const { y: windowY } = useWindowScroll()
const isOpen = ref(false)
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
function onContextMenu () {
const top = unref(y) - unref(windowY)
const left = unref(x)
virtualElement.value.getBoundingClientRect = () => ({
width: 0,
height: 0,
top,
left
})
isOpen.value = true
}
</script>

<template>
<div class="w-full" @contextmenu.prevent="onContextMenu">
<Placeholder class="h-96 select-none w-full flex items-center justify-center">
Right click here
</Placeholder>

<UContextMenu v-model="isOpen" :virtual-element="virtualElement" :popper="{ offset: 0 }">
<div class="p-4">
Menu
</div>
</UContextMenu>
</div>
</template>
35 changes: 35 additions & 0 deletions docs/components/content/examples/ContextMenuExamplePlacement.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script setup>
const { x, y } = useMouse()
const { y: windowY } = useWindowScroll()
const isOpen = ref(false)
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
function onContextMenu () {
const top = unref(y) - unref(windowY)
const left = unref(x)
virtualElement.value.getBoundingClientRect = () => ({
width: 0,
height: 0,
top,
left
})
isOpen.value = true
}
</script>

<template>
<div class="w-full" @contextmenu.prevent="onContextMenu">
<Placeholder class="h-96 select-none w-full flex items-center justify-center">
Right click here
</Placeholder>

<UContextMenu v-model="isOpen" :virtual-element="virtualElement" :popper="{ placement: 'right-start' }">
<div class="p-4">
Menu
</div>
</UContextMenu>
</div>
</template>
16 changes: 16 additions & 0 deletions docs/components/content/examples/DropdownExampleArrow.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script setup>
const items = [
[{
label: 'Profile',
avatar: {
src: 'https://avatars.githubusercontent.com/u/739984?v=4'
}
}]
]
</script>

<template>
<UDropdown :items="items" :popper="{ arrow: true }">
<UButton color="white" label="Options" trailing-icon="i-heroicons-chevron-down-20-solid" />
</UDropdown>
</template>
16 changes: 16 additions & 0 deletions docs/components/content/examples/DropdownExampleOffset.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script setup>
const items = [
[{
label: 'Profile',
avatar: {
src: 'https://avatars.githubusercontent.com/u/739984?v=4'
}
}]
]
</script>

<template>
<UDropdown :items="items" :popper="{ offsetDistance: 0, placement: 'right-start' }">
<UButton color="white" label="Options" trailing-icon="i-heroicons-chevron-down-20-solid" />
</UDropdown>
</template>
16 changes: 16 additions & 0 deletions docs/components/content/examples/DropdownExamplePlacement.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script setup>
const items = [
[{
label: 'Profile',
avatar: {
src: 'https://avatars.githubusercontent.com/u/739984?v=4'
}
}]
]
</script>

<template>
<UDropdown :items="items" :popper="{ placement: 'right-start' }">
<UButton color="white" label="Options" trailing-icon="i-heroicons-chevron-down-20-solid" />
</UDropdown>
</template>
11 changes: 11 additions & 0 deletions docs/components/content/examples/PopoverExampleArrow.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<UPopover :popper="{ arrow: true }">
<UButton color="white" label="Open" trailing-icon="i-heroicons-chevron-down-20-solid" />

<template #panel>
<div class="p-4">
<Placeholder class="h-20 w-48" />
</div>
</template>
</UPopover>
</template>
11 changes: 11 additions & 0 deletions docs/components/content/examples/PopoverExampleOffset.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<UPopover :popper="{ offsetDistance: 0 }">
<UButton color="white" label="Open" trailing-icon="i-heroicons-chevron-down-20-solid" />

<template #panel>
<div class="p-4">
<Placeholder class="h-20 w-48" />
</div>
</template>
</UPopover>
</template>
11 changes: 11 additions & 0 deletions docs/components/content/examples/PopoverExamplePlacement.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<UPopover :popper="{ placement: 'top-end' }">
<UButton color="white" label="Open" trailing-icon="i-heroicons-chevron-down-20-solid" />

<template #panel>
<div class="p-4">
<Placeholder class="h-20 w-48" />
</div>
</template>
</UPopover>
</template>
9 changes: 9 additions & 0 deletions docs/components/content/examples/SelectMenuExampleArrow.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script setup>
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
const selected = ref(people[0])
</script>

<template>
<USelectMenu v-model="selected" :options="people" :popper="{ arrow: true }" />
</template>
9 changes: 9 additions & 0 deletions docs/components/content/examples/SelectMenuExampleOffset.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script setup>
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
const selected = ref(people[0])
</script>

<template>
<USelectMenu v-model="selected" :options="people" :popper="{ offsetDistance: 0 }" />
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script setup>
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
const selected = ref(people[0])
</script>

<template>
<USelectMenu v-model="selected" :options="people" :popper="{ placement: 'left-end' }" />
</template>
16 changes: 16 additions & 0 deletions docs/content/2.elements/6.dropdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ Use the `mode` prop to switch between `click` and `hover` modes.

:component-example{component="dropdown-example-mode"}

## Popper

Use the `popper` prop to customize the popper instance.

### Arrow

:component-example{component="dropdown-example-arrow"}

### Placement

:component-example{component="dropdown-example-placement"}

### Offset

:component-example{component="dropdown-example-offset"}

## Slots

### `item`
Expand Down
16 changes: 16 additions & 0 deletions docs/content/3.forms/4.select-menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,22 @@ Try to search for something that doesn't exist in the example below.

:component-example{component="select-menu-example-creatable" :componentProps='{"class": "w-full lg:w-40"}'}

## Popper

Use the `popper` prop to customize the popper instance.

### Arrow

:component-example{component="select-menu-example-arrow"}

### Placement

:component-example{component="select-menu-example-placement"}

### Offset

:component-example{component="select-menu-example-offset"}

## Slots

### `label`
Expand Down
16 changes: 16 additions & 0 deletions docs/content/6.overlays/3.popover.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,22 @@ Use the `open` prop to manually control showing the panel.

:component-example{component="popover-example-open"}

## Popper

Use the `popper` prop to customize the popper instance.

### Arrow

:component-example{component="popover-example-arrow"}

### Placement

:component-example{component="popover-example-placement"}

### Offset

:component-example{component="popover-example-offset"}

## Slots

### `panel`
Expand Down
2 changes: 1 addition & 1 deletion docs/content/6.overlays/4.tooltip.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ links:

## Popper

Use the `popper` prop to customize the tootip.
Use the `popper` prop to customize the popper instance.

### Arrow

Expand Down
16 changes: 16 additions & 0 deletions docs/content/6.overlays/5.context-menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@ links:

:component-example{component="context-menu-example"}

## Popper

Use the `popper` prop to customize the popper instance.

### Arrow

:component-example{component="context-menu-example-arrow"}

### Placement

:component-example{component="context-menu-example-placement"}

### Offset

:component-example{component="context-menu-example-offset"}

## Props

:component-props
Expand Down
49 changes: 27 additions & 22 deletions src/runtime/components/elements/Dropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,31 @@

<div v-if="open && items.length" ref="container" :class="[ui.container, ui.width]" :style="containerStyle" @mouseover="onMouseOver">
<Transition appear v-bind="ui.transition">
<HMenuItems :class="[ui.base, ui.divide, ui.ring, ui.rounded, ui.shadow, ui.background, ui.height]" static>
<div v-for="(subItems, index) of items" :key="index" :class="ui.padding">
<HMenuItem v-for="(item, subIndex) of subItems" :key="subIndex" v-slot="{ active, disabled: itemDisabled }" :disabled="item.disabled">
<ULink
v-bind="omit(item, ['label', 'slot', 'icon', 'iconClass', 'avatar', 'shortcuts', 'disabled', 'click'])"
:class="[ui.item.base, ui.item.padding, ui.item.size, ui.item.rounded, active ? ui.item.active : ui.item.inactive, itemDisabled && ui.item.disabled]"
@click="item.click"
>
<slot :name="item.slot || 'item'" :item="item">
<UIcon v-if="item.icon" :name="item.icon" :class="[ui.item.icon.base, active ? ui.item.icon.active : ui.item.icon.inactive, item.iconClass]" />
<UAvatar v-else-if="item.avatar" v-bind="{ size: ui.item.avatar.size, ...item.avatar }" :class="ui.item.avatar.base" />

<span class="truncate">{{ item.label }}</span>

<span v-if="item.shortcuts?.length" :class="ui.item.shortcuts">
<UKbd v-for="shortcut of item.shortcuts" :key="shortcut">{{ shortcut }}</UKbd>
</span>
</slot>
</ULink>
</HMenuItem>
</div>
</HMenuItems>
<div>
<div v-if="popper.arrow" data-popper-arrow :class="['invisible before:visible before:block before:rotate-45 before:z-[-1]', Object.values(ui.arrow)]" />
<HMenuItems :class="[ui.base, ui.divide, ui.ring, ui.rounded, ui.shadow, ui.background, ui.height]" static>
<div v-for="(subItems, index) of items" :key="index" :class="ui.padding">
<HMenuItem v-for="(item, subIndex) of subItems" :key="subIndex" v-slot="{ active, disabled: itemDisabled }" :disabled="item.disabled">
<ULink
v-bind="omit(item, ['label', 'slot', 'icon', 'iconClass', 'avatar', 'shortcuts', 'disabled', 'click'])"
:class="[ui.item.base, ui.item.padding, ui.item.size, ui.item.rounded, active ? ui.item.active : ui.item.inactive, itemDisabled && ui.item.disabled]"
@click="item.click"
>
<slot :name="item.slot || 'item'" :item="item">
<UIcon v-if="item.icon" :name="item.icon" :class="[ui.item.icon.base, active ? ui.item.icon.active : ui.item.icon.inactive, item.iconClass]" />
<UAvatar v-else-if="item.avatar" v-bind="{ size: ui.item.avatar.size, ...item.avatar }" :class="ui.item.avatar.base" />

<span class="truncate">{{ item.label }}</span>

<span v-if="item.shortcuts?.length" :class="ui.item.shortcuts">
<UKbd v-for="shortcut of item.shortcuts" :key="shortcut">{{ shortcut }}</UKbd>
</span>
</slot>
</ULink>
</HMenuItem>
</div>
</HMenuItems>
</div>
</Transition>
</div>
</HMenu>
Expand Down Expand Up @@ -185,6 +188,8 @@ export default defineComponent({
// eslint-disable-next-line vue/no-dupe-keys
ui,
attrs,
// eslint-disable-next-line vue/no-dupe-keys
popper,
trigger,
container,
containerStyle,
Expand Down
Loading

1 comment on commit f785ecd

@vercel
Copy link

@vercel vercel bot commented on f785ecd Oct 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

ui – ./

ui-nuxt-js.vercel.app
ui.nuxt.com
ui-git-dev-nuxt-js.vercel.app

Please sign in to comment.