Updated layout of the Chat navigator (#5537)

Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
Alexander Platov 2024-05-08 06:42:44 +03:00 committed by GitHub
parent 5584f2702b
commit bf80ba02e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 273 additions and 370 deletions

View File

@ -680,6 +680,7 @@ input.search {
.w-min { width: min-content; }
.w-max { width: max-content; }
.w-full { width: 100%; }
.w-auto { width: auto !important; }
.w-2 { width: .5rem; }
.w-4 { width: 1rem; }
.w-6 { width: 1.5rem; }

View File

@ -399,6 +399,17 @@
}
}
&.small .hulyAccordionItem-header__chevron {
margin: 0 0.125rem;
width: 1.25rem;
height: 1.25rem;
border: 1px solid transparent;
}
&.medium .hulyAccordionItem-header__chevron {
margin-right: var(--spacing-0_75);
background-color: var(--global-ui-BackgroundColor);
border: 1px solid var(--global-subtle-ui-BorderColor);
}
&.small,
&.medium {
padding: var(--spacing-1) var(--spacing-2);
@ -413,11 +424,6 @@
text-transform: uppercase;
}
.hulyAccordionItem-header__chevron {
background-color: var(--global-ui-BackgroundColor);
border: 1px solid var(--global-subtle-ui-BorderColor);
}
&:hover {
.hulyAccordionItem-header__label {
color: var(--global-primary-TextColor);
@ -516,10 +522,10 @@
color: var(--global-secondary-TextColor);
}
}
&:hover .hulyAccordionItem-header__chevron {
color: var(--button-subtle-IconColor);
background-color: var(--global-ui-hover-BackgroundColor);
}
}
&:hover .hulyAccordionItem-header__chevron {
color: var(--button-subtle-IconColor);
background-color: var(--global-ui-hover-BackgroundColor);
}
&.isOpen {
@ -533,13 +539,11 @@
&.medium.bottomSpace + .hulyAccordionItem-content {
padding-bottom: var(--spacing-2);
}
&.large {
.hulyAccordionItem-header__chevron > * {
transform: rotate(90deg);
}
&.bottomSpace + .hulyAccordionItem-content {
padding-bottom: var(--spacing-2);
}
&.large.bottomSpace + .hulyAccordionItem-content {
padding-bottom: var(--spacing-2);
}
&:is(.small, .large) .hulyAccordionItem-header__chevron > * {
transform: rotate(90deg);
}
}
}

View File

@ -30,6 +30,14 @@
border-radius: var(--small-focus-BorderRadius);
}
}
.hulyNavPanel-container a.noUnderline {
display: inline-flex;
flex-shrink: 0;
min-width: 0;
min-height: 0;
button.type-link { width: 100%; }
}
.hulyNavPanel-container .hulyNavItem-container,
.hulyNavPanel-container .hulyTaskNavLink-container {
margin: 0 0.75rem;

View File

@ -29,6 +29,7 @@
export let placeholder: IntlString = plugin.string.EditBoxPlaceholder
export let placeholderParam: any | undefined = undefined
export let autoFocus: boolean = false
export let kind: 'ghost' | 'secondary' = 'ghost'
export let size: 'small' | 'medium' | 'large' = 'medium'
export let loading = false
@ -52,7 +53,7 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="flex-between editbox {size}"
class="flex-between editbox {kind} {size}"
style={width != null ? 'width: ' + width : ''}
on:click={() => {
textHTML.focus()
@ -116,5 +117,12 @@
color: var(--theme-dark-color);
}
}
&.secondary {
padding: var(--spacing-1);
background-color: var(--theme-button-default);
border: 1px solid var(--theme-button-border);
border-radius: var(--small-BorderRadius);
}
}
</style>

View File

@ -13,29 +13,56 @@
// limitations under the License.
-->
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import type { IntlString } from '@hcengineering/platform'
import type { AnyComponent } from '..'
import { Label, Component } from '..'
import { showPopup, Menu, Action, Label, Component, IconOpenedArrow } from '..'
export let label: IntlString | undefined = undefined
export let title: string | undefined = undefined
export let categoryName: string
export let tools: AnyComponent | undefined = undefined
export let isOpen: boolean = true
export let isFold: boolean = false
export let selected: boolean = false
export let second: boolean = false
export let actions: Action[] = []
const dispatch = createEventDispatcher()
$: id = `navGroup-${categoryName}`
const toggle = (): void => {
isOpen = !isOpen
dispatch('toggle', isOpen)
}
function handleMenuClicked (ev: MouseEvent): void {
if (actions.length === 0) return
showPopup(Menu, { actions }, ev.target as HTMLElement)
}
</script>
<div class="hulyAccordionItem-container" class:second>
<button class="hulyAccordionItem-header nav small" class:isOpen class:selected on:click={() => (isOpen = !isOpen)}>
<button class="hulyAccordionItem-header nav small" class:isOpen class:selected on:click={toggle}>
{#if isFold}
<button class="hulyAccordionItem-header__chevron" class:collapsed={!isOpen}>
<IconOpenedArrow size={'small'} />
</button>
{/if}
<div class="hulyAccordionItem-header__label-wrapper font-medium-12">
<span class="hulyAccordionItem-header__label">
<!-- svelte-ignore a11y-no-static-element-interactions -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<span
class="hulyAccordionItem-header__label"
class:cursor-default={actions.length === 0}
on:click|stopPropagation={handleMenuClicked}
>
{#if label}<Label {label} />{/if}
{#if title}{title}{/if}
</span>
</div>
{#if isFold}<div class="flex-grow" />{/if}
{#if tools || $$slots.tools}
<div class="hulyAccordionItem-header__tools">
{#if tools}

View File

@ -14,50 +14,74 @@
-->
<script lang="ts">
import type { Asset, IntlString } from '@hcengineering/platform'
import { Icon, Label, IconOpenedArrow, Fold } from '..'
import { Icon, Label, IconOpenedArrow, Fold, AnySvelteComponent, IconSize } from '..'
export let icon: Asset | undefined = undefined
export let icon: Asset | AnySvelteComponent | undefined = undefined
export let iconProps: any | undefined = undefined
export let iconSize: IconSize = 'small'
export let label: IntlString | undefined = undefined
export let title: string | undefined = undefined
export let description: string | undefined = undefined
export let type: 'type-link' | 'type-tag' | 'type-anchor-link' | 'type-object' = 'type-link'
export let color: string | null = null
export let count: number | null = null
export let selected: boolean = false
export let isFold: boolean = false
export let isOpen: boolean = false
export let isSecondary: boolean = false
export let withBackground: boolean = false
export let showMenu: boolean = false
export let empty: boolean = false
export let level: number = 1
</script>
<button
class="hulyNavItem-container {type} {type === 'type-anchor-link' ? 'font-regular-12' : 'font-regular-14'}"
class="hulyNavItem-container {type} {type === 'type-anchor-link' || isSecondary
? 'font-regular-12'
: 'font-regular-14'}"
class:fold={isFold}
class:selected
on:click|stopPropagation
on:contextmenu|preventDefault|stopPropagation
class:showMenu
on:click
on:contextmenu
>
{#if isFold}
<Fold {isOpen} {empty} {level} />
{/if}
{#if icon || (type === 'type-tag' && color)}
<div class="hulyNavItem-icon">
<div class="hulyNavItem-icon" class:withBackground class:w-auto={iconSize === 'x-small'}>
{#if type !== 'type-tag' && icon}
<Icon {icon} size={'small'} />
<Icon {icon} size={iconSize} {iconProps} />
{:else if type === 'type-tag'}
<div style:background-color={color} class="hulyNavItem-icon__tag" />
{/if}
</div>
{/if}
<span class="hulyNavItem-label" style:color={type === 'type-tag' && selected ? color : null}>
<span
class="hulyNavItem-label"
class:font-medium-12={description}
class:flex-grow={!(type === 'type-anchor-link' || description)}
style:color={type === 'type-tag' && selected ? color : null}
>
{#if label}<Label {label} />{/if}
{#if title}{title}{/if}
<slot />
</span>
{#if description}
<span class="hulyNavItem-label description flex-grow">{description}</span>
{/if}
{#if showMenu || $$slots.actions}
<div class="hulyNavItem-actions">
<slot name="actions" />
</div>
{/if}
{#if count !== null}
<span class="hulyNavItem-count font-regular-12">
{count}
</span>
{/if}
{#if selected && type === 'type-link'}
<slot name="notify" />
{#if selected && (type === 'type-link' || type === 'type-object')}
<div class="hulyNavItem-icon right"><IconOpenedArrow size={'small'} /></div>
{/if}
</button>
@ -68,9 +92,10 @@
justify-content: stretch;
align-items: center;
padding: 0;
min-height: 2rem;
min-width: 0;
min-height: var(--global-small-Size);
border: none;
border-radius: 0.375rem;
border-radius: var(--small-BorderRadius);
outline: none;
.hulyNavItem-icon {
@ -78,8 +103,8 @@
justify-content: center;
align-items: center;
flex-shrink: 0;
width: 1rem;
height: 1rem;
width: var(--global-min-Size);
height: var(--global-min-Size);
color: var(--global-primary-TextColor);
&__tag {
@ -90,11 +115,18 @@
}
&.right {
visibility: hidden;
margin-left: 0.5rem;
margin-left: var(--spacing-0_5);
color: var(--global-accent-IconColor);
}
&:not(.right) {
margin-right: 0.5rem;
margin-right: var(--spacing-1);
}
&.withBackground {
width: var(--global-extra-small-Size);
height: var(--global-extra-small-Size);
background: var(--global-ui-BackgroundColor);
border: 1px solid var(--global-subtle-ui-BorderColor);
border-radius: var(--extra-small-BorderRadius);
}
}
.hulyNavItem-label {
@ -105,19 +137,39 @@
text-align: left;
min-width: 0;
color: var(--global-primary-TextColor);
&.description {
font-size: 0.875rem;
font-weight: 400;
}
}
.hulyNavItem-label + .hulyNavItem-label {
margin-left: var(--spacing-0_5);
}
.hulyNavItem-actions {
display: none;
align-items: center;
flex-shrink: 0;
min-width: 0;
min-height: 0;
gap: var(--spacing-0_25);
}
.hulyNavItem-count {
margin-left: 0.5rem;
margin-left: var(--spacing-1);
color: var(--global-tertiary-TextColor);
}
&:not(.selected):hover {
&:not(.selected) .hulyNavItem-count {
margin-right: var(--spacing-1);
}
&:not(.selected):hover,
&:not(.selected).showMenu {
background-color: var(--global-ui-hover-highlight-BackgroundColor);
}
&.selected {
cursor: auto;
background-color: var(--global-ui-highlight-BackgroundColor);
&:not(.type-anchor-link) .hulyNavItem-label {
&:not(.type-anchor-link) .hulyNavItem-label:not(.description) {
font-weight: 700;
}
.hulyNavItem-count {
@ -126,22 +178,19 @@
}
&.type-link {
padding: 0 0.625rem;
padding: 0 var(--spacing-1_25);
.hulyNavItem-label {
flex-grow: 1;
}
&.selected {
&:not(.fold) {
padding: 0 0.375rem 0 0.625rem;
padding: 0 var(--spacing-0_75) 0 var(--spacing-1_25);
}
&.fold {
padding: 0 0.375rem 0 0.25rem;
padding: 0 var(--spacing-0_75) 0 var(--spacing-0_5);
}
.hulyNavItem-icon {
color: var(--global-accent-TextColor);
}
.hulyNavItem-label {
.hulyNavItem-label:not(.description) {
color: var(--global-accent-TextColor);
}
.hulyNavItem-icon.right {
@ -150,34 +199,36 @@
}
}
&.type-tag {
padding: 0 0.625rem;
.hulyNavItem-label {
flex-grow: 1;
}
padding: 0 var(--spacing-1_25);
}
&.type-object {
padding: 0 0.625rem 0 0.25rem;
padding: 0 var(--spacing-0_5) 0 var(--spacing-0_5);
.hulyNavItem-icon {
width: 1.5rem;
height: 1.5rem;
background-color: var(--global-ui-BackgroundColor);
border-radius: 0.25rem;
width: var(--global-extra-small-Size);
height: var(--global-extra-small-Size);
&:not(.right) {
margin-right: 0.375rem;
margin-right: var(--spacing-0_75);
background-color: var(--global-ui-BackgroundColor);
border-radius: var(--extra-small-BorderRadius);
}
}
.hulyNavItem-label {
flex-grow: 1;
}
&.selected .hulyNavItem-label {
color: var(--global-accent-TextColor);
&.selected {
.hulyNavItem-label:not(.description) {
color: var(--global-accent-TextColor);
}
.hulyNavItem-icon {
color: var(--global-accent-TextColor);
&.right {
visibility: visible;
}
}
}
}
&.type-anchor-link {
padding: 0 0.75rem 0 0.625rem;
padding: 0 var(--spacing-1_5) 0 var(--spacing-1_25);
width: fit-content;
min-height: 1.75rem;
@ -194,11 +245,16 @@
}
}
&.fold {
padding-left: 0.25rem;
padding-left: var(--spacing-0_5);
:global(.hulyFold-container) {
margin-right: 0.375rem;
margin-right: var(--spacing-0_75);
}
}
&:hover .hulyNavItem-actions,
&.showMenu .hulyNavItem-actions {
display: flex;
}
}
</style>

View File

@ -6,6 +6,7 @@
export let value: string = ''
export let width: string = '12rem'
export let kind: 'ghost' | 'secondary' = 'ghost'
$: _search = value
const dispatch = createEventDispatcher()
@ -27,6 +28,7 @@
icon={IconSearch}
{width}
placeholder={plugin.string.Search}
{kind}
bind:value={_search}
on:change={() => {
restartTimer()

View File

@ -133,7 +133,7 @@
<div class="flex-row-top h-full">
{#if visibleNav}
<div class="antiPanel-navigator {appsDirection === 'horizontal' ? 'portrait' : 'landscape'}">
<div class="antiPanel-wrap__content">
<div class="antiPanel-wrap__content hulyNavPanel-container">
<ChatNavigator objectId={selectedData?._id} {object} {currentSpecial} on:select={handleChannelSelected} />
</div>
<Separator name="chat" float={navFloat ? 'navigator' : true} index={0} />

View File

@ -36,6 +36,7 @@
export let context: DocNotifyContext | undefined
export let item: ChatNavItemModel
export let isSelected = false
export let type: 'type-link' | 'type-tag' | 'type-anchor-link' | 'type-object' = 'type-link'
const client = getClient()
const hierarchy = client.getHierarchy()
@ -44,7 +45,7 @@
let notifications: InboxNotification[] = []
let notificationsCount = 0
let count: number | null = null
let actions: Action[] = []
notificationClient.inboxNotificationsByContext.subscribe((res) => {
@ -60,7 +61,7 @@
})
$: void getNotificationsCount(context, notifications).then((res) => {
notificationsCount = res
count = res === 0 ? null : res
})
$: void getChannelActions(context, item.object).then((res) => {
@ -121,10 +122,11 @@
iconSize={item.iconSize}
{isSelected}
iconProps={{ ...item.iconProps, value: item.object }}
{notificationsCount}
{count}
title={item.title}
description={item.description}
{actions}
{type}
on:click={() => {
dispatch('select', { object: item.object })
}}

View File

@ -16,7 +16,7 @@
import { Doc, Ref } from '@hcengineering/core'
import { DocNotifyContext } from '@hcengineering/notification'
import { getClient } from '@hcengineering/presentation'
import ui, { Action, AnySvelteComponent, IconSize, ModernButton } from '@hcengineering/ui'
import ui, { Action, AnySvelteComponent, IconSize, ModernButton, NavGroup } from '@hcengineering/ui'
import { getDocTitle } from '@hcengineering/view-resources'
import contact from '@hcengineering/contact'
import { getResource, translate } from '@hcengineering/platform'
@ -26,7 +26,6 @@
import chunter from '../../../plugin'
import { ChatNavItemModel } from '../types'
import { getObjectIcon, getChannelName } from '../../../utils'
import ChatSectionHeader from './ChatSectionHeader.svelte'
import { navigatorStateStore, toggleSections } from '../utils'
export let id: string
@ -134,19 +133,21 @@
</script>
{#if items.length > 0 && contexts.length > 0}
<div class="section">
<ChatSectionHeader
{header}
{actions}
{isCollapsed}
on:collapse={() => {
toggleSections(id)
}}
/>
<NavGroup
title={header}
categoryName={id}
{actions}
isOpen={!isCollapsed}
isFold
second
on:toggle={() => {
toggleSections(id)
}}
>
{#if !isCollapsed}
{#each visibleItems as item (item.id)}
{@const context = contexts.find(({ attachedTo }) => attachedTo === item.id)}
<ChatNavItem {context} isSelected={objectId === item.id} {item} on:select />
<ChatNavItem {context} isSelected={objectId === item.id} {item} type={'type-object'} on:select />
{/each}
{#if canShowMore}
<div class="showMore">
@ -166,18 +167,10 @@
<ChatNavItem {context} isSelected {item} on:select />
{/if}
{/if}
</div>
</NavGroup>
{/if}
<style lang="scss">
.section {
display: flex;
gap: 0.125rem;
flex-direction: column;
padding: 0 var(--spacing-1) var(--spacing-1_5) var(--spacing-1);
border-bottom: 1px solid var(--global-surface-02-BorderColor);
}
.showMore {
margin-top: var(--spacing-1);
font-size: 0.75rem;

View File

@ -70,10 +70,10 @@
}
</script>
<div class="header">
<div class="overflow-label">
<div class="hulyNavPanel-header">
<span class="overflow-label">
<Label label={chunter.string.Chat} />
</div>
</span>
<ButtonIcon icon={IconAdd} kind={'primary'} size={'small'} on:click={addButtonClicked} />
</div>
@ -94,6 +94,7 @@
<SearchEdit
value={searchValue}
width="auto"
kind={'secondary'}
on:change={(ev) => {
userSearch.set(ev.detail)
@ -111,17 +112,8 @@
</Scroller>
<style lang="scss">
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--spacing-1_5) var(--spacing-1_5) var(--spacing-3) var(--spacing-2_5);
font-weight: 700;
font-size: 1.25rem;
color: var(--global-primary-TextColor);
}
.search {
padding: var(--spacing-1_5);
padding: var(--spacing-3) var(--spacing-1_5) var(--spacing-1_5);
border-bottom: 1px solid var(--theme-navpanel-divider);
}
</style>

View File

@ -1,77 +0,0 @@
<!--
// Copyright © 2024 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 { Action, ButtonIcon, IconDropdownDown, IconDropdownRight, Menu, showPopup } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
export let header: string
export let actions: Action[] = []
export let isCollapsed = false
const dispatch = createEventDispatcher()
function handleMenuClicked (ev: MouseEvent): void {
if (actions.length === 0) {
return
}
showPopup(Menu, { actions }, ev.target as HTMLElement)
}
</script>
<div class="root">
<ButtonIcon
size="extra-small"
kind="tertiary"
inheritColor
icon={isCollapsed ? IconDropdownRight : IconDropdownDown}
on:click={() => dispatch('collapse')}
/>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div class="header uppercase" class:disabled={actions.length === 0} on:click={handleMenuClicked}>
{header}
</div>
</div>
<style lang="scss">
.root {
display: flex;
align-items: center;
flex-shrink: 0;
border-radius: 0.375rem;
padding-right: 0.25rem;
color: var(--global-secondary-TextColor);
font-size: 0.75rem;
}
.header {
cursor: pointer;
padding: var(--spacing-0_5) var(--spacing-0_75);
border-radius: var(--extra-small-BorderRadius);
background-color: var(--global-ui-BackgroundColor);
width: fit-content;
margin: 0.5rem 0.25rem;
&.disabled {
cursor: default;
}
&:hover:not(.disabled) {
color: var(--global-primary-TextColor);
background-color: var(--global-ui-highlight-BackgroundColor);
}
}
</style>

View File

@ -27,15 +27,16 @@
export let special: SpecialNavModel
export let currentSpecial: SpecialNavModel | undefined = undefined
export let type: 'type-link' | 'type-tag' | 'type-anchor-link' | 'type-object' = 'type-link'
const notificationsClient = InboxNotificationsClientImpl.getClient()
const notificationsByContextStore = notificationsClient.inboxNotificationsByContext
let notificationsCount = 0
let count: number | null = null
let elementsCount = 0
$: void getNotificationsCount(special, $notificationsByContextStore).then((res) => {
notificationsCount = res
count = res === 0 ? null : res
})
$: elementsCount = getElementsCount(special, $savedMessagesStore, $savedAttachmentsStore)
@ -65,17 +66,13 @@
}
</script>
<div class="mr-2 ml-2">
<NavItem
id={special.id}
icon={special.icon}
iconPadding="0 0 0 0.375rem"
iconSize="small"
padding="var(--spacing-1) var(--spacing-0_5)"
intlTitle={special.label}
withIconBackground={false}
{notificationsCount}
{elementsCount}
isSelected={special.id === currentSpecial?.id}
/>
</div>
<NavItem
id={special.id}
icon={special.icon}
intlTitle={special.label}
withIconBackground={false}
{count}
{elementsCount}
isSelected={special.id === currentSpecial?.id}
{type}
/>

View File

@ -14,16 +14,15 @@
-->
<script lang="ts">
import {
Action,
type Action,
ActionIcon,
AnySvelteComponent,
type AnySvelteComponent,
Icon,
IconMoreH,
IconRight,
IconSize,
Label,
Menu,
showPopup
showPopup,
NavItem
} from '@hcengineering/ui'
import { NotifyMarker } from '@hcengineering/notification-resources'
import { Asset, IntlString } from '@hcengineering/platform'
@ -31,18 +30,17 @@
export let id: string
export let icon: Asset | AnySvelteComponent | undefined
export let iconProps: any | undefined = undefined
export let iconSize: IconSize = 'x-small'
export let iconPadding: string | null = null
export let padding: string | null = null
export let withIconBackground = true
export let isSelected = false
export let isSecondary = false
export let notificationsCount = 0
export let iconSize: IconSize = 'small'
export let withIconBackground: boolean = true
export let isSelected: boolean = false
export let isSecondary: boolean = false
export let count: number | null = null
export let title: string | undefined = undefined
export let intlTitle: IntlString | undefined = undefined
export let description: string | undefined = undefined
export let actions: Action[] = []
export let elementsCount = 0
export let elementsCount: number = 0
export let type: 'type-link' | 'type-tag' | 'type-anchor-link' | 'type-object' = 'type-link'
let menuOpened = false
let inlineActions: Action[] = []
@ -63,173 +61,64 @@
}
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div class="root" class:pressed={menuOpened || isSelected} style:padding on:click>
{#if icon}
<div class="icon" class:withBackground={withIconBackground} style:padding={iconPadding}>
<Icon
{icon}
{iconProps}
size={iconSize}
fill={isSelected ? 'var(--theme-link-color)' : 'var(--global-primary-TextColor)'}
/>
</div>
{/if}
<div class="content">
<span
class="label overflow-label"
class:secondary={isSecondary}
class:extraBold={notificationsCount > 0}
class:selected={isSelected}
style="flex-shrink: 0"
>
{#if title}
{title}
{:else if intlTitle}
<Label label={intlTitle} />
{/if}
{#if description}
<span class="label overflow-label ml-1-5" title={description}>
{description}
</span>
{/if}
</span>
</div>
<div class="grower" />
<div class="controls">
<div class="flex-center">
{#each inlineActions as action}
<div
class="action"
class:pressed={menuOpened}
on:click|preventDefault|stopPropagation={(ev) => handleInlineActionClicked(ev, action)}
>
<Icon icon={action.icon ?? ActionIcon} size="small" />
</div>
{/each}
{#if menuActions.length > 0}
<div class="action" class:pressed={menuOpened} on:click|preventDefault|stopPropagation={handleMenuClicked}>
<IconMoreH size={'small'} />
</div>
{/if}
{#if elementsCount > 0}
<div class="ml-2" />
<div class="elementsCounter">{elementsCount}</div>
{/if}
{#if notificationsCount > 0}
<div class="ml-2" />
<NotifyMarker count={notificationsCount} />
{/if}
{#if isSelected}
<div class="ml-2" />
<IconRight size="small" fill="var(--theme-link-color)" />
{/if}
</div>
</div>
</div>
<NavItem
{icon}
{iconProps}
{iconSize}
label={intlTitle}
{title}
{description}
selected={isSelected}
{isSecondary}
count={elementsCount > 0 ? elementsCount : null}
{type}
withBackground={withIconBackground}
showMenu={menuOpened}
on:click
on:contextmenu
>
<svelte:fragment slot="actions">
{#each inlineActions as action}
<button
class="action"
class:pressed={menuOpened}
on:click|preventDefault|stopPropagation={(ev) => handleInlineActionClicked(ev, action)}
>
<Icon icon={action.icon ?? ActionIcon} size="small" />
</button>
{/each}
{#if menuActions.length > 0}
<button class="action" class:pressed={menuOpened} on:click|preventDefault|stopPropagation={handleMenuClicked}>
<IconMoreH size={'small'} />
</button>
{/if}
</svelte:fragment>
<svelte:fragment slot="notify">
{#if count != null && count > 0}
<div class="antiHSpacer" />
<NotifyMarker {count} />
<div class="antiHSpacer" />
{/if}
</svelte:fragment>
</NavItem>
<style lang="scss">
.root {
display: flex;
align-items: center;
flex-shrink: 0;
padding: var(--spacing-0_5) var(--spacing-0_5);
border-radius: var(--small-BorderRadius);
cursor: pointer;
position: relative;
&:hover {
background-color: var(--global-ui-highlight-BackgroundColor);
.action {
visibility: visible;
}
}
&.pressed {
background-color: var(--global-ui-highlight-BackgroundColor);
}
.action {
display: flex;
align-items: center;
justify-content: center;
padding: 0.25rem;
border-radius: 0.25rem;
flex-shrink: 0;
margin-left: 0.5rem;
visibility: hidden;
&:hover,
&.pressed {
visibility: visible;
color: var(--global-primary-TextColor);
background-color: var(--global-ui-highlight-BackgroundColor);
}
}
}
.grower {
flex-grow: 1;
min-width: 0;
}
.icon {
.action {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
margin-right: 0.375rem;
color: var(--global-primary-TextColor);
&.withBackground {
background: var(--global-ui-BackgroundColor);
width: 1.5rem;
height: 1.5rem;
border-radius: var(--extra-small-BorderRadius);
border: 1px solid var(--global-subtle-ui-BorderColor);
}
}
.label {
font-size: 0.875rem;
color: var(--global-primary-TextColor);
font-weight: 400;
&.secondary {
font-size: 0.75rem;
font-weight: 500;
}
&.extraBold {
font-weight: 700;
}
&.selected {
color: var(--global-accent-TextColor);
}
}
.controls {
display: flex;
height: 100%;
align-items: flex-start;
}
.content {
display: flex;
flex-direction: column;
overflow: hidden;
justify-content: center;
max-height: 3.75rem;
}
.elementsCounter {
margin-left: var(--spacing-1);
padding: var(--spacing-0_5);
color: var(--global-tertiary-TextColor);
font-size: 0.75rem;
border: none;
border-radius: var(--extra-small-BorderRadius);
outline: none;
&:hover,
&.pressed {
color: var(--global-primary-TextColor);
background-color: var(--global-ui-highlight-BackgroundColor);
}
}
</style>

View File

@ -34,6 +34,7 @@
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
border-radius: 50%;
background-color: var(--global-higlight-Color);
color: var(--global-on-accent-TextColor);

View File

@ -7,7 +7,7 @@ export class ChunterPage {
this.page = page
}
readonly buttonChannelBrowser = (): Locator => this.page.locator('.header > button.type-button-icon')
readonly buttonChannelBrowser = (): Locator => this.page.locator('.hulyNavPanel-header > button.type-button-icon')
readonly buttonNewChannelHeader = (): Locator => this.page.getByRole('button', { name: 'New channel' })
readonly inputNewChannelName = (): Locator => this.page.getByPlaceholder('New channel')
readonly inputDescription = (): Locator => this.page.getByPlaceholder('Description (optional)')