Updated Planner layout (#4756)

Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
Alexander Platov 2024-02-23 10:02:54 +03:00 committed by GitHub
parent 0d2501a95a
commit cc8a1d549a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 296 additions and 119 deletions

View File

@ -44,6 +44,7 @@
export let withoutContentScroll: boolean = false
export let customAside: ButtonItem[] | undefined = undefined
export let selectedAside: string | boolean = customAside ? customAside[0].id : isAside
export let kind: 'default' | 'modern' = 'default'
export function getAside (): string | boolean {
return panel.getAside()
@ -103,6 +104,7 @@
on:close
{allowClose}
{embedded}
{kind}
{floatAside}
bind:useMaxWidth
{isFullSize}

View File

@ -717,6 +717,7 @@ input.search {
.min-h-9 { min-height: 2.25rem; }
.min-h-11 { min-height: 2.75rem; }
.min-h-12 { min-height: 3rem; }
.min-h-16 { min-height: 4rem; }
.min-h-30 { min-height: 7.5rem; }
.min-h-60 { min-height: 15rem; }
.max-w-2 { max-width: .5rem; }

View File

@ -54,6 +54,9 @@
--global-higlight-Color: #F76E53;
--global-accent-SkyText: #B9D1F5;
--tag-on-subtle-PorpoiseText: #F2F4F6;
--tag-subtle-PorpoiseBackground: #343F49;
/** Buttons **/
--button-subtle-LabelColor: #fff;
--button-subtle-IconColor: #fff;
@ -113,6 +116,9 @@
--global-higlight-Color: #F76E53;
--global-accent-SkyText:#B9D1F5;
--tag-on-subtle-PorpoiseText: #293139;
--tag-subtle-PorpoiseBackground: #C8D1D9;
/** Buttons **/
--button-subtle-LabelColor: #000;
--button-subtle-IconColor: #000;

View File

@ -14,6 +14,7 @@
//
/* Typography */
.font-medium-11,
.font-regular-12,
.font-medium-12,
.font-bold-12,
@ -29,6 +30,9 @@
line-height: 1rem;
color: var(--global-primary-TextColor);
}
.font-medium-11 {
font-size: 0.6875rem;
}
.font-regular-12,
.font-medium-12,
.font-bold-12 {
@ -45,8 +49,11 @@
.paragraph-regular-14 {
font-weight: 400;
}
.font-medium-11,
.font-medium-12,
.font-medium-14 {
.font-medium-14,
.heading-medium-16,
.heading-medium-20 {
font-weight: 500;
}
.font-bold-12,
@ -54,10 +61,6 @@
.heading-bold-20 {
font-weight: 700;
}
.heading-medium-16,
.heading-medium-20 {
font-weight: 500;
}
.heading-medium-16 {
font-size: 1rem;
line-height: 1.125rem;

View File

@ -277,6 +277,11 @@
color: var(--global-secondary-TextColor);
}
}
&.type-component {
background-color: var(--theme-comp-header-color); // var(--global-surface-02-BackgroundColor);
border: 1px solid var(--theme-navpanel-divider); // var(--global-surface-02-BorderColor);
border-radius: var(--small-focus-BorderRadius);
}
textarea {
font-weight: 400 !important;
color: var(--global-tertiary-TextColor) !important;
@ -476,7 +481,8 @@
& + .hulyAccordionItem-content {
max-height: 100%;
}
&.small.bottomSpace + .hulyAccordionItem-content {
&.small.bottomSpace + .hulyAccordionItem-content,
&.small.nav + .hulyAccordionItem-content {
padding-bottom: var(--spacing-1_5);
}
&.medium.bottomSpace + .hulyAccordionItem-content {

View File

@ -364,6 +364,15 @@
// border-radius: 0 0 .5rem .5rem;
// }
}
&.modern {
border: 1px solid transparent;
border-radius: var(--small-focus-BorderRadius);
.popupPanel-title {
min-height: 3.5rem;
}
}
}
// Full size state

View File

@ -16,6 +16,7 @@
import type { Asset, IntlString } from '@hcengineering/platform'
import { AnySvelteComponent, IconSize, LabelAndProps } from '../types'
import { tooltip as tp } from '../tooltips'
import { registerFocus } from '../focus'
import { ComponentType } from 'svelte'
import Spinner from './Spinner.svelte'
import Icon from './Icon.svelte'
@ -46,6 +47,29 @@
} else if (type === 'type-button' && !hasMenu) {
actualIconSize = 'medium'
}
// Focusable control with index
export let focusIndex = -1
const { idx, focusManager } = registerFocus(focusIndex, {
focus: () => {
if (!disabled) {
element?.focus()
}
return !disabled && element != null
},
isFocus: () => document.activeElement === element
})
$: if (idx !== -1 && focusManager) {
focusManager.updateFocus(idx, focusIndex)
}
const updateFocus = () => {
focusManager?.setFocus(idx)
}
$: if (element != null) {
element.addEventListener('focus', updateFocus, { once: true })
}
</script>
<button

View File

@ -28,6 +28,7 @@
export let loading: boolean = false
export let inheritColor: boolean = false
export let tooltip: LabelAndProps | undefined = undefined
export let focusIndex = -1
</script>
<ButtonBase
@ -42,5 +43,6 @@
{pressed}
{hasMenu}
{tooltip}
{focusIndex}
on:click
/>

View File

@ -36,6 +36,7 @@
export let params: Record<string, any> = {}
export let selected: DropdownIntlItem['id'] | undefined = undefined
export let element: HTMLButtonElement | undefined = undefined
export let focusIndex = -1
let opened: boolean = false
@ -81,5 +82,6 @@
{loading}
{inheritColor}
pressed={opened}
{focusIndex}
on:click={openPopup}
/>

View File

@ -19,7 +19,7 @@
export let symbol: 'check' | 'minus' = 'check'
export let size: 'small' | 'medium' | 'large' = 'small'
export let circle: boolean = false
export let kind: 'default' | 'primary' | 'positive' | 'negative' = 'default'
export let kind: 'default' | 'primary' | 'positive' | 'negative' | 'todo' = 'default'
export let readonly = false
const dispatch = createEventDispatcher()
@ -42,16 +42,7 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<label
class="checkbox {size}"
class:circle
class:primary={kind === 'primary'}
class:positive={kind === 'positive'}
class:negative={kind === 'negative'}
class:readonly
class:checked
on:click|stopPropagation
>
<label class="checkbox {size} {kind}" class:circle class:readonly class:checked on:click|stopPropagation>
<input class="chBox" disabled={readonly} type="checkbox" bind:checked on:change|capture={handleValueChanged} />
<svg class="checkSVG" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
{#if checked}
@ -132,6 +123,9 @@
background-color: var(--negative-button-default);
}
}
&.todo {
border-color: var(--theme-divider-color);
}
.chBox {
position: absolute;

View File

@ -18,6 +18,7 @@
export let type: 'type-aside' | 'type-popup' | 'type-component' | 'type-panel' = 'type-component'
export let minimize: boolean = false
export let noResize: boolean = false
export let hideSeparator: boolean = false
const dispatch = createEventDispatcher()
@ -25,13 +26,16 @@
<div class="hulyHeader-container" class:topIndent={type === 'type-panel'} class:hideSeparator>
{#if type === 'type-component'}
<button class="hulyHeader-button" on:click={() => dispatch('resize', minimize)}>
{#if minimize}
<IconMinimize size={'small'} />
{:else}
<IconMaximize size={'small'} />
{/if}
</button>
{#if !noResize}
<button class="hulyHeader-button" on:click={() => dispatch('resize', minimize)}>
{#if minimize}
<IconMinimize size={'small'} />
{:else}
<IconMaximize size={'small'} />
{/if}
</button>
{/if}
<slot name="beforeTitle" />
<div class="hulyHeader-divider" />
{/if}
<div class="hulyHeader-titleGroup">

View File

@ -23,14 +23,15 @@
import ui from '..'
export let type: 'type-aside' | 'type-popup' | 'type-component'
export let label: IntlString
export let label: IntlString | undefined = undefined
export let labelProps: any | undefined = undefined
export let okAction: () => Promise<void> | void
export let okAction: () => Promise<void> | void = () => {}
export let onCancel: (() => void) | undefined = undefined
export let canSave: boolean = false
export let okLabel: IntlString = ui.string.Ok
export let padding: string | undefined = undefined
export let hidden = false
export let hidden: boolean = false
export let noResize: boolean = false
const dispatch = createEventDispatcher()
@ -47,18 +48,23 @@
? 'var(--spacing-2) var(--spacing-3) var(--spacing-4)'
: type === 'type-aside'
? 'var(--spacing-2) var(--spacing-1_5)'
: 'var(--spacing-3)'
: 'var(--spacing-4)'
</script>
<svelte:window on:keydown={onKeyDown} />
<div class="hulyModal-container {type}" class:hidden>
<Header {type} on:close={close}>
<Label {label} params={labelProps} />
<Header {type} {noResize} on:close={close}>
<svelte:fragment slot="beforeTitle">
<slot name="beforeTitle" />
</svelte:fragment>
{#if label}<Label {label} params={labelProps} />{/if}
<slot name="title" />
<svelte:fragment slot="actions">
<slot name="actions" />
</svelte:fragment>
</Header>
<slot name="beforeContent" />
<div class="hulyModal-content">
<Scroller
padding={padding ?? typePadding}
@ -66,11 +72,12 @@
? undefined
: type === 'type-aside'
? 'var(--spacing-2)'
: 'var(--spacing-3)'}
: 'var(--spacing-4)'}
>
<slot />
</Scroller>
</div>
<slot name="afterContent" />
{#if type !== 'type-component'}
<div class="hulyModal-footer">
<ButtonBase

View File

@ -20,6 +20,7 @@
export let loading: boolean = false
export let hasMenu: boolean = false
export let inheritFont: boolean = false
export let focusIndex = -1
</script>
<ButtonBase
@ -35,6 +36,7 @@
{disabled}
{hasMenu}
{inheritFont}
{focusIndex}
on:click
>
<slot />

View File

@ -6,6 +6,7 @@
import { createEventDispatcher, onMount } from 'svelte'
import { IntlString, translate } from '@hcengineering/platform'
import { registerFocus } from '../focus'
import Label from './Label.svelte'
import { themeStore } from '..'
@ -39,6 +40,22 @@
element.focus()
}
})
// Focusable control with index
export let focusIndex = -1
const { idx, focusManager } = registerFocus(focusIndex, {
focus: () => {
element?.focus()
return element != null
},
isFocus: () => document.activeElement === element
})
const updateFocus = () => {
focusManager?.setFocus(idx)
}
$: if (element) {
element.addEventListener('focus', updateFocus)
}
</script>
<!-- svelte-ignore a11y-no-static-element-interactions -->

View File

@ -27,8 +27,8 @@
$: id = `navGroup-${categoryName}`
</script>
<div class="hulyAccordionItem-container" class:isOpen class:second>
<button class="hulyAccordionItem-header small" class:isOpen class:selected on:click={() => (isOpen = !isOpen)}>
<div class="hulyAccordionItem-container" class:second>
<button class="hulyAccordionItem-header nav small" class:isOpen class:selected on:click={() => (isOpen = !isOpen)}>
<div class="hulyAccordionItem-header__label-wrapper font-medium-12">
<span class="hulyAccordionItem-header__label">
<Label {label} />
@ -46,7 +46,7 @@
</div>
{/if}
</button>
<div {id} class="hulyAccordionItem-content" class:isOpen>
<div {id} class="hulyAccordionItem-content">
<slot />
</div>
</div>

View File

@ -44,6 +44,7 @@
export let useMaxWidth: boolean | undefined = undefined
export let customAside: ButtonItem[] | undefined = undefined
export let selectedAside: string | boolean = customAside ? customAside[0].id : isAside
export let kind: 'default' | 'modern' = 'default'
export function getAside (): string | boolean {
if (customAside) return selectedAside
@ -124,7 +125,7 @@
</script>
<div
class="popupPanel panel"
class="popupPanel panel {kind}"
class:embedded
use:resizeObserver={(element) => {
panelWidth = element.clientWidth

View File

@ -24,6 +24,7 @@
import Spinner from './Spinner.svelte'
export let contentPanel: HTMLElement
export let kind: 'default' | 'modern' = 'default'
let modalHTML: HTMLElement
let componentInstance: any
@ -162,6 +163,7 @@
_class={props._class}
rightSection={props.rightSection}
position={props.element}
{kind}
bind:popupOptions={options}
on:open={_open}
on:close={_close}

View File

@ -225,7 +225,7 @@
item.maxSize !== -1 ? item.size + 'px' : item.minSize === -1 ? '0' : item.minSize + 'px'
};`
style += item.maxSize === -1 ? '' : `max-${side}:${item.size + 'px'};`
style += item.maxSize !== -1 ? `${side}:${item.size}px;` : `${side}:calc(100% - ${sum}px);`
style += item.maxSize !== -1 ? `${side}:${item.size}px;` : '' // `${side}:calc(100% - ${sum}px);`
if (item.styles !== null) {
item.styles.forEach((value, key) => {
if (key !== 'pointer-events' || final) style += `${key}:${value};`

View File

@ -130,6 +130,7 @@ export { default as Breadcrumb } from './components/Breadcrumb.svelte'
export { default as Breadcrumbs } from './components/Breadcrumbs.svelte'
export { default as ButtonIcon } from './components/ButtonIcon.svelte'
export { default as ButtonMenu } from './components/ButtonMenu.svelte'
export { default as ButtonBase } from './components/ButtonBase.svelte'
export { default as ModernButton } from './components/ModernButton.svelte'
export { default as ModernEditbox } from './components/ModernEditbox.svelte'
export { default as ModernPopup } from './components/ModernPopup.svelte'

View File

@ -212,7 +212,7 @@
<CalendarSelector bind:value={space} focusIndex={10101} />
<div class="flex-row-center flex-gap-1">
<Icon icon={calendar.icon.Hidden} size={'small'} />
<VisibilityEditor bind:value={visibility} kind={'ghost'} focusIndex={10102} withoutIcon />
<VisibilityEditor bind:value={visibility} kind={'tertiary'} focusIndex={10102} withoutIcon />
</div>
<EventReminders bind:reminders focusIndex={10103} />
</div>

View File

@ -218,7 +218,7 @@
<CalendarSelector bind:value={space} focusIndex={10008} />
<div class="flex-row-center flex-gap-1">
<Icon icon={calendar.icon.Hidden} size={'small'} />
<VisibilityEditor bind:value={visibility} kind={'ghost'} withoutIcon focusIndex={10009} />
<VisibilityEditor bind:value={visibility} kind={'tertiary'} withoutIcon focusIndex={10009} />
</div>
<EventReminders bind:reminders focusIndex={10010} />
</div>

View File

@ -14,45 +14,39 @@
-->
<script lang="ts">
import { Visibility } from '@hcengineering/calendar'
import { translate } from '@hcengineering/platform'
import { ButtonKind, Dropdown, ListItem, themeStore } from '@hcengineering/ui'
import { ButtonMenu, DropdownIntlItem, themeStore } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import calendar from '../plugin'
export let value: Visibility | undefined
export let disabled: boolean = false
export let kind: ButtonKind = 'regular'
export let kind: 'primary' | 'secondary' | 'tertiary' | 'negative' = 'secondary'
export let size: 'small' | 'medium' | 'large' = 'medium'
export let withoutIcon: boolean = false
export let focusIndex = -1
let items: ListItem[] = []
$: fill($themeStore.language)
async function fill (lang: string) {
items = [
{
_id: 'public',
label: await translate(calendar.string.Public, {}, lang),
icon: calendar.icon.Public
},
{
_id: 'freeBusy',
label: await translate(calendar.string.FreeBusy, {}, lang),
icon: calendar.icon.Private
},
{
_id: 'private',
label: await translate(calendar.string.Private, {}, lang),
icon: calendar.icon.Hidden
}
]
}
$: selected = value !== undefined ? items.find((item) => item._id === value) : undefined
const dispatch = createEventDispatcher()
const items: DropdownIntlItem[] = [
{
id: 'public',
label: calendar.string.Public,
icon: calendar.icon.Public
},
{
id: 'freeBusy',
label: calendar.string.FreeBusy,
icon: calendar.icon.Private
},
{
id: 'private',
label: calendar.string.Private,
icon: calendar.icon.Hidden
}
]
$: selected = value !== undefined ? items.find((item) => item.id === value) : undefined
function change (val: Visibility) {
if (value !== val) {
dispatch('change', val)
@ -61,17 +55,16 @@
}
</script>
<Dropdown
{disabled}
<ButtonMenu
icon={withoutIcon ? undefined : calendar.icon.Hidden}
{kind}
size={'medium'}
placeholder={calendar.string.DefaultVisibility}
label={selected?.label}
selected={selected?.id}
{items}
withSearch={false}
{kind}
{size}
{disabled}
{focusIndex}
{selected}
on:selected={(e) => {
change(e.detail._id)
on:selected={(event) => {
if (event.detail) change(event.detail)
}}
/>

View File

@ -13,10 +13,11 @@
// limitations under the License.
-->
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import { Class, Doc, Ref } from '@hcengineering/core'
import { createQuery, getClient } from '@hcengineering/presentation'
import tags, { TagReference } from '@hcengineering/tags'
import { Button, ButtonKind, Icon, Label, getEventPopupPositionElement, showPopup } from '@hcengineering/ui'
import { ButtonBase, ButtonKind, Icon, Label, getEventPopupPositionElement, showPopup } from '@hcengineering/ui'
import tagsPlugin from '../plugin'
import TagReferencePresenter from './TagReferencePresenter.svelte'
import TagsEditorPopup from './TagsEditorPopup.svelte'
@ -24,9 +25,14 @@
export let object: Doc
export let targetClass: Ref<Class<Doc>>
export let kind: ButtonKind = 'ghost'
export let type: 'type-button-only' | 'type-content-only' = 'type-content-only'
export let buttonParams: Record<string, any> = {}
export let contentParams: Record<string, any> = {}
const dispatch = createEventDispatcher()
let items: TagReference[] = []
let pressed: boolean = false
const query = createQuery()
const client = getClient()
@ -35,37 +41,54 @@
})
async function click (evt: MouseEvent): Promise<void> {
showPopup(TagsEditorPopup, { object, targetClass }, getEventPopupPositionElement(evt))
pressed = true
showPopup(TagsEditorPopup, { object, targetClass }, getEventPopupPositionElement(evt), () => {
pressed = false
})
}
async function removeTag (tag: TagReference): Promise<void> {
if (tag !== undefined) await client.remove(tag)
}
let count: number = 0
$: updated(items)
const updated = (its: TagReference[]): void => {
if (count === its.length) return
count = its.length
dispatch('change', count)
}
</script>
<div>
<Button {kind} padding={'0rem;'} on:click={click}>
<div slot="content" class="flex-row-center flex-gap-1">
<Icon icon={TagIcon} size={'medium'} />
<span class="overflow-label label"><Label label={tagsPlugin.string.AddLabel} /></span>
</div>
</Button>
{#if type === 'type-button-only'}
<ButtonBase
icon={TagIcon}
type={'type-button-icon'}
kind={'secondary'}
size={'small'}
{pressed}
hasMenu
{...buttonParams}
on:click={click}
/>
{/if}
{#if type === 'type-content-only'}
{#if items.length}
<div class="flex-row-center flex-wrap">
<div class="flex-row-center flex-wrap flex-gap-1-5">
{#each items as value}
<div class="step-container clear-mins">
<TagReferencePresenter
attr={undefined}
isEditable
{value}
kind={'list'}
on:remove={(res) => removeTag(res.detail)}
/>
</div>
<TagReferencePresenter
attr={undefined}
isEditable
{value}
kind={'todo'}
{...contentParams}
on:remove={(res) => removeTag(res.detail)}
/>
{/each}
</div>
{/if}
</div>
{/if}
<style lang="scss">
.step-container {

View File

@ -9,15 +9,17 @@
import TagsReferencePresenter from './TagsReferencePresenter.svelte'
import TagsEditorPopup from './TagsEditorPopup.svelte'
import TagsItemPresenter from './TagsItemPresenter.svelte'
import LabelsPresenter from './LabelsPresenter.svelte'
export let value: number
export let object: WithLookup<Doc>
export let full: boolean
export let ckeckFilled: boolean = false
export let kind: 'short' | 'full' | 'list' | 'link' | 'todo' = 'short'
export let kind: 'short' | 'full' | 'list' | 'link' | 'todo' | 'todo-compact' = 'short'
export let isEditable: boolean = false
export let action: (evt: MouseEvent) => Promise<void> | void = async () => {}
export let compression: boolean = false
export let ignoreFirst: boolean = false
const dispatch = createEventDispatcher()
@ -29,7 +31,7 @@
function update (object: WithLookup<Doc>, value: number) {
if (value > 0) {
query.query(tags.class.TagReference, { attachedTo: object._id }, (result) => {
items = result
items = result.slice(ignoreFirst ? 1 : 0)
})
} else {
query.unsubscribe()
@ -52,7 +54,7 @@
})
</script>
{#if kind === 'list' || kind === 'link' || kind === 'todo'}
{#if kind === 'list' || kind === 'link'}
{#if items.length > 4}
<div
class="label-box no-shrink"
@ -70,6 +72,29 @@
</div>
{/each}
{/if}
{:else if kind === 'todo'}
<div class="flex-row-top flex-wrap flex-gap-0-5">
{#each items as value}
<TagReferencePresenter attr={undefined} {value} {kind} />
{/each}
</div>
{:else if kind === 'todo-compact'}
{#if items.length > 1}
<div class="flex-row-top flex-wrap flex-gap-0-5">
<TagReferencePresenter attr={undefined} value={items[0]} kind={'todo'} />
<div
class="todoLabel-plus-container font-medium-11"
use:tooltip={{
component: LabelsPresenter,
props: { value, object, isEditable, kind: 'todo', ignoreFirst: true }
}}
>
+{items.length - 1}
</div>
</div>
{:else if items.length === 1}
<TagReferencePresenter attr={undefined} value={items[0]} kind={'todo'} />
{/if}
{:else}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
@ -96,6 +121,12 @@
{/if}
<style lang="scss">
.todoLabel-plus-container {
padding: var(--spacing-0_25) var(--spacing-0_75);
color: var(--tag-on-subtle-PorpoiseText);
background-color: var(--tag-subtle-PorpoiseBackground);
border-radius: var(--extra-small-BorderRadius);
}
.labels-container {
overflow: hidden;
display: flex;

View File

@ -66,13 +66,19 @@
</div>
{:else if kind === 'todo'}
<div
class="todoLabel-container font-medium-12 overflow-label max-w-40"
class="todoLabel-container font-medium-11 overflow-label max-w-40"
class:isEditable
style:background-color={color.color}
use:resizeObserver={(element) => {
realWidth = element.clientWidth
}}
>
{value.title}
{#if isEditable}
<button class="btn-close" on:click|stopPropagation={() => dispatch('remove', value)}>
<Icon icon={IconClose} size={'x-small'} />
</button>
{/if}
</div>
{/if}
{/if}
@ -82,6 +88,28 @@
padding: var(--spacing-0_25) var(--spacing-0_5);
color: var(--global-on-accent-TextColor);
border-radius: var(--extra-small-BorderRadius);
&.isEditable {
display: inline-flex;
align-items: center;
gap: var(--spacing-0_5);
padding: var(--spacing-0_25) var(--spacing-0_25) var(--spacing-0_25) var(--spacing-0_75);
}
.btn-close {
flex-shrink: 0;
margin: 0;
padding: 0;
width: var(--global-min-Size);
height: var(--global-min-Size);
color: var(--global-on-accent-TextColor);
border: none;
border-radius: var(--min-BorderRadius);
outline: none;
&:hover {
background-color: var(--button-tertiary-hover-BackgroundColor);
}
}
}
.listitems-container {
overflow: hidden;
@ -117,7 +145,6 @@
}
}
}
.link-container {
display: flex;
justify-content: center;

View File

@ -1,22 +1,17 @@
<script lang="ts">
export let size: 'x-small' | 'small' | 'medium' | 'large'
// export let fill: string = 'currentColor'
export let fill: string = 'currentColor'
</script>
<svg class="svg-{size}" fill="none" viewBox="0 0 16 16">
<svg class="svg-{size}" {fill} viewBox="0 0 32 32">
<path
opacity="0.01"
fill-rule="evenodd"
clip-rule="evenodd"
d="M0 16L16 16L16 2.54292e-07L-6.99382e-07 9.53674e-07L0 16Z"
d="M10 24.0001C11.1046 24.0001 12 23.1047 12 22.0001C12 20.8956 11.1046 20.0001 10 20.0001C8.89543 20.0001 8 20.8956 8 22.0001C8 23.1047 8.89543 24.0001 10 24.0001ZM10 26.0001C12.2091 26.0001 14 24.2093 14 22.0001C14 19.791 12.2091 18.0001 10 18.0001C7.79086 18.0001 6 19.791 6 22.0001C6 24.2093 7.79086 26.0001 10 26.0001Z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M6.28273 14.1415L1.86168 9.72159C1.63012 9.49034 1.5 9.17654 1.5 8.84932C1.5 8.5221 1.63012 8.20831 1.86168 7.97706L8.04102 1.79315C8.22858 1.60546 8.48305 1.5 8.74839 1.5L13.5 1.5C14.0523 1.5 14.5 1.94772 14.5 2.5L14.5 7.25015C14.5 7.5154 14.3946 7.76979 14.207 7.95733L8.02156 14.1415C7.54056 14.6195 6.76373 14.6195 6.28273 14.1415Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
d="M20.4142 4.58591C19.6332 3.80486 18.3668 3.80486 17.5858 4.58591L4.58579 17.5859C4.19487 17.9768 4 18.4852 4 19.0001V28.0001H13C13.5149 28.0001 14.0233 27.8053 14.4142 27.4143L27.4142 14.4143C28.1953 13.6333 28.1953 12.367 27.4142 11.5859L20.4142 4.58591ZM21.8284 3.17169C20.2663 1.6096 17.7337 1.6096 16.1716 3.17169L3.17157 16.1717C2.39052 16.9527 2 17.9764 2 19.0001V28.0001C2 29.1047 2.89543 30.0001 4 30.0001H13C14.0237 30.0001 15.0474 29.6096 15.8284 28.8285L28.8284 15.8285C30.3905 14.2665 30.3905 11.7338 28.8284 10.1717L21.8284 3.17169Z"
/>
<circle cx="11.4996" cy="4.49961" r="0.9" />
</svg>

View File

@ -16,7 +16,7 @@
<script lang="ts">
import { Ref, WithLookup } from '@hcengineering/core'
import { ProjectType } from '@hcengineering/task'
import { Location, resolvedLocationStore } from '@hcengineering/ui'
import { Location, resolvedLocationStore, resizeObserver } from '@hcengineering/ui'
import { onDestroy } from 'svelte'
import { typeStore } from '../../'
@ -24,6 +24,7 @@
export let visibleNav: boolean = true
let visibleSecondNav: boolean = true
let type: WithLookup<ProjectType> | undefined
let typeId: Ref<ProjectType> | undefined
@ -38,8 +39,13 @@
$: type = typeId !== undefined ? $typeStore.get(typeId) : undefined
</script>
<div class="hulyComponent">
<div
class="hulyComponent"
use:resizeObserver={(element) => {
visibleSecondNav = element.clientWidth > 720
}}
>
{#if type !== undefined}
<ProjectEditor {type} descriptor={type.$lookup?.descriptor} {visibleNav} on:change />
<ProjectEditor {type} descriptor={type.$lookup?.descriptor} {visibleNav} {visibleSecondNav} on:change />
{/if}
</div>

View File

@ -61,6 +61,7 @@
export let type: ProjectType
export let descriptor: ProjectTypeDescriptor | undefined
export let visibleNav: boolean = true
export let visibleSecondNav: boolean = true
const dispatch = createEventDispatcher()
@ -223,7 +224,7 @@
</svelte:fragment> -->
</Header>
<div class="hulyComponent-content__container columns">
{#if selectedTaskTypeId === undefined}
{#if selectedTaskTypeId === undefined && visibleSecondNav}
<div class="hulyComponent-content__column">
<div class="hulyComponent-content__navHeader">
<div class="hulyComponent-content__navHeader-menu">

View File

@ -57,6 +57,7 @@
export let _id: Ref<Issue>
export let _class: Ref<Class<Issue>>
export let embedded: boolean = false
export let kind: 'default' | 'modern' = 'default'
let lastId: Ref<Doc> = _id
const queryClient = createQuery()
@ -183,6 +184,7 @@
isAside={true}
isSub={false}
{embedded}
{kind}
withoutActivity={false}
bind:content
bind:innerWidth

View File

@ -83,6 +83,7 @@
import TopMenu from './icons/TopMenu.svelte'
let contentPanel: HTMLElement
let replacedPanel: HTMLElement
const { setTheme } = getContext<{ setTheme: (theme: string) => void }>('theme')
@ -617,6 +618,9 @@
let lastLoc: Location | undefined = undefined
defineSeparators('workbench', workbenchSeparators)
let modern: boolean
$: modern = ['setting', 'time'].some((app) => currentApplication?.alias === app)
</script>
{#if employee && !employee.active}
@ -656,7 +660,7 @@
</svg>
<div
class="workbench-container"
class:modern-app={['setting', 'time'].some((app) => currentApplication?.alias === app)}
class:modern-app={modern}
style:flex-direction={appsDirection === 'horizontal' ? 'column-reverse' : 'row'}
>
<div class="antiPanel-application {appsDirection}" class:lastDivider={!visibleNav}>
@ -811,7 +815,15 @@
{/if}
<div class="antiPanel-component antiComponent" bind:this={contentPanel}>
{#if currentApplication && currentApplication.component}
<Component is={currentApplication.component} props={{ currentSpace, visibleNav, navFloat, appsDirection }} />
<Component
is={currentApplication.component}
props={{ currentSpace, visibleNav, navFloat, appsDirection }}
on:change={(e) => {
if (e.detail?.type === 'replacedPanel' && e.detail?.replacedPanel !== undefined) {
replacedPanel = e.detail.replacedPanel
}
}}
/>
{:else if specialComponent}
<Component
is={specialComponent.component}
@ -853,12 +865,16 @@
</div>
<div bind:this={cover} class="cover" />
<TooltipInstance />
<PanelInstance bind:this={panelInstance} {contentPanel}>
<PanelInstance
bind:this={panelInstance}
contentPanel={modern ? replacedPanel : contentPanel}
kind={modern ? 'modern' : 'default'}
>
<svelte:fragment slot="panel-header">
<ActionContext context={{ mode: 'panel' }} />
</svelte:fragment>
</PanelInstance>
<Popup bind:this={popupInstance} {contentPanel}>
<Popup bind:this={popupInstance} contentPanel={modern ? replacedPanel : contentPanel}>
<svelte:fragment slot="popup-header">
<ActionContext context={{ mode: 'popup' }} />
</svelte:fragment>