Skip to content

Commit e7a5f34

Browse files
authored
Merge pull request #487 from microsoftgraph/nivogt/people-picker-flyout
people-picker behavior on focus and selection
2 parents cb5ddd3 + 4bc24ba commit e7a5f34

File tree

2 files changed

+46
-29
lines changed

2 files changed

+46
-29
lines changed

src/components/mgt-people-picker/mgt-people-picker.scss

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ mgt-people-picker .flyout-root {
7777

7878
:host .people-selected-input,
7979
mgt-people-picker .people-selected-input {
80+
box-sizing: border-box;
81+
width: 100%;
82+
display: flex;
83+
flex: 1 0 auto;
8084
font-family: var(--default-font-family, 'Segoe UI');
8185
position: relative;
8286
border: none;
@@ -98,6 +102,7 @@ mgt-people-picker .people-selected-input {
98102

99103
:host .people-selected-list,
100104
mgt-people-picker .people-selected-list {
105+
flex: 1 0 auto;
101106
display: flex;
102107
flex-wrap: wrap;
103108
vertical-align: middle;
@@ -219,6 +224,7 @@ mgt-people-picker .input-search.input-search--start {
219224
:host .people-picker-input,
220225
mgt-people-picker .people-picker-input {
221226
display: flex;
227+
flex-wrap: wrap;
222228
order: 2;
223229
background-color: $input-background-color;
224230
margin: $avatar-margin;
@@ -347,3 +353,7 @@ mgt-people-picker .people-person-text-area {
347353
overflow: hidden;
348354
color: $font-color;
349355
}
356+
357+
mgt-flyout {
358+
flex: 1 0 auto;
359+
}

src/components/mgt-people-picker/mgt-people-picker.ts

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
266266
// List of people requested if group property is provided
267267
private _groupPeople: IDynamicPerson[];
268268
private _debouncedSearch: { (): void; (): void };
269+
269270
@internalProperty() private _isFocused = false;
270271

271272
@internalProperty() private _foundPeople: IDynamicPerson[];
@@ -302,23 +303,8 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
302303
if (!peopleInput) {
303304
return;
304305
}
305-
306306
peopleInput.focus(options);
307307
peopleInput.select();
308-
309-
// handles hiding control if default people have no more selections available
310-
const peopleLeft = this.filterPeople(this.defaultPeople);
311-
let shouldShow = true;
312-
if (peopleLeft && peopleLeft.length === 0) {
313-
shouldShow = false;
314-
}
315-
316-
if (shouldShow) {
317-
window.requestAnimationFrame(() => {
318-
// Mouse is focused on input
319-
this.showFlyout();
320-
});
321-
}
322308
}
323309

324310
/**
@@ -364,11 +350,9 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
364350
'people-picker': true
365351
};
366352
return html`
367-
<div class=${classMap(inputClasses)} @click=${() => this.focus()}>
368-
<div class="people-picker-input">
369-
<div class="people-selected-list">
370-
${selectedPeopleTemplate} ${flyoutTemplate}
371-
</div>
353+
<div class=${classMap(inputClasses)} @click=${e => this.focus(e)}>
354+
<div class="people-selected-list">
355+
${selectedPeopleTemplate} ${flyoutTemplate}
372356
</div>
373357
</div>
374358
`;
@@ -429,6 +413,7 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
429413
@keydown="${this.onUserKeyDown}"
430414
@keyup="${this.onUserKeyUp}"
431415
@blur=${this.lostFocus}
416+
@click=${this.handleFlyout}
432417
/>
433418
</div>
434419
`;
@@ -454,14 +439,14 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
454439
<div class="people-person">
455440
${this.renderTemplate('selected-person', { person }, `selected-${person.id}`) ||
456441
this.renderSelectedPerson(person)}
442+
457443
<div class="overflow-gradient"></div>
458-
<div class="CloseIcon" @click="${() => this.removePerson(person)}">\uE711</div>
444+
<div class="CloseIcon" @click="${e => this.removePerson(person, e)}">\uE711</div>
459445
</div>
460446
`
461447
)}
462448
`;
463449
}
464-
465450
/**
466451
* Render the flyout chrome.
467452
*
@@ -575,7 +560,7 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
575560
'list-person': true
576561
};
577562
return html`
578-
<li class="${classMap(listPersonClasses)}" @click="${() => this.onPersonClick(person)}">
563+
<li class="${classMap(listPersonClasses)}" @click="${e => this.onPersonClick(person)}">
579564
${this.renderPersonResult(person)}
580565
</li>
581566
`;
@@ -667,8 +652,8 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
667652
}
668653
this.defaultPeople = people;
669654
}
670-
this._showLoading = false;
671655
}
656+
this._showLoading = false;
672657

673658
if (this.defaultSelectedUserIds && !this.selectedPeople.length) {
674659
const defaultSelectedUsers = await getUsersForUserIds(graph, this.defaultSelectedUserIds);
@@ -760,7 +745,8 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
760745
* Removes person from selected people
761746
* @param person - person and details pertaining to user selected
762747
*/
763-
protected removePerson(person: IDynamicPerson): void {
748+
protected removePerson(person: IDynamicPerson, e: MouseEvent): void {
749+
e.stopPropagation();
764750
const filteredPersonArr = this.selectedPeople.filter(p => {
765751
return p.id !== person.id;
766752
});
@@ -794,6 +780,22 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
794780
}
795781
}
796782

783+
private handleFlyout() {
784+
// handles hiding control if default people have no more selections available
785+
const peopleLeft = this.filterPeople(this.defaultPeople);
786+
let shouldShow = true;
787+
if (peopleLeft && peopleLeft.length === 0) {
788+
shouldShow = false;
789+
}
790+
791+
if (shouldShow) {
792+
window.requestAnimationFrame(() => {
793+
// Mouse is focused on input
794+
this.showFlyout();
795+
});
796+
}
797+
}
798+
797799
private gainedFocus() {
798800
this._isFocused = true;
799801
const input = this.renderRoot.querySelector('.people-selected-input') as HTMLInputElement;
@@ -869,9 +871,7 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
869871
// remove last person in selected list
870872
this.selectedPeople = this.selectedPeople.splice(0, this.selectedPeople.length - 1);
871873
this.loadState();
872-
// reset flyout position
873874
this.hideFlyout();
874-
this.showFlyout();
875875
// fire selected people changed event
876876
this.fireCustomEvent('selectionChanged', this.selectedPeople);
877877
return;
@@ -883,10 +883,17 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
883883
private onPersonClick(person: IDynamicPerson): void {
884884
this.addPerson(person);
885885
this.hideFlyout();
886+
887+
const peopleInput = this.renderRoot.querySelector('.people-selected-input') as HTMLInputElement;
888+
if (!peopleInput) {
889+
return;
890+
}
891+
peopleInput.focus();
892+
this._isFocused = true;
893+
this.hideFlyout();
886894
if (this.selectionMode === 'single') {
887895
return;
888896
}
889-
this.focus();
890897
}
891898

892899
/**
@@ -895,6 +902,7 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
895902
*/
896903
private handleUserSearch(input: HTMLInputElement) {
897904
if (!this._debouncedSearch) {
905+
this._showLoading = true;
898906
this._debouncedSearch = debounce(async () => {
899907
// Wait a few milliseconds before showing the flyout.
900908
// This helps prevent loading state flickering while the user is actively changing the query.
@@ -916,7 +924,6 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
916924
}
917925

918926
if (this.userInput !== input.value) {
919-
this._showLoading = true;
920927
this.userInput = input.value;
921928
this._debouncedSearch();
922929
}

0 commit comments

Comments
 (0)