mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-06-23 15:30:34 -04:00
Jumpbar Tweaks (#1305)
* Adjusted the detail drawer to be slightly larger. * Attempted to shorten the jump bar on smaller screens. Robbie needs to take a look at this. * Adding plex-like styling to jumpbar * style fixes * style fixes * More fixes *sigh* * fix height issue * Fixing jumpbar on mobile * viewport height fix * added --primary-color-scrollbar for overflow across the app Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
parent
7f51ea2d0f
commit
a19f4641f4
@ -3,7 +3,7 @@
|
|||||||
<a id="content"></a>
|
<a id="content"></a>
|
||||||
<app-side-nav *ngIf="navService.sideNavVisibility$ | async as sideNavVisibile"></app-side-nav>
|
<app-side-nav *ngIf="navService.sideNavVisibility$ | async as sideNavVisibile"></app-side-nav>
|
||||||
<div class="container-fluid" [ngClass]="{'g-0': !(navService.sideNavVisibility$ | async)}">
|
<div class="container-fluid" [ngClass]="{'g-0': !(navService.sideNavVisibility$ | async)}">
|
||||||
<div style="padding: 20px 0;" *ngIf="navService.sideNavVisibility$ | async else noSideNav">
|
<div style="padding: 20px 0 0;" *ngIf="navService.sideNavVisibility$ | async else noSideNav">
|
||||||
<div class="companion-bar" [ngClass]="{'companion-bar-content': !(navService?.sideNavCollapsed$ | async)}">
|
<div class="companion-bar" [ngClass]="{'companion-bar-content': !(navService?.sideNavCollapsed$ | async)}">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,5 +12,5 @@
|
|||||||
|
|
||||||
.tab-content {
|
.tab-content {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
height: calc(40vh - 62px); // drawer height - offcanvas heading height
|
height: calc(45vh - 63px); // drawer height - offcanvas heading height
|
||||||
}
|
}
|
||||||
|
@ -14,18 +14,16 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-metadata-filter [filterSettings]="filterSettings" [filterOpen]="filterOpen" (applyFilter)="applyMetadataFilter($event)"></app-metadata-filter>
|
<app-metadata-filter [filterSettings]="filterSettings" [filterOpen]="filterOpen" (applyFilter)="applyMetadataFilter($event)"></app-metadata-filter>
|
||||||
|
<div class="content-container">
|
||||||
|
<div class="card-container">
|
||||||
|
<ng-container [ngTemplateOutlet]="cardTemplate"></ng-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ng-container [ngTemplateOutlet]="paginationTemplate" [ngTemplateOutletContext]="{ id: 'top' }"></ng-container>
|
<ng-container [ngTemplateOutlet]="paginationTemplate" [ngTemplateOutletContext]="{ id: 'bottom' }"></ng-container>
|
||||||
|
|
||||||
<div>
|
|
||||||
<ng-container [ngTemplateOutlet]="cardTemplate"></ng-container>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-container [ngTemplateOutlet]="paginationTemplate" [ngTemplateOutletContext]="{ id: 'bottom' }"></ng-container>
|
|
||||||
|
|
||||||
<ng-template #cardTemplate>
|
<ng-template #cardTemplate>
|
||||||
|
|
||||||
<div class="card-container row g-0 mt-3 mb-3" >
|
<div class="grid row g-0 mb-3" >
|
||||||
<div class="card col-auto mt-2 mb-2" *ngFor="let item of items; trackBy:trackByIdentity; index as i" id="jumpbar-index--{{i}}" [attr.jumpbar-index]="i">
|
<div class="card col-auto mt-2 mb-2" *ngFor="let item of items; trackBy:trackByIdentity; index as i" id="jumpbar-index--{{i}}" [attr.jumpbar-index]="i">
|
||||||
<ng-container [ngTemplateOutlet]="itemTemplate" [ngTemplateOutletContext]="{ $implicit: item, idx: i }"></ng-container>
|
<ng-container [ngTemplateOutlet]="itemTemplate" [ngTemplateOutletContext]="{ $implicit: item, idx: i }"></ng-container>
|
||||||
</div>
|
</div>
|
||||||
@ -36,60 +34,7 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #paginationTemplate let-id="id">
|
<ng-template #paginationTemplate let-id="id">
|
||||||
<ng-container *ngIf="pagination && items.length > 0 && id == 'bottom' && pagination.totalPages > 1 ">
|
<ng-container *ngIf="pagination && items.length > 0 && id == 'bottom' && pagination.totalPages > 1 " [ngTemplateOutlet]="jumpBar"></ng-container>
|
||||||
<div class="jump-bar d-flex justify-content-center">
|
|
||||||
<button *ngFor="let jumpKey of jumpBarKeys" class="btn btn-link" (click)="scrollTo(jumpKey)">
|
|
||||||
{{jumpKey.title}}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
<div class="d-flex justify-content-center mb-0" *ngIf="pagination && items.length > 0">
|
|
||||||
<ngb-pagination
|
|
||||||
*ngIf="pagination.totalPages > 1"
|
|
||||||
[maxSize]="8"
|
|
||||||
[rotate]="true"
|
|
||||||
[ellipses]="false"
|
|
||||||
[(page)]="pagination.currentPage"
|
|
||||||
[pageSize]="pagination.itemsPerPage"
|
|
||||||
(pageChange)="onPageChange($event)"
|
|
||||||
[collectionSize]="pagination.totalItems">
|
|
||||||
|
|
||||||
<ng-template ngbPaginationPages let-page let-pages="pages" *ngIf="pagination.totalItems / pagination.itemsPerPage > 20">
|
|
||||||
<li class="ngb-custom-pages-item" *ngIf="pagination.totalPages > 1">
|
|
||||||
<div class="d-flex flex-nowrap px-2">
|
|
||||||
<label
|
|
||||||
id="paginationInputLabel-{{id}}"
|
|
||||||
for="paginationInput-{{id}}"
|
|
||||||
class="col-form-label me-2 ms-1 form-label"
|
|
||||||
>Page</label>
|
|
||||||
<input #i
|
|
||||||
type="text"
|
|
||||||
inputmode="numeric"
|
|
||||||
pattern="[0-9]*"
|
|
||||||
class="form-control custom-pages-input"
|
|
||||||
id="paginationInput-{{id}}"
|
|
||||||
[value]="page"
|
|
||||||
(keyup.enter)="selectPageStr(i.value)"
|
|
||||||
(blur)="selectPageStr(i.value)"
|
|
||||||
(input)="formatInput($any($event).target)"
|
|
||||||
attr.aria-labelledby="paginationInputLabel-{{id}} paginationDescription-{{id}}"
|
|
||||||
[ngStyle]="{width: (0.5 + pagination.currentPage + '').length + 'rem'} "
|
|
||||||
/>
|
|
||||||
<span id="paginationDescription-{{id}}" class="col-form-label text-nowrap px-2">
|
|
||||||
of {{pagination.totalPages}}</span>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ng-template>
|
|
||||||
|
|
||||||
</ngb-pagination>
|
|
||||||
</div>
|
|
||||||
<ng-container *ngIf="pagination && items.length > 0 && id == 'top' && pagination.totalPages > 1">
|
|
||||||
<div class="jump-bar d-flex justify-content-center">
|
|
||||||
<button *ngFor="let jumpKey of jumpBarKeys" class="btn btn-link" (click)="scrollTo(jumpKey)">
|
|
||||||
{{jumpKey.title}}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<div class="mx-auto" *ngIf="isLoading" style="width: 200px;">
|
<div class="mx-auto" *ngIf="isLoading" style="width: 200px;">
|
||||||
@ -97,3 +42,13 @@
|
|||||||
<span class="invisible">Loading...</span>
|
<span class="invisible">Loading...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ng-template #jumpBar>
|
||||||
|
<div class="jump-bar">
|
||||||
|
<ng-container *ngFor="let jumpKey of jumpBarKeys; let i = index;">
|
||||||
|
<button class="btn btn-link {{i % 2 !== 0 ? 'd-lg-flex' : 'd-md-flex'}}" (click)="scrollTo(jumpKey)">
|
||||||
|
{{jumpKey.title}}
|
||||||
|
</button>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
@ -1,6 +1,59 @@
|
|||||||
|
.content-container {
|
||||||
|
display: inline-flex;
|
||||||
|
width: 100%;
|
||||||
|
height: calc((var(--vh) *100) - 152px);
|
||||||
|
}
|
||||||
|
|
||||||
.card-container {
|
.card-container {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, 158px);
|
grid-template-columns: repeat(auto-fill, 158px);
|
||||||
grid-gap: 0.5rem;
|
grid-gap: 0.5rem;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
|
width: 100%;
|
||||||
|
max-height: calc((var(--vh) *100) - 152px);
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jump-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-size: 13px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0 10px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
text-decoration: none;
|
||||||
|
color: hsla(0,0%,100%,.7);
|
||||||
|
height: 25px;
|
||||||
|
text-align: center;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
background: none;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: inherit;
|
||||||
|
margin: 0;
|
||||||
|
outline: none;
|
||||||
|
padding: 0;
|
||||||
|
text-align: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
touch-action: manipulation;
|
||||||
|
transition: color .2s;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
import { AfterViewInit, Component, ContentChild, EventEmitter, Inject, Input, OnDestroy, OnInit, Output, Renderer2, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';
|
import { AfterViewInit, Component, ContentChild, EventEmitter, HostListener, Inject, Input, OnDestroy, OnInit, Output, Renderer2, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';
|
||||||
import { from, Subject } from 'rxjs';
|
import { from, Subject } from 'rxjs';
|
||||||
import { FilterSettings } from 'src/app/metadata-filter/filter-settings';
|
import { FilterSettings } from 'src/app/metadata-filter/filter-settings';
|
||||||
import { Breakpoint, UtilityService } from 'src/app/shared/_services/utility.service';
|
import { Breakpoint, UtilityService } from 'src/app/shared/_services/utility.service';
|
||||||
@ -38,7 +38,8 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy, AfterViewIn
|
|||||||
@Input() trackByIdentity!: (index: number, item: any) => string;
|
@Input() trackByIdentity!: (index: number, item: any) => string;
|
||||||
@Input() filterSettings!: FilterSettings;
|
@Input() filterSettings!: FilterSettings;
|
||||||
|
|
||||||
@Input() jumpBarKeys: Array<JumpKey> = [];
|
|
||||||
|
@Input() jumpBarKeys: Array<JumpKey> = []; // This is aprox 784 pixels wide
|
||||||
|
|
||||||
@Output() itemClicked: EventEmitter<any> = new EventEmitter();
|
@Output() itemClicked: EventEmitter<any> = new EventEmitter();
|
||||||
@Output() pageChange: EventEmitter<Pagination> = new EventEmitter();
|
@Output() pageChange: EventEmitter<Pagination> = new EventEmitter();
|
||||||
@ -67,6 +68,21 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy, AfterViewIn
|
|||||||
this.filter = this.seriesService.createSeriesFilter();
|
this.filter = this.seriesService.createSeriesFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@HostListener('window:resize', ['$event'])
|
||||||
|
@HostListener('window:orientationchange', ['$event'])
|
||||||
|
resizeJumpBar() {
|
||||||
|
console.log('resizing jump bar');
|
||||||
|
//const breakpoint = this.utilityService.getActiveBreakpoint();
|
||||||
|
// if (window.innerWidth < 784) {
|
||||||
|
// // We need to remove a few sections of keys
|
||||||
|
// const len = this.jumpBarKeys.length;
|
||||||
|
// if (this.jumpBarKeys.length <= 8) return;
|
||||||
|
// this.jumpBarKeys = this.jumpBarKeys.filter((item, index) => {
|
||||||
|
// return index % 2 === 0;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.trackByIdentity = (index: number, item: any) => `${this.header}_${this.pagination?.currentPage}_${this.updateApplied}_${item?.libraryId}`;
|
this.trackByIdentity = (index: number, item: any) => `${this.header}_${this.pagination?.currentPage}_${this.updateApplied}_${item?.libraryId}`;
|
||||||
|
|
||||||
|
@ -67,3 +67,15 @@ label, select, .clickable {
|
|||||||
app-root {
|
app-root {
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background-clip: padding-box;
|
||||||
|
background-color: var(--primary-color-scrollbar);
|
||||||
|
border: 3px solid transparent;
|
||||||
|
border-radius: 8px;
|
||||||
|
min-height: 50px;
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
--bs-body-bg: #343a40;
|
--bs-body-bg: #343a40;
|
||||||
--body-text-color: #efefef;
|
--body-text-color: #efefef;
|
||||||
--btn-icon-filter: invert(1) grayscale(100%) brightness(200%);
|
--btn-icon-filter: invert(1) grayscale(100%) brightness(200%);
|
||||||
|
--primary-color-scrollbar: rgba(74,198,148,0.75);
|
||||||
|
|
||||||
/* Navbar */
|
/* Navbar */
|
||||||
--navbar-bg-color: black;
|
--navbar-bg-color: black;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user