Update UserBoxList layout. Fix AccountPopup. (#1397)

This commit is contained in:
Alexander Platov 2022-04-14 14:04:24 +03:00 committed by GitHub
parent 942295b26b
commit b204009eab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 245 additions and 204 deletions

View File

@ -14,6 +14,7 @@
"Members": "Members",
"Search": "Search...",
"Unassigned": "Unassigned",
"CreateMore": "Create more"
"CreateMore": "Create more",
"NumberMembers": "{lenght, plural, =0 {no members} =1 {1 member} other {# members}}"
}
}

View File

@ -14,6 +14,7 @@
"Members": "Участники",
"Search": "Поиск...",
"Unassigned": "Не назначен",
"CreateMore": "Создать еще"
"CreateMore": "Создать еще",
"NumberMembers": "{lenght, plural, =0 {нет участников} =1 {1 участик} other {# участника}}"
}
}

View File

@ -20,7 +20,7 @@
export let avatar: string | null | undefined = undefined
export let direct: Blob | undefined = undefined
export let size: 'x-small' | 'small' | 'medium' | 'large' | 'x-large'
export let size: 'inline' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large'
let url: string | undefined
$: if (direct !== undefined) {
@ -50,7 +50,7 @@
flex-shrink: 0;
position: relative;
overflow: hidden;
background-color: var(--popup-bg-hover);
background-color: var(--avatar-bg-color);
border-radius: 50%;
pointer-events: none;
@ -61,6 +61,10 @@
&.no-img { border-color: transparent; }
}
.ava-inline {
width: .875rem; // 24
height: .875rem;
}
.ava-x-small {
width: 1.5rem; // 24
height: 1.5rem;
@ -92,6 +96,7 @@
border-radius: 50%;
}
.ava-inline .ava-mask, .ava-inline.no-img,
.ava-x-small .ava-mask, .ava-x-small.no-img,
.ava-small .ava-mask, .ava-small.no-img,
.ava-medium .ava-mask, .ava-medium.no-img { border-style: none; }

View File

@ -0,0 +1,53 @@
<!--
// Copyright © 2020 Anticrm Platform Contributors.
//
// 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 { Class, Doc, Ref } from '@anticrm/core'
import { createQuery } from '../utils'
import { Person } from '@anticrm/contact'
import Avatar from './Avatar.svelte'
export let _class: Ref<Class<Doc>>
export let items: Ref<Person>[] = []
export let size: 'inline' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large'
export let limit: number = 3
let persons: Person[] = []
const query = createQuery()
$: query.query<Person>(_class, { _id: { $in: items } }, result => { persons = result }, { limit })
</script>
<div class="avatars-container">
{#each persons as person}
<div class="combine-avatar {size}">
<Avatar avatar={person.avatar} {size} />
</div>
{/each}
</div>
<style lang="scss">
.avatars-container {
display: flex;
align-items: center;
.combine-avatar.inline:not(:first-child) { margin-left: calc(1px - (.875rem / 2)); }
.combine-avatar.x-small:not(:first-child) { margin-left: calc(1px - (1.5rem / 2)); }
.combine-avatar.small:not(:first-child) { margin-left: calc(1px - 1rem); }
.combine-avatar.medium:not(:first-child) { margin-left: calc(1px - (2.25rem / 2)); }
.combine-avatar.large:not(:first-child) { margin-left: calc(1px - (4.5rem / 2)); }
.combine-avatar.x-large:not(:first-child) { margin-left: calc(1px - (7.5rem / 2)); }
.combine-avatar:not(:last-child) { mask: radial-gradient(circle at 100% 50%, rgba(0, 0, 0, 0) 48.5%, rgb(0, 0, 0) 50%); }
}
</style>

View File

@ -13,7 +13,6 @@
// limitations under the License.
-->
<script lang="ts">
import { onMount } from 'svelte'
import type { IntlString } from '@anticrm/platform'
import { getClient } from '../utils'

View File

@ -36,7 +36,7 @@
<div class="selectPopup">
<div class="header">
<input type='text' bind:value={search} placeholder={phTraslate} on:input={(ev) => { }} on:change/>
<input type='text' bind:value={search} placeholder={phTraslate} on:input={() => { }} on:change/>
</div>
<div class="scroll">
<div class="box">

View File

@ -18,7 +18,7 @@
import contact, { Contact, formatName } from '@anticrm/contact'
import type { Class, Ref } from '@anticrm/core'
import type { IntlString } from '@anticrm/platform'
import type { TooltipAlignment } from '@anticrm/ui'
import type { TooltipAlignment, ButtonKind, ButtonSize } from '@anticrm/ui'
import { Button, Label, showPopup, Tooltip } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte'
import presentation from '..'
@ -35,8 +35,8 @@
export let allowDeselect = false
export let titleDeselect: IntlString | undefined = undefined
export let readonly = false
export let kind: 'primary' | 'secondary' | 'no-border' | 'transparent' | 'link' | 'dangerous' = 'no-border'
export let size: 'small' | 'medium' | 'large' | 'x-large' = 'small'
export let kind: ButtonKind = 'no-border'
export let size: ButtonSize = 'small'
export let justify: 'left' | 'center' = 'center'
export let width: string | undefined = undefined
export let labelDirection: TooltipAlignment | undefined = undefined
@ -45,7 +45,6 @@
let selected: Contact | undefined
let container: HTMLElement
let opened: boolean = false
const client = getClient()
@ -62,14 +61,13 @@
</script>
<div bind:this={container} class="min-w-0">
<Tooltip label={label} fill={width === '100%'} direction={labelDirection}>
<Tooltip {label} fill={width === '100%'} direction={labelDirection}>
<Button
icon={(size === 'x-large' && selected) ? undefined : IconPerson}
width={width ?? 'min-content'}
{size} {kind} {justify}
on:click={() => {
if (!opened && !readonly) {
opened = true
if (!readonly) {
showPopup(UsersPopup, { _class, allowDeselect, selected: value, titleDeselect, placeholder }, container, (result) => {
if (result === null) {
value = null
@ -79,7 +77,6 @@
value = result._id
dispatch('change', value)
}
opened = false
})
}
}}

View File

@ -15,18 +15,26 @@
<script lang="ts">
import { Person } from '@anticrm/contact'
import type { Class, Doc, Ref } from '@anticrm/core'
import { IntlString } from '@anticrm/platform'
import { ActionIcon, CircleButton, IconAdd, IconClose, Label, ShowMore, showPopup } from '@anticrm/ui'
import type { IntlString } from '@anticrm/platform'
import { translate } from '@anticrm/platform'
import type { ButtonKind, ButtonSize, TooltipAlignment } from '@anticrm/ui'
import { Tooltip, showPopup, Button } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte'
import { UserInfo } from '..'
import presentation, { CombineAvatars, UsersPopup } from '..'
import { createQuery } from '../utils'
import UsersPopup from './UsersPopup.svelte'
import Members from './icons/Members.svelte'
export let items: Ref<Person>[] = []
export let _class: Ref<Class<Doc>>
export let title: IntlString
export let label: IntlString
export let noItems: IntlString
export let kind: ButtonKind = 'no-border'
export let size: ButtonSize = 'small'
export let justify: 'left' | 'center' = 'center'
export let width: string | undefined = undefined
export let labelDirection: TooltipAlignment | undefined = undefined
let persons: Person[] = []
const query = createQuery()
@ -37,71 +45,45 @@
const dispatch = createEventDispatcher()
async function addRef (person: Person): Promise<void> {
dispatch('open', person)
}
async function addPerson (evt: Event): Promise<void> {
showPopup(
UsersPopup,
{
_class,
title,
label,
multiSelect: true,
allowDeselect: false,
ignoreUsers: items
selectedUsers: items
},
evt.target as HTMLElement,
() => { },
(result) => {
// We have some value selected
if (result !== undefined) {
addRef(result)
items = result
dispatch('update', items)
}
}
)
}
async function removePerson (person: Person): Promise<void> {
dispatch('delete', person)
}
</script>
<div class="flex-row">
<ShowMore>
<div class="persons-container">
<div class="flex flex-reverse">
<div class="ml-4">
<CircleButton icon={IconAdd} size={'small'} selected on:click={addPerson} />
<Tooltip {label} fill={width === '100%'} direction={labelDirection}>
<Button
icon={persons.length === 0 ? Members : undefined}
label={persons.length === 0 ? presentation.string.Members : undefined}
width={width ?? 'min-content'}
{kind} {size} {justify}
on:click={addPerson}
>
<svelte:fragment slot="content">
{#if persons.length > 0}
<div class="flex-row-center flex-nowrap">
<CombineAvatars {_class} bind:items size={'inline'} />
{#await translate(presentation.string.NumberMembers, { lenght: persons.length }) then text}
<span class="ml-1-5">{text}</span>
{/await}
</div>
<div class="person-items">
{#if items?.length === 0}
<div class="flex flex-grow title-center">
<Label label={noItems} />
</div>
{/if}
{#each persons as person}
<div class="antiComponentBox flex-center antiComponentBoxFocused">
<UserInfo value={person} size={'x-small'} />
<div class="ml-1">
<ActionIcon icon={IconClose} size={'small'} action={() => removePerson(person)} />
</div>
</div>
{/each}
</div>
</div>
</div>
</ShowMore>
</div>
<style lang="scss">
.persons-container {
color: var(--theme-caption-color);
}
.person-items {
flex-grow: 1;
display: grid;
gap: 0.25rem;
grid-template-columns: repeat(3, 1fr);
}
.margin_025 {
margin: 0.25rem;
}
</style>
{/if}
</svelte:fragment>
</Button>
</Tooltip>

View File

@ -15,7 +15,7 @@
<script lang="ts">
import type { IntlString } from '@anticrm/platform'
import { translate } from '@anticrm/platform'
import { afterUpdate, createEventDispatcher } from 'svelte'
import { createEventDispatcher } from 'svelte'
import { Tooltip, CheckBox } from '@anticrm/ui'
import UserInfo from './UserInfo.svelte'
@ -28,10 +28,11 @@
export let _class: Ref<Class<Person>>
export let selected: Ref<Person> | undefined
export let multiSelect: boolean = false
export let allowDeselect: boolean = false
export let titleDeselect: IntlString | undefined = undefined
export let placeholder: IntlString = presentation.string.Search
export let selectedUsers: Ref<Person>[] = []
export let ignoreUsers: Ref<Person>[] = []
let search: string = ''
@ -43,23 +44,47 @@
let phTraslate: string = ''
$: if (placeholder) translate(placeholder, {}).then(res => { phTraslate = res })
afterUpdate(() => { dispatch('update', Date.now()) })
const isSelected = (person: Person): boolean => {
if (selectedUsers.filter(p => p === person._id).length > 0) return true
return false
}
const checkSelected = (person: Person): void => {
if (isSelected(person)) selectedUsers = selectedUsers.filter(p => p !== person._id)
else selectedUsers.push(person._id)
objects = objects
dispatch('update', selectedUsers)
}
</script>
<div class="selectPopup">
<div class="header">
<input type='text' bind:value={search} placeholder={phTraslate} on:input={(ev) => { }} on:change/>
<input type='text' bind:value={search} placeholder={phTraslate} on:change/>
</div>
<div class="scroll">
<div class="box">
{#each objects as person}
<button class="menu-item flex-between" on:click={() => { dispatch('close', person) }}>
<button class="menu-item" on:click={() => {
if (!multiSelect) {
selected = person._id === selected ? undefined : person._id
dispatch('close', selected != undefined ? person : undefined)
} else checkSelected(person)
}}>
{#if multiSelect}
<div class="check pointer-events-none">
<CheckBox checked={isSelected(person)} primary />
</div>
{/if}
<UserInfo size={'x-small'} value={person} />
{#if allowDeselect && person._id === selected}
<div class="check" on:click|stopPropagation={() => { dispatch('close', null) }}>
<Tooltip label={titleDeselect ?? presentation.string.Deselect}>
<CheckBox checked primary />
</Tooltip>
<div class="check-right pointer-events-none">
{#if titleDeselect}
<Tooltip label={titleDeselect ?? presentation.string.Deselect}>
<CheckBox checked circle primary />
</Tooltip>
{:else}
<CheckBox checked circle primary />
{/if}
</div>
{/if}
</button>

View File

@ -15,7 +15,7 @@
-->
<script lang="ts">
export let size: 'x-small' | 'small' | 'medium' | 'large' | 'x-large'
export let size: 'inline' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large'
const fill: string = 'var(--theme-caption-color)'
</script>
@ -30,6 +30,10 @@
.svg-avatar {
.op { opacity: .05; }
}
.inline {
width: .75rem;
height: .75rem;
}
.x-small {
width: 1rem;
height: 1rem;

View File

@ -0,0 +1,29 @@
<!--
// 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">
export let size: 'small' | 'medium' | 'large'
const fill: string = 'currentColor'
</script>
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M10.2857 5.44444C10.2857 6.79447 9.26237 7.88889 8 7.88889C6.73764 7.88889 5.71429 6.79447 5.71429 5.44444C5.71429 4.09441 6.73764 3 8 3C9.26237 3 10.2857 4.09441 10.2857 5.44444Z" />
<path d="M3.42857 11.9603C3.42857 10.9748 3.98128 10.081 4.85831 9.7786C5.79546 9.45545 7.02325 9.11111 8 9.11111C8.97675 9.11111 10.2045 9.45545 11.1417 9.77859C12.0187 10.081 12.5714 10.9748 12.5714 11.9603V12.7778C12.5714 13.4528 12.0598 14 11.4286 14H4.57143C3.94025 14 3.42857 13.4528 3.42857 12.7778V11.9603Z" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.63272 4.75066C4.59249 4.97531 4.57143 5.20725 4.57143 5.44444C4.57143 6.00206 4.68782 6.5306 4.89604 7.00381C4.59565 7.53433 4.05083 7.88889 3.42857 7.88889C2.4818 7.88889 1.71429 7.06808 1.71429 6.05556C1.71429 5.04303 2.4818 4.22222 3.42857 4.22222C3.89788 4.22222 4.32315 4.42391 4.63272 4.75066Z" />
<path d="M2.28571 12.7778V11.9603C2.28571 10.8522 2.76028 9.77952 3.59669 9.11537C3.5397 9.11257 3.48361 9.11111 3.42857 9.11111C2.69601 9.11111 1.77516 9.36937 1.0723 9.61172C0.414531 9.83853 0 10.5089 0 11.248V11.8611C0 12.3674 0.383756 12.7778 0.857143 12.7778H2.28571Z" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.3716 4.75066C11.4118 4.97531 11.4329 5.20725 11.4329 5.44444C11.4329 6.00206 11.3166 6.5306 11.1086 7.00381C11.4087 7.53433 11.953 7.88889 12.5747 7.88889C13.5205 7.88889 14.2873 7.06808 14.2873 6.05556C14.2873 5.04303 13.5205 4.22222 12.5747 4.22222C12.1058 4.22222 11.6809 4.42391 11.3716 4.75066Z" />
<path d="M13.7164 12.7778V11.9603C13.7164 10.8522 13.2423 9.77952 12.4067 9.11537C12.4636 9.11257 12.5197 9.11111 12.5747 9.11111C13.3065 9.11111 14.2265 9.36937 14.9287 9.61172C15.5859 9.83853 16 10.5089 16 11.248V11.8611C16 12.3674 15.6166 12.7778 15.1437 12.7778H13.7164Z" />
</svg>

View File

@ -21,6 +21,7 @@ export { default as AttributeBarEditor } from './components/AttributeBarEditor.s
export { default as AttributeEditor } from './components/AttributeEditor.svelte'
export { default as AttributesBar } from './components/AttributesBar.svelte'
export { default as Avatar } from './components/Avatar.svelte'
export { default as CombineAvatars } from './components/CombineAvatars.svelte'
export { default as Card } from './components/Card.svelte'
export { default as EditableAvatar } from './components/EditableAvatar.svelte'
export { default as Members } from './components/Members.svelte'

View File

@ -43,7 +43,8 @@ export default plugin(presentationId, {
Members: '' as IntlString,
Search: '' as IntlString,
Unassigned: '' as IntlString,
CreateMore: '' as IntlString
CreateMore: '' as IntlString,
NumberMembers: '' as IntlString
},
metadata: {
RequiredVersion: '' as Metadata<string>

View File

@ -79,6 +79,7 @@
--popup-shadow: rgb(0 0 0 / 20%) 0px 4px 24px;
--card-shadow: rgb(0 0 0 / 50%) 0px 16px 70px;
--card-overlay-color: rgba(28, 29, 31, .5);
--avatar-bg-color: #4f5358;
--button-bg-color: #303236;
--button-bg-hover: #37383b;

View File

@ -185,7 +185,7 @@ p:last-child { margin-block-end: 0; }
&.circle {
padding: .25rem;
background-color: var(--popup-bg-hover);
background-color: var(--avatar-bg-color);
border-radius: 50%;
}
}
@ -286,6 +286,7 @@ p:last-child { margin-block-end: 0; }
.step-tb75 + .step-tb75 { margin-top: .75rem; }
.ml-1 { margin-left: .25rem; }
.ml-1-5 { margin-left: .375rem; }
.ml-2 { margin-left: .5rem; }
.ml-3 { margin-left: .75rem; }
.ml-4 { margin-left: 1rem; }
@ -378,6 +379,7 @@ p:last-child { margin-block-end: 0; }
.h-full { height: 100%; }
.h-2 { height: .5rem; }
.h-9 { height: 2.25rem; }
.h-16 { height: 4rem; }
.h-18 { height: 4.5rem; }
.w-full { width: 100%; }
.w-9 { width: 2.25rem; }

View File

@ -65,6 +65,7 @@
color: var(--caption-color);
cursor: pointer;
&.high { height: 3rem; }
.icon {
margin-right: .75rem;
width: 1rem;
@ -84,14 +85,13 @@
text-overflow: ellipsis;
overflow: hidden;
}
.check {
.check, .check-right {
display: flex;
justify-content: flex-end;
align-items: center;
margin-left: 1rem;
width: 1rem;
margin-right: .75rem;
height: 2rem;
}
.check-right { margin: 0 0 0 2rem; }
&:hover { background-color: var(--popup-bg-hover); }
}
}

View File

@ -14,7 +14,7 @@
-->
<script lang="ts">
import type { IntlString, Asset } from '@anticrm/platform'
import type { AnySvelteComponent } from '../types'
import type { AnySvelteComponent, ButtonKind, ButtonSize } from '../types'
import Spinner from './Spinner.svelte'
import Label from './Label.svelte'
import Icon from './Icon.svelte'
@ -22,8 +22,8 @@
export let label: IntlString | undefined = undefined
export let labelParams: Record<string, any> = {}
export let kind: 'primary' | 'secondary' | 'no-border' | 'transparent' | 'link' | 'link-bordered' | 'dangerous' = 'secondary'
export let size: 'small' | 'medium' | 'large' | 'x-large' = 'medium'
export let kind: ButtonKind = 'secondary'
export let size: ButtonSize = 'medium'
export let shape: 'circle' | undefined = undefined
export let icon: Asset | AnySvelteComponent | undefined = undefined
export let justify: 'left' | 'center' = 'center'
@ -83,7 +83,8 @@
<style lang="scss">
.small {
height: 1.5rem;
line-height: 1.5rem;
font-size: .75rem;
line-height: .75rem;
&.only-icon { width: 1.5rem; }
}
.medium {

View File

@ -34,13 +34,6 @@
<label class="checkbox" class:circle class:primary class:checked>
<input class="chBox" type="checkbox" bind:checked on:change={handleValueChanged} />
<svg class="checkSVG" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
{#if !circle}
<path
class="back"
class:primary
d="M4,0h8c2.2,0,4,1.8,4,4v8c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4V4C0,1.8,1.8,0,4,0z"
/>
{/if}
{#if checked}
{#if symbol === 'minus'}
<rect class="check" class:primary x="4" y="7.4" width="8" height="1.2" />
@ -54,12 +47,27 @@
<style lang="scss">
.checkbox {
flex-shrink: 0;
display: inline-flex;
justify-content: center;
align-items: center;
width: 1rem;
height: 1rem;
width: .875rem;
height: .875rem;
border: 1px solid var(--dark-color);
border-radius: .25rem;
&.circle {
width: 1rem;
height: 1rem;
border-radius: 50%;
}
&.checked {
background-color: var(--accent-color);
border-color: transparent;
}
&.primary.checked {
background-color: var(--primary-bg-color);
border-color: transparent;
}
.chBox {
position: absolute;
@ -94,35 +102,13 @@
}
}
.checkSVG {
width: 1rem;
height: 1rem;
border-radius: 0.25rem;
width: .875rem;
height: .875rem;
.back {
fill: var(--theme-button-bg-hovered);
}
.check {
visibility: hidden;
fill: var(--theme-button-bg-enabled);
}
}
}
.circle {
width: 1.25rem;
height: 1.25rem;
background-color: var(--theme-button-bg-hovered);
border: 1px solid var(--theme-bg-focused-color);
border-radius: 50%;
&.checked {
background-color: var(--theme-bg-check);
}
&.primary {
border-color: transparent;
&.checked {
background-color: var(--primary-button-enabled);
}
}
}
</style>

View File

@ -20,7 +20,7 @@
import Label from './Label.svelte'
import Icon from './Icon.svelte'
import { showPopup, Button, Tooltip, DropdownPopup } from '..'
import type { AnySvelteComponent, ListItem, TooltipAlignment } from '../types'
import type { AnySvelteComponent, ListItem, TooltipAlignment, ButtonKind, ButtonSize } from '../types'
export let icon: Asset | AnySvelteComponent | undefined = undefined
export let label: IntlString
@ -28,8 +28,8 @@
export let items: ListItem[] = []
export let selected: ListItem | undefined = undefined
export let kind: 'primary' | 'secondary' | 'no-border' | 'transparent' | 'link' | 'dangerous' = 'no-border'
export let size: 'small' | 'medium' | 'large' | 'x-large' = 'small'
export let kind: ButtonKind = 'no-border'
export let size: ButtonSize = 'small'
export let justify: 'left' | 'center' = 'center'
export let width: string | undefined = undefined
export let labelDirection: TooltipAlignment | undefined = undefined

View File

@ -16,7 +16,7 @@
<script lang="ts">
import { IntlString, Asset } from '@anticrm/platform'
import DropdownLabelsPopup from './DropdownLabelsPopup.svelte'
import type { AnySvelteComponent, DropdownTextItem, TooltipAlignment } from '../types'
import type { AnySvelteComponent, DropdownTextItem, TooltipAlignment, ButtonKind, ButtonSize } from '../types'
import { showPopup, Tooltip, Button, Label } from '..'
import { createEventDispatcher } from 'svelte'
import ui from '../plugin'
@ -27,8 +27,8 @@
export let items: DropdownTextItem[]
export let selected: DropdownTextItem['id'] | undefined = undefined
export let kind: 'primary' | 'secondary' | 'no-border' | 'transparent' | 'link' | 'dangerous' = 'no-border'
export let size: 'small' | 'medium' | 'large' | 'x-large' = 'small'
export let kind: ButtonKind = 'no-border'
export let size: ButtonSize = 'small'
export let justify: 'left' | 'center' = 'center'
export let width: string | undefined = undefined
export let labelDirection: TooltipAlignment | undefined = undefined
@ -73,46 +73,3 @@
</Button>
</Tooltip>
</div>
<!-- <div class="flex-col cursor-pointer"
bind:this={btn}
on:click|preventDefault={() => {
if (!opened) {
opened = true
showPopup(DropdownLabelsPopup, { placeholder, items, selected }, btn, (result) => {
if (result) {
selected = result
dispatch('selected', result)
}
opened = false
})
}
}}
>
<div class="overflow-label label"><Label label={label} /></div>
<div class="flex-row-center space">
<span class="mr-1">
{#if opened}
<IconUp size={'small'} />
{:else}
<IconDown size={'small'} />
{/if}
</span>
<span class="overflow-label" class:caption-color={selected} class:content-dark-color={!selected}>
{#if selectedItem}
{selectedItem.label}
{:else}
<Label label={none} />
{/if}
</span>
</div>
</div>
<style lang="scss">
.label {
margin-bottom: .125rem;
font-weight: 500;
font-size: .75rem;
color: var(--theme-content-accent-color);
}
</style> -->

View File

@ -20,7 +20,7 @@ import { readable } from 'svelte/store'
import Root from './components/internal/Root.svelte'
export type { AnyComponent, AnySvelteComponent, Action, LabelAndProps, TooltipAlignment, AnySvelteComponentWithProps, Location, PopupAlignment } from './types'
export type { AnyComponent, AnySvelteComponent, Action, LabelAndProps, TooltipAlignment, AnySvelteComponentWithProps, Location, PopupAlignment, ButtonKind, ButtonSize } from './types'
// export { applicationShortcutKey } from './utils'
export { getCurrentLocation, locationToUrl, navigate, location } from './location'

View File

@ -123,9 +123,9 @@ export function fitPopupElement (modalHTML: HTMLElement, element?: PopupAlignmen
const rectPopup = modalHTML.getBoundingClientRect()
// Vertical
if (rect.bottom + rectPopup.height + 28 <= document.body.clientHeight) {
modalHTML.style.top = `calc(${rect.bottom}px + .75rem)`
modalHTML.style.top = `calc(${rect.bottom}px + .125rem)`
} else if (rectPopup.height + 28 < rect.top) {
modalHTML.style.bottom = `calc(${document.body.clientHeight - rect.y}px + .75rem)`
modalHTML.style.bottom = `calc(${document.body.clientHeight - rect.y}px + .125rem)`
} else {
modalHTML.style.top = modalHTML.style.bottom = '1rem'
}

View File

@ -63,8 +63,9 @@ export interface Tab {
export type TabModel = Tab[]
export type ButtonKind = 'primary' | 'secondary' | 'no-border' | 'transparent' | 'link' | 'link-bordered' | 'dangerous'
export type ButtonSize = 'small' | 'medium' | 'large' | 'x-large'
export type PopupAlignment = HTMLElement | EventTarget | null | 'right' | 'top' | 'account' | 'full' | 'content' | 'middle'
export type TooltipAlignment = 'top' | 'bottom' | 'left' | 'right'
export interface LabelAndProps {

View File

@ -72,7 +72,7 @@
<UserBoxList
_class={contact.class.Employee}
items={participants}
title={calendar.string.Participants}
label={calendar.string.Participants}
on:open={(evt) => {
participants.push(evt.detail._id)
participants = participants

View File

@ -61,7 +61,7 @@
<UserBoxList
_class={contact.class.Employee}
items={object.participants}
title={calendar.string.Participants}
label={calendar.string.Participants}
on:open={(evt) => {
client.update(object, { $push: { participants: evt.detail._id } })
}}

View File

@ -78,7 +78,7 @@
<UserBoxList
_class={contact.class.Employee}
items={participants}
title={calendar.string.Participants}
label={calendar.string.Participants}
on:open={(evt) => {
participants.push(evt.detail._id)
participants = participants

View File

@ -19,7 +19,7 @@
import { IntlString } from '@anticrm/platform'
import { createQuery } from '@anticrm/presentation'
import { Dropdown } from '@anticrm/ui'
import type { TooltipAlignment } from '@anticrm/ui'
import type { TooltipAlignment, ButtonKind, ButtonSize } from '@anticrm/ui'
import { ListItem } from '@anticrm/ui/src/types'
import { createEventDispatcher } from 'svelte'
import contact from '../plugin'
@ -28,8 +28,8 @@
export let value: Ref<Organization> | undefined
export let label: IntlString = contact.string.Organization
export let kind: 'primary' | 'secondary' | 'no-border' | 'transparent' | 'link' | 'dangerous' = 'no-border'
export let size: 'small' | 'medium' | 'large' | 'x-large' = 'small'
export let kind: ButtonKind = 'no-border'
export let size: ButtonSize = 'small'
export let justify: 'left' | 'center' = 'center'
export let width: string | undefined = undefined
export let labelDirection: TooltipAlignment | undefined = undefined

View File

@ -165,18 +165,6 @@
placeholder={recruit.string.Location} bind:value={location}
maxWidth={'37.5rem'} kind={'small-style'}
/>
<UserBoxList
_class={contact.class.Employee}
items={doc.participants}
title={calendar.string.Participants}
on:open={(evt) => {
doc.participants = [...(doc.participants ?? []), evt.detail._id]
}}
on:delete={(evt) => {
doc.participants = doc.participants?.filter((it) => it !== evt.detail._id) ?? [currentUser.employee]
}}
noItems={calendar.string.NoParticipants}
/>
<StyledTextBox
emphasized
showButtons={false}
@ -199,5 +187,14 @@
/>
<DateRangePresenter bind:value={startDate} labelNull={recruit.string.StartDate} withTime editable on:change={updateStart} />
<DateRangePresenter bind:value={dueDate} labelNull={recruit.string.DueDate} withTime editable />
<UserBoxList
_class={contact.class.Employee}
items={doc.participants}
label={calendar.string.Participants}
on:update={(evt) => {
doc.participants = evt.detail
}}
noItems={calendar.string.NoParticipants}
/>
</svelte:fragment>
</Card>

View File

@ -86,7 +86,7 @@
<UserBoxList
_class={contact.class.Employee}
items={object.participants}
title={calendar.string.Participants}
label={calendar.string.Participants}
on:open={(evt) => {
client.update(object, { $push: { participants: evt.detail._id } })
}}

View File

@ -69,11 +69,10 @@
}
</script>
<div class="antiPopup">
<div class="ap-space" />
<div class="ap-scroll"><div class="ap-box">
<div class="selectPopup">
<div class="scroll"><div class="box">
{#await getItems() then items}
<div class="ap-menuItem flex-row-center" on:click={() => { editProfile(items) }}>
<div class="menu-item high flex-row-center" on:click={() => { editProfile(items) }}>
{#if employee}
<Avatar avatar={employee.avatar} size={'medium'} />
{/if}
@ -86,7 +85,7 @@
</div>
{#if items}
{#each filterItems(items) as item }
<button class="ap-menuItem" on:click={() => selectCategory(item)}>
<button class="menu-item" on:click={() => selectCategory(item)}>
<div class='mr-2'>
<Icon icon={item.icon} size={'small'}/>
</div>
@ -94,13 +93,13 @@
</button>
{/each}
{/if}
<button class="ap-menuItem" on:click={selectWorkspace}>
<button class="menu-item" on:click={selectWorkspace}>
<div class='mr-2'>
<Icon icon={setting.icon.SelectWorkspace} size={'small'}/>
</div>
<Label label={setting.string.SelectWorkspace} />
</button>
<button class="ap-menuItem" on:click={signOut}>
<button class="menu-item" on:click={signOut}>
<div class='mr-2'>
<Icon icon={setting.icon.Signout} size={'small'}/>
</div>
@ -108,5 +107,4 @@
</button>
{/await}
</div></div>
<div class="ap-space" />
</div>