Skip to content

Commit 16e9b6e

Browse files
committed
working both directions
1 parent c5e1358 commit 16e9b6e

File tree

4 files changed

+99
-107
lines changed

4 files changed

+99
-107
lines changed

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
<mgt-login></mgt-login>
3636
<mgt-person person-query="me" person-card="click"></mgt-person>
37-
<mgt-agenda></mgt-agenda>
37+
<mgt-tasks></mgt-tasks>
3838

3939
<mgt-flyout>
4040
<div>hello</div>

src/components/mgt-person/mgt-person.ts

Lines changed: 41 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ export class MgtPerson extends MgtTemplatedComponent {
117117
})
118118
public personCardInteraction: PersonCardInteraction = PersonCardInteraction.none;
119119

120-
@property({ attribute: false }) private _isPersonCardVisible: boolean = false;
121-
@property({ attribute: false }) private _personCardShouldRender: boolean = false;
120+
@property({ attribute: false }) private isPersonCardVisible: boolean = false;
121+
@property({ attribute: false }) private personCardShouldRender: boolean = false;
122122

123123
private _mouseLeaveTimeout;
124124
private _mouseEnterTimeout;
@@ -171,40 +171,16 @@ export class MgtPerson extends MgtTemplatedComponent {
171171
</div>
172172
`;
173173

174-
const image = this.getImage();
175-
176174
return html`
177175
<div
178176
class="root"
179-
@mouseenter=${this._handleMouseEnter}
180-
@mouseleave=${this._handleMouseLeave}
181-
@click=${this._handleMouseClick}
177+
@mouseenter=${this.handleMouseEnter}
178+
@mouseleave=${this.handleMouseLeave}
179+
@click=${this.handleMouseClick}
182180
>
183181
${this.renderFlyout(person)}
184182
</div>
185183
`;
186-
187-
// ${person} ${this.renderPersonCard()}
188-
}
189-
190-
public renderFlyout(anchor: TemplateResult) {
191-
if (this.personCardInteraction === PersonCardInteraction.none) {
192-
return anchor;
193-
}
194-
195-
const image = this.getImage();
196-
197-
return html`
198-
<mgt-flyout .isOpen=${this._isPersonCardVisible}>
199-
${anchor}
200-
<div slot="flyout" class="flyout">
201-
${this.renderTemplate('person-card', { person: this.personDetails, personImage: image }) ||
202-
html`
203-
<mgt-person-card .personDetails=${this.personDetails} .personImage=${image}> </mgt-person-card>
204-
`}
205-
</div>
206-
</mgt-flyout>
207-
`;
208184
}
209185

210186
/**
@@ -219,6 +195,9 @@ export class MgtPerson extends MgtTemplatedComponent {
219195
protected updated(changedProps: PropertyValues) {
220196
super.updated(changedProps);
221197

198+
const flyout = this.renderRoot.querySelector('.flyout') as HTMLElement;
199+
// const rect = flyout.getBoundingClientRect();
200+
222201
const initials = this.renderRoot.querySelector('.initials-text') as HTMLElement;
223202
if (initials && initials.parentNode && (initials.parentNode as HTMLElement).getBoundingClientRect) {
224203
const parent = initials.parentNode as HTMLElement;
@@ -310,39 +289,39 @@ export class MgtPerson extends MgtTemplatedComponent {
310289
this.requestUpdate();
311290
}
312291

313-
private _handleMouseClick() {
314-
if (this.personCardInteraction === PersonCardInteraction.click && !this._isPersonCardVisible) {
315-
this._showPersonCard();
292+
private handleMouseClick() {
293+
if (this.personCardInteraction === PersonCardInteraction.click && !this.isPersonCardVisible) {
294+
this.showPersonCard();
316295
} else {
317-
this._hidePersonCard();
296+
this.hidePersonCard();
318297
}
319298
}
320299

321-
private _handleMouseEnter(e: MouseEvent) {
300+
private handleMouseEnter(e: MouseEvent) {
322301
clearTimeout(this._mouseEnterTimeout);
323302
clearTimeout(this._mouseLeaveTimeout);
324303
if (this.personCardInteraction !== PersonCardInteraction.hover) {
325304
return;
326305
}
327-
this._mouseEnterTimeout = setTimeout(this._showPersonCard.bind(this), 500);
306+
this._mouseEnterTimeout = setTimeout(this.showPersonCard.bind(this), 500);
328307
}
329308

330-
private _handleMouseLeave(e: MouseEvent) {
309+
private handleMouseLeave(e: MouseEvent) {
331310
clearTimeout(this._mouseEnterTimeout);
332311
clearTimeout(this._mouseLeaveTimeout);
333-
this._mouseLeaveTimeout = setTimeout(this._hidePersonCard.bind(this), 500);
312+
this._mouseLeaveTimeout = setTimeout(this.hidePersonCard.bind(this), 500);
334313
}
335314

336-
private _showPersonCard() {
337-
if (!this._personCardShouldRender) {
338-
this._personCardShouldRender = true;
315+
private showPersonCard() {
316+
if (!this.personCardShouldRender) {
317+
this.personCardShouldRender = true;
339318
}
340319

341-
this._isPersonCardVisible = true;
320+
this.isPersonCardVisible = true;
342321
}
343322

344-
private _hidePersonCard() {
345-
this._isPersonCardVisible = false;
323+
private hidePersonCard() {
324+
this.isPersonCardVisible = false;
346325
const personCard = (this.querySelector('mgt-person-card') ||
347326
this.renderRoot.querySelector('mgt-person-card')) as MgtPersonCard;
348327
if (personCard) {
@@ -359,53 +338,28 @@ export class MgtPerson extends MgtTemplatedComponent {
359338
return null;
360339
}
361340

362-
private renderPersonCard() {
363-
// ensure person card is only rendered when needed
364-
if (this.personCardInteraction === PersonCardInteraction.none || !this._personCardShouldRender) {
365-
return;
366-
}
367-
// logic for rendering left if there is no space
368-
const personRect = this.renderRoot.querySelector('.root').getBoundingClientRect();
369-
const leftEdge = personRect.left;
370-
const rightEdge = (window.innerWidth || document.documentElement.clientWidth) - personRect.right;
371-
// this._openLeft = rightEdge < leftEdge;
372-
373-
// logic for rendering up
374-
const bottomEdge = (window.innerHeight || document.documentElement.clientHeight) - personRect.bottom;
375-
this._openUp = bottomEdge < 175;
376-
377-
// find position to renderup to
378-
const customStyle: any = {};
379-
if (this._openUp) {
380-
const personSize = this.getBoundingClientRect().bottom - this.getBoundingClientRect().top;
381-
customStyle.bottom = `${personSize / 2 + 8}px`;
382-
}
383-
384-
// determines if there is space to render on right side
385-
if (rightEdge < 340) {
386-
customStyle.left = `${rightEdge - 350}px`;
387-
} else if (leftEdge > 20) {
388-
customStyle.left = '-20px';
341+
private renderFlyout(anchor: TemplateResult) {
342+
if (this.personCardInteraction === PersonCardInteraction.none) {
343+
return anchor;
389344
}
390345

391-
const flyoutClasses = {
392-
flyout: true,
393-
openLeft: this._openLeft,
394-
openUp: this._openUp,
395-
visible: this._isPersonCardVisible
396-
};
397-
if (this._isPersonCardVisible) {
398-
const image = this.getImage();
346+
const image = this.getImage();
347+
const flyout = this.personCardShouldRender
348+
? html`
349+
<div slot="flyout" class="flyout">
350+
${this.renderTemplate('person-card', { person: this.personDetails, personImage: image }) ||
351+
html`
352+
<mgt-person-card .personDetails=${this.personDetails} .personImage=${image}> </mgt-person-card>
353+
`}
354+
</div>
355+
`
356+
: null;
399357

400-
return html`
401-
<div style=${styleMap(customStyle)} class=${classMap(flyoutClasses)}>
402-
${this.renderTemplate('person-card', { person: this.personDetails, personImage: image }) ||
403-
html`
404-
<mgt-person-card .personDetails=${this.personDetails} .personImage=${image}> </mgt-person-card>
405-
`}
406-
</div>
407-
`;
408-
}
358+
return html`
359+
<mgt-flyout .isOpen=${this.isPersonCardVisible}>
360+
${anchor} ${flyout}
361+
</mgt-flyout>
362+
`;
409363
}
410364

411365
private renderDetails() {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.root .flyout {
2+
display: none;
3+
position: absolute;
4+
z-index: 1;
5+
opacity: 0;
6+
transition-property: opacity;
7+
transition-duration: 0.1s;
8+
}
9+
10+
.root .flyout.visible {
11+
display: inline-block;
12+
opacity: 1;
13+
&.openLeft {
14+
right: 0;
15+
}
16+
}

src/components/sub-components/mgt-flyout/mgt-flyout.ts

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -80,33 +80,55 @@ export class MgtFlyout extends LitElement {
8080
const anchor = this.renderRoot.querySelector('.anchor');
8181
const flyout = this.renderRoot.querySelector('.flyout') as HTMLElement;
8282
if (flyout && anchor) {
83-
const flyoutRect = flyout.getBoundingClientRect();
84-
const anchorRect = anchor.getBoundingClientRect();
85-
86-
const windowWidth = window.innerWidth || document.documentElement.clientWidth;
87-
const windowHeight = window.innerHeight || document.documentElement.clientHeight;
88-
8983
let left: number;
9084
let right: number;
9185
let top: number;
9286
let bottom: number;
9387

94-
if (anchorRect.width >= flyoutRect.width) {
95-
left = 0;
96-
} else {
97-
const centerOffset = flyoutRect.width / 2 - anchorRect.width / 2;
98-
99-
if (anchorRect.left - centerOffset < 0) {
100-
left = -anchorRect.left;
88+
if (this.isOpen) {
89+
const flyoutRect = flyout.getBoundingClientRect();
90+
const anchorRect = anchor.getBoundingClientRect();
91+
92+
const windowWidth =
93+
window.innerWidth && document.documentElement.clientWidth
94+
? Math.min(window.innerWidth, document.documentElement.clientWidth)
95+
: window.innerWidth || document.documentElement.clientWidth;
96+
97+
const windowHeight =
98+
window.innerHeight && document.documentElement.clientHeight
99+
? Math.min(window.innerHeight, document.documentElement.clientHeight)
100+
: window.innerHeight || document.documentElement.clientHeight;
101+
102+
if (flyoutRect.width > windowWidth) {
103+
// page width is smaller than flyout, render all the way to the left
104+
left = -flyoutRect.left;
105+
} else if (anchorRect.width >= flyoutRect.width) {
106+
// anchor is large than flyout, render aligned to anchor
107+
left = 0;
101108
} else {
102-
left = -centerOffset;
103-
} // todo check if offscreen to the right and move left
109+
const centerOffset = flyoutRect.width / 2 - anchorRect.width / 2;
110+
111+
if (flyoutRect.left - centerOffset < 0) {
112+
// centered flyout is off screen to the left, render on the left edge
113+
left = -flyoutRect.left;
114+
} else if (flyoutRect.right - centerOffset > windowWidth) {
115+
// centered flyout is off screen to the right, render on the right edge
116+
left = -(flyoutRect.right - windowWidth);
117+
} else {
118+
// render centered
119+
left = -centerOffset;
120+
}
121+
}
122+
123+
if (windowHeight < flyoutRect.bottom) {
124+
bottom = anchorRect.height;
125+
}
104126
}
105127

106-
flyout.style.left = left ? `${left}px` : '';
107-
flyout.style.right = right ? `${right}px` : '';
108-
flyout.style.top = top ? `${top}px` : '';
109-
flyout.style.bottom = bottom ? `${bottom}px` : '';
128+
flyout.style.left = typeof left !== 'undefined' ? `${left}px` : '';
129+
flyout.style.right = typeof right !== 'undefined' ? `${right}px` : '';
130+
flyout.style.top = typeof top !== 'undefined' ? `${top}px` : '';
131+
flyout.style.bottom = typeof bottom !== 'undefined' ? `${bottom}px` : '';
110132
}
111133
}
112134

0 commit comments

Comments
 (0)