Position tooltip and edit box in same place. (#1770)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov 2022-05-17 13:04:07 +03:00 committed by GitHub
parent 29058d8c84
commit e0ea083287
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 106 additions and 28 deletions

View File

@ -24,7 +24,11 @@
let modalHTML: HTMLElement
let componentInstance: any
let show: boolean = false
let options: {
show: boolean
direction: string
} = { show: false, direction: 'bottom' }
let component: AnySvelteComponent
@ -58,7 +62,7 @@
const fitPopup = (props: PanelProps, contentPanel: HTMLElement): void => {
if (modalHTML) {
show = fitPopupElement(modalHTML, props.element, contentPanel)
options = fitPopupElement(modalHTML, props.element, contentPanel)
}
}
@ -108,7 +112,13 @@
</div>
</div>
{#if props.element !== 'content'}
<div class="modal-overlay" class:show on:click={() => escapeClose()} on:keydown={() => {}} on:keyup={() => {}} />
<div
class="modal-overlay"
class:show={options.show}
on:click={() => escapeClose()}
on:keydown={() => {}}
on:keyup={() => {}}
/>
{/if}
{/if}
{/if}

View File

@ -29,9 +29,13 @@
let modalHTML: HTMLElement
let componentInstance: any
let show: boolean = false
let height: number
let options: {
show: boolean
direction: string
} = { show: false, direction: 'bottom' }
function _update (result: any): void {
if (onUpdate !== undefined) onUpdate(result)
fitPopup()
@ -51,7 +55,7 @@
const fitPopup = (): void => {
if (modalHTML) {
show = fitPopupElement(modalHTML, element)
options = fitPopupElement(modalHTML, element)
}
}
@ -71,13 +75,19 @@
this={is}
bind:this={componentInstance}
{...props}
direction={options.direction}
on:update={(ev) => {
_update(ev.detail)
}}
on:close={(ev) => _close(ev.detail)}
/>
</div>
<div class="modal-overlay" class:antiOverlay={show} style={`z-index: ${zIndex};`} on:click={() => escapeClose()} />
<div
class="modal-overlay"
class:antiOverlay={options.show}
style={`z-index: ${zIndex};`}
on:click={() => escapeClose()}
/>
<style lang="scss">
.popup {

View File

@ -196,7 +196,7 @@
background-color: var(--accent-bg-color);
border: 1px solid var(--divider-color);
border-radius: 0.75rem;
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.2);
box-shadow: var(--popup-aside-shadow);
user-select: none;
z-index: 10000;
@ -285,7 +285,7 @@
background-color: var(--accent-bg-color);
border: 1px solid var(--divider-color);
border-radius: 0.75rem;
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.2);
box-shadow: var(--popup-aside-shadow);
user-select: none;
z-index: 10000;

View File

@ -117,7 +117,8 @@ export function fitPopupPositionedElement (
modalHTML: HTMLElement,
alignment: PopupPositionElement,
newProps: Record<string, string | number>
): boolean {
): { show: boolean, direction: string } {
let direction: string = ''
const rect = alignment.getBoundingClientRect()
const rectPopup = modalHTML.getBoundingClientRect()
newProps.left = newProps.right = newProps.top = newProps.bottom = ''
@ -135,24 +136,30 @@ export function fitPopupPositionedElement (
} else if (alignment.position.h === 'left') {
newProps.left = `calc(${rect.left - rectPopup.width}px - .125rem)`
}
direction = alignment.position.v + '|' + alignment.position.h
} else {
// Vertical
if (rect.bottom + rectPopup.height + 28 <= document.body.clientHeight) {
newProps.top = `${rect.bottom + 1}px`
direction = 'bottom'
} else if (rectPopup.height + 28 < rect.top) {
newProps.bottom = `${document.body.clientHeight - rect.top + 1}px`
direction = 'top'
} else {
newProps.top = modalHTML.style.bottom = '1rem'
direction = 'top'
}
// Horizontal
if (rect.left + rectPopup.width + 16 > document.body.clientWidth) {
newProps.right = `${document.body.clientWidth - rect.right}px`
direction += '|left'
} else {
newProps.left = `${rect.left}px`
direction += '|right'
}
}
return false
return { show: false, direction }
}
function applyStyle (values: Record<string, string | number>, modalHTML: HTMLElement): void {
@ -171,7 +178,11 @@ function applyStyle (values: Record<string, string | number>, modalHTML: HTMLEle
*
* return boolean to show or not modal overlay.
*/
export function fitPopupElement (modalHTML: HTMLElement, element?: PopupAlignment, contentPanel?: HTMLElement): boolean {
export function fitPopupElement (
modalHTML: HTMLElement,
element?: PopupAlignment,
contentPanel?: HTMLElement
): { show: boolean, direction: string } {
let show = true
const newProps: Record<string, string | number> = {}
if (element != null) {
@ -238,7 +249,7 @@ export function fitPopupElement (modalHTML: HTMLElement, element?: PopupAlignmen
show = true
}
applyStyle(newProps, modalHTML)
return show
return { show, direction: '' }
}
export function eventToHTMLElement (evt: MouseEvent): HTMLElement {

View File

@ -1,11 +1,11 @@
// This file is read by tools that parse documentation comments conforming to the TSDoc standard.
// It should be published with your NPM package. It should not be tracked by Git.
{
"tsdocVersion": "0.12",
"toolPackages": [
{
"packageName": "@microsoft/api-extractor",
"packageVersion": "7.23.0"
}
]
}
// This file is read by tools that parse documentation comments conforming to the TSDoc standard.
// It should be published with your NPM package. It should not be tracked by Git.
{
"tsdocVersion": "0.12",
"toolPackages": [
{
"packageName": "@microsoft/api-extractor",
"packageVersion": "7.23.0"
}
]
}

View File

@ -13,7 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import { createEventDispatcher, onMount } from 'svelte'
import { createEventDispatcher, onMount, afterUpdate } from 'svelte'
import type { IntlString } from '@anticrm/platform'
import { translate } from '@anticrm/platform'
import {
@ -34,6 +34,7 @@
export let placeholder: IntlString
export let editable: boolean | undefined = undefined
export let openable: boolean = false
export let direction: string = 'bottom'
const dispatch = createEventDispatcher()
let input: HTMLInputElement
@ -73,11 +74,21 @@
$: if (input) {
input.addEventListener('focus', updateFocus, { once: true })
}
const vDir = (d: string): string => d.split('|')[0]
const fitEditor = (): void => {
dir = vDir(direction)
}
$: dir = vDir(direction)
afterUpdate(() => {
fitEditor()
})
</script>
<svelte:window on:resize={fitEditor} on:scroll={fitEditor} />
<FocusHandler manager={mgr} />
{#if editable && editable === true}
<div class="editor-container buttons-group xsmall-gap">
<div class="editor-container {dir} buttons-group xsmall-gap">
<div class="cover-channel" class:show class:copied={label === plugin.string.Copied} data-tooltip={lTraslate}>
<input
bind:this={input}
@ -210,11 +221,47 @@
}
.editor-container {
margin-top: 0.25rem;
padding: 0.5rem;
background-color: var(--accent-bg-color);
border: 1px solid var(--divider-color);
border-radius: 0.25rem;
box-shadow: var(--popup-panel-shadow);
border-radius: 0.75rem;
box-shadow: var(--popup-aside-shadow);
&.top {
transform: translate(calc(-50% + 0.75rem), -0.5rem);
}
&.bottom {
transform: translate(calc(-50% + 0.75rem), 0.5rem);
}
&.top::after,
&.top::before,
&.bottom::after,
&.bottom::before {
content: '';
position: absolute;
margin-left: -9px;
top: -6px;
left: 50%;
width: 18px;
height: 7px;
}
&.top::before,
&.bottom::before {
background-color: var(--accent-bg-color);
clip-path: url('#nub-bg');
z-index: 1;
}
&.top::after,
&.bottom::after {
background-color: var(--divider-color);
clip-path: url('#nub-border');
z-index: 2;
}
&.top::after,
&.top::before {
top: calc(100% - 1px);
transform-origin: center center;
transform: rotate(180deg);
}
}
</style>