forked from EVOgeek/Vmeda.Online
		
	MOBILE-3814 format-text: collapsible item directive replaces maxHeight
This commit is contained in:
		
							parent
							
								
									09cd1af733
								
							
						
					
					
						commit
						112f00bcb5
					
				| @ -8,7 +8,7 @@ | |||||||
|                     {{ 'addon.mod_assign.feedbacknotsupported' | translate }} |                     {{ 'addon.mod_assign.feedbacknotsupported' | translate }} | ||||||
|                 </ion-badge> |                 </ion-badge> | ||||||
|                 <p *ngIf="text"> |                 <p *ngIf="text"> | ||||||
|                     <core-format-text [component]="component" [componentId]="assign.cmid" [maxHeight]="120" [text]="text" |                     <core-format-text [component]="component" [componentId]="assign.cmid" [collapsible-item]="120" [text]="text" | ||||||
|                         contextLevel="module" [contextInstanceId]="assign.cmid" [courseId]="assign.course"> |                         contextLevel="module" [contextInstanceId]="assign.cmid" [courseId]="assign.course"> | ||||||
|                     </core-format-text> |                     </core-format-text> | ||||||
|                 </p> |                 </p> | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ | |||||||
|                     {{ 'addon.mod_assign.submissionnotsupported' | translate }} |                     {{ 'addon.mod_assign.submissionnotsupported' | translate }} | ||||||
|                 </ion-badge> |                 </ion-badge> | ||||||
|                 <p *ngIf="text"> |                 <p *ngIf="text"> | ||||||
|                     <core-format-text [component]="component" [componentId]="assign.cmid" [maxHeight]="120" [text]="text" |                     <core-format-text [component]="component" [componentId]="assign.cmid" [collapsible-item]="120" [text]="text" | ||||||
|                         contextLevel="module" [contextInstanceId]="assign.cmid" [courseId]="assign.course"> |                         contextLevel="module" [contextInstanceId]="assign.cmid" [courseId]="assign.course"> | ||||||
|                     </core-format-text> |                     </core-format-text> | ||||||
|                 </p> |                 </p> | ||||||
|  | |||||||
| @ -3,8 +3,8 @@ | |||||||
|     <ion-label> |     <ion-label> | ||||||
|         <h2>{{ plugin.name }}</h2> |         <h2>{{ plugin.name }}</h2> | ||||||
|         <p> |         <p> | ||||||
|             <core-format-text [component]="component" [componentId]="assign.cmid" [maxHeight]="120" [text]="text" contextLevel="module" |             <core-format-text [component]="component" [componentId]="assign.cmid" [collapsible-item]="120" [text]="text" | ||||||
|                 [contextInstanceId]="assign.cmid" [courseId]="assign.course"> |                 contextLevel="module" [contextInstanceId]="assign.cmid" [courseId]="assign.course"> | ||||||
|             </core-format-text> |             </core-format-text> | ||||||
|         </p> |         </p> | ||||||
|     </ion-label> |     </ion-label> | ||||||
|  | |||||||
| @ -4,8 +4,8 @@ | |||||||
|         <h2>{{ plugin.name }}</h2> |         <h2>{{ plugin.name }}</h2> | ||||||
|         <p *ngIf="words">{{ 'addon.mod_assign.numwords' | translate: {'$a': words} }}</p> |         <p *ngIf="words">{{ 'addon.mod_assign.numwords' | translate: {'$a': words} }}</p> | ||||||
|         <p> |         <p> | ||||||
|             <core-format-text [component]="component" [componentId]="assign.cmid" [maxHeight]="120" [text]="text" contextLevel="module" |             <core-format-text [component]="component" [componentId]="assign.cmid" [collapsible-item]="120" [text]="text" | ||||||
|                 [contextInstanceId]="assign.cmid" [courseId]="assign.course"> |                 contextLevel="module" [contextInstanceId]="assign.cmid" [courseId]="assign.course"> | ||||||
|             </core-format-text> |             </core-format-text> | ||||||
|         </p> |         </p> | ||||||
|     </ion-label> |     </ion-label> | ||||||
|  | |||||||
| @ -87,7 +87,7 @@ | |||||||
|                         <ion-label> |                         <ion-label> | ||||||
|                             <h3 class="item-heading">{{ 'addon.mod_lesson.question' | translate }}</h3> |                             <h3 class="item-heading">{{ 'addon.mod_lesson.question' | translate }}</h3> | ||||||
|                             <p> |                             <p> | ||||||
|                                 <core-format-text [component]="component" [componentId]="lesson?.coursemodule" [maxHeight]="50" |                                 <core-format-text [component]="component" [componentId]="lesson?.coursemodule" [collapsible-item]="50" | ||||||
|                                     [text]="page.contents" contextLevel="module" [contextInstanceId]="lesson?.coursemodule" |                                     [text]="page.contents" contextLevel="module" [contextInstanceId]="lesson?.coursemodule" | ||||||
|                                     [courseId]="courseId"> |                                     [courseId]="courseId"> | ||||||
|                                 </core-format-text> |                                 </core-format-text> | ||||||
|  | |||||||
| @ -58,8 +58,8 @@ | |||||||
|                 <ion-item class="ion-text-wrap"> |                 <ion-item class="ion-text-wrap"> | ||||||
|                     <ion-label> |                     <ion-label> | ||||||
|                         <h2>{{ 'addon.mod_workshop.conclusion' | translate }}</h2> |                         <h2>{{ 'addon.mod_workshop.conclusion' | translate }}</h2> | ||||||
|                         <core-format-text [maxHeight]="120" [component]="component" [componentId]="module.id" [text]="workshop!.conclusion" |                         <core-format-text [collapsible-item]="120" [component]="component" [componentId]="module.id" | ||||||
|                             contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> |                             [text]="workshop!.conclusion" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> | ||||||
|                         </core-format-text> |                         </core-format-text> | ||||||
|                     </ion-label> |                     </ion-label> | ||||||
|                 </ion-item> |                 </ion-item> | ||||||
| @ -91,8 +91,8 @@ | |||||||
|             <ion-item class="ion-text-wrap"> |             <ion-item class="ion-text-wrap"> | ||||||
|                 <ion-label> |                 <ion-label> | ||||||
|                     <h2>{{ 'addon.mod_workshop.areainstructauthors' | translate }}</h2> |                     <h2>{{ 'addon.mod_workshop.areainstructauthors' | translate }}</h2> | ||||||
|                     <core-format-text [maxHeight]="120" [component]="component" [componentId]="module.id" [text]="workshop!.instructauthors" |                     <core-format-text [collapsible-item]="120" [component]="component" [componentId]="module.id" | ||||||
|                         contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> |                         [text]="workshop!.instructauthors" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> | ||||||
|                     </core-format-text> |                     </core-format-text> | ||||||
|                 </ion-label> |                 </ion-label> | ||||||
|             </ion-item> |             </ion-item> | ||||||
| @ -141,7 +141,7 @@ | |||||||
|                 <ion-item class="ion-text-wrap"> |                 <ion-item class="ion-text-wrap"> | ||||||
|                     <ion-label> |                     <ion-label> | ||||||
|                         <h2>{{ 'addon.mod_workshop.areainstructreviewers' | translate }}</h2> |                         <h2>{{ 'addon.mod_workshop.areainstructreviewers' | translate }}</h2> | ||||||
|                         <core-format-text [maxHeight]="120" [component]="component" [componentId]="module.id" |                         <core-format-text [collapsible-item]="120" [component]="component" [componentId]="module.id" | ||||||
|                             [text]="workshop!.instructreviewers" contextLevel="module" [contextInstanceId]="module.id" |                             [text]="workshop!.instructreviewers" contextLevel="module" [contextInstanceId]="module.id" | ||||||
|                             [courseId]="courseId"> |                             [courseId]="courseId"> | ||||||
|                         </core-format-text> |                         </core-format-text> | ||||||
|  | |||||||
| @ -64,7 +64,7 @@ | |||||||
|                 <ion-item class="ion-text-wrap"> |                 <ion-item class="ion-text-wrap"> | ||||||
|                     <ion-label> |                     <ion-label> | ||||||
|                         <core-format-text [text]="notification.mobiletext | coreCreateLinks" contextLevel="system" [contextInstanceId]="0" |                         <core-format-text [text]="notification.mobiletext | coreCreateLinks" contextLevel="system" [contextInstanceId]="0" | ||||||
|                             [maxHeight]="120"> |                             [collapsible-item]="120"> | ||||||
|                         </core-format-text> |                         </core-format-text> | ||||||
|                     </ion-label> |                     </ion-label> | ||||||
|                 </ion-item> |                 </ion-item> | ||||||
|  | |||||||
| @ -46,6 +46,7 @@ export class CoreCollapsibleItemDirective implements OnInit { | |||||||
|     protected toggleExpandEnabled = false; |     protected toggleExpandEnabled = false; | ||||||
|     protected expanded = false; |     protected expanded = false; | ||||||
|     protected maxHeight = defaultMaxHeight; |     protected maxHeight = defaultMaxHeight; | ||||||
|  |     protected expandedHeight = 0; | ||||||
|     protected loadingChangedListener?: CoreEventObserver; |     protected loadingChangedListener?: CoreEventObserver; | ||||||
| 
 | 
 | ||||||
|     constructor(el: ElementRef<HTMLElement>) { |     constructor(el: ElementRef<HTMLElement>) { | ||||||
| @ -72,9 +73,10 @@ export class CoreCollapsibleItemDirective implements OnInit { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         this.element.classList.add('collapsible-item'); | ||||||
|  | 
 | ||||||
|         // Calculate the height now.
 |         // Calculate the height now.
 | ||||||
|         await this.calculateHeight(); |         await this.calculateHeight(); | ||||||
|         setTimeout(() => this.calculateHeight(), 200); // Try again, sometimes the first calculation is wrong.
 |  | ||||||
| 
 | 
 | ||||||
|         // Recalculate the height if a parent core-loading displays the content.
 |         // Recalculate the height if a parent core-loading displays the content.
 | ||||||
|         this.loadingChangedListener = |         this.loadingChangedListener = | ||||||
| @ -82,7 +84,6 @@ export class CoreCollapsibleItemDirective implements OnInit { | |||||||
|                 if (data.loaded && CoreDomUtils.closest(this.element.parentElement, '#' + data.uniqueId)) { |                 if (data.loaded && CoreDomUtils.closest(this.element.parentElement, '#' + data.uniqueId)) { | ||||||
|                     // The element is inside the loading, re-calculate the height.
 |                     // The element is inside the loading, re-calculate the height.
 | ||||||
|                     await this.calculateHeight(); |                     await this.calculateHeight(); | ||||||
|                     setTimeout(() => this.calculateHeight(), 200); |  | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|     } |     } | ||||||
| @ -93,9 +94,15 @@ export class CoreCollapsibleItemDirective implements OnInit { | |||||||
|      * @param element Element. |      * @param element Element. | ||||||
|      */ |      */ | ||||||
|     protected async waitFormatTextsRendered(element: Element): Promise<void> { |     protected async waitFormatTextsRendered(element: Element): Promise<void> { | ||||||
|         const formatTexts = Array |         let formatTextElements: HTMLElement[] = []; | ||||||
|             .from(element.querySelectorAll('core-format-text')) | 
 | ||||||
|             .map(element => CoreComponentsRegistry.resolve(element, CoreFormatTextDirective)); |         if (this.element.tagName == 'CORE-FORMAT-TEXT') { | ||||||
|  |             formatTextElements = [this.element]; | ||||||
|  |         } else { | ||||||
|  |             formatTextElements = Array.from(element.querySelectorAll('core-format-text')); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const formatTexts = formatTextElements.map(element => CoreComponentsRegistry.resolve(element, CoreFormatTextDirective)); | ||||||
| 
 | 
 | ||||||
|         await Promise.all(formatTexts.map(formatText => formatText?.rendered())); |         await Promise.all(formatTexts.map(formatText => formatText?.rendered())); | ||||||
|     } |     } | ||||||
| @ -103,22 +110,25 @@ export class CoreCollapsibleItemDirective implements OnInit { | |||||||
|     /** |     /** | ||||||
|      * Calculate the height and check if we need to display show more or not. |      * Calculate the height and check if we need to display show more or not. | ||||||
|      */ |      */ | ||||||
|     protected async calculateHeight(): Promise<void> { |     protected async calculateHeight(retries = 3): Promise<void> { | ||||||
|         await this.waitFormatTextsRendered(this.element); |  | ||||||
| 
 |  | ||||||
|         // Remove max-height (if any) to calculate the real height.
 |         // Remove max-height (if any) to calculate the real height.
 | ||||||
|         const initialMaxHeight = this.element.style.maxHeight; |         this.element.classList.add('collapsible-loading-height'); | ||||||
|         this.element.style.maxHeight = 'none'; | 
 | ||||||
|  |         await this.waitFormatTextsRendered(this.element); | ||||||
| 
 | 
 | ||||||
|         await CoreUtils.nextTick(); |         await CoreUtils.nextTick(); | ||||||
| 
 | 
 | ||||||
|         const height = CoreDomUtils.getElementHeight(this.element) || 0; |         this.expandedHeight = CoreDomUtils.getElementHeight(this.element) || 0; | ||||||
| 
 | 
 | ||||||
|         // Restore the max height now.
 |         // Restore the max height now.
 | ||||||
|         this.element.style.maxHeight = initialMaxHeight; |         this.element.classList.remove('collapsible-loading-height'); | ||||||
| 
 | 
 | ||||||
|         // If cannot calculate height, shorten always.
 |         // If cannot calculate height, shorten always.
 | ||||||
|         this.setExpandButtonEnabled(!height || height >= this.maxHeight); |         this.setExpandButtonEnabled(!this.expandedHeight || this.expandedHeight >= this.maxHeight); | ||||||
|  | 
 | ||||||
|  |         if (this.expandedHeight == 0 && retries > 0) { | ||||||
|  |             setTimeout(() => this.calculateHeight(retries - 1), 200); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -163,8 +173,11 @@ export class CoreCollapsibleItemDirective implements OnInit { | |||||||
|     protected setMaxHeight(maxHeight?: number): void { |     protected setMaxHeight(maxHeight?: number): void { | ||||||
|         if (maxHeight) { |         if (maxHeight) { | ||||||
|             this.element.style.setProperty('--max-height', maxHeight + buttonHeight + 'px'); |             this.element.style.setProperty('--max-height', maxHeight + buttonHeight + 'px'); | ||||||
|  |         } else if (this.expandedHeight) { | ||||||
|  |             this.element.style.setProperty('--max-height', this.expandedHeight + 'px'); | ||||||
|         } else { |         } else { | ||||||
|             this.element.style.removeProperty('--max-height'); |             this.element.style.removeProperty('--max-height'); | ||||||
|  | 
 | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -195,7 +208,7 @@ export class CoreCollapsibleItemDirective implements OnInit { | |||||||
|      * |      * | ||||||
|      * @param e Click event. |      * @param e Click event. | ||||||
|      */ |      */ | ||||||
|     protected elementClicked(e: MouseEvent): void { |     elementClicked(e: MouseEvent): void { | ||||||
|         if (e.defaultPrevented) { |         if (e.defaultPrevented) { | ||||||
|             // Ignore it if the event was prevented by some other listener.
 |             // Ignore it if the event was prevented by some other listener.
 | ||||||
|             return; |             return; | ||||||
|  | |||||||
| @ -22,10 +22,10 @@ import { | |||||||
|     SimpleChange, |     SimpleChange, | ||||||
|     Optional, |     Optional, | ||||||
|     ViewContainerRef, |     ViewContainerRef, | ||||||
|  |     ViewChild, | ||||||
| } from '@angular/core'; | } from '@angular/core'; | ||||||
| import { IonContent } from '@ionic/angular'; | import { IonContent } from '@ionic/angular'; | ||||||
| 
 | 
 | ||||||
| import { CoreEventLoadingChangedData, CoreEventObserver, CoreEvents } from '@singletons/events'; |  | ||||||
| import { CoreSites } from '@services/sites'; | import { CoreSites } from '@services/sites'; | ||||||
| import { CoreDomUtils } from '@services/utils/dom'; | import { CoreDomUtils } from '@services/utils/dom'; | ||||||
| import { CoreIframeUtils, CoreIframeUtilsProvider } from '@services/utils/iframe'; | import { CoreIframeUtils, CoreIframeUtilsProvider } from '@services/utils/iframe'; | ||||||
| @ -40,6 +40,7 @@ import { CoreFilterDelegate } from '@features/filter/services/filter-delegate'; | |||||||
| import { CoreFilterHelper } from '@features/filter/services/filter-helper'; | import { CoreFilterHelper } from '@features/filter/services/filter-helper'; | ||||||
| import { CoreSubscriptions } from '@singletons/subscriptions'; | import { CoreSubscriptions } from '@singletons/subscriptions'; | ||||||
| import { CoreComponentsRegistry } from '@singletons/components-registry'; | import { CoreComponentsRegistry } from '@singletons/components-registry'; | ||||||
|  | import { CoreCollapsibleItemDirective } from './collapsible-item'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Directive to format text rendered. It renders the HTML and treats all links and media, using CoreLinkDirective |  * Directive to format text rendered. It renders the HTML and treats all links and media, using CoreLinkDirective | ||||||
| @ -55,6 +56,8 @@ import { CoreComponentsRegistry } from '@singletons/components-registry'; | |||||||
| }) | }) | ||||||
| export class CoreFormatTextDirective implements OnChanges { | export class CoreFormatTextDirective implements OnChanges { | ||||||
| 
 | 
 | ||||||
|  |     @ViewChild(CoreCollapsibleItemDirective) collapsible?: CoreCollapsibleItemDirective; | ||||||
|  | 
 | ||||||
|     @Input() text?: string; // The text to format.
 |     @Input() text?: string; // The text to format.
 | ||||||
|     @Input() siteId?: string; // Site ID to use.
 |     @Input() siteId?: string; // Site ID to use.
 | ||||||
|     @Input() component?: string; // Component for CoreExternalContentDirective.
 |     @Input() component?: string; // Component for CoreExternalContentDirective.
 | ||||||
| @ -73,23 +76,18 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|     @Input() hideIfEmpty = false; // If true, the tag will contain nothing if text is empty.
 |     @Input() hideIfEmpty = false; // If true, the tag will contain nothing if text is empty.
 | ||||||
| 
 | 
 | ||||||
|     @Input() fullOnClick?: boolean | string; // @deprecated on 4.0 Won't do anything.
 |     @Input() fullOnClick?: boolean | string; // @deprecated on 4.0 Won't do anything.
 | ||||||
|     @Input() fullTitle?: string; // @deprecated on 4.0 Won't do anything..
 |     @Input() fullTitle?: string; // @deprecated on 4.0 Won't do anything.
 | ||||||
|     /** |     /** | ||||||
|      * Max height in pixels to render the content box. It should be 50 at least to make sense. |      * Max height in pixels to render the content box. It should be 50 at least to make sense. | ||||||
|      * Using this parameter will force display: block to calculate height better. |  | ||||||
|      * If you want to avoid this use class="inline" at the same time to use display: inline-block. |  | ||||||
|      */ |      */ | ||||||
|     @Input() maxHeight?: number; |     @Input() maxHeight?: number; // @deprecated on 4.0 Use collapsible-item directive instead.
 | ||||||
| 
 | 
 | ||||||
|     @Output() afterRender: EventEmitter<void>; // Called when the data is rendered.
 |     @Output() afterRender: EventEmitter<void>; // Called when the data is rendered.
 | ||||||
|     @Output() onClick: EventEmitter<void> = new EventEmitter(); // Called when clicked.
 |     @Output() onClick: EventEmitter<void> = new EventEmitter(); // Called when clicked.
 | ||||||
| 
 | 
 | ||||||
|     protected element: HTMLElement; |     protected element: HTMLElement; | ||||||
|     protected expanded = false; |  | ||||||
|     protected loadingChangedListener?: CoreEventObserver; |  | ||||||
|     protected emptyText = ''; |     protected emptyText = ''; | ||||||
|     protected contentSpan: HTMLElement; |     protected contentSpan: HTMLElement; | ||||||
|     protected toggleExpandEnabled = false; |  | ||||||
| 
 | 
 | ||||||
|     constructor( |     constructor( | ||||||
|         element: ElementRef, |         element: ElementRef, | ||||||
| @ -122,8 +120,6 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|      */ |      */ | ||||||
|     ngOnChanges(changes: { [name: string]: SimpleChange }): void { |     ngOnChanges(changes: { [name: string]: SimpleChange }): void { | ||||||
|         if (changes.text || changes.filter || changes.contextLevel || changes.contextInstanceId) { |         if (changes.text || changes.filter || changes.contextLevel || changes.contextInstanceId) { | ||||||
|             this.setExpandButtonEnabled(false); |  | ||||||
| 
 |  | ||||||
|             this.formatAndRenderContents(); |             this.formatAndRenderContents(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -269,101 +265,6 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * Calculate the height and check if we need to display show more or not. |  | ||||||
|      */ |  | ||||||
|     protected async calculateHeight(): Promise<void> { |  | ||||||
|         // @todo: Work on calculate this height better.
 |  | ||||||
|         if (!this.maxHeight) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         await this.rendered(); |  | ||||||
| 
 |  | ||||||
|         // Remove max-height (if any) to calculate the real height.
 |  | ||||||
|         const initialMaxHeight = this.element.style.maxHeight; |  | ||||||
|         this.element.style.maxHeight = 'none'; |  | ||||||
| 
 |  | ||||||
|         await CoreUtils.nextTick(); |  | ||||||
| 
 |  | ||||||
|         const height = this.getElementHeight(this.element); |  | ||||||
| 
 |  | ||||||
|         // Restore the max height now.
 |  | ||||||
|         this.element.style.maxHeight = initialMaxHeight; |  | ||||||
| 
 |  | ||||||
|         // If cannot calculate height, shorten always.
 |  | ||||||
|         this.setExpandButtonEnabled(!height || height >= this.maxHeight); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Set max height to element. |  | ||||||
|      * |  | ||||||
|      * @param maxHeight Max height if collapsed or undefined if expanded. |  | ||||||
|      */ |  | ||||||
|     protected setMaxHeight(maxHeight?: number): void { |  | ||||||
|         if (maxHeight) { |  | ||||||
|             this.element.style.setProperty('--max-height', maxHeight + 'px'); |  | ||||||
|         } else { |  | ||||||
|             this.element.style.removeProperty('--max-height'); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Sets if expand button is enabled or not. |  | ||||||
|      * |  | ||||||
|      * @param enable Wether enable or disable. |  | ||||||
|      */ |  | ||||||
|     protected setExpandButtonEnabled(enable: boolean): void { |  | ||||||
|         this.toggleExpandEnabled = enable; |  | ||||||
|         this.element.classList.toggle('collapsible-enabled', enable); |  | ||||||
| 
 |  | ||||||
|         if (!enable || this.element.querySelector('ion-button.collapsible-toggle'))  { |  | ||||||
|             this.setMaxHeight(!enable || this.expanded? undefined : this.maxHeight); |  | ||||||
| 
 |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Add expand/collapse buttons
 |  | ||||||
|         const toggleButton = document.createElement('ion-button'); |  | ||||||
|         toggleButton.classList.add('collapsible-toggle'); |  | ||||||
|         toggleButton.setAttribute('fill', 'clear'); |  | ||||||
| 
 |  | ||||||
|         const toggleText = document.createElement('span'); |  | ||||||
|         toggleText.classList.add('collapsible-toggle-text'); |  | ||||||
|         toggleText.classList.add('sr-only'); |  | ||||||
|         toggleButton.appendChild(toggleText); |  | ||||||
| 
 |  | ||||||
|         const expandArrow = document.createElement('span'); |  | ||||||
|         expandArrow.classList.add('collapsible-toggle-arrow'); |  | ||||||
|         toggleButton.appendChild(expandArrow); |  | ||||||
| 
 |  | ||||||
|         this.element.appendChild(toggleButton); |  | ||||||
| 
 |  | ||||||
|         this.toggleExpand(this.expanded); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Expand or collapse text. |  | ||||||
|      * |  | ||||||
|      * @param expand Wether expand or collapse text. If undefined, will toggle. |  | ||||||
|      */ |  | ||||||
|     protected toggleExpand(expand?: boolean): void { |  | ||||||
|         if (expand === undefined) { |  | ||||||
|             expand = !this.expanded; |  | ||||||
|         } |  | ||||||
|         this.expanded = expand; |  | ||||||
|         this.element.classList.toggle('collapsible-collapsed', !expand); |  | ||||||
|         this.setMaxHeight(!expand? this.maxHeight: undefined); |  | ||||||
| 
 |  | ||||||
|         const toggleButton = this.element.querySelector('ion-button.collapsible-toggle'); |  | ||||||
|         const toggleText = toggleButton?.querySelector('.collapsible-toggle-text'); |  | ||||||
|         if (!toggleButton || !toggleText) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         toggleText.innerHTML = expand ? Translate.instant('core.showless') : Translate.instant('core.showmore'); |  | ||||||
|         toggleButton.setAttribute('aria-expanded', expand ? 'true' : 'false'); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * Listener to call when the element is clicked. |      * Listener to call when the element is clicked. | ||||||
|      * |      * | ||||||
| @ -385,24 +286,18 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!this.toggleExpandEnabled) { |         this.collapsible?.elementClicked(e); | ||||||
|             // Nothing to do on click, just stop.
 |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         e.preventDefault(); |  | ||||||
|         e.stopPropagation(); |  | ||||||
| 
 |  | ||||||
|         this.toggleExpand(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Finish the rendering, displaying the element again and calling afterRender. |      * Finish the rendering, displaying the element again and calling afterRender. | ||||||
|      */ |      */ | ||||||
|     protected finishRender(): void { |     protected async finishRender(): Promise<void> { | ||||||
|         // Show the element again.
 |         // Show the element again.
 | ||||||
|         this.element.classList.remove('core-format-text-loading'); |         this.element.classList.remove('core-format-text-loading'); | ||||||
| 
 | 
 | ||||||
|  |         await CoreUtils.nextTick(); | ||||||
|  | 
 | ||||||
|         // Emit the afterRender output.
 |         // Emit the afterRender output.
 | ||||||
|         this.afterRender.emit(); |         this.afterRender.emit(); | ||||||
|     } |     } | ||||||
| @ -413,15 +308,12 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|     protected async formatAndRenderContents(): Promise<void> { |     protected async formatAndRenderContents(): Promise<void> { | ||||||
|         if (!this.text) { |         if (!this.text) { | ||||||
|             this.contentSpan.innerHTML = this.emptyText; // Remove current contents.
 |             this.contentSpan.innerHTML = this.emptyText; // Remove current contents.
 | ||||||
|             this.finishRender(); | 
 | ||||||
|  |             await this.finishRender(); | ||||||
| 
 | 
 | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // In AOT the inputs and ng-reflect aren't in the DOM sometimes. Add them so styles are applied.
 |  | ||||||
|         if (this.maxHeight && !this.element.getAttribute('maxHeight')) { |  | ||||||
|             this.element.setAttribute('maxHeight', String(this.maxHeight)); |  | ||||||
|         } |  | ||||||
|         if (!this.element.getAttribute('singleLine')) { |         if (!this.element.getAttribute('singleLine')) { | ||||||
|             this.element.setAttribute('singleLine', String(CoreUtils.isTrueOrOne(this.singleLine))); |             this.element.setAttribute('singleLine', String(CoreUtils.isTrueOrOne(this.singleLine))); | ||||||
|         } |         } | ||||||
| @ -434,36 +326,22 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|         this.element.classList.add('core-disable-media-adapt'); |         this.element.classList.add('core-disable-media-adapt'); | ||||||
| 
 | 
 | ||||||
|         this.contentSpan.innerHTML = ''; // Remove current contents.
 |         this.contentSpan.innerHTML = ''; // Remove current contents.
 | ||||||
|         if (this.maxHeight && result.div.innerHTML != '') { |  | ||||||
| 
 | 
 | ||||||
|         // Move the children to the current element to be able to calculate the height.
 |         // Move the children to the current element to be able to calculate the height.
 | ||||||
|         CoreDomUtils.moveChildren(result.div, this.contentSpan); |         CoreDomUtils.moveChildren(result.div, this.contentSpan); | ||||||
| 
 | 
 | ||||||
|             // Calculate the height now.
 |         await CoreUtils.nextTick(); | ||||||
|             this.calculateHeight(); | 
 | ||||||
|             setTimeout(() => this.calculateHeight(), 200); // Try again, sometimes the first calculation is wrong.
 |         // Use collapsible-item directive instead.
 | ||||||
|  |         if (this.maxHeight && !this.collapsible) { | ||||||
|  |             this.collapsible = new CoreCollapsibleItemDirective(new ElementRef(this.element)); | ||||||
|  |             this.collapsible.height = this.maxHeight; | ||||||
|  |             this.collapsible.ngOnInit(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         // Add magnifying glasses to images.
 |         // Add magnifying glasses to images.
 | ||||||
|         this.addMagnifyingGlasses(); |         this.addMagnifyingGlasses(); | ||||||
| 
 | 
 | ||||||
|             if (!this.loadingChangedListener) { |  | ||||||
|                 // Recalculate the height if a parent core-loading displays the content.
 |  | ||||||
|                 this.loadingChangedListener = |  | ||||||
|                     CoreEvents.on(CoreEvents.CORE_LOADING_CHANGED, (data: CoreEventLoadingChangedData) => { |  | ||||||
|                         if (data.loaded && CoreDomUtils.closest(this.element.parentElement, '#' + data.uniqueId)) { |  | ||||||
|                             // The format-text is inside the loading, re-calculate the height.
 |  | ||||||
|                             this.calculateHeight(); |  | ||||||
|                             setTimeout(() => this.calculateHeight(), 200); |  | ||||||
|                         } |  | ||||||
|                     }); |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             CoreDomUtils.moveChildren(result.div, this.contentSpan); |  | ||||||
| 
 |  | ||||||
|             // Add magnifying glasses to images.
 |  | ||||||
|             this.addMagnifyingGlasses(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (result.options.filter) { |         if (result.options.filter) { | ||||||
|             // Let filters handle HTML. We do it here because we don't want them to block the render of the text.
 |             // Let filters handle HTML. We do it here because we don't want them to block the render of the text.
 | ||||||
|             CoreFilterDelegate.handleHtml( |             CoreFilterDelegate.handleHtml( | ||||||
| @ -479,7 +357,7 @@ export class CoreFormatTextDirective implements OnChanges { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         this.element.classList.remove('core-disable-media-adapt'); |         this.element.classList.remove('core-disable-media-adapt'); | ||||||
|         this.finishRender(); |         await this.finishRender(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| <ion-card *ngIf="description"> | <ion-card *ngIf="description"> | ||||||
|     <ion-item class="ion-text-wrap"> |     <ion-item class="ion-text-wrap"> | ||||||
|         <ion-label> |         <ion-label> | ||||||
|             <core-format-text [text]="description" [component]="component" [componentId]="componentId" [maxHeight]="120" |             <core-format-text [text]="description" [component]="component" [componentId]="componentId" [collapsible-item]="120" | ||||||
|                 [contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId"> |                 [contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId"> | ||||||
|             </core-format-text> |             </core-format-text> | ||||||
|         </ion-label> |         </ion-label> | ||||||
|  | |||||||
| @ -46,7 +46,7 @@ | |||||||
| <ion-item class="ion-text-wrap" *ngIf="description"> | <ion-item class="ion-text-wrap" *ngIf="description"> | ||||||
|     <ion-label> |     <ion-label> | ||||||
|         <core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module" |         <core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module" | ||||||
|             [contextInstanceId]="module.id" [courseId]="courseId" [maxHeight]="expandDescription ? null : 120"> |             [contextInstanceId]="module.id" [courseId]="courseId" [collapsible-item]="expandDescription ? null : 120"> | ||||||
|         </core-format-text> |         </core-format-text> | ||||||
|     </ion-label> |     </ion-label> | ||||||
| </ion-item> | </ion-item> | ||||||
|  | |||||||
| @ -49,7 +49,7 @@ | |||||||
|                     {{ 'core.description' | translate}} |                     {{ 'core.description' | translate}} | ||||||
|                 </p> |                 </p> | ||||||
|                 <core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module" |                 <core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module" | ||||||
|                     [contextInstanceId]="module.id" [courseId]="courseId" [maxHeight]="120"> |                     [contextInstanceId]="module.id" [courseId]="courseId" [collapsible-item]="120"> | ||||||
|                 </core-format-text> |                 </core-format-text> | ||||||
|             </ion-label> |             </ion-label> | ||||||
|         </ion-item> |         </ion-item> | ||||||
| @ -169,7 +169,7 @@ | |||||||
|                             <ion-label> |                             <ion-label> | ||||||
|                                 <p class="item-heading">{{ 'core.grades.feedback' | translate}}</p> |                                 <p class="item-heading">{{ 'core.grades.feedback' | translate}}</p> | ||||||
|                                 <p> |                                 <p> | ||||||
|                                     <core-format-text [maxHeight]="120" [text]="grade.feedback" contextLevel="course" |                                     <core-format-text [collapsible-item]="120" [text]="grade.feedback" contextLevel="course" | ||||||
|                                         [contextInstanceId]="courseId"> |                                         [contextInstanceId]="courseId"> | ||||||
|                                     </core-format-text> |                                     </core-format-text> | ||||||
|                                 </p> |                                 </p> | ||||||
|  | |||||||
| @ -72,7 +72,8 @@ | |||||||
|                     <p class="item-heading"> |                     <p class="item-heading"> | ||||||
|                         {{'core.summary' | translate}} |                         {{'core.summary' | translate}} | ||||||
|                     </p> |                     </p> | ||||||
|                     <core-format-text [text]="course.summary" [maxHeight]="120" contextLevel="course" [contextInstanceId]="course.id"> |                     <core-format-text [text]="course.summary" [collapsible-item]="120" contextLevel="course" | ||||||
|  |                         [contextInstanceId]="course.id"> | ||||||
|                     </core-format-text> |                     </core-format-text> | ||||||
|                 </ion-label> |                 </ion-label> | ||||||
|             </ion-item> |             </ion-item> | ||||||
| @ -104,7 +105,7 @@ | |||||||
|                                 </core-format-text> |                                 </core-format-text> | ||||||
|                             </span><span class="core-customfieldseparator">: </span> |                             </span><span class="core-customfieldseparator">: </span> | ||||||
|                             <span class="core-customfieldvalue"> |                             <span class="core-customfieldvalue"> | ||||||
|                                 <core-format-text [text]="field.value" [maxHeight]="120" contextLevel="course" |                                 <core-format-text [text]="field.value" [collapsible-item]="120" contextLevel="course" | ||||||
|                                     [contextInstanceId]="course.id"> |                                     [contextInstanceId]="course.id"> | ||||||
|                                 </core-format-text> |                                 </core-format-text> | ||||||
|                             </span> |                             </span> | ||||||
|  | |||||||
| @ -34,7 +34,7 @@ | |||||||
|                         </core-format-text> |                         </core-format-text> | ||||||
|                     </p> |                     </p> | ||||||
|                     <p *ngIf="currentCategory.description"> |                     <p *ngIf="currentCategory.description"> | ||||||
|                         <core-format-text [text]="currentCategory.description" [maxHeight]="120" contextLevel="coursecat" |                         <core-format-text [text]="currentCategory.description" [collapsible-item]="120" contextLevel="coursecat" | ||||||
|                             [contextInstanceId]="currentCategory.id"></core-format-text> |                             [contextInstanceId]="currentCategory.id"></core-format-text> | ||||||
|                     </p> |                     </p> | ||||||
|                 </ion-label> |                 </ion-label> | ||||||
|  | |||||||
| @ -55,7 +55,7 @@ | |||||||
|                                     </td> |                                     </td> | ||||||
|                                     <td *ngIf="column.name === 'feedback' && row.feedback !== undefined" |                                     <td *ngIf="column.name === 'feedback' && row.feedback !== undefined" | ||||||
|                                         class="ion-text-start core-grades-table-feedback" [class.ion-hide-md-down]="column.hiddenPhone"> |                                         class="ion-text-start core-grades-table-feedback" [class.ion-hide-md-down]="column.hiddenPhone"> | ||||||
|                                         <core-format-text [maxHeight]="120" [text]="row.feedback" contextLevel="course" |                                         <core-format-text [collapsible-item]="120" [text]="row.feedback" contextLevel="course" | ||||||
|                                             [contextInstanceId]="courseId"> |                                             [contextInstanceId]="courseId"> | ||||||
|                                         </core-format-text> |                                         </core-format-text> | ||||||
|                                     </td> |                                     </td> | ||||||
| @ -124,7 +124,7 @@ | |||||||
|                                         <ion-label> |                                         <ion-label> | ||||||
|                                             <h2>{{ 'core.grades.feedback' | translate}}</h2> |                                             <h2>{{ 'core.grades.feedback' | translate}}</h2> | ||||||
|                                             <p> |                                             <p> | ||||||
|                                                 <core-format-text [maxHeight]="120" [text]="row.feedback" contextLevel="course" |                                                 <core-format-text [collapsible-item]="120" [text]="row.feedback" contextLevel="course" | ||||||
|                                                     [contextInstanceId]="courseId"> |                                                     [contextInstanceId]="courseId"> | ||||||
|                                                 </core-format-text> |                                                 </core-format-text> | ||||||
|                                             </p> |                                             </p> | ||||||
|  | |||||||
							
								
								
									
										82
									
								
								src/theme/components/collapsible-item.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/theme/components/collapsible-item.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | |||||||
|  | 
 | ||||||
|  | .collapsible-item { | ||||||
|  |     --display-toggle: none; | ||||||
|  |     --max-height: none; | ||||||
|  | 
 | ||||||
|  |     &.collapsible-loading-height { | ||||||
|  |         display: block !important; | ||||||
|  |         height: auto !important; | ||||||
|  |         --max-height: none !important; | ||||||
|  |         --display-toggle: none !important; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .collapsible-toggle { | ||||||
|  |         display: var(--display-toggle); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @include media-breakpoint-down(sm) { | ||||||
|  |         &.collapsible-enabled { | ||||||
|  |             position: relative; | ||||||
|  |             padding-bottom: var(--collapsible-min-button-height); // So the Show less button can fit. | ||||||
|  |             --display-toggle: block; | ||||||
|  |             @include core-transition(height max-height, 500ms); | ||||||
|  |             height: calc(var(--max-height, auto)); | ||||||
|  | 
 | ||||||
|  |             .collapsible-toggle { | ||||||
|  |                 position: absolute; | ||||||
|  |                 @include position (null, 0, 0, null); | ||||||
|  |                 text-align: center; | ||||||
|  |                 z-index: 7; | ||||||
|  |                 text-transform: none; | ||||||
|  |                 font-size: 14px; | ||||||
|  |                 font-weight: normal; | ||||||
|  |                 background-color: var(--collapsible-toggle-background); | ||||||
|  |                 color: var(--collapsible-toggle-text); | ||||||
|  |                 min-height: var(--a11y-min-target-size); | ||||||
|  |                 min-width: var(--a11y-min-target-size); | ||||||
|  |                 --border-radius: var(--huge-radius); | ||||||
|  |                 border-radius: var(--border-radius); | ||||||
|  |                 --padding-start: 0px; | ||||||
|  |                 --padding-end: 0px; | ||||||
|  |                 margin: 0px; | ||||||
|  | 
 | ||||||
|  |                 .collapsible-toggle-arrow { | ||||||
|  |                     width: var(--a11y-min-target-size); | ||||||
|  |                     height: var(--a11y-min-target-size); | ||||||
|  | 
 | ||||||
|  |                     background-position: center; | ||||||
|  |                     background-repeat: no-repeat; | ||||||
|  |                     background-size: 14px 14px; | ||||||
|  |                     transform: rotate(-90deg); | ||||||
|  | 
 | ||||||
|  |                     @include core-transition(transform, 500ms); | ||||||
|  | 
 | ||||||
|  |                     @include push-arrow-color(626262, true); | ||||||
|  | 
 | ||||||
|  |                     @include darkmode() { | ||||||
|  |                         @include push-arrow-color(ffffff, true); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             &.collapsible-collapsed { | ||||||
|  |                 overflow: hidden; | ||||||
|  |                 min-height: calc(var(--collapsible-min-button-height) + 12px); | ||||||
|  | 
 | ||||||
|  |                 .collapsible-toggle-arrow { | ||||||
|  |                     transform: rotate(90deg); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 &:before { | ||||||
|  |                     content: ''; | ||||||
|  |                     height: 100%; | ||||||
|  |                     position: absolute; | ||||||
|  |                     @include position(null, 0, 0, 0); | ||||||
|  |                     background: -webkit-linear-gradient(top, rgba(var(--background-gradient-rgb), 0) calc(100% - 56px), rgba(var(--background-gradient-rgb), 1) calc(100% - 5px)); | ||||||
|  |                     background: linear-gradient(to bottom, rgba(var(--background-gradient-rgb), 0) calc(100% - 56px), rgba(var(--background-gradient-rgb), 1) calc(100% - 5px)); | ||||||
|  |                     z-index: 6; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -48,14 +48,6 @@ core-format-text { | |||||||
|             opacity: 0; |             opacity: 0; | ||||||
|             display: inline; |             display: inline; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         .collapsible-toggle { |  | ||||||
|             display: none !important; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     .collapsible-toggle { |  | ||||||
|         display: none; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .core-format-text-content { |     .core-format-text-content { | ||||||
| @ -68,33 +60,20 @@ core-format-text { | |||||||
|         word-wrap: break-word; |         word-wrap: break-word; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     &[maxHeight], |     &.collapsible-item { | ||||||
|     &[ng-reflect-max-height] { |  | ||||||
|         display: block; |         display: block; | ||||||
|         position: relative; |  | ||||||
|         width: 100%; |  | ||||||
|         overflow: hidden; |  | ||||||
| 
 |  | ||||||
|         /* Force display inline */ |  | ||||||
|         &.inline { |  | ||||||
|             display: inline-block; |  | ||||||
|             width: auto; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // This is to allow clicks in radio/checkbox content. |         // This is to allow clicks in radio/checkbox content. | ||||||
|         &.collapsible-enabled { |  | ||||||
|         cursor: pointer; |         cursor: pointer; | ||||||
|         pointer-events: auto; |         pointer-events: auto; | ||||||
| 
 | 
 | ||||||
|             @include collapsible-item(); |         .core-format-text-content { | ||||||
|         } |             display: block; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         @if ($core-format-text-never-shorten) { |         @if ($core-format-text-never-shorten) { | ||||||
|         &[maxHeight], |             &.collapsible-enabled { | ||||||
|         &[ng-reflect-max-height] { |                 --display-toggle: none !important; | ||||||
|             &.collapsible-enabled.collapsible-expanded { |                 --max-height: none !important; | ||||||
|                 max-height: none !important; |  | ||||||
| 
 | 
 | ||||||
|                 .collapsible-toggle { |                 .collapsible-toggle { | ||||||
|                     display: none !important; |                     display: none !important; | ||||||
|  | |||||||
| @ -226,78 +226,6 @@ | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @mixin collapsible-item() { |  | ||||||
|     --display-toggle: none; |  | ||||||
|     .collapsible-toggle { |  | ||||||
|         display: var(--display-toggle); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @include media-breakpoint-down(sm) { |  | ||||||
|         &.collapsible-enabled { |  | ||||||
|             position:relative; |  | ||||||
|             padding-bottom: var(--collapsible-min-button-height); // So the Show less button can fit. |  | ||||||
|             --display-toggle: block; |  | ||||||
| 
 |  | ||||||
|             .collapsible-toggle { |  | ||||||
|                 position: absolute; |  | ||||||
|                 @include position (null, 0, 0, null); |  | ||||||
|                 text-align: center; |  | ||||||
|                 z-index: 7; |  | ||||||
|                 text-transform: none; |  | ||||||
|                 font-size: 14px; |  | ||||||
|                 font-weight: normal; |  | ||||||
|                 background-color: var(--collapsible-toggle-background); |  | ||||||
|                 color: var(--collapsible-toggle-text); |  | ||||||
|                 min-height: var(--a11y-min-target-size); |  | ||||||
|                 min-width: var(--a11y-min-target-size); |  | ||||||
|                 --border-radius: var(--huge-radius); |  | ||||||
|                 border-radius: var(--border-radius); |  | ||||||
|                 --padding-start: 0px; |  | ||||||
|                 --padding-end: 0px; |  | ||||||
|                 margin: 0px; |  | ||||||
| 
 |  | ||||||
|                 .collapsible-toggle-arrow { |  | ||||||
|                     width: var(--a11y-min-target-size); |  | ||||||
|                     height: var(--a11y-min-target-size); |  | ||||||
| 
 |  | ||||||
|                     background-position: center; |  | ||||||
|                     background-repeat: no-repeat; |  | ||||||
|                     background-size: 14px 14px; |  | ||||||
|                     transform: rotate(-90deg); |  | ||||||
| 
 |  | ||||||
|                     @include core-transition(transform, 500ms); |  | ||||||
| 
 |  | ||||||
|                     @include push-arrow-color(626262, true); |  | ||||||
| 
 |  | ||||||
|                     @include darkmode() { |  | ||||||
|                         @include push-arrow-color(ffffff, true); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             &.collapsible-collapsed { |  | ||||||
|                 overflow: hidden; |  | ||||||
|                 min-height: calc(var(--collapsible-min-button-height) + 12px); |  | ||||||
|                 max-height: calc(var(--max-height, auto)); |  | ||||||
| 
 |  | ||||||
|                 .collapsible-toggle-arrow { |  | ||||||
|                     transform: rotate(90deg); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 &:before { |  | ||||||
|                     content: ''; |  | ||||||
|                     height: 100%; |  | ||||||
|                     position: absolute; |  | ||||||
|                     @include position(null, 0, 0, 0); |  | ||||||
|                     background: -webkit-linear-gradient(top, rgba(var(--background-gradient-rgb), 0) calc(100% - 56px), rgba(var(--background-gradient-rgb), 1) calc(100% - 5px)); |  | ||||||
|                     background: linear-gradient(to bottom, rgba(var(--background-gradient-rgb), 0) calc(100% - 56px), rgba(var(--background-gradient-rgb), 1) calc(100% - 5px)); |  | ||||||
|                     z-index: 6; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Color mixins. | // Color mixins. | ||||||
| @function get_brightness($color) { | @function get_brightness($color) { | ||||||
|     @return (red($color) + green($color) + blue($color)) / 3; |     @return (red($color) + green($color) + blue($color)) / 3; | ||||||
|  | |||||||
| @ -1419,10 +1419,6 @@ ion-grid.core-no-grid > ion-row { | |||||||
|     right: 0; |     right: 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [collapsible-item] { |  | ||||||
|     @include collapsible-item(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| [collapsible-footer] { | [collapsible-footer] { | ||||||
|     &.footer-collapsed { |     &.footer-collapsed { | ||||||
|         --core-collapsible-footer-height: 0; |         --core-collapsible-footer-height: 0; | ||||||
|  | |||||||
| @ -20,6 +20,7 @@ | |||||||
| 
 | 
 | ||||||
| /* Components */ | /* Components */ | ||||||
| @import "./components/collapsible-header.scss"; | @import "./components/collapsible-header.scss"; | ||||||
|  | @import "./components/collapsible-item.scss"; | ||||||
| @import "./components/format-text.scss"; | @import "./components/format-text.scss"; | ||||||
| @import "./components/rubrics.scss"; | @import "./components/rubrics.scss"; | ||||||
| @import "./components/mod-label.scss"; | @import "./components/mod-label.scss"; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user