[CL-334] transparent popup-header (#10242)
* add background input to popup header; update styles; update stories
This commit is contained in:
parent
2be34c3b8f
commit
4d3026d2ea
|
@ -1,5 +1,11 @@
|
|||
<header
|
||||
class="tw-p-4 tw-border-0 tw-border-solid tw-border-b tw-border-secondary-300 tw-bg-background"
|
||||
class="tw-p-4 tw-transition-colors tw-duration-200 tw-border-0 tw-border-b tw-border-solid"
|
||||
[ngClass]="{
|
||||
'tw-bg-background-alt tw-border-transparent':
|
||||
this.background === 'alt' && !pageContentScrolled(),
|
||||
'tw-bg-background tw-border-secondary-300':
|
||||
(this.background === 'alt' && pageContentScrolled()) || this.background === 'default'
|
||||
}"
|
||||
>
|
||||
<div class="tw-max-w-screen-sm tw-mx-auto tw-flex tw-justify-between tw-w-full">
|
||||
<div class="tw-inline-flex tw-items-center tw-gap-2 tw-h-9">
|
||||
|
@ -11,7 +17,10 @@
|
|||
[ariaLabel]="'back' | i18n"
|
||||
[bitAction]="backAction"
|
||||
></button>
|
||||
<h1 bitTypography="h3" class="!tw-mb-0.5 tw-text-headers">{{ pageTitle }}</h1>
|
||||
<h1 *ngIf="pageTitle" bitTypography="h3" class="!tw-mb-0.5 tw-text-headers">
|
||||
{{ pageTitle }}
|
||||
</h1>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
<div class="tw-inline-flex tw-items-center tw-gap-2 tw-h-9">
|
||||
<ng-content select="[slot=end]"></ng-content>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { BooleanInput, coerceBooleanProperty } from "@angular/cdk/coercion";
|
||||
import { CommonModule, Location } from "@angular/common";
|
||||
import { Component, Input } from "@angular/core";
|
||||
import { Component, Input, Signal, inject } from "@angular/core";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import {
|
||||
|
@ -10,6 +10,8 @@ import {
|
|||
TypographyModule,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
import { PopupPageComponent } from "./popup-page.component";
|
||||
|
||||
@Component({
|
||||
selector: "popup-header",
|
||||
templateUrl: "popup-header.component.html",
|
||||
|
@ -17,6 +19,12 @@ import {
|
|||
imports: [TypographyModule, CommonModule, IconButtonModule, JslibModule, AsyncActionsModule],
|
||||
})
|
||||
export class PopupHeaderComponent {
|
||||
protected pageContentScrolled: Signal<boolean> = inject(PopupPageComponent).isScrolled;
|
||||
|
||||
/** Background color */
|
||||
@Input()
|
||||
background: "default" | "alt" = "default";
|
||||
|
||||
/** Display the back button, which uses Location.back() to go back one page in history */
|
||||
@Input()
|
||||
get showBackButton() {
|
||||
|
|
|
@ -74,6 +74,9 @@ Basic usage example:
|
|||
- `showBackButton`: optional, defaults to `false`
|
||||
- Toggles the back button to appear. The back button uses `Location.back()` to navigate back one
|
||||
page in history.
|
||||
- `background`: optional
|
||||
- `"default"` uses a white background
|
||||
- `"alt"` uses a transparent background
|
||||
|
||||
**Slots**
|
||||
|
||||
|
@ -92,6 +95,12 @@ Usage example:
|
|||
</popup-header>
|
||||
```
|
||||
|
||||
### Transparent header
|
||||
|
||||
<Canvas>
|
||||
<Story of={stories.TransparentHeader} />
|
||||
</Canvas>
|
||||
|
||||
Common interactive elements to insert into the `end` slot are:
|
||||
|
||||
- `app-current-account`: shows current account and switcher
|
||||
|
|
|
@ -303,6 +303,7 @@ export default {
|
|||
MockSettingsPageComponent,
|
||||
MockVaultPagePoppedComponent,
|
||||
NoItemsModule,
|
||||
VaultComponent,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
|
@ -311,6 +312,7 @@ export default {
|
|||
return new I18nMockService({
|
||||
back: "Back",
|
||||
loading: "Loading",
|
||||
search: "Search",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
@ -421,3 +423,20 @@ export const Loading: Story = {
|
|||
`,
|
||||
}),
|
||||
};
|
||||
|
||||
export const TransparentHeader: Story = {
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: /* HTML */ `
|
||||
<extension-container>
|
||||
<popup-page>
|
||||
<popup-header slot="header" background="alt"
|
||||
><span class="tw-italic tw-text-main">🤠 Custom Content</span></popup-header
|
||||
>
|
||||
|
||||
<vault-placeholder></vault-placeholder>
|
||||
</popup-page>
|
||||
</extension-container>
|
||||
`,
|
||||
}),
|
||||
};
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
<ng-content select="[slot=header]"></ng-content>
|
||||
<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 }">
|
||||
<div
|
||||
#nonScrollable
|
||||
class="tw-transition-colors tw-duration-200 tw-border-0 tw-border-b tw-border-solid"
|
||||
[ngClass]="{
|
||||
'tw-invisible': loading || nonScrollable.childElementCount === 0,
|
||||
'tw-border-secondary-300': scrolled(),
|
||||
'tw-border-transparent': !scrolled()
|
||||
}"
|
||||
>
|
||||
<ng-content select="[slot=above-scroll-area]"></ng-content>
|
||||
</div>
|
||||
<div
|
||||
class="tw-max-w-screen-sm tw-mx-auto tw-overflow-y-auto tw-flex tw-flex-col tw-w-full tw-h-full"
|
||||
(scroll)="handleScroll($event)"
|
||||
[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"
|
||||
>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { CommonModule } from "@angular/common";
|
||||
import { Component, Input, inject } from "@angular/core";
|
||||
import { Component, Input, inject, signal } from "@angular/core";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
|
@ -17,6 +17,13 @@ export class PopupPageComponent {
|
|||
|
||||
@Input() loading = false;
|
||||
|
||||
protected scrolled = signal(false);
|
||||
isScrolled = this.scrolled.asReadonly();
|
||||
|
||||
/** Accessible loading label for the spinner. Defaults to "loading" */
|
||||
@Input() loadingText?: string = this.i18nService.t("loading");
|
||||
|
||||
handleScroll(event: Event) {
|
||||
this.scrolled.set((event.currentTarget as HTMLElement).scrollTop !== 0);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue