mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 13:53:34 +00:00
[SG-286] Allow vault filter to be scrollable (#2687)
* Switch to programmatic CdkOverlay instead of directive * lint && prettier
This commit is contained in:
@@ -112,12 +112,14 @@ app-root > div {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main::-webkit-scrollbar,
|
main::-webkit-scrollbar,
|
||||||
cdk-virtual-scroll-viewport::-webkit-scrollbar {
|
cdk-virtual-scroll-viewport::-webkit-scrollbar,
|
||||||
|
.vault-select::-webkit-scrollbar {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
main::-webkit-scrollbar-track {
|
main::-webkit-scrollbar-track,
|
||||||
|
.vault-select::-webkit-scrollbar-track {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +130,8 @@ cdk-virtual-scroll-viewport::-webkit-scrollbar-track {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main::-webkit-scrollbar-thumb,
|
main::-webkit-scrollbar-thumb,
|
||||||
cdk-virtual-scroll-viewport::-webkit-scrollbar-thumb {
|
cdk-virtual-scroll-viewport::-webkit-scrollbar-thumb,
|
||||||
|
.vault-select::-webkit-scrollbar-thumb {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
margin-right: 1px;
|
margin-right: 1px;
|
||||||
|
|
||||||
@@ -483,6 +486,10 @@ main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.vault-select {
|
.vault-select {
|
||||||
|
overflow-y: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
@include themify($themes) {
|
@include themify($themes) {
|
||||||
background-color: themed("boxBackgroundColor");
|
background-color: themed("boxBackgroundColor");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
<div class="content org-filter-content" *ngIf="loaded && show">
|
<div class="content org-filter-content" *ngIf="loaded && show">
|
||||||
<button
|
<button
|
||||||
|
#toggleVaults
|
||||||
class="org-filter"
|
class="org-filter"
|
||||||
(click)="toggle()"
|
(click)="openOverlay()"
|
||||||
cdkOverlayOrigin
|
|
||||||
#trigger="cdkOverlayOrigin"
|
|
||||||
aria-haspopup="menu"
|
aria-haspopup="menu"
|
||||||
aria-controls="cdk-overlay-container"
|
aria-controls="cdk-overlay-container"
|
||||||
[attr.aria-expanded]="isOpen"
|
[attr.aria-expanded]="isOpen"
|
||||||
@@ -16,16 +15,7 @@
|
|||||||
[ngClass]="{ 'bwi-angle-down': !isOpen, 'bwi-chevron-up': isOpen }"
|
[ngClass]="{ 'bwi-angle-down': !isOpen, 'bwi-chevron-up': isOpen }"
|
||||||
></i>
|
></i>
|
||||||
</button>
|
</button>
|
||||||
<ng-template
|
<ng-template class="vault-select-container" #vaultSelectorTemplate>
|
||||||
cdkConnectedOverlay
|
|
||||||
[cdkConnectedOverlayOrigin]="trigger"
|
|
||||||
[cdkConnectedOverlayHasBackdrop]="true"
|
|
||||||
[cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
|
|
||||||
[cdkConnectedOverlayOpen]="isOpen"
|
|
||||||
[cdkConnectedOverlayPositions]="overlayPostition"
|
|
||||||
(backdropClick)="close()"
|
|
||||||
(detach)="close()"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="vault-select"
|
class="vault-select"
|
||||||
[@transformPanel]="'open'"
|
[@transformPanel]="'open'"
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
import { animate, state, style, transition, trigger } from "@angular/animations";
|
import { animate, state, style, transition, trigger } from "@angular/animations";
|
||||||
import { ConnectedPosition } from "@angular/cdk/overlay";
|
import { ConnectedPosition, Overlay, OverlayRef } from "@angular/cdk/overlay";
|
||||||
import { Component, EventEmitter, NgZone, OnInit, Output } from "@angular/core";
|
import { TemplatePortal } from "@angular/cdk/portal";
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
ElementRef,
|
||||||
|
EventEmitter,
|
||||||
|
NgZone,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
TemplateRef,
|
||||||
|
ViewChild,
|
||||||
|
ViewContainerRef,
|
||||||
|
} from "@angular/core";
|
||||||
|
import { merge } from "rxjs";
|
||||||
|
|
||||||
import { VaultFilter } from "jslib-angular/modules/vault-filter/models/vault-filter.model";
|
import { VaultFilter } from "jslib-angular/modules/vault-filter/models/vault-filter.model";
|
||||||
import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service";
|
import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service";
|
||||||
@@ -36,6 +48,10 @@ import { VaultFilterService } from "../../services/vaultFilter.service";
|
|||||||
export class VaultSelectComponent implements OnInit {
|
export class VaultSelectComponent implements OnInit {
|
||||||
@Output() onVaultSelectionChanged = new EventEmitter();
|
@Output() onVaultSelectionChanged = new EventEmitter();
|
||||||
|
|
||||||
|
@ViewChild("toggleVaults", { read: ElementRef })
|
||||||
|
buttonRef: ElementRef<HTMLButtonElement>;
|
||||||
|
@ViewChild("vaultSelectorTemplate", { read: TemplateRef }) templateRef: TemplateRef<HTMLElement>;
|
||||||
|
|
||||||
isOpen = false;
|
isOpen = false;
|
||||||
loaded = false;
|
loaded = false;
|
||||||
organizations: Organization[];
|
organizations: Organization[];
|
||||||
@@ -51,6 +67,8 @@ export class VaultSelectComponent implements OnInit {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
private overlayRef: OverlayRef;
|
||||||
|
|
||||||
get show() {
|
get show() {
|
||||||
return (
|
return (
|
||||||
(this.organizations.length > 0 && !this.enforcePersonalOwnwership) ||
|
(this.organizations.length > 0 && !this.enforcePersonalOwnwership) ||
|
||||||
@@ -62,7 +80,9 @@ export class VaultSelectComponent implements OnInit {
|
|||||||
private vaultFilterService: VaultFilterService,
|
private vaultFilterService: VaultFilterService,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private ngZone: NgZone,
|
private ngZone: NgZone,
|
||||||
private broadcasterService: BroadcasterService
|
private broadcasterService: BroadcasterService,
|
||||||
|
private overlay: Overlay,
|
||||||
|
private viewContainerRef: ViewContainerRef
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
@@ -108,11 +128,44 @@ export class VaultSelectComponent implements OnInit {
|
|||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle() {
|
openOverlay() {
|
||||||
this.isOpen = !this.isOpen;
|
const viewPortHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
|
||||||
|
const positionStrategyBuilder = this.overlay.position();
|
||||||
|
|
||||||
|
const positionStrategy = positionStrategyBuilder
|
||||||
|
.flexibleConnectedTo(this.buttonRef.nativeElement)
|
||||||
|
.withFlexibleDimensions(true)
|
||||||
|
.withPush(true)
|
||||||
|
.withViewportMargin(10)
|
||||||
|
.withGrowAfterOpen(true)
|
||||||
|
.withPositions(this.overlayPostition);
|
||||||
|
|
||||||
|
this.overlayRef = this.overlay.create({
|
||||||
|
hasBackdrop: false,
|
||||||
|
positionStrategy,
|
||||||
|
maxHeight: viewPortHeight - 160,
|
||||||
|
backdropClass: "cdk-overlay-transparent-backdrop",
|
||||||
|
});
|
||||||
|
|
||||||
|
const templatePortal = new TemplatePortal(this.templateRef, this.viewContainerRef);
|
||||||
|
this.overlayRef.attach(templatePortal);
|
||||||
|
this.isOpen = true;
|
||||||
|
|
||||||
|
// Handle closing
|
||||||
|
merge(
|
||||||
|
this.overlayRef.outsidePointerEvents(),
|
||||||
|
this.overlayRef.backdropClick(),
|
||||||
|
this.overlayRef.detachments()
|
||||||
|
).subscribe(() => {
|
||||||
|
this.close();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
|
if (this.overlayRef) {
|
||||||
|
this.overlayRef.dispose();
|
||||||
|
this.overlayRef = undefined;
|
||||||
|
}
|
||||||
this.isOpen = false;
|
this.isOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user