From 835a37c6f04c6da4beb850bfb0de56efb2fd02a8 Mon Sep 17 00:00:00 2001
From: Alexander Platov <sas_lord@mail.ru>
Date: Tue, 17 Jan 2023 04:07:05 +0300
Subject: [PATCH] Update EstimationPopup layout (#2513)

---
 packages/theme/styles/_layouts.scss           | 27 ++++--
 packages/theme/styles/common.scss             |  3 +
 packages/theme/styles/dialogs.scss            |  4 +-
 packages/ui/src/components/Chevron.svelte     | 85 ++++++++++++++++++
 .../ui/src/components/ExpandCollapse.svelte   |  2 +-
 packages/ui/src/components/Expandable.svelte  | 73 +++++++++-------
 packages/ui/src/components/ListView.svelte    |  4 +-
 .../src/components/icons/DownOutline.svelte   |  2 +-
 packages/ui/src/index.ts                      |  1 +
 .../src/components/EntityMapping.svelte       |  4 +-
 .../FieldMappingSynchronizer.svelte           | 69 ++++++++-------
 .../components/issues/edit/SubIssues.svelte   | 14 +--
 .../issues/timereport/EstimationPopup.svelte  | 21 ++---
 .../timereport/EstimationSubIssueList.svelte  | 76 ++++++----------
 .../timereport/SubIssuesEstimations.svelte    | 14 +--
 .../timereport/TimeReportDayDropdown.svelte   |  4 +-
 .../timereport/TimeSpendReportPopup.svelte    | 18 ++--
 .../issues/timereport/TimeSpendReports.svelte | 18 ++--
 .../timereport/TimeSpendReportsList.svelte    | 86 +++++++------------
 .../src/components/FixedColumn.svelte         |  3 +-
 20 files changed, 301 insertions(+), 227 deletions(-)
 create mode 100644 packages/ui/src/components/Chevron.svelte

diff --git a/packages/theme/styles/_layouts.scss b/packages/theme/styles/_layouts.scss
index fb202b6e21..980ff21b30 100644
--- a/packages/theme/styles/_layouts.scss
+++ b/packages/theme/styles/_layouts.scss
@@ -381,11 +381,6 @@ input.search {
 }
 
 /* Margins & Paddings */
-.step-lr25 + .step-lr25 { margin-left: .25rem; }
-.step-lr75 + .step-lr75 { margin-left: .75rem; }
-.step-tb75 + .step-tb75 { margin-top: .75rem; }
-.step-tb-6 + .step-tb-6 { margin-top: 1.5rem; }
-
 .ml-0-5 { margin-left: .125rem; }
 .ml-1 { margin-left: .25rem; }
 .ml-1-5 { margin-left: .375rem; }
@@ -476,6 +471,28 @@ input.search {
 .p-6 { padding: 1.5rem; }
 .p-10 { padding: 2.5rem; }
 
+.p-text { padding: .125rem .25rem; }
+.p-text-2 { padding: .25rem .5rem; }
+
+.step-lr25 + .step-lr25 { margin-left: .25rem; }
+.step-lr75 + .step-lr75 { margin-left: .75rem; }
+.step-tb75 + .step-tb75 { margin-top: .75rem; }
+.step-tb-6 + .step-tb-6 { margin-top: 1.5rem; }
+
+.step-tb-2-accent + .step-tb-2-accent {
+  position: relative;
+  margin-top: .5rem;
+  &::before {
+    content: '';
+    position: absolute;
+    top: -.25rem;
+    left: 0;
+    width: 100%;
+    height: 1px;
+    background-color: var(--popup-bg-hover);
+  }
+}
+
 /* --------- */
 .no-word-wrap { word-wrap: none; }
 .relative { position: relative; }
diff --git a/packages/theme/styles/common.scss b/packages/theme/styles/common.scss
index 0655b57b6f..b37399b398 100644
--- a/packages/theme/styles/common.scss
+++ b/packages/theme/styles/common.scss
@@ -275,6 +275,9 @@
   min-height: 1px;
   height: 1px;
   background-color: var(--divider-color);
+
+  &.dark { background-color: var(--body-accent); }
+  &.noMargin { margin: 0; }
 }
 
 .antiSection {
diff --git a/packages/theme/styles/dialogs.scss b/packages/theme/styles/dialogs.scss
index 119d21da8c..b827aea51f 100644
--- a/packages/theme/styles/dialogs.scss
+++ b/packages/theme/styles/dialogs.scss
@@ -173,10 +173,10 @@
     .antiCard-pool {
       flex-direction: row;
       align-items: center;
-      margin: 0 .75rem .75rem;
+      margin: 0 .5rem .25rem;
       font-size: .75rem;
 
-      & > *:not(:last-child) { margin-right: .375rem; }
+      & > * { margin: 0 .25rem .5rem; }
     }
     .antiCard-footer {
       direction: ltr;
diff --git a/packages/ui/src/components/Chevron.svelte b/packages/ui/src/components/Chevron.svelte
new file mode 100644
index 0000000000..06dd53004f
--- /dev/null
+++ b/packages/ui/src/components/Chevron.svelte
@@ -0,0 +1,85 @@
+<!--
+// Copyright © 2022 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 IconDownOutline from './icons/DownOutline.svelte'
+
+  export let size: 'small' | 'medium' = 'medium'
+  export let fill = 'var(--dark-color)'
+  export let expanded: boolean = false
+  export let direction: 'left' | 'right' = 'right'
+  export let outline: boolean = false
+  export let marginRight: string | undefined = undefined
+  export let marginLeft: string | undefined = undefined
+  export let margin: string | undefined = undefined
+</script>
+
+<div
+  class="chevron {size} {direction}"
+  class:outline
+  class:expanded
+  style:margin-right={marginRight}
+  style:margin-left={marginLeft}
+  style:margin
+>
+  {#if outline}
+    <IconDownOutline {size} {fill} />
+  {:else}
+    <svg {fill} viewBox="0 0 6 6" xmlns="http://www.w3.org/2000/svg">
+      <path d="M0,0L6,3L0,6Z" />
+    </svg>
+  {/if}
+</div>
+
+<style lang="scss">
+  .chevron {
+    flex-shrink: 0;
+    transition: transform 0.15s var(--timing-main);
+
+    &.outline {
+      transform-origin: center;
+      &.right {
+        transform: rotate(-90deg);
+      }
+      &.left {
+        transform: rotate(90deg);
+      }
+      &.expanded {
+        transform: rotate(0deg);
+      }
+    }
+    &:not(.outline) {
+      transform-origin: 35% center;
+      transform: rotate(0deg);
+
+      &.small {
+        width: 0.325rem;
+        height: 0.325rem;
+      }
+      &.medium {
+        width: 0.375rem;
+        height: 0.375rem;
+      }
+      &.right {
+        transform: rotate(0deg);
+      }
+      &.left {
+        transform: rotate(180deg);
+      }
+      &.expanded {
+        transform: rotate(90deg);
+      }
+    }
+  }
+</style>
diff --git a/packages/ui/src/components/ExpandCollapse.svelte b/packages/ui/src/components/ExpandCollapse.svelte
index 1ffcd64d1f..540be85b44 100644
--- a/packages/ui/src/components/ExpandCollapse.svelte
+++ b/packages/ui/src/components/ExpandCollapse.svelte
@@ -18,7 +18,7 @@
   import { tweened } from 'svelte/motion'
 
   export let isExpanded = false
-  export let duration = 200
+  export let duration = 150
   export let easing: (t: number) => number = quintOut
 
   const dispatch = createEventDispatcher()
diff --git a/packages/ui/src/components/Expandable.svelte b/packages/ui/src/components/Expandable.svelte
index f23ddf82c7..98866f779f 100644
--- a/packages/ui/src/components/Expandable.svelte
+++ b/packages/ui/src/components/Expandable.svelte
@@ -17,51 +17,62 @@
   import ExpandCollapse from './ExpandCollapse.svelte'
   import Icon from './Icon.svelte'
   import Label from './Label.svelte'
+  import Chevron from './Chevron.svelte'
 
   export let icon: Asset | undefined = undefined
   export let label: IntlString | undefined = undefined
   export let expanded: boolean = false
+  export let bordered: boolean = false
   export let expandable = true
+  export let contentColor = false
 </script>
 
-<!-- svelte-ignore a11y-mouse-events-have-key-events -->
-<!-- svelte-ignore a11y-click-events-have-key-events -->
-<div class="flex-grow flex" class:expanded class:expandable>
-  <div
-    class="fs-title flex-row-center mr-4"
-    on:click|stopPropagation={() => {
-      expanded = !expanded
-    }}
-  >
-    <div class="chevron" class:expanded>▶</div>
-    <div class="an-element__icon">
+<div class="flex-col">
+  <div class="expandable-header flex-between" class:expanded class:bordered>
+    <!-- svelte-ignore a11y-click-events-have-key-events -->
+    <div
+      class="flex-row-center mr-4"
+      class:cursor-pointer={expandable}
+      on:click|stopPropagation={() => {
+        if (expandable) expanded = !expanded
+      }}
+    >
+      <Chevron {expanded} marginRight={'.5rem'} />
       {#if icon}
-        <Icon {icon} size={'small'} />
+        <div class="min-w-4 mr-2">
+          <Icon {icon} size={'small'} />
+        </div>
       {/if}
+      <span class="fs-title overflow-label" class:content-color={contentColor}>
+        {#if label}<Label {label} />{/if}<slot name="title" />
+      </span>
     </div>
-    <span class="an-element__label title">
-      {#if label}<Label {label} />{/if}
-      <slot name="title" />
-    </span>
+    {#if $$slots.tools}
+      <div class="buttons-group small-gap">
+        <slot name="tools" />
+      </div>
+    {/if}
   </div>
-  <slot name="tools" />
-</div>
-<ExpandCollapse isExpanded={expanded}>
-  <div class="antiComponent p-2">
+  <ExpandCollapse isExpanded={expanded}>
     <slot />
-  </div>
-</ExpandCollapse>
+  </ExpandCollapse>
+</div>
 
 <style lang="scss">
-  .expandable {
-    .chevron {
-      content: '▶';
-      margin-right: 0.5rem;
-      font-size: 0.75rem;
-      color: var(--dark-color);
-      &.expanded {
-        transform: rotateZ(90deg);
-      }
+  .expandable-header {
+    transition: margin-bottom 0.15s var(--timing-main);
+
+    &:not(.expanded) {
+      margin-bottom: 0;
+    }
+    &.expanded {
+      margin-bottom: 0.75rem;
+    }
+    &.bordered {
+      padding: 0.25rem 0.5rem;
+      background-color: var(--body-accent);
+      border: 1px solid var(--divider-color);
+      border-radius: 0.25rem;
     }
   }
 </style>
diff --git a/packages/ui/src/components/ListView.svelte b/packages/ui/src/components/ListView.svelte
index 36a1ab452b..b114942bad 100644
--- a/packages/ui/src/components/ListView.svelte
+++ b/packages/ui/src/components/ListView.svelte
@@ -18,6 +18,7 @@
 
   export let selection: number = 0
   export let count: number
+  export let addClass: string | undefined = undefined
 
   const refs: HTMLElement[] = []
 
@@ -66,8 +67,9 @@
   >
     {#each Array(count) as _, row}
       <slot name="category" item={row} />
+      <!-- svelte-ignore a11y-click-events-have-key-events -->
       <div
-        class="list-item"
+        class="list-item{addClass ? ` ${addClass}` : ''}"
         class:selection={row === selection}
         on:mouseover={() => onRow(row)}
         on:focus={() => {}}
diff --git a/packages/ui/src/components/icons/DownOutline.svelte b/packages/ui/src/components/icons/DownOutline.svelte
index ee3b5954f7..b8dcda616e 100644
--- a/packages/ui/src/components/icons/DownOutline.svelte
+++ b/packages/ui/src/components/icons/DownOutline.svelte
@@ -1,6 +1,6 @@
 <script lang="ts">
   export let size: 'x-small' | 'small' | 'medium' | 'large' | 'full'
-  const fill: string = 'currentColor'
+  export let fill: string = 'currentColor'
 </script>
 
 <svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts
index 269e7f083d..13dcc14e52 100644
--- a/packages/ui/src/index.ts
+++ b/packages/ui/src/index.ts
@@ -99,6 +99,7 @@ export { default as ErrorPresenter } from './components/ErrorPresenter.svelte'
 export { default as Scroller } from './components/Scroller.svelte'
 export { default as ScrollerBar } from './components/ScrollerBar.svelte'
 export { default as TabList } from './components/TabList.svelte'
+export { default as Chevron } from './components/Chevron.svelte'
 
 export { default as IconAdd } from './components/icons/Add.svelte'
 export { default as IconBack } from './components/icons/Back.svelte'
diff --git a/plugins/bitrix-resources/src/components/EntityMapping.svelte b/plugins/bitrix-resources/src/components/EntityMapping.svelte
index 77257794d7..2d1824c7be 100644
--- a/plugins/bitrix-resources/src/components/EntityMapping.svelte
+++ b/plugins/bitrix-resources/src/components/EntityMapping.svelte
@@ -75,9 +75,7 @@
 <div class="antiComponent max-w-240 flex-grow p-1">
   <Expandable icon={ofClass?.icon} label={getEmbeddedLabel(typeTitle?.label ?? '')}>
     <svelte:fragment slot="tools">
-      <div class="flex flex-reverse flex-grow">
-        <Button icon={IconDelete} on:click={() => client.remove(mapping)} size={'small'} />
-      </div>
+      <Button icon={IconDelete} on:click={() => client.remove(mapping)} size={'small'} />
     </svelte:fragment>
     <Expandable label={getEmbeddedLabel('Options')}>
       <div class="flex-col">
diff --git a/plugins/bitrix-resources/src/components/FieldMappingSynchronizer.svelte b/plugins/bitrix-resources/src/components/FieldMappingSynchronizer.svelte
index e14de729e8..85cce34098 100644
--- a/plugins/bitrix-resources/src/components/FieldMappingSynchronizer.svelte
+++ b/plugins/bitrix-resources/src/components/FieldMappingSynchronizer.svelte
@@ -323,44 +323,43 @@
 
 <Expandable label={getEmbeddedLabel(mapping.type)}>
   <svelte:fragment slot="tools">
-    <div class="flex-row-center">
-      <SpaceSelect
-        _class={core.class.Space}
-        label={core.string.Space}
-        bind:value={space}
-        on:change={(evt) => {
-          space = evt.detail
+    <SpaceSelect
+      _class={core.class.Space}
+      label={core.string.Space}
+      bind:value={space}
+      on:change={(evt) => {
+        space = evt.detail
+      }}
+      autoSelect
+      spaceQuery={{ _id: { $in: [contact.space.Contacts] } }}
+    />
+    <DropdownLabels
+      label={getEmbeddedLabel('Direction')}
+      items={[
+        { id: 'ASC', label: 'Ascending' },
+        { id: 'DSC', label: 'Descending' }
+      ]}
+      bind:selected={direction}
+    />
+    <div class="fs-title">
+      <NumberEditor
+        kind={'button'}
+        value={limit}
+        focus={false}
+        placeholder={getEmbeddedLabel('Limit')}
+        onChange={(val) => {
+          if (val) {
+            limit = val
+          }
         }}
-        autoSelect
-        spaceQuery={{ _id: { $in: [contact.space.Contacts] } }}
       />
-      <DropdownLabels
-        label={getEmbeddedLabel('Direction')}
-        items={[
-          { id: 'ASC', label: 'Ascending' },
-          { id: 'DSC', label: 'Descending' }
-        ]}
-        bind:selected={direction}
-      />
-      <div class="fs-title flex-row-center">
-        <NumberEditor
-          kind={'button'}
-          value={limit}
-          focus={false}
-          placeholder={getEmbeddedLabel('Limit')}
-          onChange={(val) => {
-            if (val) {
-              limit = val
-            }
-          }}
-        />
-      </div>
-      <div class="ml-2 flex-row-center">
-        <div class="p-1">
-          {state}
-        </div>
-        <Button size={'large'} label={getEmbeddedLabel('Synchronize')} {loading} on:click={doSync} />
+    </div>
+    <div class="buttons-divider" />
+    <div class="flex-row-center">
+      <div class="p-1">
+        {state}
       </div>
+      <Button size={'large'} label={getEmbeddedLabel('Synchronize')} {loading} on:click={doSync} />
     </div>
   </svelte:fragment>
   <div class="flex-row flex-grow bottom-divider p-2">
diff --git a/plugins/tracker-resources/src/components/issues/edit/SubIssues.svelte b/plugins/tracker-resources/src/components/issues/edit/SubIssues.svelte
index 87d633e428..6ab8d78e8a 100644
--- a/plugins/tracker-resources/src/components/issues/edit/SubIssues.svelte
+++ b/plugins/tracker-resources/src/components/issues/edit/SubIssues.svelte
@@ -16,10 +16,8 @@
   import { Ref, SortingOrder, WithLookup } from '@hcengineering/core'
   import { createQuery, getClient } from '@hcengineering/presentation'
   import { calcRank, Issue, IssueStatus, Team } from '@hcengineering/tracker'
-  import { Button, Spinner, ExpandCollapse, closeTooltip, IconAdd } from '@hcengineering/ui'
+  import { Button, Spinner, ExpandCollapse, closeTooltip, IconAdd, Chevron, Label } from '@hcengineering/ui'
   import tracker from '../../../plugin'
-  import Collapsed from '../../icons/Collapsed.svelte'
-  import Expanded from '../../icons/Expanded.svelte'
   import CreateSubIssue from './CreateSubIssue.svelte'
   import SubIssueList from './SubIssueList.svelte'
 
@@ -62,16 +60,18 @@
   {#if hasSubIssues}
     <Button
       width="min-content"
-      icon={isCollapsed ? Collapsed : Expanded}
       size="small"
       kind="transparent"
-      label={tracker.string.SubIssuesList}
-      labelParams={{ subIssues: issue.subIssues }}
       on:click={() => {
         isCollapsed = !isCollapsed
         isCreating = false
       }}
-    />
+    >
+      <svelte:fragment slot="content">
+        <Chevron size={'small'} expanded={!isCollapsed} outline fill={'var(--caption-color)'} marginRight={'.375rem'} />
+        <Label label={tracker.string.SubIssuesList} params={{ subIssues: issue.subIssues }} />
+      </svelte:fragment>
+    </Button>
   {/if}
 
   <Button
diff --git a/plugins/tracker-resources/src/components/issues/timereport/EstimationPopup.svelte b/plugins/tracker-resources/src/components/issues/timereport/EstimationPopup.svelte
index d333c70e3b..5994500e8f 100644
--- a/plugins/tracker-resources/src/components/issues/timereport/EstimationPopup.svelte
+++ b/plugins/tracker-resources/src/components/issues/timereport/EstimationPopup.svelte
@@ -120,9 +120,6 @@
     <IssuePresenter value={object} disableClick />
   </svelte:fragment>
 
-  <div class="header no-border flex-col p-1">
-    <div class="flex-row-center flex-between" />
-  </div>
   {#if currentTeam && issueStatuses}
     <SubIssuesEstimations
       issue={object}
@@ -143,13 +140,17 @@
       icon={IconAdd}
       size={'small'}
       on:click={(event) => {
-        showPopup(TimeSpendReportPopup, {
-          issueId: object._id,
-          issueClass: object._class,
-          space: object.space,
-          assignee: object.assignee,
-          defaultTimeReportDay
-        })
+        showPopup(
+          TimeSpendReportPopup,
+          {
+            issueId: object._id,
+            issueClass: object._class,
+            space: object.space,
+            assignee: object.assignee,
+            defaultTimeReportDay
+          },
+          'top'
+        )
       }}
       label={tracker.string.TimeSpendReportAdd}
     />
diff --git a/plugins/tracker-resources/src/components/issues/timereport/EstimationSubIssueList.svelte b/plugins/tracker-resources/src/components/issues/timereport/EstimationSubIssueList.svelte
index da202ffdfd..843b4348d9 100644
--- a/plugins/tracker-resources/src/components/issues/timereport/EstimationSubIssueList.svelte
+++ b/plugins/tracker-resources/src/components/issues/timereport/EstimationSubIssueList.svelte
@@ -17,7 +17,7 @@
   import { Doc, Ref } from '@hcengineering/core'
   import { UserBox } from '@hcengineering/presentation'
   import { Issue, Team } from '@hcengineering/tracker'
-  import { getEventPositionElement, ListView, showPopup } from '@hcengineering/ui'
+  import { getEventPositionElement, ListView, showPopup, deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
   import { ContextMenu, FixedColumn, ListSelectionProvider, SelectDirection } from '@hcengineering/view-resources'
   import { getIssueId } from '../../../issues'
   import tracker from '../../../plugin'
@@ -28,18 +28,19 @@
   export let teams: Map<Ref<Team>, Team>
 
   function showContextMenu (ev: MouseEvent, object: Issue) {
-    showPopup(ContextMenu, { object }, getEventPositionElement(ev))
+    showPopup(ContextMenu, { object }, $deviceInfo.isMobile ? 'top' : getEventPositionElement(ev))
   }
 
   const listProvider = new ListSelectionProvider((offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {})
+  $: twoRows = $deviceInfo.twoRows
 </script>
 
-<ListView count={issues.length}>
+<ListView count={issues.length} addClass={'step-tb-2-accent'}>
   <svelte:fragment slot="item" let:item>
     {@const issue = issues[item]}
     {@const currentTeam = teams.get(issue.space)}
     <div
-      class="flex-between row"
+      class="{twoRows ? 'flex-col' : 'flex-between'} p-text-2"
       on:contextmenu|preventDefault={(ev) => showContextMenu(ev, issue)}
       on:mouseover={() => {
         listProvider.updateFocus(issue)
@@ -48,55 +49,32 @@
         listProvider.updateFocus(issue)
       }}
     >
-      <div class="flex-row-center clear-mins gap-2 p-2 flex-grow">
-        <span class="issuePresenter">
-          <FixedColumn key={'estimation_issue'} justify={'left'}>
-            {#if currentTeam}
-              {getIssueId(currentTeam, issue)}
-            {/if}
-          </FixedColumn>
-        </span>
-        <span class="text name" title={issue.title}>
+      <div class="flex-row-center clear-mins gap-2 flex-grow mr-4" class:p-text={twoRows}>
+        <FixedColumn key={'estimation_issue'} justify={'left'} addClass={'fs-bold'}>
+          {#if currentTeam}
+            {getIssueId(currentTeam, issue)}
+          {/if}
+        </FixedColumn>
+        <span class="overflow-label fs-bold caption-color" title={issue.title}>
           {issue.title}
         </span>
       </div>
 
-      <FixedColumn key={'estimation_issue_assignee'} justify={'right'}>
-        <UserBox
-          width={'100%'}
-          label={tracker.string.Assignee}
-          _class={contact.class.Employee}
-          value={issue.assignee}
-          readonly
-          showNavigate={false}
-        />
-      </FixedColumn>
-      <FixedColumn key={'estimation'} justify={'left'}>
-        <EstimationEditor value={issue} kind={'list'} />
-      </FixedColumn>
+      <div class="flex-row-center clear-mins gap-2 self-end" class:p-text={twoRows}>
+        <FixedColumn key={'estimation_issue_assignee'} justify={'right'}>
+          <UserBox
+            width={'100%'}
+            label={tracker.string.Assignee}
+            _class={contact.class.Employee}
+            value={issue.assignee}
+            readonly
+            showNavigate={false}
+          />
+        </FixedColumn>
+        <FixedColumn key={'estimation'} justify={'left'}>
+          <EstimationEditor value={issue} kind={'list'} />
+        </FixedColumn>
+      </div>
     </div>
   </svelte:fragment>
 </ListView>
-
-<style lang="scss">
-  .row {
-    .text {
-      font-weight: 500;
-      color: var(--caption-color);
-    }
-
-    .issuePresenter {
-      flex-shrink: 0;
-      min-width: 0;
-      min-height: 0;
-      font-weight: 500;
-      color: var(--content-color);
-    }
-
-    .name {
-      white-space: nowrap;
-      text-overflow: ellipsis;
-      overflow: hidden;
-    }
-  }
-</style>
diff --git a/plugins/tracker-resources/src/components/issues/timereport/SubIssuesEstimations.svelte b/plugins/tracker-resources/src/components/issues/timereport/SubIssuesEstimations.svelte
index e8689c12e0..556dadb62e 100644
--- a/plugins/tracker-resources/src/components/issues/timereport/SubIssuesEstimations.svelte
+++ b/plugins/tracker-resources/src/components/issues/timereport/SubIssuesEstimations.svelte
@@ -16,7 +16,7 @@
   import { Ref, SortingOrder, WithLookup } from '@hcengineering/core'
   import { createQuery } from '@hcengineering/presentation'
   import { Issue, IssueStatus, Team } from '@hcengineering/tracker'
-  import { Scroller, Spinner } from '@hcengineering/ui'
+  import { Spinner } from '@hcengineering/ui'
   import Expandable from '@hcengineering/ui/src/components/Expandable.svelte'
   import tracker from '../../../plugin'
   import EstimationSubIssueList from './EstimationSubIssueList.svelte'
@@ -38,15 +38,9 @@
 
 {#if subIssues && issueStatuses}
   {#if hasSubIssues}
-    <Expandable label={tracker.string.ChildEstimation}>
-      <svelte:fragment slot="title">
-        : {total}
-      </svelte:fragment>
-      <div class="h-50">
-        <Scroller>
-          <EstimationSubIssueList issues={subIssues} {teams} />
-        </Scroller>
-      </div>
+    <Expandable label={tracker.string.ChildEstimation} contentColor bordered>
+      <svelte:fragment slot="title">: <span class="caption-color">{total}</span></svelte:fragment>
+      <EstimationSubIssueList issues={subIssues} {teams} />
     </Expandable>
   {/if}
 {:else}
diff --git a/plugins/tracker-resources/src/components/issues/timereport/TimeReportDayDropdown.svelte b/plugins/tracker-resources/src/components/issues/timereport/TimeReportDayDropdown.svelte
index 1c97dec981..fccde324e3 100644
--- a/plugins/tracker-resources/src/components/issues/timereport/TimeReportDayDropdown.svelte
+++ b/plugins/tracker-resources/src/components/issues/timereport/TimeReportDayDropdown.svelte
@@ -15,11 +15,13 @@
 <script lang="ts">
   import { TimeReportDayType } from '@hcengineering/tracker'
   import { DropdownIntlItem, DropdownLabelsIntl } from '@hcengineering/ui'
+  import type { ButtonKind } from '@hcengineering/ui'
   import tracker from '../../../plugin'
   import TimeReportDayIcon from './TimeReportDayIcon.svelte'
 
   export let label = tracker.string.TimeReportDayTypeLabel
   export let selected: TimeReportDayType | undefined
+  export let kind: ButtonKind = 'link-bordered'
 
   const workDaysDropdownItems: DropdownIntlItem[] = [
     {
@@ -34,7 +36,7 @@
 </script>
 
 <DropdownLabelsIntl
-  kind="link-bordered"
+  {kind}
   icon={TimeReportDayIcon}
   shouldUpdateUndefined={false}
   {label}
diff --git a/plugins/tracker-resources/src/components/issues/timereport/TimeSpendReportPopup.svelte b/plugins/tracker-resources/src/components/issues/timereport/TimeSpendReportPopup.svelte
index c3e15265d5..c8ef856a53 100644
--- a/plugins/tracker-resources/src/components/issues/timereport/TimeSpendReportPopup.svelte
+++ b/plugins/tracker-resources/src/components/issues/timereport/TimeSpendReportPopup.svelte
@@ -18,7 +18,7 @@
   import type { IntlString } from '@hcengineering/platform'
   import presentation, { Card, getClient, UserBox } from '@hcengineering/presentation'
   import { Issue, TimeReportDayType, TimeSpendReport } from '@hcengineering/tracker'
-  import { DatePresenter, EditBox } from '@hcengineering/ui'
+  import { DatePresenter, EditBox, Button } from '@hcengineering/ui'
   import tracker from '../../../plugin'
   import { getTimeReportDate, getTimeReportDayType } from '../../../utils'
   import TimeReportDayDropdown from './TimeReportDayDropdown.svelte'
@@ -85,23 +85,31 @@
 >
   <div class="flex-row-center gap-2">
     <EditBox focus bind:value={data.value} {placeholder} format={'number'} maxDigitsAfterPoint={3} kind={'editbox'} />
+    <Button kind={'link-bordered'} on:click={() => (data.value = 0.125)}><span slot="content">1/8</span></Button>
+    <Button kind={'link-bordered'} on:click={() => (data.value = 0.25)}><span slot="content">1/4</span></Button>
+    <Button kind={'link-bordered'} on:click={() => (data.value = 0.5)}><span slot="content">1/2</span></Button>
+    <Button kind={'link-bordered'} on:click={() => (data.value = 0.75)}><span slot="content">3/4</span></Button>
+    <div class="buttons-divider" />
+    <Button kind={'link-bordered'} on:click={() => (data.value = 1)}><span slot="content">1</span></Button>
+  </div>
+  <EditBox bind:value={data.description} placeholder={tracker.string.TimeSpendReportDescription} kind={'editbox'} />
+  <svelte:fragment slot="pool">
     <UserBox
       _class={contact.class.Employee}
       label={contact.string.Employee}
-      kind={'link-bordered'}
+      kind={'no-border'}
       bind:value={data.employee}
       showNavigate={false}
     />
     <TimeReportDayDropdown
+      kind={'no-border'}
       bind:selected={selectedTimeReportDay}
       on:selected={({ detail }) => (data.date = getTimeReportDate(detail))}
     />
     <DatePresenter
-      kind={'link'}
       bind:value={data.date}
       editable
       on:change={({ detail }) => (selectedTimeReportDay = getTimeReportDayType(detail))}
     />
-  </div>
-  <EditBox bind:value={data.description} placeholder={tracker.string.TimeSpendReportDescription} kind={'editbox'} />
+  </svelte:fragment>
 </Card>
diff --git a/plugins/tracker-resources/src/components/issues/timereport/TimeSpendReports.svelte b/plugins/tracker-resources/src/components/issues/timereport/TimeSpendReports.svelte
index cda62950e0..ae836d683a 100644
--- a/plugins/tracker-resources/src/components/issues/timereport/TimeSpendReports.svelte
+++ b/plugins/tracker-resources/src/components/issues/timereport/TimeSpendReports.svelte
@@ -16,7 +16,7 @@
   import { DocumentQuery, Ref, SortingOrder } from '@hcengineering/core'
   import { createQuery } from '@hcengineering/presentation'
   import { Issue, Team, TimeSpendReport } from '@hcengineering/tracker'
-  import { Expandable, floorFractionDigits, Label, Scroller, Spinner } from '@hcengineering/ui'
+  import { Expandable, floorFractionDigits, Label, Spinner } from '@hcengineering/ui'
   import tracker from '../../../plugin'
   import TimePresenter from './TimePresenter.svelte'
   import TimeSpendReportsList from './TimeSpendReportsList.svelte'
@@ -42,21 +42,19 @@
 </script>
 
 {#if reports}
-  <Expandable expanded={true}>
+  <Expandable expanded={true} contentColor bordered>
     <svelte:fragment slot="title">
       <span class="overflow-label flex-nowrap">
-        <Label label={tracker.string.ReportedTime} />: <TimePresenter value={reportedTime} {workDayLength} />
-        <Label label={tracker.string.TimeSpendReports} />: <TimePresenter value={total} {workDayLength} />
+        <Label label={tracker.string.ReportedTime} />:
+        <span class="caption-color"><TimePresenter value={reportedTime} {workDayLength} /></span>.
+        <Label label={tracker.string.TimeSpendReports} />:
+        <span class="caption-color"><TimePresenter value={total} {workDayLength} /></span>
       </span>
     </svelte:fragment>
-    <div class="h-50">
-      <Scroller>
-        <TimeSpendReportsList {reports} {teams} />
-      </Scroller>
-    </div>
+    <TimeSpendReportsList {reports} {teams} />
   </Expandable>
 {:else}
-  <div class="flex-center pt-3">
+  <div class="flex-center">
     <Spinner />
   </div>
 {/if}
diff --git a/plugins/tracker-resources/src/components/issues/timereport/TimeSpendReportsList.svelte b/plugins/tracker-resources/src/components/issues/timereport/TimeSpendReportsList.svelte
index 713e3f9ca4..f99db970ce 100644
--- a/plugins/tracker-resources/src/components/issues/timereport/TimeSpendReportsList.svelte
+++ b/plugins/tracker-resources/src/components/issues/timereport/TimeSpendReportsList.svelte
@@ -18,6 +18,7 @@
   import UserBox from '@hcengineering/presentation/src/components/UserBox.svelte'
   import { Team, TimeReportDayType, TimeSpendReport } from '@hcengineering/tracker'
   import { eventToHTMLElement, getEventPositionElement, ListView, showPopup } from '@hcengineering/ui'
+  import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
   import DatePresenter from '@hcengineering/ui/src/components/calendar/DatePresenter.svelte'
   import { ContextMenu, FixedColumn, ListSelectionProvider, SelectDirection } from '@hcengineering/view-resources'
   import { getIssueId } from '../../../issues'
@@ -51,18 +52,19 @@
         assignee: value.employee,
         defaultTimeReportDay
       },
-      eventToHTMLElement(event)
+      $deviceInfo.isMobile ? 'top' : eventToHTMLElement(event)
     )
   }
+  $: twoRows = $deviceInfo.twoRows
 </script>
 
 <!-- svelte-ignore a11y-click-events-have-key-events -->
-<ListView count={reports.length}>
+<ListView count={reports.length} addClass={'step-tb-2-accent'}>
   <svelte:fragment slot="item" let:item>
     {@const report = reports[item]}
     {@const currentTeam = teams.get(toTeamId(report.space))}
     <div
-      class="flex-between row"
+      class="{twoRows ? 'flex-col' : 'flex-between'} p-text-2"
       on:contextmenu|preventDefault={(ev) => showContextMenu(ev, report)}
       on:mouseover={() => {
         listProvider.updateFocus(report)
@@ -72,62 +74,36 @@
       }}
       on:click={(evt) => editSpendReport(evt, report, currentTeam?.defaultTimeReportDay)}
     >
-      <div class="flex-row-center clear-mins gap-2 p-2 flex-grow">
-        <span class="issuePresenter">
-          <FixedColumn key={'tmiespend_issue'} justify={'left'}>
-            {#if currentTeam && report.$lookup?.attachedTo}
-              {getIssueId(currentTeam, report.$lookup?.attachedTo)}
-            {/if}
-          </FixedColumn>
-        </span>
+      <div class="flex-row-center clear-mins gap-2 flex-grow mr-4" class:p-text={twoRows}>
+        <FixedColumn key={'tmiespend_issue'} justify={'left'} addClass={'fs-bold'}>
+          {#if currentTeam && report.$lookup?.attachedTo}
+            {getIssueId(currentTeam, report.$lookup?.attachedTo)}
+          {/if}
+        </FixedColumn>
         {#if report.$lookup?.attachedTo?.title}
-          <span class="text name" title={report.$lookup?.attachedTo?.title}>
+          <span class="overflow-label fs-bold caption-color" title={report.$lookup?.attachedTo?.title}>
             {report.$lookup?.attachedTo?.title}
           </span>
         {/if}
       </div>
-      <FixedColumn key={'timespend_assignee'} justify={'left'}>
-        <UserBox
-          width={'100%'}
-          label={tracker.string.Assignee}
-          _class={contact.class.Employee}
-          value={report.employee}
-          readonly
-          showNavigate={false}
-        />
-      </FixedColumn>
-
-      <FixedColumn key={'timespend_reported'} justify={'center'}>
-        <div class="p-1">
+      <div class="flex-row-center clear-mins gap-2 self-end" class:p-text={twoRows}>
+        <FixedColumn key={'timespend_assignee'} justify={'left'}>
+          <UserBox
+            width={'100%'}
+            label={tracker.string.Assignee}
+            _class={contact.class.Employee}
+            value={report.employee}
+            readonly
+            showNavigate={false}
+          />
+        </FixedColumn>
+        <FixedColumn key={'timespend_reported'} justify={'center'}>
           <TimePresenter value={report.value} workDayLength={currentTeam?.workDayLength} />
-        </div>
-      </FixedColumn>
-      <FixedColumn key={'timespend_date'} justify={'left'}>
-        <DatePresenter value={report.date} />
-      </FixedColumn>
-    </div>
-  </svelte:fragment>
+        </FixedColumn>
+        <FixedColumn key={'timespend_date'} justify={'left'}>
+          <DatePresenter value={report.date} />
+        </FixedColumn>
+      </div>
+    </div></svelte:fragment
+  >
 </ListView>
-
-<style lang="scss">
-  .row {
-    .text {
-      font-weight: 500;
-      color: var(--caption-color);
-    }
-
-    .issuePresenter {
-      flex-shrink: 0;
-      min-width: 0;
-      min-height: 0;
-      font-weight: 500;
-      color: var(--content-color);
-    }
-
-    .name {
-      white-space: nowrap;
-      text-overflow: ellipsis;
-      overflow: hidden;
-    }
-  }
-</style>
diff --git a/plugins/view-resources/src/components/FixedColumn.svelte b/plugins/view-resources/src/components/FixedColumn.svelte
index 840d159b08..1654c50780 100644
--- a/plugins/view-resources/src/components/FixedColumn.svelte
+++ b/plugins/view-resources/src/components/FixedColumn.svelte
@@ -20,6 +20,7 @@
 
   export let key: string
   export let justify: string = ''
+  export let addClass: string | undefined = undefined
   let prevKey = key
   let element: HTMLDivElement | undefined
 
@@ -48,7 +49,7 @@
 
 <div
   bind:this={element}
-  class="flex-no-shrink"
+  class="flex-no-shrink{addClass ? ` ${addClass}` : ''}"
   style="{justify !== '' ? `text-align: ${justify}; ` : ''} min-width: {$fixedWidthStore[key] ?? 0}px;"
   use:resizeObserver={resize}
 >