A tooltip with a new approach (#2172)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov 2022-06-30 06:41:46 +03:00 committed by GitHub
parent c1a8b89855
commit 94ee6f5afe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 704 additions and 656 deletions

View File

@ -26,7 +26,7 @@
IconCheck, IconCheck,
ListView, ListView,
showPopup, showPopup,
Tooltip tooltip
} from '@anticrm/ui' } from '@anticrm/ui'
import { createEventDispatcher, afterUpdate } from 'svelte' import { createEventDispatcher, afterUpdate } from 'svelte'
import presentation from '..' import presentation from '..'
@ -207,12 +207,11 @@
<div class="icon"> <div class="icon">
{#if obj._id === selected} {#if obj._id === selected}
{#if titleDeselect} {#if titleDeselect}
<Tooltip label={titleDeselect ?? presentation.string.Deselect}> <div class="clear-mins" use:tooltip={{ label: titleDeselect ?? presentation.string.Deselect }}>
<Icon icon={IconCheck} {size} /> <Icon icon={IconCheck} {size} />
</Tooltip> </div>
{:else} {:else}
<Icon icon={IconCheck} {size} /> <Icon icon={IconCheck} {size} />
<!-- <CheckBox checked circle primary /> -->
{/if} {/if}
{/if} {/if}
</div> </div>
@ -222,7 +221,7 @@
<slot name="item" item={obj} /> <slot name="item" item={obj} />
</span> </span>
{#if multiSelect} {#if multiSelect}
<div class="check pointer-events-none"> <div class="check-right pointer-events-none">
<CheckBox checked={selectedElements.has(obj._id)} primary /> <CheckBox checked={selectedElements.has(obj._id)} primary />
</div> </div>
{/if} {/if}

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
--> -->
<script lang="ts"> <script lang="ts">
import { Button, Tooltip, Panel } from '@anticrm/ui' import { Button, Panel } from '@anticrm/ui'
import type { PopupOptions } from '@anticrm/ui' import type { PopupOptions } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import presentation from '..' import presentation from '..'
@ -90,9 +90,12 @@
<div class="buttons-divider" /> <div class="buttons-divider" />
{/if} {/if}
<a class="no-line" href={getFileUrl(file)} download={name}> <a class="no-line" href={getFileUrl(file)} download={name}>
<Tooltip label={presentation.string.Download}> <Button
<Button icon={Download} kind={'transparent'} shape={'circle'} /> icon={Download}
</Tooltip> kind={'transparent'}
shape={'circle'}
showTooltip={{ label: presentation.string.Download }}
/>
</a> </a>
</svelte:fragment> </svelte:fragment>

View File

@ -17,7 +17,7 @@
import type { IntlString } from '@anticrm/platform' import type { IntlString } from '@anticrm/platform'
import { translate } from '@anticrm/platform' import { translate } from '@anticrm/platform'
import type { ButtonKind, ButtonSize, TooltipAlignment } from '@anticrm/ui' import type { ButtonKind, ButtonSize, TooltipAlignment } from '@anticrm/ui'
import { Tooltip, showPopup, Button } from '@anticrm/ui' import { showPopup, Button } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import presentation, { SpacesMultiPopup } from '..' import presentation, { SpacesMultiPopup } from '..'
@ -53,23 +53,22 @@
} }
</script> </script>
<Tooltip {label} fill={width === '100%'} direction={labelDirection}> <Button
<Button label={selectedItems.length === 0 ? presentation.string.Spaces : undefined}
label={selectedItems.length === 0 ? presentation.string.Spaces : undefined} width={width ?? 'min-content'}
width={width ?? 'min-content'} {kind}
{kind} {size}
{size} {justify}
{justify} on:click={addSpace}
on:click={addSpace} showTooltip={{ label: label, direction: labelDirection }}
> >
<svelte:fragment slot="content"> <svelte:fragment slot="content">
{#if selectedItems.length > 0} {#if selectedItems.length > 0}
<div class="flex-row-center flex-nowrap"> <div class="flex-row-center flex-nowrap">
{#await translate(presentation.string.NumberSpaces, { count: selectedItems.length }) then text} {#await translate(presentation.string.NumberSpaces, { count: selectedItems.length }) then text}
<span class="overflow-label disabled ml-1-5">{text}</span> <span class="overflow-label disabled ml-1-5">{text}</span>
{/await} {/await}
</div> </div>
{/if} {/if}
</svelte:fragment> </svelte:fragment>
</Button> </Button>
</Tooltip>

View File

@ -23,7 +23,6 @@
Button, Button,
eventToHTMLElement, eventToHTMLElement,
getFocusManager, getFocusManager,
Tooltip,
TooltipAlignment, TooltipAlignment,
ButtonKind, ButtonKind,
ButtonSize ButtonSize
@ -84,10 +83,18 @@
} }
</script> </script>
<Tooltip {label} fill={false} direction={labelDirection}> <Button
<Button {focus} {focusIndex} icon={IconFolder} {size} {kind} {justify} {width} on:click={showSpacesPopup}> {focus}
<span slot="content" class="overflow-label disabled text-sm"> {focusIndex}
{#if selected}{selected.name}{:else}<Label {label} />{/if} icon={IconFolder}
</span> {size}
</Button> {kind}
</Tooltip> {justify}
{width}
showTooltip={{ label, direction: labelDirection }}
on:click={showSpacesPopup}
>
<span slot="content" class="overflow-label disabled text-sm">
{#if selected}{selected.name}{:else}<Label {label} />{/if}
</span>
</Button>

View File

@ -18,7 +18,7 @@
import { createEventDispatcher, onMount } from 'svelte' import { createEventDispatcher, onMount } from 'svelte'
import core, { Class, getCurrentAccount, Ref, Space } from '@anticrm/core' import core, { Class, getCurrentAccount, Ref, Space } from '@anticrm/core'
import { Tooltip, CheckBox } from '@anticrm/ui' import { tooltip, CheckBox } from '@anticrm/ui'
import { createQuery } from '../utils' import { createQuery } from '../utils'
import presentation from '..' import presentation from '..'
@ -111,9 +111,9 @@
{#if allowDeselect && space._id === selected} {#if allowDeselect && space._id === selected}
<div class="check-right pointer-events-none"> <div class="check-right pointer-events-none">
{#if titleDeselect} {#if titleDeselect}
<Tooltip label={titleDeselect ?? presentation.string.Deselect}> <div class="clear-mins" use:tooltip={{ label: titleDeselect ?? presentation.string.Deselect }}>
<CheckBox checked circle primary /> <CheckBox checked circle primary />
</Tooltip> </div>
{:else} {:else}
<CheckBox checked circle primary /> <CheckBox checked circle primary />
{/if} {/if}

View File

@ -17,7 +17,7 @@
import type { Class, DocumentQuery, Ref } from '@anticrm/core' import type { Class, DocumentQuery, Ref } from '@anticrm/core'
import type { IntlString } from '@anticrm/platform' import type { IntlString } from '@anticrm/platform'
import { ButtonKind, ButtonSize, Label, TooltipAlignment } from '@anticrm/ui' import { ButtonKind, ButtonSize, Label, TooltipAlignment } from '@anticrm/ui'
import { Tooltip, showPopup, Button } from '@anticrm/ui' import { showPopup, Button } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import presentation, { CombineAvatars, UsersPopup } from '..' import presentation, { CombineAvatars, UsersPopup } from '..'
import { createQuery } from '../utils' import { createQuery } from '../utils'
@ -69,25 +69,24 @@
} }
</script> </script>
<Tooltip {label} fill={width === '100%'} direction={labelDirection}> <Button
<Button icon={persons.length === 0 ? Members : undefined}
icon={persons.length === 0 ? Members : undefined} label={persons.length === 0 ? presentation.string.Members : undefined}
label={persons.length === 0 ? presentation.string.Members : undefined} width={width ?? 'min-content'}
width={width ?? 'min-content'} {kind}
{kind} {size}
{size} {justify}
{justify} showTooltip={{ label, direction: labelDirection }}
on:click={addPerson} on:click={addPerson}
> >
<svelte:fragment slot="content"> <svelte:fragment slot="content">
{#if persons.length > 0} {#if persons.length > 0}
<div class="flex-row-center flex-nowrap pointer-events-none"> <div class="flex-row-center flex-nowrap pointer-events-none">
<CombineAvatars {_class} bind:items size={'inline'} /> <CombineAvatars {_class} bind:items size={'inline'} />
<span class="overflow-label ml-1-5"> <span class="overflow-label ml-1-5">
<Label label={presentation.string.NumberMembers} params={{ count: persons.length }} /> <Label label={presentation.string.NumberMembers} params={{ count: persons.length }} />
</span> </span>
</div> </div>
{/if} {/if}
</svelte:fragment> </svelte:fragment>
</Button> </Button>
</Tooltip>

View File

@ -2,8 +2,7 @@
import emojiRegex from 'emoji-regex' import emojiRegex from 'emoji-regex'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import { IntlString } from '@anticrm/platform' import { IntlString } from '@anticrm/platform'
import { AnySvelteComponent, Label } from '@anticrm/ui' import { AnySvelteComponent, Label, tooltip } from '@anticrm/ui'
import Tooltip from '@anticrm/ui/src/components/Tooltip.svelte'
import Emoji from './icons/Emoji.svelte' import Emoji from './icons/Emoji.svelte'
import Food from './icons/Food.svelte' import Food from './icons/Food.svelte'
import Nature from './icons/Nature.svelte' import Nature from './icons/Nature.svelte'
@ -137,15 +136,14 @@
<div class="antiPopup antiPopup-withHeader pb-3 popup"> <div class="antiPopup antiPopup-withHeader pb-3 popup">
<div class="flex-between ml-4 pt-2 pb-2 mr-4 header"> <div class="flex-between ml-4 pt-2 pb-2 mr-4 header">
{#each categories as category} {#each categories as category}
<Tooltip label={category.label}> <div
<div use:tooltip={{ label: category.label }}
class="flex-grow pt-2 pb-2 pl-2 pr-2 element" class="flex-grow pt-2 pb-2 pl-2 pr-2 element"
class:selected={currentCategory === category} class:selected={currentCategory === category}
on:click={() => handleScrollToCategory(category.id)} on:click={() => handleScrollToCategory(category.id)}
> >
<svelte:component this={category.icon} size={'large'} opacity={currentCategory === category ? '1' : '0.3'} /> <svelte:component this={category.icon} size={'large'} opacity={currentCategory === category ? '1' : '0.3'} />
</div> </div>
</Tooltip>
{/each} {/each}
</div> </div>
<div class="flex-col vScroll" bind:this={div} on:scroll={handleScroll}> <div class="flex-col vScroll" bind:this={div} on:scroll={handleScroll}>

View File

@ -15,7 +15,7 @@
<script lang="ts"> <script lang="ts">
import { Asset, getResource, IntlString } from '@anticrm/platform' import { Asset, getResource, IntlString } from '@anticrm/platform'
import presentation, { getClient, ObjectSearchCategory } from '@anticrm/presentation' import presentation, { getClient, ObjectSearchCategory } from '@anticrm/presentation'
import { AnySvelteComponent, Icon, Button, Tooltip, showPopup } from '@anticrm/ui' import { AnySvelteComponent, Icon, Button, showPopup } from '@anticrm/ui'
import { AnyExtension } from '@tiptap/core' import { AnyExtension } from '@tiptap/core'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import { Completion } from '../Completion' import { Completion } from '../Completion'
@ -214,91 +214,82 @@
<div class="ref-container"> <div class="ref-container">
{#if isFormatting} {#if isFormatting}
<div class="formatPanel buttons-group xsmall-gap" class:withoutTopBorder> <div class="formatPanel buttons-group xsmall-gap" class:withoutTopBorder>
<Tooltip label={textEditorPlugin.string.Bold}> <Button
<Button icon={Bold}
icon={Bold} kind={'transparent'}
kind={'transparent'} size={'small'}
size={'small'} selected={activeModes.has('bold')}
selected={activeModes.has('bold')} showTooltip={{ label: textEditorPlugin.string.Bold }}
on:click={getToggler(textEditor.toggleBold)} on:click={getToggler(textEditor.toggleBold)}
/> />
</Tooltip> <Button
<Tooltip label={textEditorPlugin.string.Italic}> icon={Italic}
<Button kind={'transparent'}
icon={Italic} size={'small'}
kind={'transparent'} selected={activeModes.has('italic')}
size={'small'} showTooltip={{ label: textEditorPlugin.string.Italic }}
selected={activeModes.has('italic')} on:click={getToggler(textEditor.toggleItalic)}
on:click={getToggler(textEditor.toggleItalic)} />
/> <Button
</Tooltip> icon={Strikethrough}
<Tooltip label={textEditorPlugin.string.Strikethrough}> kind={'transparent'}
<Button size={'small'}
icon={Strikethrough} selected={activeModes.has('strike')}
kind={'transparent'} showTooltip={{ label: textEditorPlugin.string.Strikethrough }}
size={'small'} on:click={getToggler(textEditor.toggleStrike)}
selected={activeModes.has('strike')} />
on:click={getToggler(textEditor.toggleStrike)} <Button
/> icon={Link}
</Tooltip> kind={'transparent'}
<Tooltip label={textEditorPlugin.string.Link}> size={'small'}
<Button selected={activeModes.has('link')}
icon={Link} disabled={isSelectionEmpty && !activeModes.has('link')}
kind={'transparent'} showTooltip={{ label: textEditorPlugin.string.Link }}
size={'small'} on:click={formatLink}
selected={activeModes.has('link')} />
disabled={isSelectionEmpty && !activeModes.has('link')}
on:click={formatLink}
/>
</Tooltip>
<div class="buttons-divider" /> <div class="buttons-divider" />
<Tooltip label={textEditorPlugin.string.OrderedList}> <Button
<Button icon={ListNumber}
icon={ListNumber} kind={'transparent'}
kind={'transparent'} size={'small'}
size={'small'} selected={activeModes.has('orderedList')}
selected={activeModes.has('orderedList')} showTooltip={{ label: textEditorPlugin.string.OrderedList }}
on:click={getToggler(textEditor.toggleOrderedList)} on:click={getToggler(textEditor.toggleOrderedList)}
/> />
</Tooltip> <Button
<Tooltip label={textEditorPlugin.string.BulletedList}> icon={ListBullet}
<Button kind={'transparent'}
icon={ListBullet} size={'small'}
kind={'transparent'} selected={activeModes.has('bulletList')}
size={'small'} showTooltip={{ label: textEditorPlugin.string.BulletedList }}
selected={activeModes.has('bulletList')} on:click={getToggler(textEditor.toggleBulletList)}
on:click={getToggler(textEditor.toggleBulletList)} />
/>
</Tooltip>
<div class="buttons-divider" /> <div class="buttons-divider" />
<Tooltip label={textEditorPlugin.string.Blockquote}> <Button
<Button icon={Quote}
icon={Quote} kind={'transparent'}
kind={'transparent'} size={'small'}
size={'small'} selected={activeModes.has('blockquote')}
selected={activeModes.has('blockquote')} showTooltip={{ label: textEditorPlugin.string.Blockquote }}
on:click={getToggler(textEditor.toggleBlockquote)} on:click={getToggler(textEditor.toggleBlockquote)}
/> />
</Tooltip>
<div class="buttons-divider" /> <div class="buttons-divider" />
<Tooltip label={textEditorPlugin.string.Code}> <Button
<Button icon={Code}
icon={Code} kind={'transparent'}
kind={'transparent'} size={'small'}
size={'small'} selected={activeModes.has('code')}
selected={activeModes.has('code')} showTooltip={{ label: textEditorPlugin.string.Code }}
on:click={getToggler(textEditor.toggleCode)} on:click={getToggler(textEditor.toggleCode)}
/> />
</Tooltip> <Button
<Tooltip label={textEditorPlugin.string.CodeBlock}> icon={CodeBlock}
<Button kind={'transparent'}
icon={CodeBlock} size={'small'}
kind={'transparent'} selected={activeModes.has('codeBlock')}
size={'small'} showTooltip={{ label: textEditorPlugin.string.CodeBlock }}
selected={activeModes.has('codeBlock')} on:click={getToggler(textEditor.toggleCodeBlock)}
on:click={getToggler(textEditor.toggleCodeBlock)} />
/>
</Tooltip>
</div> </div>
{/if} {/if}
<div class="textInput" class:withoutTopBorder={withoutTopBorder || isFormatting}> <div class="textInput" class:withoutTopBorder={withoutTopBorder || isFormatting}>

View File

@ -17,7 +17,7 @@
import type { AnySvelteComponent, TooltipAlignment } from '../types' import type { AnySvelteComponent, TooltipAlignment } from '../types'
import Icon from './Icon.svelte' import Icon from './Icon.svelte'
import Tooltip from './Tooltip.svelte' import { tooltip } from '../tooltips'
export let label: IntlString = '' as IntlString export let label: IntlString = '' as IntlString
export let labelProps: any = undefined export let labelProps: any = undefined
@ -28,13 +28,16 @@
export let invisible: boolean = false export let invisible: boolean = false
</script> </script>
<Tooltip {label} {direction} props={labelProps}> <button
<button class="button {size}" on:click|stopPropagation={action}> class="button {size}"
<div class="icon {size}" class:invisible> use:tooltip={{ label, direction, props: labelProps }}
<Icon {icon} {size} /> tabindex="0"
</div> on:click|stopPropagation={action}
</button> >
</Tooltip> <div class="icon {size}" class:invisible>
<Icon {icon} {size} />
</div>
</button>
<style lang="scss"> <style lang="scss">
.button { .button {

View File

@ -20,7 +20,6 @@
import Button from './Button.svelte' import Button from './Button.svelte'
import DropdownPopup from './DropdownPopup.svelte' import DropdownPopup from './DropdownPopup.svelte'
import Label from './Label.svelte' import Label from './Label.svelte'
import Tooltip from './Tooltip.svelte'
export let icon: Asset | AnySvelteComponent | undefined = undefined export let icon: Asset | AnySvelteComponent | undefined = undefined
export let label: IntlString | undefined = undefined export let label: IntlString | undefined = undefined
@ -42,28 +41,27 @@
</script> </script>
<div bind:this={container} class="min-w-0"> <div bind:this={container} class="min-w-0">
<Tooltip {label} fill={width === '100%'} direction={labelDirection}> <Button
<Button {focusIndex}
{focusIndex} {icon}
{icon} width={width ?? 'min-content'}
width={width ?? 'min-content'} {size}
{size} {kind}
{kind} {justify}
{justify} showTooltip={{ label, direction: labelDirection }}
on:click={() => { on:click={() => {
if (!opened) { if (!opened) {
opened = true opened = true
showPopup(DropdownPopup, { title: label, items, icon }, container, (result) => { showPopup(DropdownPopup, { title: label, items, icon }, container, (result) => {
if (result) selected = result if (result) selected = result
opened = false opened = false
mgr?.setFocusPos(focusIndex) mgr?.setFocusPos(focusIndex)
}) })
} }
}} }}
> >
<span slot="content" class="overflow-label disabled"> <span slot="content" class="overflow-label disabled">
{#if selected}{selected.label}{:else}<Label label={placeholder} />{/if} {#if selected}{selected.label}{:else}<Label label={placeholder} />{/if}
</span> </span>
</Button> </Button>
</Tooltip>
</div> </div>

View File

@ -22,7 +22,6 @@
import Button from './Button.svelte' import Button from './Button.svelte'
import DropdownLabelsPopup from './DropdownLabelsPopup.svelte' import DropdownLabelsPopup from './DropdownLabelsPopup.svelte'
import Label from './Label.svelte' import Label from './Label.svelte'
import Tooltip from './Tooltip.svelte'
export let icon: Asset | AnySvelteComponent | undefined = undefined export let icon: Asset | AnySvelteComponent | undefined = undefined
export let label: IntlString export let label: IntlString
@ -54,31 +53,30 @@
</script> </script>
<div bind:this={container} class="min-w-0"> <div bind:this={container} class="min-w-0">
<Tooltip {label} fill={width === '100%'} direction={labelDirection}> <Button
<Button {focusIndex}
{focusIndex} {icon}
{icon} width={width ?? 'min-content'}
width={width ?? 'min-content'} {size}
{size} {kind}
{kind} {justify}
{justify} showTooltip={{ label, direction: labelDirection }}
on:click={() => { on:click={() => {
if (!opened) { if (!opened) {
opened = true opened = true
showPopup(DropdownLabelsPopup, { placeholder, items, selected }, container, (result) => { showPopup(DropdownLabelsPopup, { placeholder, items, selected }, container, (result) => {
if (result) { if (result) {
selected = result selected = result
dispatch('selected', result) dispatch('selected', result)
} }
opened = false opened = false
mgr?.setFocusPos(focusIndex) mgr?.setFocusPos(focusIndex)
}) })
} }
}} }}
> >
<span slot="content" class="overflow-label disabled"> <span slot="content" class="overflow-label disabled">
{#if selectedItem}{selectedItem.label}{:else}<Label label={label ?? ui.string.NotSelected} />{/if} {#if selectedItem}{selectedItem.label}{:else}<Label label={label ?? ui.string.NotSelected} />{/if}
</span> </span>
</Button> </Button>
</Tooltip>
</div> </div>

View File

@ -21,7 +21,6 @@
import Button from './Button.svelte' import Button from './Button.svelte'
import DropdownLabelsPopupIntl from './DropdownLabelsPopupIntl.svelte' import DropdownLabelsPopupIntl from './DropdownLabelsPopupIntl.svelte'
import Label from './Label.svelte' import Label from './Label.svelte'
import Tooltip from './Tooltip.svelte'
export let icon: Asset | AnySvelteComponent | undefined = undefined export let icon: Asset | AnySvelteComponent | undefined = undefined
export let label: IntlString export let label: IntlString
@ -48,33 +47,32 @@
</script> </script>
<div bind:this={container} class="min-w-0"> <div bind:this={container} class="min-w-0">
<Tooltip {label} fill={width === '100%'} direction={labelDirection}> <Button
<Button {icon}
{icon} width={width ?? 'min-content'}
width={width ?? 'min-content'} {size}
{size} {kind}
{kind} {justify}
{justify} showTooltip={{ label, direction: labelDirection }}
on:click={() => { on:click={() => {
if (!opened) { if (!opened) {
opened = true opened = true
showPopup(DropdownLabelsPopupIntl, { placeholder, items, selected }, container, (result) => { showPopup(DropdownLabelsPopupIntl, { placeholder, items, selected }, container, (result) => {
if (result) { if (result) {
selected = result selected = result
dispatch('selected', result) dispatch('selected', result)
} }
opened = false opened = false
}) })
} }
}} }}
> >
<span slot="content" class="overflow-label disabled"> <span slot="content" class="overflow-label disabled">
{#if selectedItem} {#if selectedItem}
<Label label={selectedItem.label} /> <Label label={selectedItem.label} />
{:else} {:else}
<Label label={label ?? ui.string.NotSelected} /> <Label label={label ?? ui.string.NotSelected} />
{/if} {/if}
</span> </span>
</Button> </Button>
</Tooltip>
</div> </div>

View File

@ -14,12 +14,12 @@
// limitations under the License. // limitations under the License.
--> -->
<script lang="ts"> <script lang="ts">
import Tooltip from './Tooltip.svelte' import { tooltip } from '../tooltips'
import ErrorPopup from './ErrorPopup.svelte' import ErrorPopup from './ErrorPopup.svelte'
export let error: any export let error: any
</script> </script>
<Tooltip component={ErrorPopup} props={{ error: error }}> <div use:tooltip={{ component: ErrorPopup, props: { error: error } }}>
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="10" cy="10" r="7.275" stroke="#EE7A7A" stroke-width="1.2" /> <circle cx="10" cy="10" r="7.275" stroke="#EE7A7A" stroke-width="1.2" />
<path <path
@ -29,4 +29,4 @@
stroke-width="0.2" stroke-width="0.2"
/> />
</svg> </svg>
</Tooltip> </div>

View File

@ -1,6 +1,6 @@
import { IntlString } from '@anticrm/platform' import { IntlString } from '@anticrm/platform'
import { writable } from 'svelte/store' import { writable } from 'svelte/store'
import { AnyComponent, AnySvelteComponent, LabelAndProps, TooltipAlignment } from './types' import type { AnyComponent, AnySvelteComponent, LabelAndProps, TooltipAlignment } from './types'
const emptyTooltip: LabelAndProps = { const emptyTooltip: LabelAndProps = {
label: undefined, label: undefined,
@ -42,6 +42,10 @@ export function tooltip (node: HTMLElement, options?: LabelAndProps): any {
return { return {
update (options: LabelAndProps) { update (options: LabelAndProps) {
opt = options opt = options
const shown = !!(storedValue.label !== undefined || storedValue.component !== undefined)
if (shown) {
showTooltip(opt.label, node, opt.direction, opt.component, opt.props, opt.anchor, opt.onUpdate, opt.kind)
}
}, },
destroy () { destroy () {

View File

@ -16,7 +16,7 @@
import { EmployeeAccount } from '@anticrm/contact' import { EmployeeAccount } from '@anticrm/contact'
import { Doc, getCurrentAccount } from '@anticrm/core' import { Doc, getCurrentAccount } from '@anticrm/core'
import { getClient } from '@anticrm/presentation' import { getClient } from '@anticrm/presentation'
import { Button, showPopup, Tooltip } from '@anticrm/ui' import { Button, showPopup } from '@anticrm/ui'
import calendar from '../plugin' import calendar from '../plugin'
import CreateReminder from './CreateReminder.svelte' import CreateReminder from './CreateReminder.svelte'
import DocRemindersPopup from './DocRemindersPopup.svelte' import DocRemindersPopup from './DocRemindersPopup.svelte'
@ -57,6 +57,10 @@
} }
</script> </script>
<Tooltip label={isEvent ? calendar.string.RemindMeAt : calendar.string.Reminders}> <Button
<Button size={'medium'} kind={'transparent'} icon={calendar.icon.Reminder} on:click={(e) => click(e)} /> size={'medium'}
</Tooltip> kind={'transparent'}
icon={calendar.icon.Reminder}
showTooltip={{ label: isEvent ? calendar.string.RemindMeAt : calendar.string.Reminders }}
on:click={(e) => click(e)}
/>

View File

@ -18,7 +18,7 @@
import { Hierarchy } from '@anticrm/core' import { Hierarchy } from '@anticrm/core'
import { Avatar } from '@anticrm/presentation' import { Avatar } from '@anticrm/presentation'
import calendar from '../plugin' import calendar from '../plugin'
import { showPanel, Tooltip } from '@anticrm/ui' import { showPanel, tooltip } from '@anticrm/ui'
import view from '@anticrm/view' import view from '@anticrm/view'
export let value: Person | Person[] export let value: Person | Person[]
@ -35,13 +35,16 @@
{#if value} {#if value}
<div class="flex persons"> <div class="flex persons">
{#each persons as p} {#each persons as p}
<Tooltip label={calendar.string.PersonsLabel} props={{ name: formatName(p.name) }}> <div
<div class="flex-presenter" class:inline-presenter={inline} on:click={() => onClick(p)}> class="flex-presenter"
<div class="icon"> class:inline-presenter={inline}
<Avatar size={'x-small'} avatar={p.avatar} /> use:tooltip={{ label: calendar.string.PersonsLabel, props: { name: formatName(p.name) } }}
</div> on:click={() => onClick(p)}
>
<div class="icon">
<Avatar size={'x-small'} avatar={p.avatar} />
</div> </div>
</Tooltip> </div>
{/each} {/each}
</div> </div>
{/if} {/if}

View File

@ -15,7 +15,7 @@
<script lang="ts"> <script lang="ts">
import { Reminder } from '@anticrm/calendar' import { Reminder } from '@anticrm/calendar'
import { getResource } from '@anticrm/platform' import { getResource } from '@anticrm/platform'
import { DateTimeRangePresenter, showPanel, Tooltip } from '@anticrm/ui' import { DateTimeRangePresenter, showPanel, tooltip } from '@anticrm/ui'
import view from '@anticrm/view' import view from '@anticrm/view'
export let value: Reminder export let value: Reminder
@ -29,13 +29,14 @@
<div class="antiSelect w-full cursor-pointer flex-between" on:click={click}> <div class="antiSelect w-full cursor-pointer flex-between" on:click={click}>
{#if value} {#if value}
<div class="mr-4"> {#await objectPresenter then component}
{#await objectPresenter then component} <div
<Tooltip {component} props={{ objectId: value.attachedTo, _class: value.attachedToClass }}> class="mr-4"
{value.title} use:tooltip={{ component, props: { objectId: value.attachedTo, _class: value.attachedToClass } }}
</Tooltip> >
{/await} {value.title}
</div> </div>
{/await}
<DateTimeRangePresenter value={value.date + value.shift} /> <DateTimeRangePresenter value={value.date + value.shift} />
{/if} {/if}
</div> </div>

View File

@ -28,7 +28,7 @@
Menu, Menu,
showPopup, showPopup,
Label, Label,
Tooltip, tooltip,
Button, Button,
getCurrentLocation, getCurrentLocation,
locationToUrl locationToUrl
@ -255,10 +255,8 @@
{/if} {/if}
<span>{getTime(message.createOn)}</span> <span>{getTime(message.createOn)}</span>
{#if message.editedOn} {#if message.editedOn}
<span> <span use:tooltip={{ label: ui.string.TimeTooltip, props: { value: getTime(message.editedOn) } }}>
<Tooltip label={ui.string.TimeTooltip} props={{ value: getTime(message.editedOn) }}> <Label label={chunter.string.Edited} />
<Label label={chunter.string.Edited} />
</Tooltip>
</span> </span>
{/if} {/if}
</div> </div>

View File

@ -15,7 +15,7 @@
<script lang="ts"> <script lang="ts">
import { Reaction } from '@anticrm/chunter' import { Reaction } from '@anticrm/chunter'
import { Account, Ref } from '@anticrm/core' import { Account, Ref } from '@anticrm/core'
import { Tooltip } from '@anticrm/ui' import { tooltip } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import ReactionsTooltip from './ReactionsTooltip.svelte' import ReactionsTooltip from './ReactionsTooltip.svelte'
@ -38,17 +38,16 @@
<div class="container"> <div class="container">
{#each [...reactionsAccounts] as [emoji, accounts]} {#each [...reactionsAccounts] as [emoji, accounts]}
<div class="reaction over-underline"> <div class="reaction over-underline">
<Tooltip component={ReactionsTooltip} props={{ reactionAccounts: accounts }}> <div
<div class="flex-row-center"
class="flex-row-center" use:tooltip={{ component: ReactionsTooltip, props: { reactionAccounts: accounts } }}
on:click={() => { on:click={() => {
dispatch('remove', emoji) dispatch('remove', emoji)
}} }}
> >
<div>{emoji}</div> <div>{emoji}</div>
<div class="caption-color counter">{accounts.length}</div> <div class="caption-color counter">{accounts.length}</div>
</div> </div>
</Tooltip>
</div> </div>
{/each} {/each}
</div> </div>

View File

@ -30,8 +30,7 @@
eventToHTMLElement, eventToHTMLElement,
getFocusManager, getFocusManager,
Menu, Menu,
showPopup, showPopup
Tooltip
} from '@anticrm/ui' } from '@anticrm/ui'
import { createEventDispatcher, tick } from 'svelte' import { createEventDispatcher, tick } from 'svelte'
import { getChannelProviders } from '../utils' import { getChannelProviders } from '../utils'
@ -275,18 +274,17 @@
on:click={showMenu} on:click={showMenu}
/> />
{:else} {:else}
<Tooltip label={presentation.string.AddSocialLinks}> <Button
<Button focusIndex={focusIndex === -1 ? focusIndex : focusIndex + 2 + displayItems.length}
focusIndex={focusIndex === -1 ? focusIndex : focusIndex + 2 + displayItems.length} id={presentation.string.AddSocialLinks}
id={presentation.string.AddSocialLinks} bind:input={addBtn}
bind:input={addBtn} icon={contact.icon.SocialEdit}
icon={contact.icon.SocialEdit} {kind}
{kind} {size}
{size} {shape}
{shape} showTooltip={{ label: presentation.string.AddSocialLinks }}
on:click={showMenu} on:click={showMenu}
/> />
</Tooltip>
{/if} {/if}
{/if} {/if}
</div> </div>

View File

@ -18,7 +18,7 @@
import type { AttachedData, Doc, Ref, Timestamp } from '@anticrm/core' import type { AttachedData, Doc, Ref, Timestamp } from '@anticrm/core'
import type { Asset, IntlString } from '@anticrm/platform' import type { Asset, IntlString } from '@anticrm/platform'
import type { AnyComponent } from '@anticrm/ui' import type { AnyComponent } from '@anticrm/ui'
import { CircleButton, Tooltip } from '@anticrm/ui' import { Button } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import { getChannelProviders } from '../utils' import { getChannelProviders } from '../utils'
import ChannelsPopup from './ChannelsPopup.svelte' import ChannelsPopup from './ChannelsPopup.svelte'
@ -109,16 +109,16 @@
> >
{#each displayItems as item} {#each displayItems as item}
<div class="channel-item"> <div class="channel-item">
<Tooltip component={ChannelsPopup} props={{ value: item }} label={undefined} anchor={divHTML}> <Button
<CircleButton icon={item.icon}
icon={item.icon} kind={'link-bordered'}
{size} {size}
primary={item.integration || item.notification} highlight={item.integration || item.notification}
on:click={() => { showTooltip={{ component: ChannelsPopup, props: { value: item }, label: undefined, anchor: divHTML }}
dispatch('click', item) on:click={() => {
}} dispatch('click', item)
/> }}
</Tooltip> />
</div> </div>
{/each} {/each}
</div> </div>

View File

@ -6,9 +6,17 @@
import EmployeePreviewPopup from './EmployeePreviewPopup.svelte' import EmployeePreviewPopup from './EmployeePreviewPopup.svelte'
import { WithLookup } from '@anticrm/core' import { WithLookup } from '@anticrm/core'
import { IntlString } from '@anticrm/platform' import { IntlString } from '@anticrm/platform'
import type { AnyComponent, AnySvelteComponent } from '@anticrm/ui'
export let value: WithLookup<Employee> | null | undefined export let value: WithLookup<Employee> | null | undefined
export let tooltipLabels: { personLabel: IntlString; placeholderLabel?: IntlString } | undefined = undefined export let tooltipLabels:
| {
personLabel?: IntlString
placeholderLabel?: IntlString
component?: AnySvelteComponent | AnyComponent
props?: any
}
| undefined = undefined
export let shouldShowAvatar: boolean = true export let shouldShowAvatar: boolean = true
export let shouldShowName: boolean = true export let shouldShowName: boolean = true
export let shouldShowPlaceholder = false export let shouldShowPlaceholder = false

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { Timestamp, TypeDate } from '@anticrm/core' import { Timestamp, TypeDate } from '@anticrm/core'
import { ticker, Tooltip } from '@anticrm/ui' import { ticker, tooltip } from '@anticrm/ui'
import { DateEditor } from '@anticrm/view-resources' import { DateEditor } from '@anticrm/view-resources'
import EmployeeStatusDueDatePopup from './EmployeeStatusDueDatePopup.svelte' import EmployeeStatusDueDatePopup from './EmployeeStatusDueDatePopup.svelte'
import { formatDate } from '../utils' import { formatDate } from '../utils'
@ -15,13 +15,9 @@
const type = { withTime: true } as TypeDate const type = { withTime: true } as TypeDate
</script> </script>
<Tooltip <div
direction={'top'} class="clear-mins"
component={EmployeeStatusDueDatePopup} use:tooltip={{ direction: 'top', component: EmployeeStatusDueDatePopup, props: { formattedDate, isOverdue } }}
props={{
formattedDate,
isOverdue
}}
> >
<DateEditor <DateEditor
value={statusDueDate} value={statusDueDate}
@ -31,4 +27,4 @@
dispatch('change', v) dispatch('change', v)
}} }}
/> />
</Tooltip> </div>

View File

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { Employee, Status } from '@anticrm/contact' import { Employee, Status } from '@anticrm/contact'
import { WithLookup } from '@anticrm/core' import { WithLookup } from '@anticrm/core'
import { Label, Tooltip } from '@anticrm/ui' import { Label, tooltip } from '@anticrm/ui'
import contact from '../plugin' import contact from '../plugin'
import { formatDate } from '../utils' import { formatDate } from '../utils'
import { IntlString } from '@anticrm/platform' import { IntlString } from '@anticrm/platform'
@ -15,12 +15,15 @@
{#if status} {#if status}
{#if withTooltip} {#if withTooltip}
<Tooltip <div
label={status.dueDate ? contact.string.StatusDueDateTooltip : contact.string.NoExpire} class="overflow-label statusName"
props={{ date: formattedDate }} use:tooltip={{
label: status.dueDate ? contact.string.StatusDueDateTooltip : contact.string.NoExpire,
props: { date: formattedDate }
}}
> >
<div class="overflow-label statusName">{status.name}</div> {status.name}
</Tooltip> </div>
{:else} {:else}
<div class="flex"> <div class="flex">
<div class="pr-4">{status.name}</div> <div class="pr-4">{status.name}</div>

View File

@ -16,6 +16,7 @@
import { formatName, Person } from '@anticrm/contact' import { formatName, Person } from '@anticrm/contact'
import { IntlString } from '@anticrm/platform' import { IntlString } from '@anticrm/platform'
import PersonContent from './PersonContent.svelte' import PersonContent from './PersonContent.svelte'
import type { AnyComponent, AnySvelteComponent } from '@anticrm/ui'
export let value: Person | null | undefined export let value: Person | null | undefined
export let inline = false export let inline = false
@ -24,7 +25,14 @@
export let shouldShowName = true export let shouldShowName = true
export let shouldShowPlaceholder = false export let shouldShowPlaceholder = false
export let defaultName: IntlString | undefined = undefined export let defaultName: IntlString | undefined = undefined
export let tooltipLabels: { personLabel: IntlString; placeholderLabel?: IntlString } | undefined = undefined export let tooltipLabels:
| {
personLabel?: IntlString
placeholderLabel?: IntlString
component?: AnySvelteComponent | AnyComponent
props?: any
}
| undefined = undefined
export let avatarSize: 'inline' | 'tiny' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large' = 'x-small' export let avatarSize: 'inline' | 'tiny' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large' = 'x-small'
export let onEdit: ((event: MouseEvent) => void) | undefined = undefined export let onEdit: ((event: MouseEvent) => void) | undefined = undefined
</script> </script>
@ -33,8 +41,9 @@
<PersonContent <PersonContent
showTooltip={tooltipLabels showTooltip={tooltipLabels
? { ? {
label: value ? tooltipLabels.personLabel : tooltipLabels.placeholderLabel, label: value ? tooltipLabels.personLabel : undefined,
props: value ? { value: formatName(value.name) } : {} component: value ? tooltipLabels.component : undefined,
props: value && tooltipLabels.personLabel ? { value: formatName(value.name) } : tooltipLabels.props
} }
: undefined} : undefined}
{value} {value}

View File

@ -16,7 +16,7 @@
<script lang="ts"> <script lang="ts">
import core, { Doc, TxCUD } from '@anticrm/core' import core, { Doc, TxCUD } from '@anticrm/core'
import { createQuery } from '@anticrm/presentation' import { createQuery } from '@anticrm/presentation'
import { ScrollBox, Tooltip } from '@anticrm/ui' import { ScrollBox, tooltip } from '@anticrm/ui'
import { toIntl } from '..' import { toIntl } from '..'
import ContentPopup from './ContentPopup.svelte' import ContentPopup from './ContentPopup.svelte'
@ -49,7 +49,9 @@
<td>{tx.objectId}</td> <td>{tx.objectId}</td>
<td>{tx.objectClass}</td> <td>{tx.objectClass}</td>
<td> <td>
<Tooltip label={toIntl('Content')} component={ContentPopup} props={{ content: tx }}>Content</Tooltip> <span use:tooltip={{ label: toIntl('Content'), component: ContentPopup, props: { content: tx } }}>
Content
</span>
</td> </td>
</tr> </tr>
{/each} {/each}

View File

@ -14,7 +14,7 @@
// limitations under the License. // limitations under the License.
--> -->
<script lang="ts"> <script lang="ts">
import { ScrollBox, Tooltip } from '@anticrm/ui' import { ScrollBox, tooltip } from '@anticrm/ui'
import ActionIcon from '@anticrm/ui/src/components/ActionIcon.svelte' import ActionIcon from '@anticrm/ui/src/components/ActionIcon.svelte'
import view from '@anticrm/view' import view from '@anticrm/view'
import { queries, toIntl } from '..' import { queries, toIntl } from '..'
@ -44,9 +44,9 @@
<td>{JSON.stringify(q.options ?? {})}</td> <td>{JSON.stringify(q.options ?? {})}</td>
<td>{q.result.length}</td> <td>{q.result.length}</td>
<td> <td>
<Tooltip label={toIntl('Content')} component={ContentPopup} props={{ content: q.result }}> <span use:tooltip={{ label: toIntl('Content'), component: ContentPopup, props: { content: q.result } }}>
Results Results
</Tooltip> </span>
</td> </td>
<td> <td>
<ActionIcon <ActionIcon

View File

@ -19,7 +19,7 @@
import gmail from '../plugin' import gmail from '../plugin'
import { Channel, Contact, EmployeeAccount, formatName } from '@anticrm/contact' import { Channel, Contact, EmployeeAccount, formatName } from '@anticrm/contact'
import contact from '@anticrm/contact' import contact from '@anticrm/contact'
import plugin, { IconShare, Button, Tooltip, Icon, Label, Scroller } from '@anticrm/ui' import plugin, { IconShare, Button, Icon, Label, Scroller } from '@anticrm/ui'
import { getCurrentAccount, Ref, SortingOrder, Space } from '@anticrm/core' import { getCurrentAccount, Ref, SortingOrder, Space } from '@anticrm/core'
import setting from '@anticrm/setting' import setting from '@anticrm/setting'
import Messages from './Messages.svelte' import Messages from './Messages.svelte'
@ -144,15 +144,14 @@
newMessage = true newMessage = true
}} }}
/> />
<Tooltip label={gmail.string.ShareMessages}> <Button
<Button icon={IconShare}
icon={IconShare} kind={'transparent'}
kind={'transparent'} showTooltip={{ label: gmail.string.ShareMessages }}
on:click={async () => { on:click={async () => {
selectable = !selectable selectable = !selectable
}} }}
/> />
</Tooltip>
</div> </div>
{/if} {/if}
</div> </div>

View File

@ -15,7 +15,7 @@
--> -->
<script lang="ts"> <script lang="ts">
import type { Customer } from '@anticrm/lead' import type { Customer } from '@anticrm/lead'
import { Icon, Tooltip } from '@anticrm/ui' import { Icon, tooltip } from '@anticrm/ui'
import LeadsPopup from './LeadsPopup.svelte' import LeadsPopup from './LeadsPopup.svelte'
import leads from '../plugin' import leads from '../plugin'
@ -24,9 +24,10 @@
</script> </script>
{#if value && value > 0} {#if value && value > 0}
<Tooltip label={leads.string.Leads} component={LeadsPopup} props={{ value: object }}> <div
<div class="sm-tool-icon"> class="sm-tool-icon"
<span class="icon"><Icon icon={leads.icon.Lead} size={'small'} /></span>&nbsp;{value} use:tooltip={{ label: leads.string.Leads, component: LeadsPopup, props: { value: object } }}
</div> >
</Tooltip> <span class="icon"><Icon icon={leads.icon.Lead} size={'small'} /></span>&nbsp;{value}
</div>
{/if} {/if}

View File

@ -22,7 +22,7 @@
import type { Applicant, Candidate } from '@anticrm/recruit' import type { Applicant, Candidate } from '@anticrm/recruit'
import task, { TodoItem } from '@anticrm/task' import task, { TodoItem } from '@anticrm/task'
import { AssigneePresenter } from '@anticrm/task-resources' import { AssigneePresenter } from '@anticrm/task-resources'
import { Component, showPanel, Tooltip } from '@anticrm/ui' import { Component, showPanel, tooltip } from '@anticrm/ui'
import view from '@anticrm/view' import view from '@anticrm/view'
import ApplicationPresenter from './ApplicationPresenter.svelte' import ApplicationPresenter from './ApplicationPresenter.svelte'
@ -73,9 +73,16 @@
<div class="sm-tool-icon step-lr75"> <div class="sm-tool-icon step-lr75">
<ApplicationPresenter value={object} /> <ApplicationPresenter value={object} />
{#if todoItems.length > 0} {#if todoItems.length > 0}
<Tooltip label={task.string.TodoItems} component={task.component.TodoItemsPopup} props={{ value: object }}> <div
<div class="ml-2">( {doneTasks?.length}/ {todoItems.length} )</div> class="ml-2"
</Tooltip> use:tooltip={{
label: task.string.TodoItems,
component: task.component.TodoItemsPopup,
props: { value: object }
}}
>
({doneTasks?.length}/{todoItems.length})
</div>
{/if} {/if}
</div> </div>
{#if (object.attachments ?? 0) > 0} {#if (object.attachments ?? 0) > 0}

View File

@ -15,25 +15,30 @@
<script lang="ts"> <script lang="ts">
import { Doc, DocumentQuery, Ref } from '@anticrm/core' import { Doc, DocumentQuery, Ref } from '@anticrm/core'
import { Vacancy } from '@anticrm/recruit' import { Vacancy } from '@anticrm/recruit'
import { Icon, Tooltip } from '@anticrm/ui' import { Icon, tooltip } from '@anticrm/ui'
import recruit from '../plugin' import recruit from '../plugin'
import VacancyApplicationsPopup from './VacancyApplicationsPopup.svelte' import VacancyApplicationsPopup from './VacancyApplicationsPopup.svelte'
export let value: Vacancy export let value: Vacancy
export let applications: Map<Ref<Vacancy>, { count: number; modifiedOn: number }> | undefined export let applications: Map<Ref<Vacancy>, { count: number; modifiedOn: number }> | undefined
export let resultQuery: DocumentQuery<Doc> export let resultQuery: DocumentQuery<Doc>
$: count = applications?.get(value._id)?.count ?? 0
</script> </script>
{#if (applications?.get(value._id)?.count ?? 0) > 0} {#if value && count > 0}
<Tooltip <div
label={recruit.string.Applications} class="sm-tool-icon"
component={VacancyApplicationsPopup} use:tooltip={{
props={{ value: value._id, resultQuery }} label: recruit.string.Applications,
component: VacancyApplicationsPopup,
props: { value: value._id, resultQuery }
}}
> >
<div class="sm-tool-icon"> <div class="icon">
<span class="icon"><Icon icon={recruit.icon.Application} size={'small'} /></span>&nbsp;{applications?.get( <Icon icon={recruit.icon.Application} size={'small'} />
value._id
)?.count ?? 0}
</div> </div>
</Tooltip> &nbsp;
{applications?.get(value._id)?.count ?? 0}
</div>
{/if} {/if}

View File

@ -15,7 +15,7 @@
<script lang="ts"> <script lang="ts">
import type { IntlString } from '@anticrm/platform' import type { IntlString } from '@anticrm/platform'
import type { ButtonKind, ButtonSize, TooltipAlignment } from '@anticrm/ui' import type { ButtonKind, ButtonSize, TooltipAlignment } from '@anticrm/ui'
import { Button, Label, Tooltip } from '@anticrm/ui' import { Button, Label } from '@anticrm/ui'
export let label: IntlString export let label: IntlString
export let tooltip: IntlString export let tooltip: IntlString
@ -31,47 +31,46 @@
export let focusIndex = -1 export let focusIndex = -1
</script> </script>
<Tooltip direction={labelDirection} label={tooltip}> <Button
<Button {focusIndex}
{focusIndex} {kind}
{kind} {size}
{size} {justify}
{justify} {width}
{width} {disabled}
{disabled} showTooltip={{ label: tooltip, direction: labelDirection }}
on:click={() => { on:click={() => {
if (value === true) value = false if (value === true) value = false
else if (value === false) value = undefined else if (value === false) value = undefined
else value = true else value = true
}} }}
> >
<svelte:fragment slot="content"> <svelte:fragment slot="content">
<div class="flex-row-center flex-no-wrap pointer-events-none"> <div class="flex-row-center flex-no-wrap pointer-events-none">
<span class="overflow-label"> <span class="overflow-label">
<Label {label} /> <Label {label} />
</span> </span>
<div class="btn-icon ml-1"> <div class="btn-icon ml-1">
<svg class="yesno-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"> <svg class="yesno-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<circle class="circle" class:yes={value === true} class:no={value === false} cx="8" cy="8" r="6" /> <circle class="circle" class:yes={value === true} class:no={value === false} cx="8" cy="8" r="6" />
{#if value === true} {#if value === true}
<polygon fill="#fff" points="7.4,10.9 4.9,8.4 5.7,7.6 7.3,9.1 10.2,5.6 11.1,6.4 " /> <polygon fill="#fff" points="7.4,10.9 4.9,8.4 5.7,7.6 7.3,9.1 10.2,5.6 11.1,6.4 " />
{:else if value === false} {:else if value === false}
<polygon <polygon
fill="#fff" fill="#fff"
points="10.7,6 10,5.3 8,7.3 6,5.3 5.3,6 7.3,8 5.3,10 6,10.7 8,8.7 10,10.7 10.7,10 8.7,8 " points="10.7,6 10,5.3 8,7.3 6,5.3 5.3,6 7.3,8 5.3,10 6,10.7 8,8.7 10,10.7 10.7,10 8.7,8 "
/> />
{:else} {:else}
<path <path
fill="#fff" fill="#fff"
d="M7.3,9.3h1.3V9c0.1-0.5,0.6-0.9,1.1-1.4c0.4-0.4,0.8-0.9,0.8-1.6c0-1.1-0.8-1.8-2.2-1.8c-1.4,0-2.4,0.8-2.5,2.2 h1.4c0.1-0.6,0.4-1,1-1C8.8,5.4,9,5.7,9,6.2c0,0.4-0.3,0.7-0.7,1.1c-0.5,0.5-1,0.9-1,1.7V9.3z M8,11.6c0.5,0,0.9-0.4,0.9-0.9 c0-0.5-0.4-0.9-0.9-0.9c-0.5,0-0.9,0.4-0.9,0.9C7.1,11.2,7.5,11.6,8,11.6z" d="M7.3,9.3h1.3V9c0.1-0.5,0.6-0.9,1.1-1.4c0.4-0.4,0.8-0.9,0.8-1.6c0-1.1-0.8-1.8-2.2-1.8c-1.4,0-2.4,0.8-2.5,2.2 h1.4c0.1-0.6,0.4-1,1-1C8.8,5.4,9,5.7,9,6.2c0,0.4-0.3,0.7-0.7,1.1c-0.5,0.5-1,0.9-1,1.7V9.3z M8,11.6c0.5,0,0.9-0.4,0.9-0.9 c0-0.5-0.4-0.9-0.9-0.9c-0.5,0-0.9,0.4-0.9,0.9C7.1,11.2,7.5,11.6,8,11.6z"
/> />
{/if} {/if}
</svg> </svg>
</div>
</div> </div>
</svelte:fragment> </div>
</Button> </svelte:fragment>
</Tooltip> </Button>
<style lang="scss"> <style lang="scss">
.btn-icon { .btn-icon {

View File

@ -15,7 +15,7 @@
--> -->
<script lang="ts"> <script lang="ts">
import type { Review } from '@anticrm/recruit' import type { Review } from '@anticrm/recruit'
import { Icon, Tooltip } from '@anticrm/ui' import { Icon, tooltip } from '@anticrm/ui'
import OpinionsPopup from './OpinionsPopup.svelte' import OpinionsPopup from './OpinionsPopup.svelte'
import recruit from '../../plugin' import recruit from '../../plugin'
@ -23,9 +23,10 @@
</script> </script>
{#if value.opinions && value.opinions > 0} {#if value.opinions && value.opinions > 0}
<Tooltip label={recruit.string.Opinions} component={OpinionsPopup} props={{ value }}> <div
<div class="sm-tool-icon"> class="sm-tool-icon"
<span class="icon"><Icon icon={recruit.icon.Opinion} size={'small'} /></span>&nbsp;{value.opinions} use:tooltip={{ label: recruit.string.Opinions, component: OpinionsPopup, props: { value } }}
</div> >
</Tooltip> <span class="icon"><Icon icon={recruit.icon.Opinion} size={'small'} /></span>&nbsp;{value.opinions}
</div>
{/if} {/if}

View File

@ -18,7 +18,7 @@
import { formatName, Person } from '@anticrm/contact' import { formatName, Person } from '@anticrm/contact'
import { Hierarchy } from '@anticrm/core' import { Hierarchy } from '@anticrm/core'
import { Avatar } from '@anticrm/presentation' import { Avatar } from '@anticrm/presentation'
import { showPanel, Tooltip } from '@anticrm/ui' import { showPanel, tooltip } from '@anticrm/ui'
import view from '@anticrm/view' import view from '@anticrm/view'
export let value: Person | Person[] export let value: Person | Person[]
@ -35,13 +35,16 @@
{#if value} {#if value}
<div class="flex persons"> <div class="flex persons">
{#each persons as p} {#each persons as p}
<Tooltip label={calendar.string.PersonsLabel} props={{ name: formatName(p.name) }}> <div
<div class="flex-presenter" class:inline-presenter={inline} on:click={() => onClick(p)}> class="flex-presenter"
<div class="icon"> class:inline-presenter={inline}
<Avatar size={'x-small'} avatar={p.avatar} /> use:tooltip={{ label: calendar.string.PersonsLabel, props: { name: formatName(p.name) } }}
</div> on:click={() => onClick(p)}
>
<div class="icon">
<Avatar size={'x-small'} avatar={p.avatar} />
</div> </div>
</Tooltip> </div>
{/each} {/each}
</div> </div>
{/if} {/if}

View File

@ -21,7 +21,6 @@
Button, Button,
eventToHTMLElement, eventToHTMLElement,
getFocusManager, getFocusManager,
Tooltip,
TooltipAlignment TooltipAlignment
} from '@anticrm/ui' } from '@anticrm/ui'
import EnumPopup from './EnumPopup.svelte' import EnumPopup from './EnumPopup.svelte'
@ -63,10 +62,16 @@
} }
</script> </script>
<Tooltip {label} fill={false} direction={labelDirection}> <Button
<Button {focus} {focusIndex} icon={IconFolder} size={'small'} kind={'no-border'} on:click={handleClick}> {focus}
<span slot="content" class="text-sm overflow-label disabled"> {focusIndex}
{#if value}{value.name}{:else}<Label {label} />{/if} icon={IconFolder}
</span> size={'small'}
</Button> kind={'no-border'}
</Tooltip> showTooltip={{ label, direction: labelDirection }}
on:click={handleClick}
>
<span slot="content" class="text-sm overflow-label disabled">
{#if value}{value.name}{:else}<Label {label} />{/if}
</span>
</Button>

View File

@ -16,7 +16,7 @@
import core, { Enum, EnumOf, Ref } from '@anticrm/core' import core, { Enum, EnumOf, Ref } from '@anticrm/core'
import { TypeEnum } from '@anticrm/model' import { TypeEnum } from '@anticrm/model'
import presentation, { getClient } from '@anticrm/presentation' import presentation, { getClient } from '@anticrm/presentation'
import { Button, Tooltip, Label, showPopup } from '@anticrm/ui' import { Button, Label, showPopup } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import setting from '../../plugin' import setting from '../../plugin'
import EnumSelect from './EnumSelect.svelte' import EnumSelect from './EnumSelect.svelte'
@ -60,9 +60,13 @@
</div> </div>
{#if value} {#if value}
<div class="ml-2"> <div class="ml-2">
<Tooltip label={presentation.string.Edit}> <Button
<Button icon={setting.icon.Setting} kind={'no-border'} on:click={edit} size={'small'} /> icon={setting.icon.Setting}
</Tooltip> kind={'no-border'}
size={'small'}
showTooltip={{ label: presentation.string.Edit }}
on:click={edit}
/>
</div> </div>
{/if} {/if}
</div> </div>

View File

@ -15,7 +15,7 @@
<script lang="ts"> <script lang="ts">
import { Asset } from '@anticrm/platform' import { Asset } from '@anticrm/platform'
import { TagElement, TagReference } from '@anticrm/tags' import { TagElement, TagReference } from '@anticrm/tags'
import { ActionIcon, AnySvelteComponent, getPlatformColor, Tooltip } from '@anticrm/ui' import { ActionIcon, AnySvelteComponent, getPlatformColor, tooltip } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import tags from '../plugin' import tags from '../plugin'
import { getTagStyle } from '../utils' import { getTagStyle } from '../utils'
@ -30,29 +30,28 @@
$: name = element?.title ?? tag?.title ?? 'New item' $: name = element?.title ?? tag?.title ?? 'New item'
</script> </script>
<Tooltip <div
label={element?.description ? tags.string.TagTooltip : undefined} class="text-sm flex flex-between tag-item"
props={{ text: element?.description }} style={`${getTagStyle(getPlatformColor(tag?.color ?? element?.color ?? 0), selected)}`}
direction="right" use:tooltip={{
label: element?.description ? tags.string.TagTooltip : undefined,
props: { text: element?.description },
direction: 'right'
}}
> >
<div {name}
class="text-sm flex flex-between tag-item" {#if action}
style={`${getTagStyle(getPlatformColor(tag?.color ?? element?.color ?? 0), selected)}`} <div class="ml-1">
> <ActionIcon
{name} icon={action}
{#if action} size={'small'}
<div class="ml-1"> action={() => {
<ActionIcon dispatch('action')
icon={action} }}
size={'small'} />
action={() => { </div>
dispatch('action') {/if}
}} </div>
/>
</div>
{/if}
</div>
</Tooltip>
<style lang="scss"> <style lang="scss">
.tag-item { .tag-item {

View File

@ -18,7 +18,7 @@
import { KeyedAttribute } from '@anticrm/presentation' import { KeyedAttribute } from '@anticrm/presentation'
import { TagElement, TagReference } from '@anticrm/tags' import { TagElement, TagReference } from '@anticrm/tags'
import type { ButtonKind, ButtonSize, TooltipAlignment } from '@anticrm/ui' import type { ButtonKind, ButtonSize, TooltipAlignment } from '@anticrm/ui'
import { Button, showPopup, Tooltip } from '@anticrm/ui' import { Button, showPopup } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import tags from '../plugin' import tags from '../plugin'
import TagsPopup from './TagsPopup.svelte' import TagsPopup from './TagsPopup.svelte'
@ -73,24 +73,23 @@
} }
</script> </script>
<Tooltip label={key.attr.label} direction={labelDirection}> <Button
<Button icon={key.attr.icon ?? tags.icon.Tags}
icon={key.attr.icon ?? tags.icon.Tags} label={items.length > 0 ? undefined : key.attr.label}
label={items.length > 0 ? undefined : key.attr.label} width={width ?? 'min-content'}
width={width ?? 'min-content'} {kind}
{kind} {size}
{size} {justify}
{justify} showTooltip={{ label: key.attr.label, direction: labelDirection }}
on:click={addTag} on:click={addTag}
> >
<svelte:fragment slot="content"> <svelte:fragment slot="content">
{#if items.length > 0} {#if items.length > 0}
<div class="flex-row-center flex-nowrap overflow-label disabled"> <div class="flex-row-center flex-nowrap overflow-label disabled">
{#await translate(countLabel, { count: items.length }) then text} {#await translate(countLabel, { count: items.length }) then text}
{text} {text}
{/await} {/await}
</div> </div>
{/if} {/if}
</svelte:fragment> </svelte:fragment>
</Button> </Button>
</Tooltip>

View File

@ -19,7 +19,7 @@
import notification from '@anticrm/notification' import notification from '@anticrm/notification'
import { Avatar } from '@anticrm/presentation' import { Avatar } from '@anticrm/presentation'
import type { Issue, TodoItem } from '@anticrm/task' import type { Issue, TodoItem } from '@anticrm/task'
import { ActionIcon, Component, IconMoreH, showPopup, Tooltip } from '@anticrm/ui' import { ActionIcon, Component, IconMoreH, showPopup, tooltip } from '@anticrm/ui'
import { ContextMenu } from '@anticrm/view-resources' import { ContextMenu } from '@anticrm/view-resources'
import task from '../plugin' import task from '../plugin'
import TaskPresenter from './TaskPresenter.svelte' import TaskPresenter from './TaskPresenter.svelte'
@ -39,9 +39,16 @@
<div class="flex"> <div class="flex">
<TaskPresenter value={object} /> <TaskPresenter value={object} />
{#if todoItems.length > 0} {#if todoItems.length > 0}
<Tooltip label={task.string.TodoItems} component={task.component.TodoItemsPopup} props={{ value: object }}> <span
<div class="ml-2">( {doneTasks?.length}/ {todoItems.length} )</div> class="ml-2"
</Tooltip> use:tooltip={{
label: task.string.TodoItems,
component: task.component.TodoItemsPopup,
props: { value: object }
}}
>
({doneTasks?.length}/{todoItems.length})
</span>
{/if} {/if}
</div> </div>
<div class="flex-row-center"> <div class="flex-row-center">

View File

@ -23,7 +23,7 @@
import { createQuery, getClient } from '@anticrm/presentation' import { createQuery, getClient } from '@anticrm/presentation'
import setting, { Integration } from '@anticrm/setting' import setting, { Integration } from '@anticrm/setting'
import type { NewTelegramMessage, SharedTelegramMessage, TelegramMessage } from '@anticrm/telegram' import type { NewTelegramMessage, SharedTelegramMessage, TelegramMessage } from '@anticrm/telegram'
import { Button, eventToHTMLElement, IconShare, Tooltip, Scroller, showPopup, Panel, Icon, Label } from '@anticrm/ui' import { Button, eventToHTMLElement, IconShare, Scroller, showPopup, Panel, Icon, Label } from '@anticrm/ui'
import telegram from '../plugin' import telegram from '../plugin'
import Connect from './Connect.svelte' import Connect from './Connect.svelte'
import TelegramIcon from './icons/Telegram.svelte' import TelegramIcon from './icons/Telegram.svelte'
@ -225,16 +225,15 @@
}} }}
/> />
{:else} {:else}
<Tooltip label={telegram.string.Share}> <Button
<Button icon={IconShare}
icon={IconShare} kind={'transparent'}
kind={'transparent'} size={'medium'}
size={'medium'} showTooltip={{ label: telegram.string.Share }}
on:click={async () => { on:click={async () => {
selectable = !selectable selectable = !selectable
}} }}
/> />
</Tooltip>
{/if} {/if}
</svelte:fragment> </svelte:fragment>

View File

@ -15,7 +15,7 @@
<script lang="ts"> <script lang="ts">
import type { IntlString, Asset } from '@anticrm/platform' import type { IntlString, Asset } from '@anticrm/platform'
import type { AnySvelteComponent } from '@anticrm/ui' import type { AnySvelteComponent } from '@anticrm/ui'
import { Icon, Tooltip } from '@anticrm/ui' import { Icon, tooltip } from '@anticrm/ui'
export let label: IntlString export let label: IntlString
export let icon: Asset | AnySvelteComponent export let icon: Asset | AnySvelteComponent
@ -24,14 +24,12 @@
export let notify: boolean export let notify: boolean
</script> </script>
<Tooltip {label}> <button class="app" class:selected id={'app-' + label} use:tooltip={{ label }} on:click|stopPropagation={action}>
<button class="app" id={'app-' + label} class:selected on:click|stopPropagation={action}> <div class="flex-center icon-container" class:noty={notify}>
<div class="flex-center icon-container" class:noty={notify}> <Icon {icon} size={'large'} />
<Icon {icon} size={'large'} /> </div>
</div> {#if notify}<div class="marker" />{/if}
{#if notify}<div class="marker" />{/if} </button>
</button>
</Tooltip>
<style lang="scss"> <style lang="scss">
.app { .app {

View File

@ -14,7 +14,7 @@
--> -->
<script lang="ts"> <script lang="ts">
import { Timestamp } from '@anticrm/core' import { Timestamp } from '@anticrm/core'
import { DatePresenter, Tooltip, getDaysDifference } from '@anticrm/ui' import { DatePresenter, tooltip, getDaysDifference } from '@anticrm/ui'
import DueDatePopup from './DueDatePopup.svelte' import DueDatePopup from './DueDatePopup.svelte'
import { getDueDateIconModifier } from '../utils' import { getDueDateIconModifier } from '../utils'
@ -43,14 +43,17 @@
{#if shouldRender} {#if shouldRender}
{#if formattedDate} {#if formattedDate}
<Tooltip <div
direction={'top'} class="clear-mins"
component={DueDatePopup} use:tooltip={{
props={{ direction: 'top',
formattedDate: formattedDate, component: DueDatePopup,
daysDifference: daysDifference, props: {
isOverdue: isOverdue, formattedDate: formattedDate,
iconModifier: iconModifier daysDifference: daysDifference,
isOverdue: isOverdue,
iconModifier: iconModifier
}
}} }}
> >
<DatePresenter <DatePresenter
@ -61,7 +64,7 @@
{kind} {kind}
on:change={handleDueDateChanged} on:change={handleDueDateChanged}
/> />
</Tooltip> </div>
{:else} {:else}
<DatePresenter <DatePresenter
value={dateMs} value={dateMs}

View File

@ -18,7 +18,7 @@
import { Kanban, TypeState } from '@anticrm/kanban' import { Kanban, TypeState } from '@anticrm/kanban'
import { createQuery } from '@anticrm/presentation' import { createQuery } from '@anticrm/presentation'
import type { Issue, IssueStatus, Team } from '@anticrm/tracker' import type { Issue, IssueStatus, Team } from '@anticrm/tracker'
import { Button, Icon, IconAdd, showPopup, Tooltip, showPanel, Component } from '@anticrm/ui' import { Button, Icon, IconAdd, showPopup, showPanel, Component } from '@anticrm/ui'
import { focusStore, ListSelectionProvider, SelectDirection, selectionStore } from '@anticrm/view-resources' import { focusStore, ListSelectionProvider, SelectDirection, selectionStore } from '@anticrm/view-resources'
import ActionContext from '@anticrm/view-resources/src/components/ActionContext.svelte' import ActionContext from '@anticrm/view-resources/src/components/ActionContext.svelte'
import Menu from '@anticrm/view-resources/src/components/Menu.svelte' import Menu from '@anticrm/view-resources/src/components/Menu.svelte'
@ -139,15 +139,14 @@
<span class="counter ml-2 text-md">{count}</span> <span class="counter ml-2 text-md">{count}</span>
</div> </div>
<div class="flex gap-1"> <div class="flex gap-1">
<Tooltip label={tracker.string.AddIssueTooltip} direction={'left'}> <Button
<Button icon={IconAdd}
icon={IconAdd} kind={'transparent'}
kind={'transparent'} showTooltip={{ label: tracker.string.AddIssueTooltip, direction: 'left' }}
on:click={() => { on:click={() => {
showPopup(CreateIssue, { space: currentSpace, status: state._id }, 'top') showPopup(CreateIssue, { space: currentSpace, status: state._id }, 'top')
}} }}
/> />
</Tooltip>
</div> </div>
</div> </div>
</div> </div>

View File

@ -19,7 +19,7 @@
import notification from '@anticrm/notification' import notification from '@anticrm/notification'
import { createQuery, getClient } from '@anticrm/presentation' import { createQuery, getClient } from '@anticrm/presentation'
import { Issue, IssuesGrouping, IssuesOrdering, IssueStatus, Team, ViewOptions } from '@anticrm/tracker' import { Issue, IssuesGrouping, IssuesOrdering, IssueStatus, Team, ViewOptions } from '@anticrm/tracker'
import { Button, Component, Icon, IconAdd, showPanel, showPopup, Tooltip } from '@anticrm/ui' import { Button, Component, Icon, IconAdd, showPanel, showPopup } from '@anticrm/ui'
import { focusStore, ListSelectionProvider, SelectDirection, selectionStore } from '@anticrm/view-resources' import { focusStore, ListSelectionProvider, SelectDirection, selectionStore } from '@anticrm/view-resources'
import ActionContext from '@anticrm/view-resources/src/components/ActionContext.svelte' import ActionContext from '@anticrm/view-resources/src/components/ActionContext.svelte'
import Menu from '@anticrm/view-resources/src/components/Menu.svelte' import Menu from '@anticrm/view-resources/src/components/Menu.svelte'
@ -144,15 +144,14 @@
</div> </div>
{#if groupBy === IssuesGrouping.Status} {#if groupBy === IssuesGrouping.Status}
<div class="flex gap-1"> <div class="flex gap-1">
<Tooltip label={tracker.string.AddIssueTooltip} direction={'left'}> <Button
<Button icon={IconAdd}
icon={IconAdd} kind={'transparent'}
kind={'transparent'} showTooltip={{ label: tracker.string.AddIssueTooltip, direction: 'left' }}
on:click={() => { on:click={() => {
showPopup(CreateIssue, { space: currentSpace, status: state._id }, 'top') showPopup(CreateIssue, { space: currentSpace, status: state._id }, 'top')
}} }}
/> />
</Tooltip>
</div> </div>
{/if} {/if}
</div> </div>

View File

@ -15,7 +15,7 @@
<script lang="ts"> <script lang="ts">
import { createQuery } from '@anticrm/presentation' import { createQuery } from '@anticrm/presentation'
import { Team, Issue } from '@anticrm/tracker' import { Team, Issue } from '@anticrm/tracker'
import { Spinner, IconClose, Tooltip } from '@anticrm/ui' import { Spinner, IconClose, tooltip } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import tracker from '../../plugin' import tracker from '../../plugin'
import { getIssueId } from '../../utils' import { getIssueId } from '../../utils'
@ -38,11 +38,13 @@
<Spinner size="small" /> <Spinner size="small" />
{/if} {/if}
<span class="overflow-label issue-title">{issue.title}</span> <span class="overflow-label issue-title">{issue.title}</span>
<Tooltip label={tracker.string.RemoveParent} direction="bottom"> <div
<div class="button-close" on:click={() => dispatch('close')}> class="button-close"
<IconClose size="x-small" /> use:tooltip={{ label: tracker.string.RemoveParent, direction: 'bottom' }}
</div> on:click={() => dispatch('close')}
</Tooltip> >
<IconClose size="x-small" />
</div>
</div> </div>
<style lang="scss"> <style lang="scss">

View File

@ -14,13 +14,16 @@
--> -->
<script lang="ts"> <script lang="ts">
import { Asset, IntlString } from '@anticrm/platform' import { Asset, IntlString } from '@anticrm/platform'
import { Button, Tooltip } from '@anticrm/ui' import { Button } from '@anticrm/ui'
export let icon: Asset export let icon: Asset
export let title: IntlString export let title: IntlString
export let text: string export let text: string
</script> </script>
<Tooltip label={title} direction="bottom" fill> <Button
<Button {icon} kind="transparent" on:click={() => navigator.clipboard.writeText(text)} /> {icon}
</Tooltip> kind={'transparent'}
showTooltip={{ label: title, direction: 'bottom' }}
on:click={() => navigator.clipboard.writeText(text)}
/>

View File

@ -18,7 +18,7 @@
import { Team, Issue, IssueStatus } from '@anticrm/tracker' import { Team, Issue, IssueStatus } from '@anticrm/tracker'
import { import {
Icon, Icon,
Tooltip, tooltip,
showPanel, showPanel,
IconForward, IconForward,
IconDetails, IconDetails,
@ -99,20 +99,22 @@
</script> </script>
{#if parentIssue} {#if parentIssue}
{@const icon = getIssueStatusIcon(issue)}
<div class="flex root"> <div class="flex root">
<div class="item clear-mins"> <div class="item clear-mins">
<Tooltip label={tracker.string.OpenParent} direction="bottom" fill> <div
{@const icon = getIssueStatusIcon(issue)} class="flex-center parent-issue cursor-pointer"
<div class="flex-center parent-issue" on:click={openParentIssue}> use:tooltip={{ label: tracker.string.OpenParent, direction: 'bottom' }}
{#if icon} on:click={openParentIssue}
<div class="pr-2"> >
<Icon {icon} size="small" /> {#if icon}
</div> <div class="pr-2">
{/if} <Icon {icon} size="small" />
<span class="overflow-label flex-no-shrink mr-2">{getIssueId(team, parentIssue)}</span> </div>
<span class="overflow-label issue-title">{parentIssue.title}</span> {/if}
</div> <span class="overflow-label flex-no-shrink mr-2">{getIssueId(team, parentIssue)}</span>
</Tooltip> <span class="overflow-label issue-title">{parentIssue.title}</span>
</div>
</div> </div>
<div class="item"> <div class="item">
@ -121,22 +123,21 @@
<Spinner size="small" /> <Spinner size="small" />
</div> </div>
{:else} {:else}
<Tooltip label={tracker.string.OpenSubIssues} direction="bottom"> <div
<div bind:this={subIssuesElement}
bind:this={subIssuesElement} class="flex-center sub-issues cursor-pointer"
class="flex-center sub-issues" use:tooltip={{ label: tracker.string.OpenSubIssues, direction: 'bottom' }}
on:click|preventDefault={areSubIssuesLoading ? undefined : showSubIssues} on:click|preventDefault={areSubIssuesLoading ? undefined : showSubIssues}
> >
<span class="overflow-label">{subIssues?.length}</span> <span class="overflow-label">{subIssues?.length}</span>
<div class="ml-2"> <div class="ml-2">
<!-- TODO: fix icon --> <!-- TODO: fix icon -->
<Icon icon={IconDetails} size="small" /> <Icon icon={IconDetails} size="small" />
</div>
<div class="ml-1-5">
<Icon icon={IconForward} size="small" />
</div>
</div> </div>
</Tooltip> <div class="ml-1-5">
<Icon icon={IconForward} size="small" />
</div>
</div>
{/if} {/if}
</div> </div>
</div> </div>

View File

@ -16,7 +16,7 @@
import { SortingOrder, WithLookup } from '@anticrm/core' import { SortingOrder, WithLookup } from '@anticrm/core'
import { createQuery, getClient } from '@anticrm/presentation' import { createQuery, getClient } from '@anticrm/presentation'
import { calcRank, Issue, IssueStatus, Team } from '@anticrm/tracker' import { calcRank, Issue, IssueStatus, Team } from '@anticrm/tracker'
import { Button, Spinner, ExpandCollapse, Tooltip, closeTooltip, IconAdd } from '@anticrm/ui' import { Button, Spinner, ExpandCollapse, closeTooltip, IconAdd } from '@anticrm/ui'
import tracker from '../../../plugin' import tracker from '../../../plugin'
import Collapsed from '../../icons/Collapsed.svelte' import Collapsed from '../../icons/Collapsed.svelte'
import Expanded from '../../icons/Expanded.svelte' import Expanded from '../../icons/Expanded.svelte'
@ -69,22 +69,21 @@
/> />
{/if} {/if}
<Tooltip label={tracker.string.AddSubIssues} props={{ subIssues: 1 }} direction="bottom"> <Button
<Button id="add-sub-issue"
id="add-sub-issue" width="min-content"
width="min-content" icon={hasSubIssues ? IconAdd : undefined}
icon={hasSubIssues ? IconAdd : undefined} label={hasSubIssues ? undefined : tracker.string.AddSubIssues}
label={hasSubIssues ? undefined : tracker.string.AddSubIssues} labelParams={{ subIssues: 0 }}
labelParams={{ subIssues: 0 }} kind={'transparent'}
size="small" size={'small'}
kind="transparent" showTooltip={{ label: tracker.string.AddSubIssues, props: { subIssues: 1 }, direction: 'bottom' }}
on:click={() => { on:click={() => {
closeTooltip() closeTooltip()
isCreating = true isCreating = true
isCollapsed = false isCollapsed = false
}} }}
/> />
</Tooltip>
</div> </div>
<div class="mt-1"> <div class="mt-1">
{#if subIssues && issueStatuses && currentTeam} {#if subIssues && issueStatuses && currentTeam}

View File

@ -18,7 +18,7 @@
import { Project } from '@anticrm/tracker' import { Project } from '@anticrm/tracker'
import { UsersPopup, getClient } from '@anticrm/presentation' import { UsersPopup, getClient } from '@anticrm/presentation'
import { AttributeModel } from '@anticrm/view' import { AttributeModel } from '@anticrm/view'
import { eventToHTMLElement, showPopup, Tooltip } from '@anticrm/ui' import { eventToHTMLElement, showPopup } from '@anticrm/ui'
import { getObjectPresenter } from '@anticrm/view-resources' import { getObjectPresenter } from '@anticrm/view-resources'
import { IntlString } from '@anticrm/platform' import { IntlString } from '@anticrm/platform'
import tracker from '../../plugin' import tracker from '../../plugin'
@ -85,19 +85,17 @@
</script> </script>
{#if value && presenter} {#if value && presenter}
<Tooltip component={LeadPopup} props={{ lead: value }}> <svelte:component
<svelte:component this={presenter.presenter}
this={presenter.presenter} {value}
{value} {defaultName}
{defaultName} avatarSize={'tiny'}
avatarSize={'tiny'} isInteractive={true}
isInteractive={true} shouldShowPlaceholder={true}
shouldShowPlaceholder={true} shouldShowName={shouldShowLabel}
shouldShowName={shouldShowLabel} onEmployeeEdit={handleLeadEditorOpened}
onEmployeeEdit={handleLeadEditorOpened} tooltipLabels={{ component: LeadPopup, props: { lead: value } }}
tooltipLabels={{ personLabel: tracker.string.AssignedTo, placeholderLabel: tracker.string.AssignTo }} />
/>
</Tooltip>
{:else if presenter} {:else if presenter}
<svelte:component <svelte:component
this={presenter.presenter} this={presenter.presenter}

View File

@ -15,7 +15,6 @@
<script lang="ts"> <script lang="ts">
import { Project, ProjectStatus } from '@anticrm/tracker' import { Project, ProjectStatus } from '@anticrm/tracker'
import { getClient } from '@anticrm/presentation' import { getClient } from '@anticrm/presentation'
import { Tooltip } from '@anticrm/ui'
import type { ButtonKind, ButtonSize } from '@anticrm/ui' import type { ButtonKind, ButtonSize } from '@anticrm/ui'
import tracker from '../../plugin' import tracker from '../../plugin'
@ -42,18 +41,17 @@
{#if value} {#if value}
{#if isEditable} {#if isEditable}
<Tooltip label={tracker.string.SetStatus} fill> <ProjectStatusSelector
<ProjectStatusSelector {kind}
{kind} {size}
{size} {width}
{width} {justify}
{justify} {isEditable}
{isEditable} {shouldShowLabel}
{shouldShowLabel} showTooltip={{ label: tracker.string.SetStatus }}
selectedProjectStatus={value.status} selectedProjectStatus={value.status}
onProjectStatusChange={handleProjectStatusChanged} onProjectStatusChange={handleProjectStatusChanged}
/> />
</Tooltip>
{:else} {:else}
<ProjectStatusSelector <ProjectStatusSelector
{kind} {kind}

View File

@ -15,7 +15,7 @@
<script lang="ts"> <script lang="ts">
import { ProjectStatus } from '@anticrm/tracker' import { ProjectStatus } from '@anticrm/tracker'
import { Button, showPopup, SelectPopup, eventToHTMLElement } from '@anticrm/ui' import { Button, showPopup, SelectPopup, eventToHTMLElement } from '@anticrm/ui'
import type { ButtonKind, ButtonSize } from '@anticrm/ui' import type { ButtonKind, ButtonSize, LabelAndProps } from '@anticrm/ui'
import tracker from '../../plugin' import tracker from '../../plugin'
import { defaultProjectStatuses, projectStatusAssets } from '../../utils' import { defaultProjectStatuses, projectStatusAssets } from '../../utils'
@ -28,6 +28,7 @@
export let size: ButtonSize = 'small' export let size: ButtonSize = 'small'
export let justify: 'left' | 'center' = 'center' export let justify: 'left' | 'center' = 'center'
export let width: string | undefined = 'min-content' export let width: string | undefined = 'min-content'
export let showTooltip: LabelAndProps | undefined = undefined
$: selectedStatusIcon = selectedProjectStatus $: selectedStatusIcon = selectedProjectStatus
? projectStatusAssets[selectedProjectStatus].icon ? projectStatusAssets[selectedProjectStatus].icon
@ -62,5 +63,6 @@
disabled={!isEditable} disabled={!isEditable}
icon={selectedStatusIcon} icon={selectedStatusIcon}
label={selectedStatusLabel} label={selectedStatusLabel}
{showTooltip}
on:click={handleProjectStatusEditorOpened} on:click={handleProjectStatusEditorOpened}
/> />

View File

@ -17,7 +17,7 @@
import { Class, Doc, FindOptions, getObjectValue, Ref } from '@anticrm/core' import { Class, Doc, FindOptions, getObjectValue, Ref } from '@anticrm/core'
import { getClient } from '@anticrm/presentation' import { getClient } from '@anticrm/presentation'
import { Issue, Project } from '@anticrm/tracker' import { Issue, Project } from '@anticrm/tracker'
import { CheckBox, Spinner, Tooltip } from '@anticrm/ui' import { CheckBox, Spinner, tooltip } from '@anticrm/ui'
import { AttributeModel, BuildModelKey } from '@anticrm/view' import { AttributeModel, BuildModelKey } from '@anticrm/view'
import { buildModel, getObjectPresenter, LoadingProps } from '@anticrm/view-resources' import { buildModel, getObjectPresenter, LoadingProps } from '@anticrm/view-resources'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
@ -115,16 +115,17 @@
{#each itemModels as attributeModel, attributeModelIndex} {#each itemModels as attributeModel, attributeModelIndex}
{#if attributeModelIndex === 0} {#if attributeModelIndex === 0}
<div class="gridElement"> <div class="gridElement">
<Tooltip direction={'bottom'} label={tracker.string.SelectIssue}> <div
<div class="eListGridCheckBox"> class="eListGridCheckBox"
<CheckBox use:tooltip={{ direction: 'bottom', label: tracker.string.SelectIssue }}
checked={selectedObjectIdsSet.has(docObject._id)} >
on:value={(event) => { <CheckBox
onObjectChecked([docObject], event.detail) checked={selectedObjectIdsSet.has(docObject._id)}
}} on:value={(event) => {
/> onObjectChecked([docObject], event.detail)
</div> }}
</Tooltip> />
</div>
<div class="iconPresenter"> <div class="iconPresenter">
<svelte:component <svelte:component
this={attributeModel.presenter} this={attributeModel.presenter}

View File

@ -16,7 +16,7 @@
import { Class, Doc, Ref } from '@anticrm/core' import { Class, Doc, Ref } from '@anticrm/core'
import { AttributesBar, getClient, KeyedAttribute } from '@anticrm/presentation' import { AttributesBar, getClient, KeyedAttribute } from '@anticrm/presentation'
import setting, { settingId } from '@anticrm/setting' import setting, { settingId } from '@anticrm/setting'
import { Button, getCurrentLocation, Label, navigate, Tooltip } from '@anticrm/ui' import { Button, getCurrentLocation, Label, navigate } from '@anticrm/ui'
import { getFiltredKeys, isCollectionAttr } from '../utils' import { getFiltredKeys, isCollectionAttr } from '../utils'
export let object: Doc export let object: Doc
@ -58,22 +58,21 @@
</div> </div>
</div> </div>
<div class="tool"> <div class="tool">
<Tooltip label={setting.string.ClassSetting}> <Button
<Button icon={setting.icon.Setting}
icon={setting.icon.Setting} kind={'transparent'}
kind={'transparent'} showTooltip={{ label: setting.string.ClassSetting }}
on:click={(ev) => { on:click={(ev) => {
ev.stopPropagation() ev.stopPropagation()
const loc = getCurrentLocation() const loc = getCurrentLocation()
loc.path[1] = settingId loc.path[1] = settingId
loc.path[2] = 'classes' loc.path[2] = 'classes'
loc.path.length = 3 loc.path.length = 3
loc.query = { _class } loc.query = { _class }
loc.fragment = undefined loc.fragment = undefined
navigate(loc) navigate(loc)
}} }}
/> />
</Tooltip>
</div> </div>
</div> </div>
{#if keys.length} {#if keys.length}

View File

@ -15,7 +15,7 @@
<script lang="ts"> <script lang="ts">
import type { IntlString, Asset } from '@anticrm/platform' import type { IntlString, Asset } from '@anticrm/platform'
import type { AnySvelteComponent } from '@anticrm/ui' import type { AnySvelteComponent } from '@anticrm/ui'
import { Icon, Tooltip } from '@anticrm/ui' import { Icon, tooltip } from '@anticrm/ui'
export let label: IntlString export let label: IntlString
export let icon: Asset | AnySvelteComponent export let icon: Asset | AnySvelteComponent
@ -24,14 +24,12 @@
export let notify: boolean export let notify: boolean
</script> </script>
<Tooltip {label}> <button class="app" class:selected id={'app-' + label} use:tooltip={{ label }} on:click|stopPropagation={action}>
<button class="app" id={'app-' + label} class:selected on:click|stopPropagation={action}> <div class="flex-center icon-container" class:noty={notify}>
<div class="flex-center icon-container" class:noty={notify}> <Icon {icon} size={'large'} />
<Icon {icon} size={'large'} /> </div>
</div> {#if notify}<div class="marker" />{/if}
{#if notify}<div class="marker" />{/if} </button>
</button>
</Tooltip>
<style lang="scss"> <style lang="scss">
.app { .app {

View File

@ -36,7 +36,7 @@ test.describe('contact tests', () => {
// await page.hover('[id="gmail:string:Email"]') // await page.hover('[id="gmail:string:Email"]')
await page.fill('[placeholder="john\\.appleseed\\@apple\\.com"]', 'wer@qwe.com') await page.fill('[placeholder="john\\.appleseed\\@apple\\.com"]', 'wer@qwe.com')
// Click text=Apply // Click text=Apply
await page.click('button:nth-child(3)') await page.click('.editor-container button:nth-child(3)')
}) })
test('create-template', async ({ page }) => { test('create-template', async ({ page }) => {
// Go to http://localhost:8083/workbench%3Acomponent%3AWorkbenchApp // Go to http://localhost:8083/workbench%3Acomponent%3AWorkbenchApp

View File

@ -37,10 +37,12 @@ test.describe('recruit tests', () => {
await page.click('form[id="tags:string:AddTag"] button:has-text("Create")') await page.click('form[id="tags:string:AddTag"] button:has-text("Create")')
await page.click('button:has-text("Other")') await page.click('button:has-text("Other")')
// Click text=s1 // Click text=s1
await page.click('text=s1') // await page.click('text=s1')
await page.click('button:has-text("s1") .check')
// Click :nth-match(:text("Cancel"), 2) // Click :nth-match(:text("Cancel"), 2)
// await page.click('button:has-text("Cancel")') // await page.click('button:has-text("Cancel")')
await page.keyboard.press('Escape') await page.keyboard.press('Escape')
await page.keyboard.press('Escape')
// Click button:has-text("Create") // Click button:has-text("Create")
await page.click('button:has-text("Create")') await page.click('button:has-text("Create")')
}) })