UX Enhancements and custom positioning behaviour for the popover

This commit is contained in:
Dean 2023-08-25 11:19:28 +01:00
parent 7492a70bcf
commit 13f6fed101
4 changed files with 93 additions and 32 deletions

View File

@ -17,6 +17,7 @@ export default function positionDropdown(element, opts) {
maxWidth,
useAnchorWidth,
offset = 5,
customUpdate,
} = opts
if (!anchor) {
return
@ -32,33 +33,42 @@ export default function positionDropdown(element, opts) {
left: null,
top: null,
}
// Determine vertical styles
if (align === "right-outside") {
styles.top = anchorBounds.top
} else if (window.innerHeight - anchorBounds.bottom < (maxHeight || 100)) {
styles.top = anchorBounds.top - elementBounds.height - offset
styles.maxHeight = maxHeight || 240
} else {
styles.top = anchorBounds.bottom + offset
styles.maxHeight =
maxHeight || window.innerHeight - anchorBounds.bottom - 20
}
// Determine horizontal styles
if (!maxWidth && useAnchorWidth) {
styles.maxWidth = anchorBounds.width
}
if (useAnchorWidth) {
styles.minWidth = anchorBounds.width
}
if (align === "right") {
styles.left = anchorBounds.left + anchorBounds.width - elementBounds.width
} else if (align === "right-outside") {
styles.left = anchorBounds.right + offset
} else if (align === "left-outside") {
styles.left = anchorBounds.left - elementBounds.width - offset
if (typeof customUpdate === "function") {
styles = customUpdate(anchorBounds, elementBounds, styles)
} else {
styles.left = anchorBounds.left
// Determine vertical styles
if (align === "right-outside") {
styles.top = anchorBounds.top
} else if (
window.innerHeight - anchorBounds.bottom <
(maxHeight || 100)
) {
styles.top = anchorBounds.top - elementBounds.height - offset
styles.maxHeight = maxHeight || 240
} else {
styles.top = anchorBounds.bottom + offset
styles.maxHeight =
maxHeight || window.innerHeight - anchorBounds.bottom - 20
}
// Determine horizontal styles
if (!maxWidth && useAnchorWidth) {
styles.maxWidth = anchorBounds.width
}
if (useAnchorWidth) {
styles.minWidth = anchorBounds.width
}
if (align === "right") {
styles.left =
anchorBounds.left + anchorBounds.width - elementBounds.width
} else if (align === "right-outside") {
styles.left = anchorBounds.right + offset
} else if (align === "left-outside") {
styles.left = anchorBounds.left - elementBounds.width - offset
} else {
styles.left = anchorBounds.left
}
}
// Apply styles

View File

@ -23,6 +23,7 @@
export let animate = true
export let customZindex
export let handlePostionUpdate
export let showPopover = true
export let clickOutsideOverride = false
@ -88,6 +89,7 @@
maxWidth,
useAnchorWidth,
offset,
customUpdate: handlePostionUpdate,
}}
use:clickOutside={{
callback: dismissible ? handleOutsideClick : () => {},

View File

@ -3,15 +3,30 @@
import { dndzone } from "svelte-dnd-action"
import { createEventDispatcher } from "svelte"
import { generate } from "shortid"
import { setContext } from "svelte"
import { writable } from "svelte/store"
export let items = []
export let showHandle = true
export let highlighted
export let listType
export let listTypeProps = {}
export let listItemKey
export let draggable = true
let store = writable({
selected: null,
actions: {
select: id => {
store.update(state => ({
...state,
selected: id,
}))
},
},
})
setContext("draggable", store)
const dispatch = createEventDispatcher()
const flipDurationMs = 150
@ -66,7 +81,7 @@
{#each draggableItems as draggable (draggable.id)}
<li
bind:this={anchors[draggable.id]}
class:highlighted={draggable.id === highlighted}
class:highlighted={draggable.id === $store.selected}
>
<div class="left-content">
{#if showHandle}
@ -113,7 +128,8 @@
border-bottom: 1px solid
var(--spectrum-table-border-color, var(--spectrum-alias-border-color-mid));
}
.list-wrap > li:hover {
.list-wrap > li:hover,
li.highlighted {
background-color: var(
--spectrum-table-row-background-color-hover,
var(--spectrum-alias-highlight-hover)
@ -135,7 +151,4 @@
padding-left: var(--spacing-s);
padding-right: var(--spacing-s);
}
li.highlighted {
background-color: pink;
}
</style>

View File

@ -4,17 +4,24 @@
import { cloneDeep } from "lodash/fp"
import { createEventDispatcher } from "svelte"
import ComponentSettingsSection from "../../../../../pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/ComponentSettingsSection.svelte"
import { getContext } from "svelte"
export let anchor
export let field
export let componentBindings
export let bindings
const draggable = getContext("draggable")
const dispatch = createEventDispatcher()
let popover
let drawers = []
let sudoComponentInstance
let open = false
$: if (open && $draggable.selected && $draggable.selected != field._id) {
popover.hide()
}
$: if (field) {
sudoComponentInstance = field
@ -61,7 +68,10 @@
hoverable
size="S"
on:click={() => {
popover.show()
if (!open) {
popover.show()
open = true
}
}}
/>
@ -69,11 +79,37 @@
bind:this={popover}
on:open={() => {
drawers = []
$draggable.actions.select(field._id)
}}
on:close={() => {
open = false
if ($draggable.selected == field._id) {
$draggable.actions.select()
}
}}
{anchor}
align="left-outside"
showPopover={drawers.length == 0}
clickOutsideOverride={drawers.length > 0}
maxHeight={600}
handlePostionUpdate={(anchorBounds, eleBounds, cfg) => {
let { left, top } = cfg
let percentageOffset = 30
// left-outside
left = anchorBounds.left - eleBounds.width - 5
// shift up from the anchor, if space allows
let offsetPos = Math.floor(eleBounds.height / 100) * percentageOffset
let defaultTop = anchorBounds.top - offsetPos
if (window.innerHeight - defaultTop < eleBounds.height) {
top = window.innerHeight - eleBounds.height - 5
} else {
top = anchorBounds.top - offsetPos
}
return { ...cfg, left, top }
}}
>
<span class="popover-wrap">
<Layout noPadding noGap>