Thumbnail Dropdown Panel
The narrative dropdown feature of the Thumbnail provides help text that is easy to access, but can be hidden from view for a more compact view.
Feature: A drop-down panel to display narrative text about the metric
Requirements
- Small button at the bottom right of the thumbnail
- Change from down-chevron to up-chevron upon toggle
- No button if no narrative text
- Animated open
Implementation
Use bootstrap collapse as it is the simplest implementation of show/hide with animation.
The narrative text div:
<div [id]="'narrtext_'+measure.id" class="collapse">
The toggle button:
<a class="narrative-button" data-toggle="collapse" [attr.data-target]="'#narrtext_'+measure.id">
Note
- the use of 'attr.' prefix on data-target to prevent error "Can't bind to 'data-target' since it isn't a known property of 'a'."
- the data-target id has suffix of measure.id to give each thumbnail a unique reference.
Changing button icon
Can't use ngIf on the icons because the structural change stops collapse from working.
Does not work
<i class="fa fa-chevron-down" *ngIf="!isExpanded" aria-hidden="true"></i>
<i class="fa fa-chevron-up" *ngIf="isExpanded" aria-hidden="true"></i>
Use ngClass instead:
[ngClass] = "{ 'fa-chevron-down': !isExpanded, 'fa-chevron-up': isExpanded }";
Click event
Simplest implementation is to give the button the attribute (click)="this.isExpanded = !this.isExpanded"
.
Can also use click method with (click)="click()"
on button and method of
click() {
this.isExpanded = !this.isExpanded;
}
Can also use @HostListener decorator for more complex scenario:
@HostListener('click', ['$event'])
clickHandler(event) {
const narText = this.elementRef.nativeElement.querySelector('#narrtext_'+this.measure.id); // Ref to affected div
const isOpen = narText.classList.contains('in'); // Query class
this.isExpanded = !this.isExpanded;
return true; // chain to next handler
}
Note return true
on clickhandler() allows other click events to happen (if they exist).
Chaining isn't available with the simple declarative click event above.
Placing the button
Initially used absolute positioning and offset from the corner,
but this behaves erratically at different media settings and browsers.
a.narrative-button {
position:absolute;
bottom: 20px;
right: 20px;
cursor: pointer;
}
@media only screen and (max-width: 768px) {
a.narrative-button {
bottom: 0;
}
}
Using flexbox proves to be reliable across all screen widths and all browsers.
div.well {
justify-content: space-between;
flex-direction: column;
height: 100vh;
display: flex;
}
a.narrative-button {
justify-content: flex-end;
display: flex;
cursor: pointer;
}