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

View File

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

View File

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

View File

@ -23,7 +23,6 @@
Button,
eventToHTMLElement,
getFocusManager,
Tooltip,
TooltipAlignment,
ButtonKind,
ButtonSize
@ -84,10 +83,18 @@
}
</script>
<Tooltip {label} fill={false} direction={labelDirection}>
<Button {focus} {focusIndex} icon={IconFolder} {size} {kind} {justify} {width} on:click={showSpacesPopup}>
<span slot="content" class="overflow-label disabled text-sm">
{#if selected}{selected.name}{:else}<Label {label} />{/if}
</span>
</Button>
</Tooltip>
<Button
{focus}
{focusIndex}
icon={IconFolder}
{size}
{kind}
{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 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 presentation from '..'
@ -111,9 +111,9 @@
{#if allowDeselect && space._id === selected}
<div class="check-right pointer-events-none">
{#if titleDeselect}
<Tooltip label={titleDeselect ?? presentation.string.Deselect}>
<div class="clear-mins" use:tooltip={{ label: titleDeselect ?? presentation.string.Deselect }}>
<CheckBox checked circle primary />
</Tooltip>
</div>
{:else}
<CheckBox checked circle primary />
{/if}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,12 +14,12 @@
// limitations under the License.
-->
<script lang="ts">
import Tooltip from './Tooltip.svelte'
import { tooltip } from '../tooltips'
import ErrorPopup from './ErrorPopup.svelte'
export let error: any
</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">
<circle cx="10" cy="10" r="7.275" stroke="#EE7A7A" stroke-width="1.2" />
<path
@ -29,4 +29,4 @@
stroke-width="0.2"
/>
</svg>
</Tooltip>
</div>

View File

@ -1,6 +1,6 @@
import { IntlString } from '@anticrm/platform'
import { writable } from 'svelte/store'
import { AnyComponent, AnySvelteComponent, LabelAndProps, TooltipAlignment } from './types'
import type { AnyComponent, AnySvelteComponent, LabelAndProps, TooltipAlignment } from './types'
const emptyTooltip: LabelAndProps = {
label: undefined,
@ -42,6 +42,10 @@ export function tooltip (node: HTMLElement, options?: LabelAndProps): any {
return {
update (options: LabelAndProps) {
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 () {

View File

@ -16,7 +16,7 @@
import { EmployeeAccount } from '@anticrm/contact'
import { Doc, getCurrentAccount } from '@anticrm/core'
import { getClient } from '@anticrm/presentation'
import { Button, showPopup, Tooltip } from '@anticrm/ui'
import { Button, showPopup } from '@anticrm/ui'
import calendar from '../plugin'
import CreateReminder from './CreateReminder.svelte'
import DocRemindersPopup from './DocRemindersPopup.svelte'
@ -57,6 +57,10 @@
}
</script>
<Tooltip label={isEvent ? calendar.string.RemindMeAt : calendar.string.Reminders}>
<Button size={'medium'} kind={'transparent'} icon={calendar.icon.Reminder} on:click={(e) => click(e)} />
</Tooltip>
<Button
size={'medium'}
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 { Avatar } from '@anticrm/presentation'
import calendar from '../plugin'
import { showPanel, Tooltip } from '@anticrm/ui'
import { showPanel, tooltip } from '@anticrm/ui'
import view from '@anticrm/view'
export let value: Person | Person[]
@ -35,13 +35,16 @@
{#if value}
<div class="flex persons">
{#each persons as p}
<Tooltip label={calendar.string.PersonsLabel} props={{ name: formatName(p.name) }}>
<div class="flex-presenter" class:inline-presenter={inline} on:click={() => onClick(p)}>
<div class="icon">
<Avatar size={'x-small'} avatar={p.avatar} />
</div>
<div
class="flex-presenter"
class:inline-presenter={inline}
use:tooltip={{ label: calendar.string.PersonsLabel, props: { name: formatName(p.name) } }}
on:click={() => onClick(p)}
>
<div class="icon">
<Avatar size={'x-small'} avatar={p.avatar} />
</div>
</Tooltip>
</div>
{/each}
</div>
{/if}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,9 +6,17 @@
import EmployeePreviewPopup from './EmployeePreviewPopup.svelte'
import { WithLookup } from '@anticrm/core'
import { IntlString } from '@anticrm/platform'
import type { AnyComponent, AnySvelteComponent } from '@anticrm/ui'
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 shouldShowName: boolean = true
export let shouldShowPlaceholder = false

View File

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

View File

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

View File

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

View File

@ -16,7 +16,7 @@
<script lang="ts">
import core, { Doc, TxCUD } from '@anticrm/core'
import { createQuery } from '@anticrm/presentation'
import { ScrollBox, Tooltip } from '@anticrm/ui'
import { ScrollBox, tooltip } from '@anticrm/ui'
import { toIntl } from '..'
import ContentPopup from './ContentPopup.svelte'
@ -49,7 +49,9 @@
<td>{tx.objectId}</td>
<td>{tx.objectClass}</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>
</tr>
{/each}

View File

@ -14,7 +14,7 @@
// limitations under the License.
-->
<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 view from '@anticrm/view'
import { queries, toIntl } from '..'
@ -44,9 +44,9 @@
<td>{JSON.stringify(q.options ?? {})}</td>
<td>{q.result.length}</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
</Tooltip>
</span>
</td>
<td>
<ActionIcon

View File

@ -19,7 +19,7 @@
import gmail from '../plugin'
import { Channel, Contact, EmployeeAccount, formatName } 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 setting from '@anticrm/setting'
import Messages from './Messages.svelte'
@ -144,15 +144,14 @@
newMessage = true
}}
/>
<Tooltip label={gmail.string.ShareMessages}>
<Button
icon={IconShare}
kind={'transparent'}
on:click={async () => {
selectable = !selectable
}}
/>
</Tooltip>
<Button
icon={IconShare}
kind={'transparent'}
showTooltip={{ label: gmail.string.ShareMessages }}
on:click={async () => {
selectable = !selectable
}}
/>
</div>
{/if}
</div>

View File

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

View File

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

View File

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

View File

@ -15,7 +15,7 @@
<script lang="ts">
import type { IntlString } from '@anticrm/platform'
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 tooltip: IntlString
@ -31,47 +31,46 @@
export let focusIndex = -1
</script>
<Tooltip direction={labelDirection} label={tooltip}>
<Button
{focusIndex}
{kind}
{size}
{justify}
{width}
{disabled}
on:click={() => {
if (value === true) value = false
else if (value === false) value = undefined
else value = true
}}
>
<svelte:fragment slot="content">
<div class="flex-row-center flex-no-wrap pointer-events-none">
<span class="overflow-label">
<Label {label} />
</span>
<div class="btn-icon ml-1">
<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" />
{#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 " />
{:else if value === false}
<polygon
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 "
/>
{:else}
<path
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"
/>
{/if}
</svg>
</div>
<Button
{focusIndex}
{kind}
{size}
{justify}
{width}
{disabled}
showTooltip={{ label: tooltip, direction: labelDirection }}
on:click={() => {
if (value === true) value = false
else if (value === false) value = undefined
else value = true
}}
>
<svelte:fragment slot="content">
<div class="flex-row-center flex-no-wrap pointer-events-none">
<span class="overflow-label">
<Label {label} />
</span>
<div class="btn-icon ml-1">
<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" />
{#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 " />
{:else if value === false}
<polygon
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 "
/>
{:else}
<path
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"
/>
{/if}
</svg>
</div>
</svelte:fragment>
</Button>
</Tooltip>
</div>
</svelte:fragment>
</Button>
<style lang="scss">
.btn-icon {

View File

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

View File

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

View File

@ -21,7 +21,6 @@
Button,
eventToHTMLElement,
getFocusManager,
Tooltip,
TooltipAlignment
} from '@anticrm/ui'
import EnumPopup from './EnumPopup.svelte'
@ -63,10 +62,16 @@
}
</script>
<Tooltip {label} fill={false} direction={labelDirection}>
<Button {focus} {focusIndex} icon={IconFolder} size={'small'} kind={'no-border'} on:click={handleClick}>
<span slot="content" class="text-sm overflow-label disabled">
{#if value}{value.name}{:else}<Label {label} />{/if}
</span>
</Button>
</Tooltip>
<Button
{focus}
{focusIndex}
icon={IconFolder}
size={'small'}
kind={'no-border'}
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 { TypeEnum } from '@anticrm/model'
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 setting from '../../plugin'
import EnumSelect from './EnumSelect.svelte'
@ -60,9 +60,13 @@
</div>
{#if value}
<div class="ml-2">
<Tooltip label={presentation.string.Edit}>
<Button icon={setting.icon.Setting} kind={'no-border'} on:click={edit} size={'small'} />
</Tooltip>
<Button
icon={setting.icon.Setting}
kind={'no-border'}
size={'small'}
showTooltip={{ label: presentation.string.Edit }}
on:click={edit}
/>
</div>
{/if}
</div>

View File

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

View File

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

View File

@ -19,7 +19,7 @@
import notification from '@anticrm/notification'
import { Avatar } from '@anticrm/presentation'
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 task from '../plugin'
import TaskPresenter from './TaskPresenter.svelte'
@ -39,9 +39,16 @@
<div class="flex">
<TaskPresenter value={object} />
{#if todoItems.length > 0}
<Tooltip label={task.string.TodoItems} component={task.component.TodoItemsPopup} props={{ value: object }}>
<div class="ml-2">( {doneTasks?.length}/ {todoItems.length} )</div>
</Tooltip>
<span
class="ml-2"
use:tooltip={{
label: task.string.TodoItems,
component: task.component.TodoItemsPopup,
props: { value: object }
}}
>
({doneTasks?.length}/{todoItems.length})
</span>
{/if}
</div>
<div class="flex-row-center">

View File

@ -23,7 +23,7 @@
import { createQuery, getClient } from '@anticrm/presentation'
import setting, { Integration } from '@anticrm/setting'
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 Connect from './Connect.svelte'
import TelegramIcon from './icons/Telegram.svelte'
@ -225,16 +225,15 @@
}}
/>
{:else}
<Tooltip label={telegram.string.Share}>
<Button
icon={IconShare}
kind={'transparent'}
size={'medium'}
on:click={async () => {
selectable = !selectable
}}
/>
</Tooltip>
<Button
icon={IconShare}
kind={'transparent'}
size={'medium'}
showTooltip={{ label: telegram.string.Share }}
on:click={async () => {
selectable = !selectable
}}
/>
{/if}
</svelte:fragment>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,13 +14,16 @@
-->
<script lang="ts">
import { Asset, IntlString } from '@anticrm/platform'
import { Button, Tooltip } from '@anticrm/ui'
import { Button } from '@anticrm/ui'
export let icon: Asset
export let title: IntlString
export let text: string
</script>
<Tooltip label={title} direction="bottom" fill>
<Button {icon} kind="transparent" on:click={() => navigator.clipboard.writeText(text)} />
</Tooltip>
<Button
{icon}
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 {
Icon,
Tooltip,
tooltip,
showPanel,
IconForward,
IconDetails,
@ -99,20 +99,22 @@
</script>
{#if parentIssue}
{@const icon = getIssueStatusIcon(issue)}
<div class="flex root">
<div class="item clear-mins">
<Tooltip label={tracker.string.OpenParent} direction="bottom" fill>
{@const icon = getIssueStatusIcon(issue)}
<div class="flex-center parent-issue" on:click={openParentIssue}>
{#if icon}
<div class="pr-2">
<Icon {icon} size="small" />
</div>
{/if}
<span class="overflow-label flex-no-shrink mr-2">{getIssueId(team, parentIssue)}</span>
<span class="overflow-label issue-title">{parentIssue.title}</span>
</div>
</Tooltip>
<div
class="flex-center parent-issue cursor-pointer"
use:tooltip={{ label: tracker.string.OpenParent, direction: 'bottom' }}
on:click={openParentIssue}
>
{#if icon}
<div class="pr-2">
<Icon {icon} size="small" />
</div>
{/if}
<span class="overflow-label flex-no-shrink mr-2">{getIssueId(team, parentIssue)}</span>
<span class="overflow-label issue-title">{parentIssue.title}</span>
</div>
</div>
<div class="item">
@ -121,22 +123,21 @@
<Spinner size="small" />
</div>
{:else}
<Tooltip label={tracker.string.OpenSubIssues} direction="bottom">
<div
bind:this={subIssuesElement}
class="flex-center sub-issues"
on:click|preventDefault={areSubIssuesLoading ? undefined : showSubIssues}
>
<span class="overflow-label">{subIssues?.length}</span>
<div class="ml-2">
<!-- TODO: fix icon -->
<Icon icon={IconDetails} size="small" />
</div>
<div class="ml-1-5">
<Icon icon={IconForward} size="small" />
</div>
<div
bind:this={subIssuesElement}
class="flex-center sub-issues cursor-pointer"
use:tooltip={{ label: tracker.string.OpenSubIssues, direction: 'bottom' }}
on:click|preventDefault={areSubIssuesLoading ? undefined : showSubIssues}
>
<span class="overflow-label">{subIssues?.length}</span>
<div class="ml-2">
<!-- TODO: fix icon -->
<Icon icon={IconDetails} size="small" />
</div>
</Tooltip>
<div class="ml-1-5">
<Icon icon={IconForward} size="small" />
</div>
</div>
{/if}
</div>
</div>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -36,7 +36,7 @@ test.describe('contact tests', () => {
// await page.hover('[id="gmail:string:Email"]')
await page.fill('[placeholder="john\\.appleseed\\@apple\\.com"]', 'wer@qwe.com')
// Click text=Apply
await page.click('button:nth-child(3)')
await page.click('.editor-container button:nth-child(3)')
})
test('create-template', async ({ page }) => {
// 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('button:has-text("Other")')
// 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)
// await page.click('button:has-text("Cancel")')
await page.keyboard.press('Escape')
await page.keyboard.press('Escape')
// Click button:has-text("Create")
await page.click('button:has-text("Create")')
})