1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-14 10:26:19 +01:00

[PM-8602-8603] Sticky search & filters (#9846)

* add "above-scroll-area" to popup page so that content can be excluded from the scroll area

* move filters and search above the scrollable area

* move bottom border to popup-page component

* fix duplicate scrollbar on popup page

* update padding to match popup header

* move all content of the popup page within the `main` element

* update documentation for `above-scroll-area` slot

* hide scrollable content when loading
This commit is contained in:
Nick Krantz 2024-07-23 21:07:03 -05:00 committed by GitHub
parent 06b370ee75
commit 26a3f6b8ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 43 additions and 7 deletions

View File

@ -41,6 +41,9 @@ page looks nice when the extension is popped out.
- `footer` - `footer`
- Use the `popup-footer` component. - Use the `popup-footer` component.
- Not every page will have a footer. - Not every page will have a footer.
- `above-scroll-area`
- When the page content overflows, this content will be "stuck" to the top of the page upon
scrolling.
- default - default
- Whatever content you want in `main`. - Whatever content you want in `main`.

View File

@ -12,6 +12,7 @@ import {
IconButtonModule, IconButtonModule,
ItemModule, ItemModule,
NoItemsModule, NoItemsModule,
SearchModule,
} from "@bitwarden/components"; } from "@bitwarden/components";
import { PopupFooterComponent } from "./popup-footer.component"; import { PopupFooterComponent } from "./popup-footer.component";
@ -103,6 +104,18 @@ class MockPopoutButtonComponent {}
}) })
class MockCurrentAccountComponent {} class MockCurrentAccountComponent {}
@Component({
selector: "mock-search",
template: `
<div class="tw-p-4">
<bit-search placeholder="Search"> </bit-search>
</div>
`,
standalone: true,
imports: [SearchModule],
})
class MockSearchComponent {}
@Component({ @Component({
selector: "mock-vault-page", selector: "mock-vault-page",
template: ` template: `
@ -114,6 +127,7 @@ class MockCurrentAccountComponent {}
<mock-current-account></mock-current-account> <mock-current-account></mock-current-account>
</ng-container> </ng-container>
</popup-header> </popup-header>
<mock-search slot="above-scroll-area"></mock-search>
<vault-placeholder></vault-placeholder> <vault-placeholder></vault-placeholder>
</popup-page> </popup-page>
`, `,
@ -124,6 +138,7 @@ class MockCurrentAccountComponent {}
MockAddButtonComponent, MockAddButtonComponent,
MockPopoutButtonComponent, MockPopoutButtonComponent,
MockCurrentAccountComponent, MockCurrentAccountComponent,
MockSearchComponent,
VaultComponent, VaultComponent,
], ],
}) })

View File

@ -1,11 +1,26 @@
<ng-content select="[slot=header]"></ng-content> <ng-content select="[slot=header]"></ng-content>
<main class="tw-flex-1 tw-overflow-y-auto tw-h-full tw-relative tw-bg-background-alt"> <main class="tw-flex-1 tw-overflow-hidden tw-flex tw-flex-col tw-relative tw-bg-background-alt">
<div #nonScrollable [ngClass]="{ 'tw-invisible': loading }">
<ng-content select="[slot=above-scroll-area]"></ng-content>
</div>
<div <div
class="tw-max-w-screen-sm tw-mx-auto tw-p-3 tw-overflow-y-auto tw-h-full" class="tw-max-w-screen-sm tw-mx-auto tw-overflow-y-auto tw-flex tw-flex-col tw-w-full tw-h-full"
[ngClass]="{ 'tw-invisible': loading }" [ngClass]="{ 'tw-invisible': loading }"
>
<!-- Only shown when the `slot=above-scroll-area` is populated -->
<!-- The first div will "stick" and show a bottom border when content is scrolled -->
<!-- The second div is displayed on top of the first to hide it until the content is scrolled -->
<ng-container *ngIf="nonScrollable.children.length">
<div class="tw-sticky tw-min-h-[1px] tw-bg-secondary-300 tw-top-0"></div>
<div class="tw-relative tw-z-10 tw-min-h-[2px] tw-bg-background-alt -tw-mt-[2px]"></div>
</ng-container>
<div
class="tw-max-w-screen-sm tw-mx-auto tw-p-3 tw-flex-1 tw-flex tw-flex-col tw-h-full tw-w-full"
> >
<ng-content></ng-content> <ng-content></ng-content>
</div> </div>
</div>
<span <span
class="tw-absolute tw-inset-0 tw-flex tw-items-center tw-justify-center tw-text-main" class="tw-absolute tw-inset-0 tw-flex tw-items-center tw-justify-center tw-text-main"
[ngClass]="{ 'tw-invisible': !loading }" [ngClass]="{ 'tw-invisible': !loading }"

View File

@ -8,7 +8,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
templateUrl: "popup-page.component.html", templateUrl: "popup-page.component.html",
standalone: true, standalone: true,
host: { host: {
class: "tw-h-full tw-flex tw-flex-col tw-flex-1 tw-overflow-y-auto", class: "tw-h-full tw-flex tw-flex-col tw-flex-1 tw-overflow-y-hidden",
}, },
imports: [CommonModule], imports: [CommonModule],
}) })

View File

@ -1,5 +1,5 @@
<div role="toolbar" [ariaLabel]="'filters' | i18n"> <div role="toolbar" [ariaLabel]="'filters' | i18n">
<form [formGroup]="filterForm" class="tw-flex tw-flex-wrap tw-gap-2 tw-mb-6 tw-mt-2"> <form [formGroup]="filterForm" class="tw-flex tw-flex-wrap tw-gap-2 tw-mt-2">
<ng-container *ngIf="organizations$ | async as organizations"> <ng-container *ngIf="organizations$ | async as organizations">
<bit-chip-select <bit-chip-select
*ngIf="organizations.length" *ngIf="organizations.length"

View File

@ -22,10 +22,13 @@
</bit-no-items> </bit-no-items>
</div> </div>
<ng-container *ngIf="vaultState !== VaultStateEnum.Empty"> <!-- Show search & filters outside of the scroll area of the page -->
<div slot="above-scroll-area" class="tw-p-4" *ngIf="vaultState !== VaultStateEnum.Empty">
<app-vault-v2-search> </app-vault-v2-search> <app-vault-v2-search> </app-vault-v2-search>
<app-vault-list-filters></app-vault-list-filters> <app-vault-list-filters></app-vault-list-filters>
</div>
<ng-container *ngIf="vaultState !== VaultStateEnum.Empty">
<div <div
*ngIf="vaultState === VaultStateEnum.NoResults" *ngIf="vaultState === VaultStateEnum.NoResults"
class="tw-flex tw-flex-col tw-justify-center tw-h-auto tw-pt-12" class="tw-flex tw-flex-col tw-justify-center tw-h-auto tw-pt-12"