From f57711e9e9ee79f1cd9db3288b2ff6b62a2a8d0c Mon Sep 17 00:00:00 2001 From: Alexander Platov <sas_lord@mail.ru> Date: Wed, 1 Sep 2021 19:31:05 +0300 Subject: [PATCH] Replace Modal with Popup (#119) Signed-off-by: Alexander Platov <sas_lord@mail.ru> --- .../ui/src/components/PopupInstance.svelte | 37 +++++---- packages/ui/src/index.ts | 14 +--- packages/ui/src/types.ts | 2 + .../src/components/DialogHeader.svelte | 4 +- .../src/components/EditCandidate.svelte | 2 +- .../src/components/TableView.svelte | 2 +- .../src/components/Modal.svelte | 83 ------------------- .../src/components/Workbench.svelte | 2 - .../src/components/navigator/SpacesNav.svelte | 4 +- 9 files changed, 32 insertions(+), 118 deletions(-) delete mode 100644 plugins/workbench-resources/src/components/Modal.svelte diff --git a/packages/ui/src/components/PopupInstance.svelte b/packages/ui/src/components/PopupInstance.svelte index 13ae9a3ec3..f919cfac0b 100644 --- a/packages/ui/src/components/PopupInstance.svelte +++ b/packages/ui/src/components/PopupInstance.svelte @@ -16,12 +16,12 @@ <script lang="ts"> import Component from './Component.svelte' -import type { AnySvelteComponent, AnyComponent } from '../types' +import type { AnySvelteComponent, AnyComponent, PopupAlignment } from '../types' import { closePopup } from '..' export let is: AnyComponent | AnySvelteComponent export let props: object -export let element: HTMLElement | undefined +export let element: PopupAlignment | undefined export let onClose: (result: any) => void | undefined export let zIndex: number @@ -37,27 +37,32 @@ function close(ev: CustomEvent) { $: { if (modalHTML) { if (element) { - const rect = element.getBoundingClientRect() - if (rect.top > document.body.clientHeight - rect.bottom) { - modalHTML.style.bottom = `calc(${document.body.clientHeight - rect.top}px + .75rem)` - } else { - modalHTML.style.top = `calc(${rect.bottom}px + .75rem)` - } - if (rect.left > document.body.clientWidth - rect.right) { - modalHTML.style.right = document.body.clientWidth - rect.right + 'px' - } else { - modalHTML.style.left = rect.left + 'px' + if (typeof element !== 'string') { + const rect = element.getBoundingClientRect() + if (rect.top > document.body.clientHeight - rect.bottom) { + modalHTML.style.bottom = `calc(${document.body.clientHeight - rect.top}px + .75rem)` + } else { + modalHTML.style.top = `calc(${rect.bottom}px + .75rem)` + } + if (rect.left > document.body.clientWidth - rect.right) { + modalHTML.style.right = document.body.clientWidth - rect.right + 'px' + } else { + modalHTML.style.left = rect.left + 'px' + } + } else if (element === 'right') { + modalHTML.style.top = '4rem' + modalHTML.style.bottom = '4rem' + modalHTML.style.right = '4rem' } } else { - modalHTML.style.top = '4rem' - modalHTML.style.bottom = '4rem' - modalHTML.style.right = '4rem' + modalHTML.style.top = '50%' + modalHTML.style.left = '50%' + modalHTML.style.transform = 'translate(-50%, -50%)' } } } </script> - <div class="popup" bind:this={modalHTML} style={`z-index: ${zIndex + 1};`}> {#if typeof(is) === 'string'} <Component is={is} props={props} on:close={close}/> diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index bbd2c405a3..31029db1d7 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -61,7 +61,7 @@ export { default as IconComments } from './components/icons/Comments.svelte' export * from './utils' -import type { AnySvelteComponent, AnyComponent } from './types' +import type { AnySvelteComponent, AnyComponent, PopupAlignment } from './types' import { writable } from 'svelte/store' export function createApp (target: HTMLElement): SvelteComponent { @@ -71,7 +71,7 @@ export function createApp (target: HTMLElement): SvelteComponent { interface CompAndProps { is: AnySvelteComponent | AnyComponent | undefined props: any - element?: HTMLElement + element?: PopupAlignment onClose?: (result: any) => void } @@ -80,17 +80,9 @@ export const store = writable<CompAndProps>({ props: {}, }) -export function showModal (component: AnySvelteComponent | AnyComponent, props: any, element?: HTMLElement): void { - store.set({ is: component, props, element: element }) -} - -export function closeModal (): void { - store.set({ is: undefined, props: {}, element: undefined }) -} - export const popupstore = writable<CompAndProps[]>([]) -export function showPopup (component: AnySvelteComponent | AnyComponent, props: any, element?: HTMLElement, onClose?: (result: any) => void): void { +export function showPopup (component: AnySvelteComponent | AnyComponent, props: any, element?: PopupAlignment, onClose?: (result: any) => void): void { popupstore.update(popups => { popups.push({ is: component, props, element, onClose }) return popups diff --git a/packages/ui/src/types.ts b/packages/ui/src/types.ts index b785966c46..20dd740b20 100644 --- a/packages/ui/src/types.ts +++ b/packages/ui/src/types.ts @@ -53,3 +53,5 @@ export interface Tab { } export type TabModel = Tab[] + +export type PopupAlignment = HTMLElement | 'right' diff --git a/plugins/recruit-resources/src/components/DialogHeader.svelte b/plugins/recruit-resources/src/components/DialogHeader.svelte index 710a06d1bc..07708ce5e6 100644 --- a/plugins/recruit-resources/src/components/DialogHeader.svelte +++ b/plugins/recruit-resources/src/components/DialogHeader.svelte @@ -19,7 +19,7 @@ import type { Ref, Space, Doc } from '@anticrm/core' import { generateId } from '@anticrm/core' - import { EditBox, Button, CircleButton, Grid, Label, showModal, Link, showPopup } from '@anticrm/ui' + import { EditBox, Button, CircleButton, Grid, Label, Link, showPopup } from '@anticrm/ui' import type { AnyComponent } from '@anticrm/ui' import { getClient } from '@anticrm/presentation' @@ -117,7 +117,7 @@ on:dragleave={ () => { dragover = false } } on:drop|preventDefault|stopPropagation={drop}> <div class="flex-row-center main-content"> - <div class="avatar" on:click|stopPropagation={() => showModal(AvatarEditor, { label: 'Profile photo' })}><User /></div> + <div class="avatar" on:click|stopPropagation={() => showPopup(AvatarEditor, { label: 'Profile photo' })}><User /></div> <div class="flex-col"> <div class="name"> <EditBox placeholder="John" bind:value={newValue.firstName} on:input={isChanged} focus={create}/> diff --git a/plugins/recruit-resources/src/components/EditCandidate.svelte b/plugins/recruit-resources/src/components/EditCandidate.svelte index 6d007c8a8e..391fbb4a28 100644 --- a/plugins/recruit-resources/src/components/EditCandidate.svelte +++ b/plugins/recruit-resources/src/components/EditCandidate.svelte @@ -16,7 +16,7 @@ <script lang="ts"> import { createEventDispatcher } from 'svelte' import type { Ref, Space, Doc } from '@anticrm/core' - import { Dialog, Tabs } from '@anticrm/ui' + import { Tabs } from '@anticrm/ui' import { getClient } from '@anticrm/presentation' import type { Candidate } from '@anticrm/recruit' import DialogHeader from './DialogHeader.svelte' diff --git a/plugins/view-resources/src/components/TableView.svelte b/plugins/view-resources/src/components/TableView.svelte index bbe8db5f6b..a962826127 100644 --- a/plugins/view-resources/src/components/TableView.svelte +++ b/plugins/view-resources/src/components/TableView.svelte @@ -50,7 +50,7 @@ const client = getClient() function onClick(object: Doc) { - showPopup(open, { object, space }) + showPopup(open, { object, space }, 'right') } </script> diff --git a/plugins/workbench-resources/src/components/Modal.svelte b/plugins/workbench-resources/src/components/Modal.svelte deleted file mode 100644 index 5c57403f55..0000000000 --- a/plugins/workbench-resources/src/components/Modal.svelte +++ /dev/null @@ -1,83 +0,0 @@ -<!-- -// Copyright © 2020 Anticrm Platform Contributors. -// -// Licensed under the Eclipse Public License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. You may -// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// -// See the License for the specific language governing permissions and -// limitations under the License. ---> -<script lang="ts"> - import { store as modal } from '@anticrm/ui' - import { Component } from '@anticrm/ui' - - let modalHTML: HTMLElement - let modalOHTML: HTMLElement - - function close () { - modalHTML.style.animationDirection = modalOHTML.style.animationDirection = 'reverse' - modalHTML.style.animationDuration = modalOHTML.style.animationDuration = '.2s' - modal.set({ is: undefined, props: {}, element: undefined }) - } - - function handleKeydown (ev: KeyboardEvent) { - if (ev.key === 'Escape' && $modal.is) { - close() - } - } - - function getStyle (element: HTMLElement | undefined) { - if (element) { - const rect = element.getBoundingClientRect() - return `top: ${rect.top + rect.height + 2}px; left: ${rect.left}px;` - } else { - return 'top: 50%; left: 50%; transform: translate(-50%, -50%);' - } - } -</script> - -<svelte:window on:keydown={handleKeydown} /> - -{#if $modal.is} - <div class="modal" class:top-arrow={$modal.element} bind:this={modalHTML} style={getStyle($modal.element)}> - {#if typeof($modal.is) === 'string'} - <Component is={$modal.is} props={$modal.props} on:close={close}/> - {:else} - <svelte:component this={$modal.is} {...$modal.props} on:close={close} /> - {/if} - </div> - <div bind:this={modalOHTML} class="modal-overlay" /> -{/if} - -<style lang="scss"> - @keyframes show { - from { opacity: 0; filter: blur(3px); } - 99% { opacity: 1; filter: blur(0px); } - to { filter: none; } - } - @keyframes showOverlay { - from { backdrop-filter: blur(0px); } - to { backdrop-filter: blur(1px); } - } - .modal { - position: fixed; - background: transparent; - z-index: 1001; - animation: show .2s ease-in-out forwards; - } - .modal-overlay { - z-index: 1000; - background: rgba(0, 0, 0, .5); - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - animation: showOverlay .2s ease-in-out forwards; - } -</style> \ No newline at end of file diff --git a/plugins/workbench-resources/src/components/Workbench.svelte b/plugins/workbench-resources/src/components/Workbench.svelte index 1fda75cd60..99cf468c30 100644 --- a/plugins/workbench-resources/src/components/Workbench.svelte +++ b/plugins/workbench-resources/src/components/Workbench.svelte @@ -26,7 +26,6 @@ import workbench from '@anticrm/workbench' import Navigator from './Navigator.svelte' - import Modal from './Modal.svelte' import SpaceHeader from './SpaceHeader.svelte' import SpaceView from './SpaceView.svelte' @@ -92,7 +91,6 @@ </div> <!-- <div class="aside"><Chat thread/></div> --> </div> - <Modal /> <Popup /> {:else} No client diff --git a/plugins/workbench-resources/src/components/navigator/SpacesNav.svelte b/plugins/workbench-resources/src/components/navigator/SpacesNav.svelte index 05091c969b..94c289fa6c 100644 --- a/plugins/workbench-resources/src/components/navigator/SpacesNav.svelte +++ b/plugins/workbench-resources/src/components/navigator/SpacesNav.svelte @@ -23,7 +23,7 @@ import { IconAdd } from '@anticrm/ui' import { getClient, createQuery } from '@anticrm/presentation' - import { showModal } from '@anticrm/ui' + import { showPopup } from '@anticrm/ui' import { classIcon } from '../../utils' @@ -42,7 +42,7 @@ label: model.addSpaceLabel, icon: IconAdd, action: async (): Promise<void> => { - showModal(model.createComponent, {}) + showPopup(model.createComponent, {}) } }