Skip to content

Commit

Permalink
Board: Extend popup positioning for Kanban card (#1483)
Browse files Browse the repository at this point in the history
Signed-off-by: Anna No <anna.no@xored.com>
  • Loading branch information
annano authored Apr 21, 2022
1 parent 588dd22 commit 70579c2
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 30 deletions.
71 changes: 50 additions & 21 deletions packages/ui/src/popups.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AnySvelteComponent, AnyComponent, PopupAlignment } from './types'
import { AnySvelteComponent, AnyComponent, PopupAlignment, PopupPositionElement } from './types'
import { getResource } from '@anticrm/platform'
import { writable } from 'svelte/store'

Expand Down Expand Up @@ -30,15 +30,17 @@ export function showPopup (
const id = `${popupId++}`
const closePopupOp = (): void => {
popupstore.update((popups) => {
const pos = popups.findIndex(p => p.id === id)
const pos = popups.findIndex((p) => p.id === id)
if (pos !== -1) {
popups.splice(pos, 1)
}
return popups
})
}
if (typeof component === 'string') {
getResource(component).then((resolved) => addPopup({ id, is: resolved, props, element, onClose, onUpdate, close: closePopupOp })).catch((err) => console.log(err))
getResource(component)
.then((resolved) => addPopup({ id, is: resolved, props, element, onClose, onUpdate, close: closePopupOp }))
.catch((err) => console.log(err))
} else {
addPopup({ id, is: component, props, element, onClose, onUpdate, close: closePopupOp })
}
Expand Down Expand Up @@ -104,6 +106,50 @@ export function closeDatePopup (): void {
})
}

/**
* @public
*
* Place element based on position and element.
*
* return boolean to show or not modal overlay.
*/
export function fitPopupPositionedElement (modalHTML: HTMLElement, alignment: PopupPositionElement): boolean {
const rect = alignment.getBoundingClientRect()
const rectPopup = modalHTML.getBoundingClientRect()
modalHTML.style.left = modalHTML.style.right = modalHTML.style.top = modalHTML.style.bottom = ''
modalHTML.style.maxHeight = modalHTML.style.height = ''
if (alignment.position) {
if (alignment.position.v === 'top') {
modalHTML.style.top = `${rect.top}px`
} else if (alignment.position.v === 'bottom') {
modalHTML.style.top = `${rect.bottom - rectPopup.height}px`
}

if (alignment.position.h === 'right') {
modalHTML.style.left = `calc(${rect.right}px + .125rem)`
} else if (alignment.position.h === 'left') {
modalHTML.style.left = `calc(${rect.left - rectPopup.width}px - .125rem)`
}
} else {
// Vertical
if (rect.bottom + rectPopup.height + 28 <= document.body.clientHeight) {
modalHTML.style.top = `calc(${rect.bottom}px + .125rem)`
} else if (rectPopup.height + 28 < rect.top) {
modalHTML.style.bottom = `calc(${document.body.clientHeight - rect.y}px + .125rem)`
} else {
modalHTML.style.top = modalHTML.style.bottom = '1rem'
}

// Horizontal
if (rect.left + rectPopup.width + 16 > document.body.clientWidth) {
modalHTML.style.right = `${document.body.clientWidth - rect.right}px`
} else {
modalHTML.style.left = `${rect.left}px`
}
}
return false
}

/**
* @public
*
Expand All @@ -118,24 +164,7 @@ export function fitPopupElement (modalHTML: HTMLElement, element?: PopupAlignmen
modalHTML.style.left = modalHTML.style.right = modalHTML.style.top = modalHTML.style.bottom = ''
modalHTML.style.maxHeight = modalHTML.style.height = ''
if (typeof element !== 'string') {
const el = element as HTMLElement
const rect = el.getBoundingClientRect()
const rectPopup = modalHTML.getBoundingClientRect()
// Vertical
if (rect.bottom + rectPopup.height + 28 <= document.body.clientHeight) {
modalHTML.style.top = `calc(${rect.bottom}px + .125rem)`
} else if (rectPopup.height + 28 < rect.top) {
modalHTML.style.bottom = `calc(${document.body.clientHeight - rect.y}px + .125rem)`
} else {
modalHTML.style.top = modalHTML.style.bottom = '1rem'
}

// Horizontal
if (rect.left + rectPopup.width + 16 > document.body.clientWidth) {
modalHTML.style.right = `${document.body.clientWidth - rect.right}px`
} else {
modalHTML.style.left = `${rect.left}px`
}
return fitPopupPositionedElement(modalHTML, element)
} else if (element === 'right' && contentPanel !== undefined) {
const rect = contentPanel.getBoundingClientRect()
modalHTML.style.top = `calc(${rect.top}px + 0.5rem)`
Expand Down
6 changes: 6 additions & 0 deletions packages/ui/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,15 @@ export type ButtonKind = 'primary' | 'secondary' | 'no-border' | 'transparent' |
export type ButtonSize = 'small' | 'medium' | 'large' | 'x-large'
export interface PopupPositionElement {
getBoundingClientRect: () => DOMRect
position?: {
v: VerticalAlignment
h: HorizontalAlignment
}
}
export type PopupAlignment = PopupPositionElement | null | 'right' | 'top' | 'account' | 'full' | 'content' | 'middle'
export type TooltipAlignment = 'top' | 'bottom' | 'left' | 'right'
export type VerticalAlignment = 'top' | 'bottom'
export type HorizontalAlignment = 'left' | 'right'

export interface LabelAndProps {
label: IntlString | undefined
Expand Down
10 changes: 6 additions & 4 deletions plugins/board-resources/src/components/KanbanCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@
import type { Ref, WithLookup } from '@anticrm/core'
import notification from '@anticrm/notification'
import { getClient, UserBoxList } from '@anticrm/presentation'
import { Button, Component, IconEdit, IconMoreH, Label, showPanel, showPopup } from '@anticrm/ui'
import { Button, Component, IconEdit, Label, showPanel, showPopup } from '@anticrm/ui'
import { ContextMenu } from '@anticrm/view-resources'
import board from '../plugin'
import { hasDate } from '../utils/CardUtils'
import { getElementPopupAlignment } from '../utils/PopupUtils'
import CardLabels from './editor/CardLabels.svelte'
import DatePresenter from './presenters/DatePresenter.svelte'
Expand All @@ -33,11 +34,12 @@
let loadingAttachment = 0
let dragoverAttachment = false
let ref: HTMLElement
const client = getClient()
function showMenu (ev?: Event): void {
showPopup(ContextMenu, { object }, (ev as MouseEvent).target as HTMLElement)
function showMenu (): void {
showPopup(ContextMenu, { object }, getElementPopupAlignment(ref, { h: 'right', v: 'top' }))
}
function showCard () {
Expand Down Expand Up @@ -65,7 +67,7 @@
objectId={object._id}
space={object.space}
canDrop={canDropAttachment}>
<div class="relative flex-col pt-2 pb-1 pr-2 pl-2">
<div class="relative flex-col pt-2 pb-1 pr-2 pl-2" bind:this={ref}>
{#if dragoverAttachment}
<div style:pointer-events="none" class="abs-full-content h-full w-full flex-center fs-title">
<Label label={board.string.DropFileToUpload} />
Expand Down
2 changes: 1 addition & 1 deletion plugins/board-resources/src/components/KanbanView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
{space}
{search}
{options}
query={{ doneState: null, isArchived: {$nin: [true]} }}
query={{ doneState: null, isArchived: { $nin: [true] } }}
{states}
fieldName={'state'}
rankFieldName={'rank'}
Expand Down
14 changes: 10 additions & 4 deletions plugins/board-resources/src/utils/PopupUtils.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { PopupAlignment } from '@anticrm/ui'
import { HorizontalAlignment, VerticalAlignment } from '@anticrm/ui/src/types'

export function getPopupAlignment (e?: Event): PopupAlignment | undefined {
export function getPopupAlignment (e?: Event, position?: {v: VerticalAlignment, h: HorizontalAlignment}): PopupAlignment | undefined {
if (!e || !e.target) {
return undefined
}
const target = e.target as HTMLElement
if (target.getBoundingClientRect) {
const result = target.getBoundingClientRect()
return getElementPopupAlignment(target, position)
}

export function getElementPopupAlignment (el: HTMLElement, position?: {v: VerticalAlignment, h: HorizontalAlignment}): PopupAlignment | undefined {
if (el?.getBoundingClientRect) {
const result = el.getBoundingClientRect()
return {
getBoundingClientRect: () => result
getBoundingClientRect: () => result,
position
}
}

Expand Down

0 comments on commit 70579c2

Please sign in to comment.