From ff0aac345cce7c58bebd1b49386c2216929158ba Mon Sep 17 00:00:00 2001 From: danielwiehl Date: Wed, 13 Jan 2021 16:59:12 +0100 Subject: [PATCH] =?UTF-8?q?fix(=C9=B5toolkit/accordion):=20remove=20viewpo?= =?UTF-8?q?rt=20from=20accordion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It turned out to be impractical to put the accordion in a viewport by default. Instead, it should be left to the developer to decide. Perhaps, if at all, only certain accordion item need to be displayed in a viewport. --- .../src/accordion/accordion.component.html | 51 ++++++++---------- .../src/accordion/accordion.component.scss | 44 ++++++++-------- .../src/accordion/accordion.component.ts | 52 ++++++++++++++++--- .../widgets/src/accordion/accordion.module.ts | 2 - 4 files changed, 87 insertions(+), 62 deletions(-) diff --git a/projects/scion/toolkit.internal/widgets/src/accordion/accordion.component.html b/projects/scion/toolkit.internal/widgets/src/accordion/accordion.component.html index ff6acc98..813e17c7 100644 --- a/projects/scion/toolkit.internal/widgets/src/accordion/accordion.component.html +++ b/projects/scion/toolkit.internal/widgets/src/accordion/accordion.component.html @@ -1,29 +1,22 @@ - -
-
-
-
-
- -
- -
-
- -
-
-
-
-
+
+
+
+
+ +
+ +
+
+ +
+
+
diff --git a/projects/scion/toolkit.internal/widgets/src/accordion/accordion.component.scss b/projects/scion/toolkit.internal/widgets/src/accordion/accordion.component.scss index 02cfeefe..1c58007a 100644 --- a/projects/scion/toolkit.internal/widgets/src/accordion/accordion.component.scss +++ b/projects/scion/toolkit.internal/widgets/src/accordion/accordion.component.scss @@ -3,36 +3,34 @@ $border-color: var(--sci-color-P400); $background-color: var(--sci-color-P100); :host { - display: grid; + display: block; border: 1px solid var(--sci-color-P400); border-radius: 5px; - > sci-viewport div.accordion-client { - // Collapse bottom borders: Render a bottom border only if the accordion items do not fill available space - &:not(.filled) > section.accordion-item:last-child { - border-bottom: 1px solid var(--sci-color-P400); - } + // Collapse bottom borders: Render a bottom border only if the accordion items do not fill available space + &:not(.filled) section.accordion-item:last-child { + border-bottom: 1px solid var(--sci-color-P400); + } - > section.accordion-item { - padding: 1em; + section.accordion-item { + padding: 1em; - &:not(:first-child) { - border-top: 1px solid var(--sci-color-P400); - } + &:not(:first-child) { + border-top: 1px solid var(--sci-color-P400); + } - > header { - display: flex; - justify-content: space-between; - align-items: center; - cursor: pointer; - user-select: none; - } + > header { + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + user-select: none; + } - > section { - display: grid; // public API - grid-template-columns: 100%; - gap: .5em; - } + > section { + display: grid; // public API + grid-template-columns: 100%; + gap: .5em; } } diff --git a/projects/scion/toolkit.internal/widgets/src/accordion/accordion.component.ts b/projects/scion/toolkit.internal/widgets/src/accordion/accordion.component.ts index 69919b1a..d031033b 100644 --- a/projects/scion/toolkit.internal/widgets/src/accordion/accordion.component.ts +++ b/projects/scion/toolkit.internal/widgets/src/accordion/accordion.component.ts @@ -8,11 +8,13 @@ * SPDX-License-Identifier: EPL-2.0 */ -import { Component, ContentChildren, HostBinding, Input, QueryList, TrackByFunction, ViewChild } from '@angular/core'; +import { Component, ContentChildren, ElementRef, HostBinding, Input, OnDestroy, OnInit, QueryList, TrackByFunction, ViewChild } from '@angular/core'; import { animate, AnimationMetadata, style, transition, trigger } from '@angular/animations'; import { SciAccordionItemDirective } from './accordion-item.directive'; -import { SciViewportComponent } from '@scion/toolkit/viewport'; -import { CdkAccordionItem } from '@angular/cdk/accordion'; +import { CdkAccordion, CdkAccordionItem } from '@angular/cdk/accordion'; +import { fromDimension$ } from '@scion/toolkit/observable'; +import { debounceTime, takeUntil } from 'rxjs/operators'; +import { combineLatest, Subject } from 'rxjs'; /** * Component that shows items in an accordion. @@ -47,7 +49,12 @@ import { CdkAccordionItem } from '@angular/cdk/accordion'; trigger('enter', SciAccordionComponent.provideEnterAnimation()), ], }) -export class SciAccordionComponent { +export class SciAccordionComponent implements OnInit, OnDestroy { + + private _destroy$ = new Subject(); + + @ViewChild(CdkAccordion, {static: true, read: ElementRef}) + private _cdkAccordion: ElementRef; @HostBinding('class.bubble') public get isBubbleVariant(): boolean { @@ -59,8 +66,8 @@ export class SciAccordionComponent { return this.variant === 'solid'; } - @ViewChild(SciViewportComponent, {static: true}) - private _viewport: SciViewportComponent; + @HostBinding('class.filled') + public filled: boolean; @ContentChildren(SciAccordionItemDirective) public items: QueryList; @@ -77,13 +84,42 @@ export class SciAccordionComponent { @Input() public variant: 'solid' | 'bubble' = 'bubble'; + constructor(private _host: ElementRef) { + } + + public ngOnInit(): void { + this.computeFilledStateOnDimensionChange(); + } + public trackByFn: TrackByFunction = (index: number, item: SciAccordionItemDirective): any => { return item.key || item; }; - public onToggle(item: CdkAccordionItem, section: HTMLElement): void { + public onToggle(item: CdkAccordionItem): void { item.toggle(); - item.expanded && setTimeout(() => this._viewport.scrollIntoView(section)); + } + + /** + * Computes whether this accordion fills the boundaries of this component. + * It does this on each dimension change and sets the CSS class 'filled' + * accordingly. + */ + private computeFilledStateOnDimensionChange(): void { + combineLatest([ + fromDimension$(this._host.nativeElement), + fromDimension$(this._cdkAccordion.nativeElement), + ]) + .pipe( + debounceTime(5), // debounce dimension changes because the animation for expanding/collapsing a panel continuously emits resize events. + takeUntil(this._destroy$), + ) + .subscribe(([hostDimension, accordionDimension]) => { + this.filled = (hostDimension.clientHeight <= accordionDimension.offsetHeight); + }); + } + + public ngOnDestroy(): void { + this._destroy$.next(); } /** diff --git a/projects/scion/toolkit.internal/widgets/src/accordion/accordion.module.ts b/projects/scion/toolkit.internal/widgets/src/accordion/accordion.module.ts index c2194553..4e6d719e 100644 --- a/projects/scion/toolkit.internal/widgets/src/accordion/accordion.module.ts +++ b/projects/scion/toolkit.internal/widgets/src/accordion/accordion.module.ts @@ -10,7 +10,6 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { SciViewportModule } from '@scion/toolkit/viewport'; import { SciAccordionComponent } from './accordion.component'; import { SciAccordionItemDirective } from './accordion-item.directive'; import { CdkAccordionModule } from '@angular/cdk/accordion'; @@ -26,7 +25,6 @@ import { SciDimensionModule } from '@scion/toolkit/dimension'; ], imports: [ CommonModule, - SciViewportModule, CdkAccordionModule, SciDimensionModule, ],