Updated DatePopup layout (#3725)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov 2023-09-21 07:08:59 +03:00 committed by GitHub
parent 07bcffe363
commit e83627ccb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 194 additions and 137 deletions

View File

@ -22,6 +22,7 @@
export let currentDate: Date | null export let currentDate: Date | null
export let withTime: boolean = false export let withTime: boolean = false
export let kind: 'default' | 'plain' = 'default'
type TEdits = 'day' | 'month' | 'year' | 'hour' | 'min' type TEdits = 'day' | 'month' | 'year' | 'hour' | 'min'
interface IEdits { interface IEdits {
@ -200,8 +201,9 @@
}) })
</script> </script>
<div class="datetime-input"> <div class="datetime-input {kind}">
<div class="flex-row-center"> <div class="flex-row-center">
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<span <span
bind:this={edits[0].el} bind:this={edits[0].el}
class="digit" class="digit"
@ -215,6 +217,7 @@
{:else}<Label label={ui.string.DD} />{/if} {:else}<Label label={ui.string.DD} />{/if}
</span> </span>
<span class="separator">.</span> <span class="separator">.</span>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<span <span
bind:this={edits[1].el} bind:this={edits[1].el}
class="digit" class="digit"
@ -228,6 +231,7 @@
{:else}<Label label={ui.string.MM} />{/if} {:else}<Label label={ui.string.MM} />{/if}
</span> </span>
<span class="separator">.</span> <span class="separator">.</span>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<span <span
bind:this={edits[2].el} bind:this={edits[2].el}
class="digit" class="digit"
@ -242,6 +246,7 @@
</span> </span>
{#if withTime} {#if withTime}
<div class="time-divider" /> <div class="time-divider" />
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<span <span
bind:this={edits[3].el} bind:this={edits[3].el}
class="digit" class="digit"
@ -255,6 +260,7 @@
{:else}<Label label={ui.string.HH} />{/if} {:else}<Label label={ui.string.HH} />{/if}
</span> </span>
<span class="separator">:</span> <span class="separator">:</span>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<span <span
bind:this={edits[4].el} bind:this={edits[4].el}
class="digit" class="digit"
@ -270,9 +276,11 @@
{/if} {/if}
</div> </div>
{#if currentDate} {#if currentDate}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div <div
class="close-btn" class="close-btn"
tabindex="0" tabindex={0}
on:click={() => { on:click={() => {
selected = 'day' selected = 'day'
startTyping = true startTyping = true
@ -293,15 +301,9 @@
align-items: center; align-items: center;
flex-shrink: 0; flex-shrink: 0;
margin: 0; margin: 0;
padding: 0.75rem;
height: 3rem; height: 3rem;
font-family: inherit; font-family: inherit;
font-size: 1rem;
color: var(--theme-content-color); color: var(--theme-content-color);
background-color: var(--theme-bg-color);
border: 1px solid var(--theme-button-border);
border-radius: 0.25rem;
transition: border-color 0.15s ease;
&:hover { &:hover {
border-color: var(--theme-button-default); border-color: var(--theme-button-default);
@ -332,9 +334,6 @@
.digit { .digit {
position: relative; position: relative;
padding: 0 0.125rem;
height: 1.5rem;
line-height: 1.5rem;
color: var(--theme-caption-color); color: var(--theme-caption-color);
outline: none; outline: none;
border-radius: 0.125rem; border-radius: 0.125rem;
@ -355,14 +354,47 @@
} }
.time-divider { .time-divider {
flex-shrink: 0; flex-shrink: 0;
margin: 0 0.25rem;
width: 1px; width: 1px;
min-width: 1px; min-width: 1px;
height: 0.75rem;
background-color: var(--theme-button-border); background-color: var(--theme-button-border);
} }
.separator {
margin: 0 0.1rem; &.plain:not(.default) {
padding: 0.5rem 0;
font-size: 1.25rem;
.digit {
padding: 0.5rem 0.125rem;
line-height: 1.25rem;
}
.separator {
margin: 0;
}
.time-divider {
margin: 0 0.375rem;
height: 1.5rem;
}
}
&.default:not(.plain) {
padding: 0.75rem;
font-size: 1rem;
background-color: var(--theme-bg-color);
border: 1px solid var(--theme-button-border);
border-radius: 0.25rem;
transition: border-color 0.15s ease;
.digit {
padding: 0 0.125rem;
height: 1.5rem;
line-height: 1.5rem;
}
.separator {
margin: 0 0.1rem;
}
.time-divider {
margin: 0 0.25rem;
height: 0.75rem;
}
} }
} }
</style> </style>

View File

@ -16,15 +16,19 @@
import { DateRangeMode } from '@hcengineering/core' import { DateRangeMode } from '@hcengineering/core'
import { IntlString } from '@hcengineering/platform' import { IntlString } from '@hcengineering/platform'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import {
ActionIcon,
Button,
Scroller,
deviceOptionsStore as deviceInfo,
checkAdaptiveMatching,
Label,
IconClose
} from '../..'
import ui from '../../plugin' import ui from '../../plugin'
import ActionIcon from '../ActionIcon.svelte'
import Button from '../Button.svelte'
import Label from '../Label.svelte'
import IconClose from '../icons/Close.svelte'
import DateInputBox from './DateInputBox.svelte' import DateInputBox from './DateInputBox.svelte'
import MonthSquare from './MonthSquare.svelte' import MonthSquare from './MonthSquare.svelte'
import Shifts from './Shifts.svelte' import Shifts from './Shifts.svelte'
import { Scroller, deviceOptionsStore as deviceInfo } from '../..'
export let currentDate: Date | null export let currentDate: Date | null
export let withTime: boolean = false export let withTime: boolean = false
@ -36,7 +40,12 @@
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
const today: Date = new Date(Date.now()) const today: Date = new Date(Date.now())
$: devSize = $deviceInfo.size
$: oneMonth = checkAdaptiveMatching(devSize, 'sm')
$: docHeight = $deviceInfo.docHeight $: docHeight = $deviceInfo.docHeight
const rem = (n: number, fs: number): number => n * fs
$: scrolled = docHeight < rem(39, $deviceInfo.fontSize)
let viewDate: Date = currentDate ?? today let viewDate: Date = currentDate ?? today
let viewDateSec: Date let viewDateSec: Date
@ -93,51 +102,74 @@
/> />
</div> </div>
<div class="content"> <div class="content">
<Scroller padding={'1.5rem 2rem'} thinScrollBars> {#if detail}
<div class="label"> <div class="label"><Label label={detail} /></div>
<span class="bold"><Label {label} /></span> {/if}
{#if detail}
<span class="divider">-</span>
<Label label={detail} />
{/if}
</div>
<DateInputBox
bind:this={dateInput}
bind:currentDate
{withTime}
on:close={() => closeDP(withTime)}
on:save={() => saveDate(withTime)}
/>
<DateInputBox
bind:this={dateInput}
bind:currentDate
{withTime}
kind={'plain'}
on:close={() => closeDP(withTime)}
on:save={() => saveDate(withTime)}
/>
<div class="divider" class:x2={!scrolled} />
{#if scrolled}
<Scroller thinScrollBars>
<div class="divider" />
<div class="month-group">
<MonthSquare
bind:currentDate
{viewDate}
{mondayStart}
viewUpdate={false}
hideNavigator={'all'}
noPadding
on:update={(result) => updateDate(result.detail)}
/>
{#if !oneMonth}
<div class="space" />
<MonthSquare
bind:currentDate
viewDate={viewDateSec}
{mondayStart}
viewUpdate={false}
noPadding
on:update={(result) => updateDate(result.detail)}
on:navigation={(result) => navigateMonth(result.detail)}
/>
{/if}
</div>
</Scroller>
{:else}
<div class="month-group"> <div class="month-group">
<MonthSquare <MonthSquare
bind:currentDate bind:currentDate
{viewDate} {viewDate}
{mondayStart} {mondayStart}
viewUpdate={false} viewUpdate={false}
hideNavigator="all" hideNavigator={'all'}
noPadding
on:update={(result) => updateDate(result.detail)} on:update={(result) => updateDate(result.detail)}
/> />
<MonthSquare {#if !oneMonth}
bind:currentDate <div class="space" />
viewDate={viewDateSec} <MonthSquare
{mondayStart} bind:currentDate
viewUpdate={false} viewDate={viewDateSec}
on:update={(result) => updateDate(result.detail)} {mondayStart}
on:navigation={(result) => navigateMonth(result.detail)} viewUpdate={false}
/> noPadding
on:update={(result) => updateDate(result.detail)}
on:navigation={(result) => navigateMonth(result.detail)}
/>
{/if}
</div> </div>
</Scroller> {/if}
</div> </div>
<div class="footer"> <div class="footer">
<Button <Button kind={'accented'} label={ui.string.Save} size={'large'} on:click={() => closeDP(withTime)} />
kind={'accented'}
label={ui.string.Save}
size={'x-large'}
width={'100%'}
on:click={() => closeDP(withTime)}
/>
</div> </div>
</div> </div>
<Shifts <Shifts
@ -159,7 +191,7 @@
max-height: calc(100vh - 2rem); max-height: calc(100vh - 2rem);
width: max-content; width: max-content;
height: max-content; height: max-content;
color: var(--caption-color); color: var(--theme-caption-color);
background: var(--theme-popup-color); background: var(--theme-popup-color);
border-radius: 0.5rem; border-radius: 0.5rem;
box-shadow: var(--theme-popup-shadow); box-shadow: var(--theme-popup-shadow);
@ -168,42 +200,46 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 1rem 1.5rem 1rem 2rem; padding: 1.5rem;
border-bottom: 1px solid var(--theme-popup-divider);
} }
.content { .content {
overflow: hidden; overflow: hidden;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 0 1.5rem 1.5rem;
min-height: 0; min-height: 0;
.label { .label {
padding-left: 2px;
margin-bottom: 0.25rem; margin-bottom: 0.25rem;
font-size: 0.8125rem; font-size: 0.875rem;
color: var(--theme-content-color); color: var(--theme-dark-color);
.bold {
font-weight: 500;
color: var(--theme-caption-color);
}
.divider {
margin: 0 0.25rem;
line-height: 1.4375rem;
color: var(--theme-darker-color);
}
} }
.month-group { .month-group {
display: flex; display: flex;
flex-wrap: nowrap; flex-wrap: nowrap;
margin: 0.5rem -0.5rem 0;
.space {
flex-shrink: 0;
width: 2rem;
}
}
}
.divider {
flex-shrink: 0;
height: 0.75rem;
&.x2 {
height: 1.5rem;
} }
} }
.footer { .footer {
padding: 1rem 2rem; display: flex;
flex-direction: row-reverse;
align-items: center;
padding: 1rem 1.5rem;
border-top: 1px solid var(--theme-popup-divider); border-top: 1px solid var(--theme-popup-divider);
} }
} }

View File

@ -14,9 +14,9 @@
--> -->
<script lang="ts"> <script lang="ts">
import { afterUpdate, createEventDispatcher } from 'svelte' import { afterUpdate, createEventDispatcher } from 'svelte'
import IconNavPrev from '../icons/NavPrev.svelte' import IconArrowLeft from '../icons/ArrowLeft.svelte'
import IconNavNext from '../icons/NavNext.svelte' import IconArrowRight from '../icons/ArrowRight.svelte'
import Icon from '../Icon.svelte' import Button from '../Button.svelte'
import { firstDay, day, getWeekDayName, areDatesEqual, getMonthName, weekday, isWeekend } from './internal/DateUtils' import { firstDay, day, getWeekDayName, areDatesEqual, getMonthName, weekday, isWeekend } from './internal/DateUtils'
import { capitalizeFirstLetter } from '../../utils' import { capitalizeFirstLetter } from '../../utils'
@ -25,6 +25,7 @@
export let mondayStart: boolean = true export let mondayStart: boolean = true
export let hideNavigator: 'all' | 'left' | 'right' | 'none' = 'none' export let hideNavigator: 'all' | 'left' | 'right' | 'none' = 'none'
export let viewUpdate: boolean = true export let viewUpdate: boolean = true
export let noPadding: boolean = false
export let displayedWeeksCount = 6 export let displayedWeeksCount = 6
export let selectedTo: Date | null | undefined = undefined export let selectedTo: Date | null | undefined = undefined
@ -81,32 +82,36 @@
<div class="month-container"> <div class="month-container">
<div class="header"> <div class="header">
{#if viewDate} {#if viewDate}
<div
class="btn"
class:hideNavigator={hideNavigator === 'left' || hideNavigator === 'all'}
on:click={() => {
if (viewUpdate) viewDate.setMonth(viewDate.getMonth() - 1)
dispatch('navigation', -1)
}}
>
<div class="icon-btn"><Icon icon={IconNavPrev} size={'full'} /></div>
</div>
<div class="monthYear">{monthYear}</div> <div class="monthYear">{monthYear}</div>
<div <div class="flex-row-center gap-1-5 mr-1">
class="btn" {#if !(hideNavigator === 'left' || hideNavigator === 'all')}
class:hideNavigator={hideNavigator === 'right' || hideNavigator === 'all'} <Button
on:click={() => { kind={'ghost'}
if (viewUpdate) viewDate.setMonth(viewDate.getMonth() + 1) size={'medium'}
dispatch('navigation', 1) icon={IconArrowLeft}
}} on:click={() => {
> if (viewUpdate) viewDate.setMonth(viewDate.getMonth() - 1)
<div class="icon-btn"><Icon icon={IconNavNext} size={'full'} /></div> dispatch('navigation', -1)
}}
/>
{/if}
{#if !(hideNavigator === 'right' || hideNavigator === 'all')}
<Button
kind={'ghost'}
size={'medium'}
icon={IconArrowRight}
on:click={() => {
if (viewUpdate) viewDate.setMonth(viewDate.getMonth() + 1)
dispatch('navigation', 1)
}}
/>
{/if}
</div> </div>
{/if} {/if}
</div> </div>
{#if viewDate} {#if viewDate}
<div class="calendar"> <div class="calendar" class:noPadding>
{#each [...Array(7).keys()] as dayOfWeek} {#each [...Array(7).keys()] as dayOfWeek}
<span class="caption" <span class="caption"
>{capitalizeFirstLetter(getWeekDayName(day(firstDayOfCurrentMonth, dayOfWeek), 'short'))}</span >{capitalizeFirstLetter(getWeekDayName(day(firstDayOfCurrentMonth, dayOfWeek), 'short'))}</span
@ -125,6 +130,7 @@
class:endRow={dayOfWeek === 6 || isNextDateWrong(date) || isEnd(currentDate, selectedTo, date)} class:endRow={dayOfWeek === 6 || isNextDateWrong(date) || isEnd(currentDate, selectedTo, date)}
class:wrongMonth={wrongM} class:wrongMonth={wrongM}
> >
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div <div
class="day" class="day"
class:weekend={isWeekend(date)} class:weekend={isWeekend(date)}
@ -161,14 +167,16 @@
flex-direction: column; flex-direction: column;
min-height: 0; min-height: 0;
height: 100%; height: 100%;
color: var(--caption-color); color: var(--theme-caption-color);
.header { .header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 1rem 0.5rem 0.75rem; flex-shrink: 0;
color: var(--caption-color); margin-bottom: 0.25rem;
height: 2.25rem;
color: var(--theme-caption-color);
.monthYear { .monthYear {
font-weight: 500; font-weight: 500;
@ -177,29 +185,6 @@
text-transform: capitalize; text-transform: capitalize;
} }
} }
.hideNavigator {
visibility: hidden;
}
.btn {
display: flex;
justify-content: center;
align-items: center;
width: 2rem;
height: 2rem;
color: var(--dark-color);
border-radius: 0.25rem;
background-color: var(--theme-refinput-color);
border: 1px solid var(--theme-refinput-color);
cursor: pointer;
.icon-btn {
height: 0.75rem;
}
&:hover {
color: var(--accent-color);
}
}
} }
} }
@ -207,7 +192,6 @@
position: relative; position: relative;
display: grid; display: grid;
grid-template-columns: repeat(7, 1fr); grid-template-columns: repeat(7, 1fr);
padding: 0 1rem 1rem;
.caption, .caption,
.day { .day {
@ -217,17 +201,23 @@
width: 2rem; width: 2rem;
height: 2rem; height: 2rem;
font-size: 1rem; font-size: 1rem;
color: var(--content-color); color: var(--theme-content-color);
} }
.caption { .caption {
align-items: start; margin-bottom: 0.5rem;
height: 2rem; height: 2.25rem;
padding: 0.25rem; color: var(--theme-dark-color);
color: var(--dark-color);
&::first-letter { &::first-letter {
text-transform: capitalize; text-transform: capitalize;
} }
} }
&:not(.noPadding) {
padding: 0 1rem 1rem;
.caption {
padding: 0.25rem;
}
}
.container { .container {
border: 0px solid transparent; border: 0px solid transparent;
@ -236,8 +226,7 @@
&.range:not(.wrongMonth), &.range:not(.wrongMonth),
&.selected:not(.wrongMonth) { &.selected:not(.wrongMonth) {
color: var(--caption-color); color: var(--theme-caption-color);
background-color: var(--accented-button-transparent);
} }
&.startRow:not(.wrongMonth) { &.startRow:not(.wrongMonth) {
border-top-left-radius: 0.25rem; border-top-left-radius: 0.25rem;
@ -255,24 +244,24 @@
.day { .day {
position: relative; position: relative;
color: var(--accent-color); color: var(--theme-content-color);
background-color: rgba(var(--accent-color), 0.05); // background-color: rgba(var(--theme-content-color), 0.05);
border: 1px solid transparent; border: 1px solid transparent;
border-radius: 0.25rem; border-radius: 0.25rem;
cursor: pointer; cursor: pointer;
&.weekend { &.weekend {
color: var(--content-color); color: var(--theme-content-color);
} }
&.wrongMonth { &.wrongMonth {
color: var(--dark-color); color: var(--theme-trans-color);
cursor: default; cursor: default;
} }
&.today:not(.worngMonth, .selected, .range) { &.today:not(.worngMonth, .selected, .range) {
font-weight: 500; font-weight: 500;
background-color: rgba(76, 56, 188, 0.2); background-color: var(--theme-button-focused);
border-radius: 50%; border-color: var(--theme-button-border);
} }
&.selected:not(.wrongMonth) { &.selected:not(.wrongMonth) {
color: var(--accented-button-color); color: var(--accented-button-color);
@ -280,7 +269,7 @@
} }
&:not(.wrongMonth):hover { &:not(.wrongMonth):hover {
color: var(--caption-color); color: var(--theme-caption-color);
background-color: var(--accented-button-transparent); background-color: var(--accented-button-transparent);
} }
} }
@ -288,11 +277,11 @@
&::before { &::before {
position: absolute; position: absolute;
content: ''; content: '';
top: 2rem; top: 2.25rem;
left: 0; left: 0;
width: 100%; width: 100%;
height: 1px; height: 1px;
background-color: var(--button-bg-color); background-color: var(--theme-divider-color);
} }
} }
</style> </style>