From 81499f0f638cd81f2bc464fa563bc9886ed4fe38 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Mon, 15 Aug 2022 12:53:53 +0300 Subject: [PATCH 01/35] update: Set rtl and images for fluent UI look --- .../mgt-teams-channel-picker.graph.ts | 56 ++++- .../mgt-teams-channel-picker.scss | 198 +++++------------ .../mgt-teams-channel-picker.ts | 208 ++++++++++++++---- .../mgt-spinner/mgt-spinner.scss | 20 -- .../sub-components/mgt-spinner/mgt-spinner.ts | 4 +- .../mgt-components/src/graph/cacheStores.ts | 3 +- .../mgt-components/src/utils/SvgHelper.ts | 18 +- 7 files changed, 275 insertions(+), 232 deletions(-) diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.graph.ts b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.graph.ts index 665e59a70b..87699c1cab 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.graph.ts +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.graph.ts @@ -5,8 +5,15 @@ * ------------------------------------------------------------------------------------------- */ -import { IGraph, prepScopes } from '@microsoft/mgt-element'; +import { IGraph, prepScopes, BetaGraph, CacheItem, CacheService, CacheStore } from '@microsoft/mgt-element'; import { Team } from '@microsoft/microsoft-graph-types'; +import { + getPhotoForResource, + CachePhoto, + getPhotoInvalidationTime, + getIsPhotosCacheEnabled +} from '../../graph/graph.photos'; +import { schemas } from '../../graph/cacheStores'; /** * async promise, returns all Teams associated with the user logged in @@ -15,11 +22,46 @@ import { Team } from '@microsoft/microsoft-graph-types'; * @memberof Graph */ export async function getAllMyTeams(graph: IGraph): Promise { - const scopes = 'team.readbasic.all'; - const teams = await graph - .api('/me/joinedTeams') - .select(['displayName', 'id', 'isArchived']) - .middlewareOptions(prepScopes(scopes)) - .get(); + const teams = await graph.api('/me/joinedTeams').select(['displayName', 'id', 'isArchived']).get(); return teams ? teams.value : null; } + +/** An object collection of cached photos. */ +type CachePhotos = { + [key: string]: CachePhoto; +}; + +export async function getTeamsPhotosforPhotoIds(graph: BetaGraph, teamIds: string[]): Promise { + let cache: CacheStore; + let photos: CachePhotos = {}; + + if (getIsPhotosCacheEnabled()) { + cache = CacheService.getCache(schemas.photos, schemas.photos.stores.teams); + for (const id of teamIds) { + try { + const photoDetail = await cache.getValue(id); + if (photoDetail && getPhotoInvalidationTime() > Date.now() - photoDetail.timeCached) { + photos[id] = photoDetail; + } + } catch (_) {} + } + if (Object.keys(photos).length) { + return photos; + } + } + + let scopes = ['team.readbasic.all']; + photos = {}; + + for (const id of teamIds) { + try { + const photoDetail = await getPhotoForResource(graph, `/teams/${id}`, scopes); + if (getIsPhotosCacheEnabled() && photoDetail) { + cache.putValue(id, photoDetail); + } + photos[id] = photoDetail; + } catch (_) {} + } + + return photos; +} diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss index b99a6a9115..b3861ed2b9 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss @@ -15,27 +15,29 @@ .root { position: relative; + ::slotted(fluent-tree-item) { + --tree-item-nested-width: 2em; + } .input-wrapper { - font-family: $font-family; - display: flex; - flex-wrap: wrap; - align-items: center; - padding: 4px 10px; - position: relative; - background-color: $input__background-color; - font-size: 14px; - color: $color; - height: 29px; - line-height: 19px; + padding: 4px; cursor: text; - @include input__border($theme-default); + box-sizing: border-box; + background: padding-box linear-gradient(var(--neutral-fill-input-rest), var(--neutral-fill-input-rest)), + border-box var(--neutral-stroke-input-rest); + border: calc(var(--stroke-width) * 1px) solid transparent; + border-radius: calc(var(--control-corner-radius) * 1px); + min-height: calc((var(--base-height-multiplier) + var(--density)) * var(--design-unit) * 1px); + &:hover { - border-color: $input__border-color--hover; + background: padding-box linear-gradient(var(--neutral-fill-input-focus), var(--neutral-fill-input-focus)), + border-box var(--neutral-stroke-input-rest); } &.focused { - border-color: $input__border-color--focus; + border-bottom: calc(var(--focus-stroke-width) * 1px) solid var(--accent-fill-rest); + border-bottom-left-radius: calc(var(--control-corner-radius) * 1px); + border-bottom-right-radius: calc(var(--control-corner-radius) * 1px); } .selected-team { @@ -103,11 +105,9 @@ } .search-icon { - margin-top: 1px; + padding: 2px 4px 2px 8px; align-self: flex-start; - font-family: 'FabricMDL2Icons'; color: var(--accent-color, $commblue_primary); - line-height: normal; } .input-search { @@ -128,102 +128,45 @@ height: 90%; top: 2px; right: 2px; - @include selected-team__overflow($theme-default); } } .close-icon { - display: inline-block; position: absolute; right: 10px; - top: 12px; - line-height: normal; - font-family: 'FabricMDL2Icons'; + top: 6px; cursor: pointer; color: $placeholder__color; - background-color: $input__background-color; &:hover { color: $color; } } - .dropdown { - padding-top: 5px; - padding-bottom: 11px; + .down-chevron, + .up-chevron { position: absolute; - box-shadow: 0px 1.3289px 2.65781px rgba(180, 180, 180, 0.182), 0px 1.3289px 2.65781px rgba(68, 68, 68, 0.3); - border-radius: 8px; - background-color: $dropdown__background-color; - z-index: 1; /* Sit on top */ - width: 100%; - text-align: left; - list-style-type: none; - font-family: $font-family; - font-style: normal; - font-weight: normal; - color: $color; - display: none; - max-height: 346px; - overflow-y: auto; + right: 10px; + top: 8px; + color: $placeholder__color; - &.visible { - display: block; + &:hover { + color: $color; } + } + .team-photo { + width: 24px; + position: inherit; + border-radius: 50%; + margin: 0px 6px; + } - .item { - .arrow svg { - fill: set-var(arrow, $theme-default, $channel-picker); - } - - &.list-team { - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; - user-select: none; - -o-user-select: none; - display: flex; - flex-direction: row; - align-items: center; - padding: 5px 12px 6px 14px; - margin: 6px 4px 4px 4px; - border-radius: 4px; - font-family: $font-family; - font-style: normal; - font-weight: 600; - font-size: 16px; - color: $color; - - flex-flow: nowrap; - position: relative; - overflow: hidden; - white-space: nowrap; - background-color: transparent; - &:after { - content: ''; - position: absolute; - width: 36px; - height: 100%; - top: 0; - right: 0; - @include dropdown-item__overflow($theme-default); - } - - &:hover { - background-color: $dropdown-item__background-color--hover; - } - .arrow { - margin-right: 5px; - margin-bottom: 1px; - } - } - - &.selected { - background-color: set-var(dropdown-item__background-color--selected, $theme-default, $channel-picker); - } + .dropdown { + z-index: 1; /* Sit on top */ + display: none; + margin-top: 4px; - &.focused { - background-color: $dropdown-item__background-color--hover; - } + &.visible { + display: inherit; } .channel-display { @@ -264,23 +207,15 @@ font-style: normal; font-weight: 600; font-size: 14px; - color: $color; + color: $gray120; line-height: 19px; text-align: center; } .message-parent { - padding: 2px; - margin-top: 30px; - margin-bottom: 30px; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - vertical-align: middle; + display: -webkit-inline-box; .loading-text { - margin-top: 3px; - margin-left: 9px; + margin: 8px 0px 0px 8px; color: #0078d4; } } @@ -288,44 +223,6 @@ } [dir='rtl'] { - .input-wrapper::after { - content: ''; - position: absolute; - width: 99%; - height: 90%; - top: 2px; - left: 0px; - background-image: linear-gradient( - to left, - rgba(255, 255, 255, 0) 0%, - rgba(255, 255, 255, 0) 80%, - $input__background-color 100% - ); - background-image: -moz-linear-gradient( - right, - rgba(255, 255, 255, 0) 0%, - rgba(255, 255, 255, 0) 80%, - $input__background-color 100% - ); - background-image: -o-linear-gradient( - right, - rgba(255, 255, 255, 0) 0%, - rgba(255, 255, 255, 0) 80%, - $input__background-color 100% - ); - background-image: -ms-linear-gradient( - right, - rgba(255, 255, 255, 0) 0%, - rgba(255, 255, 255, 0) 80%, - $input__background-color 100% - ); - background-image: -webkit-linear-gradient( - right, - rgba(255, 255, 255, 0) 0%, - rgba(255, 255, 255, 0) 80%, - $input__background-color 100% - ); - } .search-wrapper { margin-right: 0px !important; } @@ -335,7 +232,10 @@ .channel-display { padding: 0px 34px 0px 10px !important; } - .close-icon { + + .close-icon, + .down-chevron, + .up-chevron { right: auto; left: 10px; } @@ -355,6 +255,14 @@ .selected-team { padding-left: 10px; } + .message-parent { + .loading-text { + right: auto; + left: 10px; + padding-right: 8px; + text-align: right; + } + } } @media (forced-colors: active) and (prefers-color-scheme: dark) { diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts index a25ed1c141..759e81d4da 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts @@ -8,14 +8,18 @@ import * as MicrosoftGraph from '@microsoft/microsoft-graph-types'; import { customElement, html, property, TemplateResult } from 'lit-element'; import { classMap } from 'lit-html/directives/class-map'; -import { Providers, ProviderState, MgtTemplatedComponent } from '@microsoft/mgt-element'; +import { Providers, ProviderState, MgtTemplatedComponent, BetaGraph } from '@microsoft/mgt-element'; import '../../styles/style-helper'; import '../sub-components/mgt-spinner/mgt-spinner'; import { getSvg, SvgIcon } from '../../utils/SvgHelper'; import { debounce } from '../../utils/Utils'; import { styles } from './mgt-teams-channel-picker-css'; -import { getAllMyTeams } from './mgt-teams-channel-picker.graph'; +import { getAllMyTeams, getTeamsPhotosforPhotoIds } from './mgt-teams-channel-picker.graph'; import { strings } from './strings'; +import { repeat } from 'lit-html/directives/repeat'; +import { registerFluentComponents } from '../../utils/FluentComponents'; +import { fluentTreeView, fluentTreeItem, fluentCard } from '@fluentui/web-components'; +registerFluentComponents(fluentCard, fluentTreeView, fluentTreeItem); /** * Team with displayName @@ -189,6 +193,7 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { private static _config = { useTeamsBasedScopes: false }; + private teamsPhotos = {}; /** * Gets Selected item to be used @@ -255,9 +260,11 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { constructor() { super(); this.handleWindowClick = this.handleWindowClick.bind(this); + this.direction = this.dir; this.addEventListener('keydown', e => this.onUserKeyDown(e)); this.addEventListener('focus', _ => this.loadTeamsIfNotLoaded()); this.addEventListener('mouseover', _ => this.loadTeamsIfNotLoaded()); + this.clearState(); } /** @@ -342,8 +349,8 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { ${this.renderSelected()}
${this.renderSearchIcon()} ${this.renderInput()}
- ${this.renderCloseButton()} -
${this.renderDropdown()}
+ ${this.renderChevrons()}${this.renderCloseButton()} + ${this.renderDropdown()} ` ); @@ -360,11 +367,18 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { if (!this._selectedItemState) { return html``; } - + let icon: TemplateResult; + if (this._selectedItemState.parent.channels) { + icon = html`${this._selectedItemState.parent.item.displayName}`; + } return html`
  • + ${icon}
    ${this._selectedItemState.parent.item.displayName}
    -
    ${getSvg(SvgIcon.TeamSeparator, '#B3B0AD')}
    +
    ${getSvg(SvgIcon.TeamSeparator, '#000000')}
    ${this._selectedItemState.item.displayName}
    ${this.renderSearchIcon()} ${this.renderInput()}
  • @@ -438,12 +452,72 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { */ protected renderCloseButton() { return html` -
    -  + `; } + /** + * Displays the close button after selecting a channel. + */ + protected showCloseIcon() { + const downChevron = this.renderRoot.querySelector('.down-chevron') as HTMLElement; + const upChevron = this.renderRoot.querySelector('.up-chevron') as HTMLElement; + const closeIcon = this.renderRoot.querySelector('.close-icon') as HTMLElement; + if (downChevron) { + downChevron.style.display = 'none'; + } + if (upChevron) { + upChevron.style.display = 'none'; + } + + if (closeIcon) { + closeIcon.style.display = null; + } + } + + /** + * Renders down chevron icon + * + * @protected + * @returns + * @memberof MgtTeamsChannelPicker + */ + protected renderDownChevron() { + return html` +
    + + + +
    `; + } + + /** + * Renders up chevron icon + * + * @protected + * @returns + * @memberof MgtTeamsChannelPicker + */ + protected renderUpChevron() { + return html` + `; + } + + /** + * Renders both chevrons + */ + private renderChevrons() { + return html`${this.renderUpChevron()}${this.renderDownChevron()}`; + } + /** * Renders dropdown content * @@ -478,18 +552,35 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { * @memberof MgtTeamsChannelPicker */ protected renderDropdownList(items: ChannelPickerItemState[], level: number = 0) { - if (items && items.length) { - return items.map((treeItem, index) => { - const isLeaf = !treeItem.channels; - const renderChannels = !isLeaf && treeItem.isExpanded; - - return html` - ${this.renderItem(treeItem)} - ${renderChannels ? this.renderDropdownList(treeItem.channels, level + 1) : html``} - `; - }); + if (items && items.length > 0) { + let icon: TemplateResult = null; + + return html` + + ${repeat( + items, + itemObj => itemObj?.item, + obj => { + if (obj.channels) { + icon = html`${obj.item.displayName}`; + } + return html` + + ${icon}${obj.item.displayName} + ${repeat( + obj?.channels, + channels => channels.item, + channel => { + return this.renderItem(channel); + } + )}`; + } + )} + `; } - return null; } @@ -501,13 +592,6 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { * @memberof MgtTeamsChannelPicker */ protected renderItem(itemState: ChannelPickerItemState) { - let icon: TemplateResult = null; - - if (itemState.channels) { - // must be team with channels - icon = itemState.isExpanded ? getSvg(SvgIcon.ArrowDown, '#252424') : getSvg(SvgIcon.ArrowRight, '#252424'); - } - let isSelected = false; if (this.selectedItem) { if (this.selectedItem.channel === itemState.item) { @@ -515,27 +599,18 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { } } - const classes = { - focused: this._focusList[this._focusedIndex] === itemState, - item: true, - 'list-team': itemState.channels ? true : false, - selected: isSelected - }; - const dropDown = this.renderRoot.querySelector('.dropdown'); - if (dropDown.children[this._focusedIndex]) { + if (dropDown?.children[this._focusedIndex]) { dropDown.children[this._focusedIndex].scrollIntoView(false); } return html` -
    this.handleItemClick(itemState)} class="${classMap(classes)}"> -
    - ${icon} -
    - ${itemState.channels ? itemState.item.displayName : this.renderHighlightedText(itemState.item)} -
    - `; + this.handleItemClick(itemState)}> + ${itemState?.item.displayName} + `; } /** @@ -652,6 +727,12 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { teams = await getAllMyTeams(graph); teams = teams.filter(t => !t.isArchived); + let teamsIds = teams.map(t => t.id); + + const beta = BetaGraph.fromGraph(graph); + + this.teamsPhotos = await getTeamsPhotosforPhotoIds(beta, teamsIds); + const batch = graph.createBatch(); const scopes = ['team.readbasic.all']; @@ -693,6 +774,7 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { this._focusedIndex = -1; this.resetFocusState(); + this.showCloseIcon(); } private handleInputChanged(e) { @@ -877,6 +959,7 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { } this._isDropdownVisible = true; + this.toggleChevron(); } private lostFocus() { @@ -888,6 +971,11 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { this._isDropdownVisible = false; this.filterList(); + this.toggleChevron(); + + if (this._selectedItemState !== undefined) { + this.showCloseIcon(); + } } private selectChannel(item: ChannelPickerItemState) { @@ -901,6 +989,44 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { input.textContent = this._inputValue = ''; } this.requestUpdate(); + // Show the down chevron and hide the close icon + this.hideCloseIcon(); this.lostFocus(); } + + /** + * Hides the close icon. + */ + private hideCloseIcon() { + const closeIcon = this.renderRoot.querySelector('.close-icon') as HTMLElement; + if (closeIcon) { + closeIcon.style.display = 'none'; + } + } + + /** + * Toggles the up and down chevron depending on the dropdown + * visibility. + */ + private toggleChevron() { + const downChevron = this.renderRoot.querySelector('.down-chevron') as HTMLElement; + const upChevron = this.renderRoot.querySelector('.up-chevron') as HTMLElement; + if (this._isDropdownVisible) { + if (downChevron) { + downChevron.style.display = 'none'; + } + if (upChevron) { + upChevron.style.display = null; + this.hideCloseIcon(); + } + } else { + if (downChevron) { + downChevron.style.display = null; + this.hideCloseIcon(); + } + if (upChevron) { + upChevron.style.display = 'none'; + } + } + } } diff --git a/packages/mgt-components/src/components/sub-components/mgt-spinner/mgt-spinner.scss b/packages/mgt-components/src/components/sub-components/mgt-spinner/mgt-spinner.scss index c9298068c7..a708ff576c 100644 --- a/packages/mgt-components/src/components/sub-components/mgt-spinner/mgt-spinner.scss +++ b/packages/mgt-components/src/components/sub-components/mgt-spinner/mgt-spinner.scss @@ -6,23 +6,3 @@ */ @import '../../../styles/shared-styles.scss'; - -:host { - .spinner { - border: 2px solid #c7e0f4; /* Light grey */ - border-top: 2px solid #0078d4; /* Blue */ - border-radius: 50%; - width: 20px; - height: 20px; - animation: spin 2s linear infinite; - } - - @keyframes spin { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } - } -} diff --git a/packages/mgt-components/src/components/sub-components/mgt-spinner/mgt-spinner.ts b/packages/mgt-components/src/components/sub-components/mgt-spinner/mgt-spinner.ts index d5a0a337ee..b0bc7712c8 100644 --- a/packages/mgt-components/src/components/sub-components/mgt-spinner/mgt-spinner.ts +++ b/packages/mgt-components/src/components/sub-components/mgt-spinner/mgt-spinner.ts @@ -33,8 +33,6 @@ export class MgtSpinner extends MgtBaseComponent { * @memberof MgtSpinner */ public render() { - return html` -
    - `; + return html``; } } diff --git a/packages/mgt-components/src/graph/cacheStores.ts b/packages/mgt-components/src/graph/cacheStores.ts index f675406420..41e6892c2d 100644 --- a/packages/mgt-components/src/graph/cacheStores.ts +++ b/packages/mgt-components/src/graph/cacheStores.ts @@ -30,7 +30,8 @@ export const schemas = { stores: { contacts: 'contacts', users: 'users', - groups: 'groups' + groups: 'groups', + teams: 'teams' }, version: 1 }, diff --git a/packages/mgt-components/src/utils/SvgHelper.ts b/packages/mgt-components/src/utils/SvgHelper.ts index 8ca79eec20..1f71cb6e9a 100644 --- a/packages/mgt-components/src/utils/SvgHelper.ts +++ b/packages/mgt-components/src/utils/SvgHelper.ts @@ -223,21 +223,9 @@ export function getSvg(svgIcon: SvgIcon, color?: string) { case SvgIcon.Search: return html` - - - - - - - - - - - - `; + + + `; case SvgIcon.SkypeArrow: return html` From 675e17fae4c22a552741ee593dae7e4ee5038fab Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Thu, 1 Sep 2022 13:38:20 +0300 Subject: [PATCH 02/35] update: Make card height wrap around the content --- .../mgt-teams-channel-picker/mgt-teams-channel-picker.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss index b3861ed2b9..d3c201a0a7 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss @@ -17,6 +17,7 @@ position: relative; ::slotted(fluent-tree-item) { --tree-item-nested-width: 2em; + --card-height: auto; } .input-wrapper { From 35cd8852d68ed469b4af579195262f4e0d2db877 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Thu, 1 Sep 2022 13:39:58 +0300 Subject: [PATCH 03/35] update: Make searched channels expand in dropdown --- .../mgt-teams-channel-picker.ts | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts index f0f7524f3f..d58482960a 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts @@ -568,15 +568,18 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { src=${this.teamsPhotos[obj.item.id].photo} />`; } return html` - - ${icon}${obj.item.displayName} - ${repeat( - obj?.channels, - channels => channels.item, - channel => { - return this.renderItem(channel); - } - )}`; + + ${icon}${obj.item.displayName} + ${repeat( + obj?.channels, + channels => channels.item, + channel => { + return this.renderItem(channel); + } + )} + `; } )} `; From dd37e34a84eaca22fd20175962def0f17c1977a6 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Thu, 1 Sep 2022 13:50:01 +0300 Subject: [PATCH 04/35] refactor: Remove deprecated even.keyCode for event.code --- .../mgt-teams-channel-picker.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts index d58482960a..e5ae8deb5c 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts @@ -880,7 +880,7 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { } private onUserKeyDown(event: KeyboardEvent) { - if (event.keyCode === 13) { + if (event.code === 'Enter') { // No new line event.preventDefault(); } @@ -891,13 +891,13 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { const currentFocusedItem = this._focusList[this._focusedIndex]; - switch (event.keyCode) { - case 40: // down + switch (event.code) { + case 'ArrowDown': // down this._focusedIndex = (this._focusedIndex + 1) % this._focusList.length; this.requestUpdate(); event.preventDefault(); break; - case 38: // up + case 'ArrowUp': // up if (this._focusedIndex === -1) { this._focusedIndex = this._focusList.length; } @@ -905,26 +905,26 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { this.requestUpdate(); event.preventDefault(); break; - case 39: // right + case 'ArrowRight': // right if (currentFocusedItem && currentFocusedItem.channels && !currentFocusedItem.isExpanded) { currentFocusedItem.isExpanded = true; this.resetFocusState(); event.preventDefault(); } break; - case 37: // left + case 'ArrowLeft': // left if (currentFocusedItem && currentFocusedItem.channels && currentFocusedItem.isExpanded) { currentFocusedItem.isExpanded = false; this.resetFocusState(); event.preventDefault(); } break; - case 9: // tab + case 'Tab': // tab if (!currentFocusedItem) { this.lostFocus(); break; } - case 13: // return/enter + case 'Enter': // return/enter if (currentFocusedItem && currentFocusedItem.channels) { // focus item is a Team currentFocusedItem.isExpanded = !currentFocusedItem.isExpanded; @@ -939,13 +939,13 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { event.preventDefault(); } break; - case 8: // backspace + case 'Backspace': // backspace if (this._inputValue.length === 0 && this._selectedItemState) { this.selectChannel(null); event.preventDefault(); } break; - case 27: // esc + case 'Escape': // esc this.selectChannel(this._selectedItemState); this._focusedIndex = -1; this.resetFocusState(); From fc7d28ff7405a96cec1557bfc44a286e9ab546d9 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Mon, 26 Sep 2022 14:50:47 +0300 Subject: [PATCH 05/35] fix: Apply auto card height on the fluent-card --- .../mgt-teams-channel-picker/mgt-teams-channel-picker.scss | 2 +- .../mgt-teams-channel-picker/mgt-teams-channel-picker.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss index d3c201a0a7..9c1f8ffd3c 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss @@ -17,7 +17,6 @@ position: relative; ::slotted(fluent-tree-item) { --tree-item-nested-width: 2em; - --card-height: auto; } .input-wrapper { @@ -168,6 +167,7 @@ &.visible { display: inherit; + --card-height: auto } .channel-display { diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts index 9d7bb296a5..5d87fc356b 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts @@ -17,7 +17,7 @@ import { debounce } from '../../utils/Utils'; import { styles } from './mgt-teams-channel-picker-css'; import { getAllMyTeams, getTeamsPhotosforPhotoIds } from './mgt-teams-channel-picker.graph'; import { strings } from './strings'; -import { repeat } from 'lit-html/directives/repeat'; +import { repeat } from 'lit/directives/repeat.js'; import { registerFluentComponents } from '../../utils/FluentComponents'; import { fluentTreeView, fluentTreeItem, fluentCard } from '@fluentui/web-components'; registerFluentComponents(fluentCard, fluentTreeView, fluentTreeItem); From 4aa9deeb0a6fbb5e4e65231dbde0b8e40aeb3350 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Mon, 26 Sep 2022 15:33:43 +0300 Subject: [PATCH 06/35] fix: Set render direction to ltr by default and auto height card --- .../mgt-teams-channel-picker.scss | 2 +- .../mgt-teams-channel-picker.ts | 13 ++++++------- .../mgt-element/src/utils/LocalizationHelper.ts | 4 +++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss index 9c1f8ffd3c..56c7da031a 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss @@ -167,7 +167,7 @@ &.visible { display: inherit; - --card-height: auto + --card-height: auto; } .channel-display { diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts index 5d87fc356b..ce5c473df2 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts @@ -257,11 +257,11 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { // determines loading state @property({ attribute: false }) private _isDropdownVisible; + private _dir: string = this.direction; constructor() { super(); this.handleWindowClick = this.handleWindowClick.bind(this); - this.direction = this.dir; this.addEventListener('keydown', e => this.onUserKeyDown(e)); this.addEventListener('focus', _ => this.loadTeamsIfNotLoaded()); this.addEventListener('mouseover', _ => this.loadTeamsIfNotLoaded()); @@ -345,7 +345,7 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { return ( this.renderTemplate('default', { teams: this.items }) || html` -
    +
    ${this.renderSelected()}
    ${this.renderSearchIcon()} ${this.renderInput()}
    @@ -548,16 +548,15 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { * * @protected * @param {ChannelPickerItemState[]} items - * @param {number} [level=0] * @returns * @memberof MgtTeamsChannelPicker */ - protected renderDropdownList(items: ChannelPickerItemState[], level: number = 0) { + protected renderDropdownList(items: ChannelPickerItemState[]) { if (items && items.length > 0) { let icon: TemplateResult = null; return html` - + ${repeat( items, itemObj => itemObj?.item, @@ -571,7 +570,7 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { return html` + dir=${this._dir}> ${icon}${obj.item.displayName} ${repeat( obj?.channels, @@ -611,7 +610,7 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { return html` this.handleItemClick(itemState)}> ${itemState?.item.displayName} `; diff --git a/packages/mgt-element/src/utils/LocalizationHelper.ts b/packages/mgt-element/src/utils/LocalizationHelper.ts index 2677de403a..0dd2634baf 100644 --- a/packages/mgt-element/src/utils/LocalizationHelper.ts +++ b/packages/mgt-element/src/utils/LocalizationHelper.ts @@ -46,7 +46,9 @@ export class LocalizationHelper { * @memberof LocalizationHelper */ public static getDocumentDirection() { - return document.body?.getAttribute('dir') || document.documentElement?.getAttribute('dir'); + // Re-set the dir to ltr if the dir attribute is already loaded and the first two options + // are returning null values. + return document.body?.getAttribute('dir') || document.documentElement?.getAttribute('dir') || 'ltr'; } /** From 9db6970aee546c72d98e25f07135c4f72a60cee8 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Fri, 14 Oct 2022 14:32:45 +0300 Subject: [PATCH 07/35] update: set the dir attribute at the top most part of the element This etogether with setting the dir attribute on the fluent-tree-view enables the fluentui components to set the dir on their own. Multiple dir attributes are unnecessary and cause the fluentui components to exhibit unexpected behaviour. --- .../mgt-teams-channel-picker.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts index ce5c473df2..e93ad9765e 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts @@ -257,7 +257,6 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { // determines loading state @property({ attribute: false }) private _isDropdownVisible; - private _dir: string = this.direction; constructor() { super(); @@ -276,6 +275,11 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { public connectedCallback() { super.connectedCallback(); window.addEventListener('click', this.handleWindowClick); + + const ownerDocument = this.renderRoot.ownerDocument; + if (ownerDocument) { + ownerDocument.documentElement.setAttribute('dir', this.direction); + } } /** @@ -345,7 +349,7 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { return ( this.renderTemplate('default', { teams: this.items }) || html` -
    +
    ${this.renderSelected()}
    ${this.renderSearchIcon()} ${this.renderInput()}
    @@ -556,7 +560,7 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { let icon: TemplateResult = null; return html` - + ${repeat( items, itemObj => itemObj?.item, @@ -568,9 +572,7 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { src=${this.teamsPhotos[obj.item.id].photo} />`; } return html` - + ${icon}${obj.item.displayName} ${repeat( obj?.channels, @@ -610,7 +612,7 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { return html` this.handleItemClick(itemState)}> ${itemState?.item.displayName} `; From 4de5ee020244b6e27d5e97f61b3bfacfb479c486 Mon Sep 17 00:00:00 2001 From: Musale Martin Date: Mon, 17 Oct 2022 18:23:35 +0300 Subject: [PATCH 08/35] update: Change the usage of fluentui components --- .../mgt-teams-channel-picker.scss | 281 ++++----------- .../mgt-teams-channel-picker.ts | 330 +++++------------- 2 files changed, 169 insertions(+), 442 deletions(-) diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss index 56c7da031a..1834971382 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.scss @@ -9,149 +9,87 @@ @import '../../styles/shared-styles.scss'; @import './mgt-teams-channel-picker.theme.scss'; -:host { +:host, +:host mgt-teams-channel-picker { font-family: $font-family; -} - -.root { - position: relative; - ::slotted(fluent-tree-item) { - --tree-item-nested-width: 2em; - } - - .input-wrapper { - padding: 4px; - cursor: text; - box-sizing: border-box; - background: padding-box linear-gradient(var(--neutral-fill-input-rest), var(--neutral-fill-input-rest)), - border-box var(--neutral-stroke-input-rest); - border: calc(var(--stroke-width) * 1px) solid transparent; - border-radius: calc(var(--control-corner-radius) * 1px); - min-height: calc((var(--base-height-multiplier) + var(--density)) * var(--design-unit) * 1px); - &:hover { - background: padding-box linear-gradient(var(--neutral-fill-input-focus), var(--neutral-fill-input-focus)), - border-box var(--neutral-stroke-input-rest); - } + .dropdown { + z-index: 1; + display: none; + margin-top: 4px; - &.focused { - border-bottom: calc(var(--focus-stroke-width) * 1px) solid var(--accent-fill-rest); - border-bottom-left-radius: calc(var(--control-corner-radius) * 1px); - border-bottom-right-radius: calc(var(--control-corner-radius) * 1px); + &.visible { + display: flex; } - .selected-team { - padding-right: 10px; - border: none; - display: flex; - position: relative; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - align-items: center; - height: 24px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - .arrow { - margin-left: 8px; - margin-right: 8px; - } - .selected-team-name { - font-weight: bold; + .team { + &-photo { + width: 24px; + position: inherit; + border-radius: 50%; + margin: 0px 6px; } - .search-wrapper { - margin-left: 12px; - height: 18px; - display: flex; - flex-wrap: nowrap; - align-items: center; - margin-right: 30px; - } - } - .search-wrapper { - overflow: hidden; - height: 18px; - display: flex; - flex-wrap: nowrap; - align-items: center; - margin-right: 30px; - } - .hide-icon { - display: none; - } + &-start-slot { + width: max-content; + } - .team-chosen-input { - display: inline-block; - border: none; - line-height: normal; - outline: none; - font-family: $font-family; - font-style: normal; - font-weight: normal; - font-size: 14px; - line-height: 19px; - background-color: transparent; - color: $color; - padding-left: 5px; - &::placeholder { - color: $placeholder__color; + &-parent-name { + width: auto; } } - .team-chosen-input[contenteditable]:empty::after { - content: attr(data-placeholder); - color: $placeholder__color; - } + } - .search-icon { - padding: 2px 4px 2px 8px; - align-self: flex-start; - color: var(--accent-color, $commblue_primary); - } + .search-error-text, + .loading-text { + font-family: $font-family; + font-style: normal; + font-weight: 600; + font-size: 14px; + color: $gray120; + line-height: 19px; + text-align: center; + } - .input-search { - height: 19px; + .message-parent { + display: -webkit-inline-box; + .loading-text { + margin: 8px 0px 0px 8px; + color: #0078d4; } + } +} - .input-search-start { - white-space: nowrap; - line-height: normal; - margin-inline-start: 0px; - margin-inline-end: 0px; - } +:host fluent-card { + --fill-color: var(--dropdown-background-color, --fill-color); + --card-height: auto; +} - &::after { - content: ''; - position: absolute; - width: 100%; - height: 90%; - top: 2px; - right: 2px; - } - } +:host fluent-text-field { + --fill-color: var(--color, $color); + --neutral-fill-input-rest: var(--input-background-color, #ffffff); + --input-placeholder-rest: var(--placeholder-color, --input-placeholder-rest); + --input-placeholder-hover: var(--placeholder-color--focus, --input-placeholder-hover); +} +:host fluent-tree-view { + --tree-item-nested-width: 2em; +} - .close-icon { - position: absolute; - right: 10px; - top: 6px; - cursor: pointer; - color: $placeholder__color; - &:hover { - color: $color; - } - } +:host fluent-tree-item { + --tree-item-nested-width: 2em; + --neutral-foreground-rest: var(--color, $color); + --neutral-fill-stealth-hover: var(--dropdown-item-hover-background, --neutral-fill-stealth-hover); + --neutral-fill-secondary-rest: var(--dropdown-item-selected-background, --neutral-fill-secondary-rest); + --neutral-fill-stealth-rest: var(--dropdown-background-color, --neutral-fill-stealth-rest); +} - .down-chevron, - .up-chevron { - position: absolute; - right: 10px; - top: 8px; - color: $placeholder__color; +:host fluent-tree-view { + min-width: 100%; +} - &:hover { - color: $color; - } +:host fluent-breadcrumb-item { + .team-parent-name { + font-weight: bold; } .team-photo { width: 24px; @@ -159,86 +97,19 @@ border-radius: 50%; margin: 0px 6px; } + .arrow { + margin-left: 8px; + margin-right: 8px; - .dropdown { - z-index: 1; /* Sit on top */ - display: none; - margin-top: 4px; - - &.visible { - display: inherit; - --card-height: auto; - } - - .channel-display { - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; - user-select: none; - -o-user-select: none; - cursor: pointer; - padding-left: 21px; - padding-right: 10px; - - .showing { - padding-left: 10px; - padding-top: 4px; - padding-bottom: 4px; - .channel-name-text { - font-size: 14px; - font-weight: normal; - color: $color; - margin: 0; - padding: 0; - - &.highlight-search-text { - font-weight: bold; - } - } - } - - &:hover { - background-color: $dropdown-item__background-color--hover; - } - } - - .search-error-text, - .loading-text { - font-family: $font-family; - font-style: normal; - font-weight: 600; - font-size: 14px; - color: $gray120; - line-height: 19px; - text-align: center; - } - - .message-parent { - display: -webkit-inline-box; - .loading-text { - margin: 8px 0px 0px 8px; - color: #0078d4; - } + svg { + stroke: var(--arrow-fill, $color); } } } [dir='rtl'] { - .search-wrapper { - margin-right: 0px !important; - } - .search-icon { - margin-left: 8px !important; - } - .channel-display { - padding: 0px 34px 0px 10px !important; - } - - .close-icon, - .down-chevron, - .up-chevron { - right: auto; - left: 10px; + :host { + --direction: rtl; } .dropdown { text-align: right; @@ -267,21 +138,17 @@ } @media (forced-colors: active) and (prefers-color-scheme: dark) { - .root { + :host fluent-text-field { svg { - fill: rgb(255, 255, 255) !important; - fill-rule: nonzero !important; - clip-rule: nonzero !important; + stroke: rgb(255, 255, 255) !important; } } } @media (forced-colors: active) and (prefers-color-scheme: light) { - .root { + :host fluent-text-field { svg { - fill: rgb(0, 0, 0) !important; - fill-rule: nonzero !important; - clip-rule: nonzero !important; + stroke: rgb(0, 0, 0) !important; } } } diff --git a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts index e93ad9765e..6ef45081a4 100644 --- a/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts +++ b/packages/mgt-components/src/components/mgt-teams-channel-picker/mgt-teams-channel-picker.ts @@ -7,7 +7,7 @@ import * as MicrosoftGraph from '@microsoft/microsoft-graph-types'; import { html, TemplateResult } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; +import { customElement, state } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; import { Providers, ProviderState, MgtTemplatedComponent, BetaGraph } from '@microsoft/mgt-element'; import '../../styles/style-helper'; @@ -19,8 +19,23 @@ import { getAllMyTeams, getTeamsPhotosforPhotoIds } from './mgt-teams-channel-pi import { strings } from './strings'; import { repeat } from 'lit/directives/repeat.js'; import { registerFluentComponents } from '../../utils/FluentComponents'; -import { fluentTreeView, fluentTreeItem, fluentCard } from '@fluentui/web-components'; -registerFluentComponents(fluentCard, fluentTreeView, fluentTreeItem); +import { + fluentBreadcrumb, + fluentBreadcrumbItem, + fluentTreeView, + fluentTreeItem, + fluentCard, + fluentTextField +} from '@fluentui/web-components'; + +registerFluentComponents( + fluentBreadcrumb, + fluentBreadcrumbItem, + fluentCard, + fluentTreeView, + fluentTreeItem, + fluentTextField +); /** * Team with displayName @@ -239,29 +254,28 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { } // User input in search - private get _input(): HTMLElement { - return this.renderRoot.querySelector('.team-chosen-input'); + private get _input(): HTMLInputElement { + const wrapper = this.renderRoot.querySelector('fluent-text-field'); + const input = wrapper.shadowRoot.querySelector('input'); + return input; } private _inputValue: string = ''; - private _isFocused = false; - private _selectedItemState: ChannelPickerItemState; private _items: DropdownItem[]; private _treeViewState: ChannelPickerItemState[] = []; // focus state private _focusList: ChannelPickerItemState[] = []; - private _focusedIndex: number = -1; private debouncedSearch; // determines loading state - @property({ attribute: false }) private _isDropdownVisible; + @state() private _isDropdownVisible: boolean; + @state() private _isFocused: boolean; constructor() { super(); this.handleWindowClick = this.handleWindowClick.bind(this); - this.addEventListener('keydown', e => this.onUserKeyDown(e)); this.addEventListener('focus', _ => this.loadTeamsIfNotLoaded()); this.addEventListener('mouseover', _ => this.loadTeamsIfNotLoaded()); this.clearState(); @@ -326,38 +340,32 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { * @memberof MgtTeamsChannelPicker */ public render() { - const inputClasses = { - focused: this._isFocused, - 'input-wrapper': true - }; - - const iconClasses = { - focused: this._isFocused && !!this._selectedItemState, - 'search-icon': true - }; - const dropdownClasses = { dropdown: true, visible: this._isDropdownVisible }; - const searchClasses = { - 'hide-icon': !!this._selectedItemState, - 'search-wrapper': true - }; - return ( this.renderTemplate('default', { teams: this.items }) || html` -
    -
    - ${this.renderSelected()} -
    ${this.renderSearchIcon()} ${this.renderInput()}
    -
    - ${this.renderChevrons()}${this.renderCloseButton()} - ${this.renderDropdown()} -
    - ` +
    + this.onUserKeyDown(e, null)} + @keyup=${(e: KeyboardEvent) => this.handleInputChanged(e)}> +
    ${this.renderSelected()}
    +
    ${this.renderChevrons()}${this.renderCloseButton()}
    +
    + + ${this.renderDropdown()} + +
    ` ); } @@ -370,24 +378,25 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { */ protected renderSelected() { if (!this._selectedItemState) { - return html``; + return this.renderSearchIcon(); } let icon: TemplateResult; if (this._selectedItemState.parent.channels) { icon = html`${this._selectedItemState.parent.item.displayName}`; + src=${this.teamsPhotos[this._selectedItemState.parent.item.id]?.photo} />`; } + return html` -
  • - ${icon} -
    ${this._selectedItemState.parent.item.displayName}
    -
    ${getSvg(SvgIcon.TeamSeparator, '#000000')}
    - ${this._selectedItemState.item.displayName} -
    ${this.renderSearchIcon()} ${this.renderInput()}
    -
  • - `; + + + ${icon} + ${this._selectedItemState.parent.item.displayName} + ${getSvg(SvgIcon.TeamSeparator, '#000000')} + + ${this._selectedItemState.item.displayName} + `; } /** @@ -401,6 +410,7 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { this._inputValue = ''; this._treeViewState = []; this._focusList = []; + this._isDropdownVisible = false; } /** @@ -418,36 +428,6 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { `; } - /** - * Renders input field - * - * @protected - * @returns - * @memberof MgtTeamsChannelPicker - */ - protected renderInput() { - const rootClasses = { - 'input-search': !!this._selectedItemState, - 'input-search-start': !this._selectedItemState - }; - - return html` -
    - this.handleInputChanged(e)} - contenteditable - > -
    - `; - } - /** * Renders close button * @@ -457,7 +437,10 @@ export class MgtTeamsChannelPicker extends MgtTemplatedComponent { */ protected renderCloseButton() { return html` -