Popover
Popover can be used for dropdowns and other popovers when element is clicked and focused.
View SourceUsage
@import "winduum/src/components/popover/index.css" layer(components);
<div class="c-popover focus">
<div role="button" class="ui-btn" tabindex="0">Popover</div>
<div class="c-popover-content center shadow dark:bg-body-secondary mt-2.5 p-2 w-32 flex-col">
<button class="ui-btn ghosted accent-main justify-start w-full">Item 1</button>
<button class="ui-btn ghosted accent-main justify-start w-full">Item 2</button>
</div>
</div>
<script setup>
import { ref } from 'vue'
import { Popover, PopoverContent } from '@/components/popover'
import { UiBtn } from '@/components/ui/btn'
</script>
<template>
<Popover>
<UiBtn>Open Popover</UiBtn>
<PopoverContent>
Popover content
</PopoverContent>
</Popover>
</template>
Variants
Tokens
Applicable to c-popover-content
bottom
bottom-start
bottom-end
right
right-start
right-end
left
left-start
left-end
top
top-start
top-end
end
block-end
center
block-center
Installation
Follow instructions for individual framework usage below
Examples
Basic
<div class="c-popover focus">
<div role="button" class="ui-btn" tabindex="0">Popover</div>
<div class="c-popover-content center shadow dark:bg-body-secondary mt-2.5 p-2 w-32 flex-col">
<button class="ui-btn ghosted accent-main justify-start w-full">Item 1</button>
<button class="ui-btn ghosted accent-main justify-start w-full">Item 2</button>
</div>
</div>
Hover
<div class="c-popover hover">
<div role="button" class="ui-btn" tabindex="0">Popover</div>
<div class="c-popover-content center shadow dark:bg-body-secondary mt-2.5 p-2 w-32 flex-col">
<button class="ui-btn ghosted accent-main justify-start w-full">Item 1</button>
<button class="ui-btn ghosted accent-main justify-start w-full">Item 2</button>
</div>
</div>
Popover API
This is using advantages of Popover API with floating-ui. It's also backwards compatible as it's leveraging only the showPopover
and hidePopover
for a top-layer support.
Popover is placed dynamically upon available space, and auto updates itself when needed.
<div class="c-popover w-full flex-col items-center">
<button class="ui-btn" popovertargetaction="toggle" popovertarget="popover">Popover</button>
<div class="c-popover-content shadow dark:bg-body-secondary p-2" id="popover" popover="manual">
<input type="text" autofocus>
</div>
</div>
JavaScript API
showPopover
- Type:
(element: HTMLElement | Element, options?: ShowPopoverOptions) => Promise<void>
- Kind:
async
Example
import { showPopover, hidePopover } from '/src/components/popover'
const popoverActionElement = document?.querySelector('[popovertargetaction="show"]')
popoverActionElement?.addEventListener('click', async (e) => {
e.preventDefault()
const currentTarget = e.currentTarget
await showPopover(currentTarget, {
placement: 'right-end',
})
})
// close on esc
window.addEventListener('keydown', ({ key }) => {
if (key === 'Escape') {
hidePopover(popoverActionElement)
}
})
// outside dismiss
window.addEventListener('click', ({ target }) => {
if (!window.popover?.contains(target) && !popoverActionElement?.isEqualNode(target) && popoverActionElement?.ariaExpanded === 'true') {
hidePopover(popoverActionElement)
}
})
ShowPopoverOptions
visibleClass
- Type:
string
- Default:
in
A string representing a CSS class that will be added when popover is visible.
compute
- Type:
boolean
- Default:
true
Determines if the popover should be anchored and computed with @floating-ui/dom
placement
- Type:
Placement
- Default:
undefined
Determines placement of the popover with @floating-ui/dom
, also adds a corresponding class to the popover target.
middleware
- Type:
Array<Middleware | null | undefined | false>
- Default:
[offset(12 ?? options?.offset), flip(options?.flip), shift({ padding: 8, ...options?.shift })]
Customize middleware for @floating-ui/dom
offset
- Type:
OffsetOptions
- Default:
12
Customize offset options for @floating-ui/dom
flip
- Type:
FlipOptions
- Default:
undefined
Customize flip options for @floating-ui/dom
shift
- Type:
ShiftOptions
- Default:
undefined
Customize shift options for @floating-ui/dom
hidePopover
- Type:
(element: HTMLElement | Element) => Promise<void>
- Kind:
async
Example
import { hidePopover } from '/src/components/popover'
const popoverActionElement = document?.querySelector('[popovertargetaction="hide"]')
popoverActionElement?.addEventListener('click', async (e) => {
e.preventDefault()
const currentTarget = e.currentTarget
await hidePopover(currentTarget)
})
togglePopover
- Type:
(element: HTMLElement | Element, options?: ShowPopoverOptions) => Promise<void>
- Kind:
async
Example
import { togglePopover, hidePopover } from '/src/components/popover'
const popoverActionElement = document?.querySelector('[popovertargetaction="toggle"]')
popoverActionElement?.addEventListener('click', async (e) => {
e.preventDefault()
const currentTarget = e.currentTarget
await togglePopover(currentTarget)
})
// close on esc
window.addEventListener('keydown', ({ key }) => {
if (key === 'Escape') {
hidePopover(popoverActionElement)
}
})
// outside dismiss
window.addEventListener('click', ({ target }) => {
if (!window.popover?.contains(target) && !popoverActionElement?.isEqualNode(target) && popoverActionElement?.ariaExpanded === 'true') {
hidePopover(popoverActionElement)
}
})