Rework panel navigation (#928)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev
2022-02-04 10:03:24 +01:00
committed by GitHub
parent f2402c3208
commit db52006a9d
25 changed files with 430 additions and 201 deletions
@@ -15,15 +15,15 @@
<script lang="ts">
import type { Ref } from '@anticrm/core';
import { getCurrentLocation,navigate } from '@anticrm/ui';
import type { Application } from '@anticrm/workbench';
import AppItem from './AppItem.svelte';
import type { Ref } from '@anticrm/core'
import { getCurrentLocation, navigate } from '@anticrm/ui'
import type { Application } from '@anticrm/workbench'
import AppItem from './AppItem.svelte'
export let active: Ref<Application> | undefined
export let apps: Application[] = []
function navigateApp(app: Ref<Application>) {
function navigateApp (app: Ref<Application>) {
const loc = getCurrentLocation()
loc.path[1] = app
loc.path.length = 2
@@ -34,6 +34,6 @@
<div class="flex-col">
{#each apps as app}
<AppItem selected={app._id === active} icon={app.icon} label={app.label} action={async () => {navigateApp(app._id)}}/>
<AppItem selected={app._id === active} icon={app.icon} label={app.label} action={async () => { navigateApp(app._id) }} notify={false}/>
{/each}
</div>
@@ -25,7 +25,8 @@
navigate,
Popup,
showPopup,
TooltipInstance
TooltipInstance,
PanelInstance
} from '@anticrm/ui'
import type { Application, NavigatorModel, ViewConfiguration } from '@anticrm/workbench'
import { onDestroy } from 'svelte'
@@ -234,6 +235,7 @@
</div>
<!-- <div class="aside"><Chat thread/></div> -->
</div>
<PanelInstance/>
<Popup />
<TooltipInstance />
{:else}
@@ -15,14 +15,12 @@
-->
<script lang="ts">
import type { IntlString, Asset } from '@anticrm/platform'
import type { Ref, Doc, Class, Space } from '@anticrm/core'
import { IconClose, Label, EditBox, ToggleWithLabel, Grid, Icon } from '@anticrm/ui'
import { getClient, createQuery, AttributeBarEditor } from '@anticrm/presentation'
import { createEventDispatcher } from 'svelte'
import type { Class, Ref, Space } from '@anticrm/core'
import core from '@anticrm/core'
import type { IntlString } from '@anticrm/platform'
import { createQuery, getClient } from '@anticrm/presentation'
import { EditBox, Grid, Icon, IconClose, Label, ToggleWithLabel } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte'
export let _id: Ref<Space>
export let spaceClass: Ref<Class<Space>>
@@ -43,7 +41,7 @@
const tabs: IntlString[] = ['General' as IntlString, 'Members' as IntlString]
let selected = 0
function onNameChange(ev: Event) {
function onNameChange (ev: Event) {
client.updateDoc(spaceClass, space.space, space._id, { name: (ev.target as HTMLInputElement).value })
}
@@ -71,20 +71,18 @@
</script>
<div>
<TreeNode label={model.label} actions={[addSpace]}>
<TreeNode label={model.label} actions={async () => [addSpace]}>
{#each spaces as space}
{#await getActions(space) then actions}
<TreeItem
_id={space._id}
title={space.name}
icon={classIcon(client, space._class)}
selected={currentSpace === space._id}
{actions}
on:click={() => {
selectSpace(space._id)
}}
/>
{/await}
<TreeItem
_id={space._id}
title={space.name}
icon={classIcon(client, space._class)}
selected={currentSpace === space._id}
actions={() => getActions(space)}
on:click={() => {
selectSpace(space._id)
}}
/>
{/each}
</TreeNode>
</div>
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import Collapsed from '../icons/Collapsed.svelte'
import Expanded from '../icons/Expanded.svelte'
@@ -31,18 +30,23 @@
export let node = false
export let collapsed = false
export let selected = false
export let actions: Action[] = []
export let actions: () => Promise<Action[]> = async () => []
const dispatch = createEventDispatcher()
let hovered = false
function onMenuClick(ev: MouseEvent) {
async function onMenuClick (ev: MouseEvent) {
showPopup(Menu, { actions: await actions(), ctx: _id }, ev.target as HTMLElement, () => {
hovered = false
})
hovered = true
showPopup(Menu, { actions, ctx: _id }, ev.target as HTMLElement, () => { hovered = false })
}
</script>
<div class="container" class:selected class:hovered
<div
class="container"
class:selected
class:hovered
on:click|stopPropagation={() => {
if (node && !icon) collapsed = !collapsed
dispatch('click')
@@ -50,29 +54,42 @@
>
<div class="icon" class:sub={!node}>
{#if icon}
<Icon {icon} size={'small'}/>
{:else}
{#if collapsed}<Collapsed size={'small'} />{:else}<Expanded size={'small'} />{/if}
{/if}
<Icon {icon} size={'small'} />
{:else if collapsed}<Collapsed size={'small'} />{:else}<Expanded size={'small'} />{/if}
</div>
<span class="label" class:sub={node}>
{#if label}<Label {label}/>{:else}{title}{/if}
{#if label}<Label {label} />{:else}{title}{/if}
</span>
{#if actions.length === 1}
<div class="tool">
<ActionIcon label={actions[0].label} icon={actions[0].icon} size={'small'} action={(ev) => { actions[0].action(_id, ev) }} />
</div>
{:else if actions.length > 1}
{#if node === false}
<div class="tool" on:click|stopPropagation={onMenuClick}>
<IconMoreV size={'small'} />
</div>
{:else}
{#await actions() then actionItems}
{#if actionItems.length === 1}
<div class="tool">
<ActionIcon
label={actionItems[0].label}
icon={actionItems[0].icon}
size={'small'}
action={(ev) => {
actionItems[0].action(_id, ev)
}}
/>
</div>
{:else if actionItems.length > 1}
<div class="tool" on:click|stopPropagation={onMenuClick}>
<IconMoreV size={'small'} />
</div>
{/if}
{/await}
{/if}
{#if notifications > 0 && collapsed}
<div class="counter">{notifications}</div>
{/if}
</div>
{#if node && !icon && !collapsed}
<div class="dropbox"><slot/></div>
<div class="dropbox"><slot /></div>
{/if}
<style lang="scss">
@@ -81,19 +98,21 @@
align-items: center;
margin: 0 1rem;
height: 2.25rem;
border-radius: .5rem;
border-radius: 0.5rem;
user-select: none;
cursor: pointer;
.icon {
min-width: 1rem;
color: var(--theme-content-trans-color);
margin: 0 1.125rem 0 .625rem;
&.sub { margin: 0 .5rem 0 2.75rem }
margin: 0 1.125rem 0 0.625rem;
&.sub {
margin: 0 0.5rem 0 2.75rem;
}
}
.label {
flex-grow: 1;
margin-right: .75rem;
margin-right: 0.75rem;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
@@ -106,31 +125,34 @@
}
}
.tool {
margin-right: .75rem;
margin-right: 0.75rem;
visibility: hidden;
}
.counter {
margin-right: .75rem;
margin-right: 0.75rem;
font-weight: 600;
font-size: .75rem;
font-size: 0.75rem;
color: var(--theme-caption-color);
}
&:hover, &.hovered {
&:hover,
&.hovered {
background-color: var(--theme-button-bg-enabled);
.tool {
visibility: visible;
}
}
&.selected {
background-color: var(--theme-menu-selection);
&:hover { background-color: var(--theme-button-bg-enabled); }
&:hover {
background-color: var(--theme-button-bg-enabled);
}
}
}
.dropbox {
height: auto;
margin-bottom: .5rem;
margin-bottom: 0.5rem;
}
</style>
</style>
@@ -24,11 +24,11 @@
export let icon: Asset
export let title: string
export let notifications = 0
export let actions: Action[] = []
export let actions: () => Promise<Action[]> = async () => []
export let selected: boolean = false
const dispatch = createEventDispatcher()
</script>
<TreeElement {_id} {icon} {title} {notifications} {selected} {actions} collapsed on:click={() => {dispatch('click')}}/>
<TreeElement {_id} {icon} {title} {notifications} {selected} {actions} collapsed on:click={() => { dispatch('click') }}/>
@@ -19,7 +19,7 @@
import TreeElement from './TreeElement.svelte'
export let label: IntlString
export let actions: Action[] = []
export let actions: () => Promise<Action[]> = async () => []
export let notifications = 0
export let collapsed = false