Skip to content

Commit

Permalink
fix(Select): panel now positioned correctly on the x axis
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamincharity committed Feb 14, 2019
1 parent cffa931 commit 69e5f05
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 67 deletions.
41 changes: 32 additions & 9 deletions demo/app/components/select/select.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ <h3 tsCardTitle tsVerticalSpacing="small--1">
Single Select
</h3>

<h5 tsVerticalSpacing>With custom trigger and option template</h5>
<h5 tsVerticalSpacing>With custom trigger</h5>

<ts-select
label="Single select"
Expand All @@ -77,14 +77,6 @@ <h4 tsSelectOptionDisplay>None</h4>
*ngFor="let option of singleWithCustomTrigger | async"
>
{{ option.slug }}
<!--
-<ng-template let-option>
- <div class="myClass">
- <h4 tsSelectOptionDisplay>{{ option?.foo }}</h4>
- <small>{{ option?.slug }}</small>
- </div>
-</ng-template>
-->
</ts-select-option>
</ts-select>

Expand Down Expand Up @@ -169,6 +161,37 @@ <h3 tsCardTitle tsVerticalSpacing="small--1">
</ts-card>


<ts-card tsVerticalSpacing fxFlex>
<h3 tsCardTitle tsVerticalSpacing>
Multiple
</h3>

<ts-select
label="Multiple select"
[allowMultiple]="true"
hint="Select one or more options"
[formControl]="myForm.get('myChoices3')"
(opened)="panelChange(true)"
(closed)="panelChange(false)"
(selectionChange)="isChanged($event)"
tsVerticalSpacing
>
<ts-select-option
[value]="option.slug"
[option]="option"
[isDisabled]="option?.disabled"
*ngFor="let option of singleWithCustomTrigger | async"
>
{{ option.slug }}
</ts-select-option>
</ts-select>

<div>
FormControl value: {{ myForm.get('myChoices3')?.value | json }}
</div>
</ts-card>


<ts-card tsVerticalSpacing fxFlex>
<h3 tsCardTitle tsVerticalSpacing>
Multiple w/Optgroups
Expand Down
2 changes: 2 additions & 0 deletions terminus-ui/select/src/optgroup/optgroup.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
// An optgroup for a select menu
//
.ts-optgroup {
display: block;

&.ts-optgroup--disabled {
color: color(utility, dark);
}
Expand Down
2 changes: 2 additions & 0 deletions terminus-ui/select/src/option/option.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
@import './../../../scss/helpers/shadows';
@import './../../../scss/helpers/cursors';
@import './../../../scss/helpers/spacing';
@import './../../../scss/helpers/z-index';


// FIXME: Remove custom color once our palette supports a color for this use-case.
Expand Down Expand Up @@ -52,6 +53,7 @@ $ts-select-item-height: 3em !default;
.ts-select-panel {
@include elevation-element(menu);
background: color(pure);
z-index: z(menu);

.ts-optgroup-label,
.ts-select-option:not(.ts-select-option--template) {
Expand Down
4 changes: 2 additions & 2 deletions terminus-ui/select/src/select-animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ export const tsSelectAnimations: {
})),
state('showing', style({
opacity: 1,
minWidth: 'calc(100% + 32px)', // 32px = 2 * 16px padding
minWidth: 'calc(100% + 32px)',
transform: 'scaleY(1)',
})),
state('showing-multiple', style({
opacity: 1,
minWidth: 'calc(100% + 64px)', // 64px = 48px padding on the left + 16px padding on the right
minWidth: 'calc(100% + 24px)',
transform: 'scaleY(1)',
})),
transition('void => *', animate('120ms cubic-bezier(0, 0, 0.2, 1)')),
Expand Down
7 changes: 4 additions & 3 deletions terminus-ui/select/src/select.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
[hideRequiredMarker]="hideRequiredMarker"
[hint]="hint"
[id]="id"
cdk-overlay-origin
#origin="cdkOverlayOrigin"
#field
>
<ts-label *ngIf="label">
{{ label }}
Expand All @@ -17,10 +20,8 @@
[class.ts-select-trigger--hidden]="autocomplete"
[attr.id]="autocomplete ? '' : id"
[attr.tabindex]="tabIndex"
cdk-overlay-origin
aria-hidden="true"
(click)="toggle()"
#origin="cdkOverlayOrigin"
#trigger
>
<div class="ts-select-value" [ngSwitch]="empty">
Expand Down Expand Up @@ -116,13 +117,13 @@
cdkConnectedOverlayLockPosition
cdkConnectedOverlayHasBackdrop
cdkConnectedOverlayBackdropClass="cdk-overlay-transparent-backdrop"
cdkConnectedOverlayOffsetX="0"
[cdkConnectedOverlayViewportMargin]="viewportMarginSpacing"
[cdkConnectedOverlayOrigin]="origin"
[cdkConnectedOverlayOpen]="panelOpen"
[cdkConnectedOverlayPositions]="positions"
[cdkConnectedOverlayMinWidth]="triggerRect?.width"
[cdkConnectedOverlayWidth]="triggerRect?.width"
[cdkConnectedOverlayOffsetX]="0"
[cdkConnectedOverlayOffsetY]="offsetY"
(backdropClick)="close()"
(attach)="onAttached()"
Expand Down
55 changes: 2 additions & 53 deletions terminus-ui/select/src/select.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ let nextUniqueId = 0;
'[class.ts-select--autocomplete]': '!!autocomplete',
'[attr.aria-owns]': 'panelOpen ? optionIds : null',
'[attr.aria-required]': 'isRequired.toString()',
'[attr.aria-multiselectable]': 'allowMultiple',
'[attr.tabindex]': 'tabIndex',
'(keydown)': 'handleKeydown($event)',
},
Expand Down Expand Up @@ -1234,7 +1235,6 @@ export class TsSelectComponent implements
public onAttached(): void {
this.overlayDir.positionChange.pipe(take(1)).subscribe(() => {
this.changeDetectorRef.detectChanges();
this.calculateOverlayOffsetX();
this.setPanelScrollTop(this.scrollTop);
});
}
Expand Down Expand Up @@ -1681,58 +1681,7 @@ export class TsSelectComponent implements


/**
* Set the x-offset of the overlay panel in relation to the trigger's top start corner.
*
* This must be adjusted to align the selected option text over the trigger text when the panel opens. Note that the offset can't be
* calculated until the panel has been attached, because we need to know the content width in order to constrain the panel within the
* viewport.
*/
private calculateOverlayOffsetX(): void {
const overlayRect = this.overlayDir.overlayRef.overlayElement.getBoundingClientRect();
const viewportSize = this.viewportRuler.getViewportSize();
// NOTE: Currently we only support ltr
const isRtl = false;
const paddingWidth = this.allowMultiple ? SELECT_MULTIPLE_PANEL_PADDING_X + SELECT_PANEL_PADDING_X : SELECT_PANEL_PADDING_X * 2;
let offsetX: number;

// Adjust the offset, depending on the option padding.
if (this.allowMultiple) {
offsetX = SELECT_MULTIPLE_PANEL_PADDING_X;
} else {
const selected = this.selectionModel.selected[0] || this.options.first;
offsetX = selected && selected.group ? SELECT_PANEL_INDENT_PADDING_X : SELECT_PANEL_PADDING_X;
}

// Invert the offset in LTR.
// istanbul ignore else
if (!isRtl) {
offsetX *= -1;
}

// Determine how much the select overflows on each side.
const leftOverflow =
0 - (overlayRect.left + offsetX - (!isRtl ? 0 /* istanbul ignore next - Unreachable */ : paddingWidth));
const rightOverflow
= overlayRect.right + offsetX - viewportSize.width + (!isRtl ? paddingWidth /* istanbul ignore next - Unreachable */ : 0);

// If the element overflows on either side, reduce the offset to allow it to fit.
if (leftOverflow > 0) {
offsetX += leftOverflow + SELECT_PANEL_VIEWPORT_PADDING;
} else if (rightOverflow > 0) {
offsetX -= rightOverflow + SELECT_PANEL_VIEWPORT_PADDING;
}

// Set the offset directly in order to avoid having to go through change detection and
// potentially triggering "changed after it was checked" errors. Round the value to avoid
// blurry content in some browsers.
this.overlayDir.offsetX = Math.round(offsetX);
this.overlayDir.overlayRef.updatePosition();
}


/**
* Calculate the y-offset of the select's overlay panel in relation to the top start corner of the trigger.
*
* Calculates the y-offset of the select's overlay panel in relation to the top start corner of the trigger.
* It has to be adjusted in order for the selected option to be aligned over the trigger when the panel opens.
*
* @param selectedIndex - The index of the selected item
Expand Down

0 comments on commit 69e5f05

Please sign in to comment.