diff --git a/packages/ui/src/components/Tooltip.svelte b/packages/ui/src/components/Tooltip.svelte
index a7af624202..6f877a9b69 100644
--- a/packages/ui/src/components/Tooltip.svelte
+++ b/packages/ui/src/components/Tooltip.svelte
@@ -15,11 +15,13 @@
 
 <script lang="ts">
   import type { IntlString } from '@anticrm/platform'
-  import type { TooltipAligment } from '..'
-  import { showTooltip, closeTooltip } from '..'
+  import type { TooltipAligment, AnySvelteComponent, AnyComponent } from '..'
+  import { showTooltip } from '..'
 
-  export let label: IntlString
+  export let label: IntlString | undefined
   export let direction: TooltipAligment | undefined
+  export let component: AnySvelteComponent | AnyComponent | undefined = undefined
+  export let props: any | undefined = undefined
 
   let triggerHTML: HTMLElement
 </script>
@@ -27,11 +29,8 @@
 <div
   class="tooltip-trigger"
   bind:this={triggerHTML}
-  on:mouseenter={() => {
-    showTooltip(label, triggerHTML, direction)
-  }}
-  on:mouseleave={() => {
-    closeTooltip()
+  on:mousemove={() => {
+    showTooltip(label, triggerHTML, direction, component, props)
   }}
 >
   <slot />
diff --git a/packages/ui/src/components/TooltipInstance.svelte b/packages/ui/src/components/TooltipInstance.svelte
index b20c800558..3dd0e7006a 100644
--- a/packages/ui/src/components/TooltipInstance.svelte
+++ b/packages/ui/src/components/TooltipInstance.svelte
@@ -13,44 +13,77 @@
 // limitations under the License.
 -->
 <script lang="ts">
-  import { tooltipstore as tooltip } from '..'
+  import { tooltipstore as tooltip, closeTooltip } from '..'
   import type { TooltipAligment } from '..'
   import Label from './Label.svelte'
 
   let tooltipHTML: HTMLElement
   let dir: TooltipAligment
+  let rect: DOMRect
 
   $: {
     if ($tooltip.label && tooltipHTML) {
       if ($tooltip.element) {
-        const rect = $tooltip.element.getBoundingClientRect()
+        rect = $tooltip.element.getBoundingClientRect()
         const doc = document.body.getBoundingClientRect()
 
-        if (!$tooltip.direction) {
-          if (rect.right < doc.width / 5) dir = 'right'
-          else if (rect.left > doc.width - doc.width / 5) dir = 'left'
-          else if (rect.top < tooltipHTML.clientHeight) dir = 'bottom'
-          else dir = 'top'
-        } else dir = $tooltip.direction
+        if ($tooltip.component) {
+
+          if (rect.bottom + tooltipHTML.clientHeight + 28 < doc.height) {
+            tooltipHTML.style.top = `calc(${rect.bottom}px + .75rem)`
+            dir = 'bottom'
+          } else if (rect.top > doc.height - rect.bottom) {
+            tooltipHTML.style.bottom = `calc(${doc.height - rect.y}px + .75rem)`
+            if (tooltipHTML.clientHeight > rect.top - 28) {
+              tooltipHTML.style.top = '1rem'
+              tooltipHTML.style.height = rect.top - 28 + 'px'
+            }
+            dir = 'top'
+          } else {
+            tooltipHTML.style.top = `calc(${rect.bottom}px + .75rem)`
+            if (tooltipHTML.clientHeight > doc.height - rect.bottom - 28) {
+              tooltipHTML.style.bottom = '1rem'
+              tooltipHTML.style.height = doc.height - rect.bottom - 28 + 'px'
+            }
+            dir = 'bottom'
+          }
+          if (rect.left + tooltipHTML.clientWidth + 16 > doc.width) {
+            tooltipHTML.style.left = ''
+            tooltipHTML.style.right = doc.width - rect.right + 'px'
+          } else {
+            tooltipHTML.style.left = rect.left + 'px'
+            tooltipHTML.style.right = ''
+          }
+
+        } else {
+
+          if (!$tooltip.direction) {
+            if (rect.right < doc.width / 5) dir = 'right'
+            else if (rect.left > doc.width - doc.width / 5) dir = 'left'
+            else if (rect.top < tooltipHTML.clientHeight) dir = 'bottom'
+            else dir = 'top'
+          } else dir = $tooltip.direction
+
+          if (dir === 'right') {
+            tooltipHTML.style.top = rect.y + rect.height / 2 + 'px'
+            tooltipHTML.style.left = `calc(${rect.right}px + .75rem)`
+            tooltipHTML.style.transform = 'translateY(-50%)'
+          } else if (dir === 'left') {
+            tooltipHTML.style.top = rect.y + rect.height / 2 + 'px'
+            tooltipHTML.style.right = `calc(${doc.width - rect.x}px + .75rem)`
+            tooltipHTML.style.transform = 'translateY(-50%)'
+          } else if (dir === 'bottom') {
+            tooltipHTML.style.top = `calc(${rect.bottom}px + .5rem)`
+            tooltipHTML.style.left = rect.x + rect.width / 2 + 'px'
+            tooltipHTML.style.transform = 'translateX(-50%)'
+          } else if (dir === 'top') {
+            tooltipHTML.style.bottom = `calc(${doc.height - rect.y}px + .75rem)`
+            tooltipHTML.style.left = rect.x + rect.width / 2 + 'px'
+            tooltipHTML.style.transform = 'translateX(-50%)'
+          }
+          tooltipHTML.classList.remove('no-arrow')
 
-        if (dir === 'right') {
-          tooltipHTML.style.top = rect.y + rect.height / 2 + 'px'
-          tooltipHTML.style.left = `calc(${rect.right}px + .75rem)`
-          tooltipHTML.style.transform = 'translateY(-50%)'
-        } else if (dir === 'left') {
-          tooltipHTML.style.top = rect.y + rect.height / 2 + 'px'
-          tooltipHTML.style.right = `calc(${doc.width - rect.x}px + .75rem)`
-          tooltipHTML.style.transform = 'translateY(-50%)'
-        } else if (dir === 'bottom') {
-          tooltipHTML.style.top = `calc(${rect.bottom}px + .5rem)`
-          tooltipHTML.style.left = rect.x + rect.width / 2 + 'px'
-          tooltipHTML.style.transform = 'translateX(-50%)'
-        } else if (dir === 'top') {
-          tooltipHTML.style.bottom = `calc(${doc.height - rect.y}px + .75rem)`
-          tooltipHTML.style.left = rect.x + rect.width / 2 + 'px'
-          tooltipHTML.style.transform = 'translateX(-50%)'
         }
-        tooltipHTML.classList.remove('no-arrow')
       } else {
         tooltipHTML.style.top = '50%'
         tooltipHTML.style.left = '50%'
@@ -62,15 +95,60 @@
       tooltipHTML.style.visibility = 'visible'
     } else if (tooltipHTML) tooltipHTML.style.visibility = 'hidden'
   }
+
+  const hideTooltip = (): void => {
+    tooltipHTML.style.visibility = 'hidden'
+    closeTooltip()
+  }
+
+  const whileShow = (ev: MouseEvent): void => {
+    if ($tooltip.element) {
+      const rectP = tooltipHTML.getBoundingClientRect()
+      const topT = (dir === 'top') ? rect.top - 16 : rect.top
+      const bottomT = (dir === 'bottom') ? rect.bottom + 16 : rect.bottom
+      const leftT = (dir === 'left') ? rect.left - 16 : rect.left
+      const rightT = (dir === 'right') ? rect.right + 16 : rect.right
+      if (!((ev.x >= leftT && ev.x <= rightT && ev.y >= topT && ev.y <= bottomT) ||
+            (ev.x >= rectP.left && ev.x <= rectP.right && ev.y >= rectP.top && ev.y <= rectP.bottom))
+         ) hideTooltip()
+    }
+  }
 </script>
 
-{#if $tooltip.label}
+<svelte:window on:mousemove={(ev) => { whileShow(ev) }} />
+{#if $tooltip.component}
+  <div class="popup" bind:this={tooltipHTML}>
+    {#if $tooltip.label}<div class="header"><Label label={$tooltip.label} /></div>{/if}
+    <svelte:component this={$tooltip.component} {...$tooltip.props} />
+  </div>
+{:else if $tooltip.label}
   <div class="tooltip {dir}" bind:this={tooltipHTML}>
     <Label label={$tooltip.label} />
   </div>
 {/if}
 
 <style lang="scss">
+  .header {
+    margin-bottom: 1.5rem;
+    font-weight: 500;
+    font-size: 1rem;
+    color: var(--theme-caption-color);
+  }
+
+  .popup {
+    position: fixed;
+    display: flex;
+    flex-direction: column;
+    padding: 1rem;
+    color: var(--theme-caption-color);
+    background-color: var(--theme-button-bg-hovered);
+    border: 1px solid var(--theme-button-border-enabled);
+    border-radius: .75rem;
+    user-select: none;
+    filter: drop-shadow(0 1.5rem 4rem rgba(0, 0, 0, .35));
+    z-index: 1000;
+  }
+
   .tooltip {
     position: fixed;
     padding: .5rem;
diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts
index a5807a4226..edd65f1232 100644
--- a/packages/ui/src/index.ts
+++ b/packages/ui/src/index.ts
@@ -120,15 +120,17 @@ export function closePopup (): void {
 export const tooltipstore = writable<LabelAndProps>({
   label: undefined,
   element: undefined,
-  direction: undefined
+  direction: undefined,
+  component: undefined,
+  props: undefined
 })
 
-export function showTooltip (label: IntlString, element: HTMLElement, direction?: TooltipAligment): void {
-  tooltipstore.set({ label: label, element: element, direction: direction })
+export function showTooltip (label: IntlString | undefined, element: HTMLElement, direction?: TooltipAligment, component?: AnySvelteComponent | AnyComponent, props?: any): void {
+  tooltipstore.set({ label: label, element: element, direction: direction, component: component, props: props })
 }
 
 export function closeTooltip (): void {
-  tooltipstore.set({ label: undefined, element: undefined, direction: undefined })
+  tooltipstore.set({ label: undefined, element: undefined, direction: undefined, component: undefined, props: undefined })
 }
 
 export const ticker = readable(Date.now(), set => {
diff --git a/packages/ui/src/types.ts b/packages/ui/src/types.ts
index ebdf3dae33..65c7bc9921 100644
--- a/packages/ui/src/types.ts
+++ b/packages/ui/src/types.ts
@@ -62,4 +62,6 @@ export interface LabelAndProps {
   label: IntlString | undefined
   element: HTMLElement | undefined
   direction?: TooltipAligment
+  component?: AnySvelteComponent | AnyComponent
+  props?: any
 }
diff --git a/plugins/chunter-resources/src/components/AttachmentPopup.svelte b/plugins/chunter-resources/src/components/AttachmentPopup.svelte
new file mode 100644
index 0000000000..c765d21ea5
--- /dev/null
+++ b/plugins/chunter-resources/src/components/AttachmentPopup.svelte
@@ -0,0 +1,87 @@
+<!--
+// Copyright © 2020, 2021 Anticrm Platform Contributors.
+// Copyright © 2021 Hardcore Engineering Inc.
+// 
+// Licensed under the Eclipse Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License. You may
+// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// 
+// See the License for the specific language governing permissions and
+// limitations under the License.
+-->
+
+<script lang="ts">
+  import type { Bag } from '@anticrm/core'
+  import type { Attachment } from '@anticrm/chunter'
+  import { showPopup, closeTooltip } from '@anticrm/ui'
+  import { PDFViewer } from '@anticrm/presentation'
+
+  export let files: Bag<Attachment>
+
+  const maxLenght: number = 32
+  const trimFilename = (fname: string): string => (fname.length > maxLenght)
+                        ? fname.substr(0, (maxLenght - 1) / 2) + '...' + fname.substr(-(maxLenght - 1) / 2)
+                        : fname
+</script>
+
+<table class="table-body">
+  <tbody>
+    {#each Object.values(files) as file}
+      <tr class="tr-body">
+        <td class="item flex-row-center">
+          <div class="flex-center file-icon">pdf</div>
+          <div class="flex-col flex-grow" style="cursor: pointer" on:click={() => {
+            closeTooltip()
+            showPopup(PDFViewer, { file: file.file }, 'right')
+          }}>
+            <div class="overflow-label caption-color">{trimFilename(file.name)}</div>
+            <div class="overflow-label file-desc">{file.type}</div>
+          </div>
+        </td>
+        <td>10 / 8</td>
+      </tr>
+    {/each}
+  </tbody>
+</table>
+
+<style lang="scss">
+  th, td {
+    padding: .75rem 0;
+    text-align: left;
+  }
+  th {
+    font-weight: 500;
+    font-size: .75rem;
+    color: var(--theme-content-dark-color);
+  }
+  td {
+    color: var(--theme-caption-color);
+  }
+  .tr-body {
+    border-top: 1px solid var(--theme-button-border-hovered);
+    &:first-child { border-top: none; }
+  }
+
+  .item { padding: .75rem 1rem .75rem 0; }
+  .file-icon {
+    margin-right: 1.25rem;
+    width: 2rem;
+    height: 2rem;
+    font-weight: 500;
+    font-size: 0.625rem;
+    line-height: 150%;
+    text-transform: uppercase;
+    color: #fff;
+    background-color: var(--primary-button-enabled);
+    border: 1px solid rgba(0, 0, 0, .1);
+    border-radius: .5rem;
+  }
+  .file-desc {
+    font-size: 0.75rem;
+    color: var(--theme-content-dark-color);
+  }
+</style>
diff --git a/plugins/chunter-resources/src/components/AttachmentPresenter.svelte b/plugins/chunter-resources/src/components/AttachmentPresenter.svelte
index ca0e9b65b8..357774d77a 100644
--- a/plugins/chunter-resources/src/components/AttachmentPresenter.svelte
+++ b/plugins/chunter-resources/src/components/AttachmentPresenter.svelte
@@ -17,9 +17,9 @@
 <script lang="ts">
   import type { Bag } from '@anticrm/core'
   import type { Attachment } from '@anticrm/chunter'
-  import { IconFile, Link, showPopup } from '@anticrm/ui'
+  import { IconFile, Link, Tooltip, showPopup } from '@anticrm/ui'
   import { PDFViewer } from '@anticrm/presentation'
-  import FileGroup from './FileGroup.svelte'
+  import AttachmentPopup from './AttachmentPopup.svelte'
 
   export let value: { attachments: Bag<Attachment> }
 
@@ -28,5 +28,7 @@
 {#if Object.keys(value.attachments).length === 1}
   <Link label={Object.values(value.attachments)[0].name} href={'#'} icon={IconFile} on:click={ () => { showPopup(PDFViewer, { file: Object.values(value.attachments)[0].file }, 'right') } }/>
 {:else if Object.keys(value.attachments).length > 1}
-  <FileGroup files={value.attachments} />
+  <Tooltip label={'Attachments (' + Object.values(value.attachments).length + ')'} component={AttachmentPopup} props={{ files: value.attachments }}>
+    <Link label={Object.values(value.attachments).length + ' files'} href={'#'} icon={IconFile} />
+  </Tooltip>
 {/if}
diff --git a/plugins/recruit-resources/src/components/ApplicationsPopup.svelte b/plugins/recruit-resources/src/components/ApplicationsPopup.svelte
index 4764fcfb72..c8af1a4c06 100644
--- a/plugins/recruit-resources/src/components/ApplicationsPopup.svelte
+++ b/plugins/recruit-resources/src/components/ApplicationsPopup.svelte
@@ -26,11 +26,7 @@
                 { label: 'Principal analyst', description: 'Google' }]
 </script>
 
-<div class="flex-col popup">
-  <div class="header">
-    <Label label={'Applications'} /> ({value.applications})
-  </div>
-  
+<div class="flex-col">
   {#each apps as app}
     <div class="flex-row-center app">
       <div class="app-icon"><CircleButton icon={Vacancy} size={'large'} /></div>
@@ -43,47 +39,30 @@
 </div>
 
 <style lang="scss">
-  .popup {
-    display: flex;
-    flex-direction: column;
-    padding: 1.25rem 1.5rem;
-    background-color: var(--theme-button-bg-focused);
-    border: 1px solid var(--theme-button-border-enabled);
-    border-radius: .75rem;
-    box-shadow: 0 .75rem 1.25rem rgba(0, 0, 0, .2);
-
-    .header {
-      margin-bottom: 1.5rem;
-      font-weight: 500;
-      font-size: 1rem;
-      color: var(--theme-caption-color);
+  .app {
+    position: relative;
+    .app-icon {
+      margin-right: 1.25rem;
+      width: 2rem;
+      height: 2rem;
     }
-
-    .app {
-      position: relative;
-      .app-icon {
-        margin-right: 1.25rem;
-        width: 2rem;
-        height: 2rem;
-      }
-      .label { color: var(--theme-caption-color); }
-      .desc {
-        font-size: .75rem;
-        color: var(--theme-content-dark-color);
-      }
+    .label { color: var(--theme-caption-color); }
+    .desc {
+      font-size: .75rem;
+      color: var(--theme-content-dark-color);
     }
+  }
 
-    .app + .app {
-      margin-top: 1.5rem;
-      &::before {
-        content: '';
-        position: absolute;
-        top: -.75rem;
-        left: 0;
-        width: 100%;
-        height: 1px;
-        background-color: var(--theme-button-border-hovered);
-      }
+  .app + .app {
+    margin-top: 1.5rem;
+    &::before {
+      content: '';
+      position: absolute;
+      top: -.75rem;
+      left: 0;
+      width: 100%;
+      height: 1px;
+      background-color: var(--theme-button-border-hovered);
     }
   }
 </style>
diff --git a/plugins/recruit-resources/src/components/ApplicationsPresenter.svelte b/plugins/recruit-resources/src/components/ApplicationsPresenter.svelte
index 9b59d3a6d8..5f4802727a 100644
--- a/plugins/recruit-resources/src/components/ApplicationsPresenter.svelte
+++ b/plugins/recruit-resources/src/components/ApplicationsPresenter.svelte
@@ -17,7 +17,7 @@
 <script lang="ts">
 
   import type { Candidate } from '@anticrm/recruit'
-  import { CircleButton, IconFile, Label, showPopup, closePopup } from '@anticrm/ui'
+  import { CircleButton, IconFile, Label, Tooltip } from '@anticrm/ui'
   import Vacancy from './icons/Vacancy.svelte'
   import ApplicationsPopup from './ApplicationsPopup.svelte'
 
@@ -29,43 +29,20 @@
 </script>
 
 {#if value.applications && value.applications > 0}
-  <div class="apps-container"
-    bind:this={trigger}
-    on:mouseenter={() => { showPopup(ApplicationsPopup, {value}, trigger) }}
-    on:mouseleave={() => { closePopup() }}
-  >
-    <div class="icon"><IconFile size={'small'} /></div>
-    {value.applications}
-  </div>
+  <Tooltip label={'Applications'} component={ApplicationsPopup} props={{ value: value }}>
+    <div class="flex-row-center">
+      <div class="icon"><IconFile size={'small'} /></div>
+      {value.applications}
+    </div>
+  </Tooltip>
 {/if}
 
 
 <style lang="scss">
-  .apps-container {
-    position: relative;
-    display: flex;
-    align-items: center;
-    color: var(--theme-content-color);
-    cursor: pointer;
-
-    .icon {
-      margin-right: .25rem;
-      transform-origin: center center;
-      transform: scale(.75);
-      opacity: .6;
-    }
-    &:hover {
-      color: var(--theme-caption-color);
-      .icon { opacity: 1; }
-      // &::after { content: ''; }
-    }
-    // &::after {
-    //   position: absolute;
-    //   top: 0;
-    //   left: 0;
-    //   right: 0;
-    //   bottom: -2rem;
-    //   background-color: rgba(255, 255, 0, .2);
-    // }
+  .icon {
+    margin-right: .25rem;
+    transform-origin: center center;
+    transform: scale(.75);
+    opacity: .6;
   }
 </style>
diff --git a/plugins/recruit-resources/src/components/Attachments.svelte b/plugins/recruit-resources/src/components/Attachments.svelte
index 41bc4585ea..52b3a2d362 100644
--- a/plugins/recruit-resources/src/components/Attachments.svelte
+++ b/plugins/recruit-resources/src/components/Attachments.svelte
@@ -147,9 +147,6 @@
     margin-right: 1.25rem;
     width: 2rem;
     height: 2rem;
-    border-radius: .5rem;
-  }
-  .file-icon {
     font-weight: 500;
     font-size: 0.625rem;
     line-height: 150%;
@@ -157,6 +154,7 @@
     color: #fff;
     background-color: var(--primary-button-enabled);
     border: 1px solid rgba(0, 0, 0, .1);
+    border-radius: .5rem;
   }
   .file-desc {
     font-size: 0.75rem;