mirror of
https://github.com/bitwarden/browser
synced 2025-12-14 15:23:33 +00:00
[PM-8307] AnonLayout Design Changes (#10166)
* update logo, padding, and add hideFooter property and hideLogo input * typography and icon adjustments * add story with hidden logo input * handle updating the icon * update storybook docs * update border radius * update icon colors to use tw classes * update storybook docs * handle default icon * make hideFooter an input * update icon sizing * update icon sizing
This commit is contained in:
@@ -1,35 +1,37 @@
|
||||
<main
|
||||
class="tw-flex tw-min-h-screen tw-w-full tw-mx-auto tw-flex-col tw-gap-9 tw-bg-background-alt tw-px-4 tw-pb-4 tw-pt-14 tw-text-main"
|
||||
class="tw-flex tw-min-h-screen tw-w-full tw-mx-auto tw-flex-col tw-gap-7 tw-bg-background-alt tw-px-8 tw-pb-4 tw-pt-8 tw-text-main"
|
||||
>
|
||||
<bit-icon *ngIf="!hideLogo" [icon]="logo" class="tw-max-w-36"></bit-icon>
|
||||
|
||||
<div class="tw-text-center">
|
||||
<div class="tw-px-8">
|
||||
<div *ngIf="icon" class="tw-mb-8">
|
||||
<bit-icon [icon]="icon"></bit-icon>
|
||||
</div>
|
||||
<bit-icon [icon]="logo" class="tw-mx-auto tw-block tw-max-w-72 sm:tw-max-w-xs"></bit-icon>
|
||||
<div class="tw-mx-auto tw-max-w-28 sm:tw-max-w-32">
|
||||
<bit-icon [icon]="icon"></bit-icon>
|
||||
</div>
|
||||
<h1 *ngIf="title" bitTypography="h3" class="tw-mt-8 sm:tw-text-2xl">
|
||||
|
||||
<h1 *ngIf="title" bitTypography="h3" class="tw-mt-2 sm:tw-text-2xl">
|
||||
{{ title }}
|
||||
</h1>
|
||||
<p *ngIf="subtitle" bitTypography="body1">{{ subtitle }}</p>
|
||||
<div *ngIf="subtitle" class="tw-text-sm sm:tw-text-base">{{ subtitle }}</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="tw-mb-auto tw-w-full tw-max-w-md tw-mx-auto tw-flex tw-flex-col tw-items-center sm:tw-min-w-[28rem]"
|
||||
[ngClass]="{ 'tw-max-w-md': maxWidth === 'md', 'tw-max-w-3xl': maxWidth === '3xl' }"
|
||||
>
|
||||
<div
|
||||
class="tw-rounded-xl tw-mb-9 tw-mx-auto tw-w-full sm:tw-bg-background sm:tw-border sm:tw-border-solid sm:tw-border-secondary-300 sm:tw-p-8"
|
||||
class="tw-rounded-2xl tw-mb-9 tw-mx-auto tw-w-full sm:tw-bg-background sm:tw-border sm:tw-border-solid sm:tw-border-secondary-300 sm:tw-p-8"
|
||||
>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
<ng-content select="[slot=secondary]"></ng-content>
|
||||
</div>
|
||||
<footer class="tw-text-center">
|
||||
|
||||
<footer *ngIf="!hideFooter" class="tw-text-center">
|
||||
<div *ngIf="showReadonlyHostname">{{ "accessing" | i18n }} {{ hostname }}</div>
|
||||
<ng-container *ngIf="!showReadonlyHostname">
|
||||
<ng-content select="[slot=environment-selector]"></ng-content>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="showYearAndVersion">
|
||||
<ng-container *ngIf="!hideYearAndVersion">
|
||||
<div>© {{ year }} Bitwarden Inc.</div>
|
||||
<div>{{ version }}</div>
|
||||
</ng-container>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component, Input } from "@angular/core";
|
||||
import { Component, Input, OnChanges, OnInit, SimpleChanges } from "@angular/core";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { ClientType } from "@bitwarden/common/enums";
|
||||
@@ -10,7 +10,8 @@ import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-stat
|
||||
import { IconModule, Icon } from "../../../../components/src/icon";
|
||||
import { SharedModule } from "../../../../components/src/shared";
|
||||
import { TypographyModule } from "../../../../components/src/typography";
|
||||
import { BitwardenLogoPrimary, BitwardenLogoWhite } from "../icons/bitwarden-logo.icon";
|
||||
import { BitwardenLogoPrimary, BitwardenLogoWhite } from "../icons";
|
||||
import { BitwardenShieldPrimary, BitwardenShieldWhite } from "../icons/bitwarden-shield.icon";
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -18,11 +19,13 @@ import { BitwardenLogoPrimary, BitwardenLogoWhite } from "../icons/bitwarden-log
|
||||
templateUrl: "./anon-layout.component.html",
|
||||
imports: [IconModule, CommonModule, TypographyModule, SharedModule],
|
||||
})
|
||||
export class AnonLayoutComponent {
|
||||
export class AnonLayoutComponent implements OnInit, OnChanges {
|
||||
@Input() title: string;
|
||||
@Input() subtitle: string;
|
||||
@Input() icon: Icon;
|
||||
@Input() showReadonlyHostname: boolean;
|
||||
@Input() hideLogo: boolean = false;
|
||||
@Input() hideFooter: boolean = false;
|
||||
/**
|
||||
* Max width of the layout content
|
||||
*
|
||||
@@ -38,7 +41,7 @@ export class AnonLayoutComponent {
|
||||
protected version: string;
|
||||
protected theme: string;
|
||||
|
||||
protected showYearAndVersion = true;
|
||||
protected hideYearAndVersion = false;
|
||||
|
||||
constructor(
|
||||
private environmentService: EnvironmentService,
|
||||
@@ -47,13 +50,12 @@ export class AnonLayoutComponent {
|
||||
) {
|
||||
this.year = new Date().getFullYear().toString();
|
||||
this.clientType = this.platformUtilsService.getClientType();
|
||||
this.showYearAndVersion = this.clientType === ClientType.Web;
|
||||
this.hideYearAndVersion = this.clientType !== ClientType.Web;
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.maxWidth = this.maxWidth ?? "md";
|
||||
this.hostname = (await firstValueFrom(this.environmentService.environment$)).getHostname();
|
||||
this.version = await this.platformUtilsService.getApplicationVersion();
|
||||
|
||||
this.theme = await firstValueFrom(this.themeStateService.selectedTheme$);
|
||||
|
||||
if (this.theme === "dark") {
|
||||
@@ -61,5 +63,29 @@ export class AnonLayoutComponent {
|
||||
} else {
|
||||
this.logo = BitwardenLogoPrimary;
|
||||
}
|
||||
|
||||
await this.updateIcon(this.theme);
|
||||
|
||||
this.hostname = (await firstValueFrom(this.environmentService.environment$)).getHostname();
|
||||
this.version = await this.platformUtilsService.getApplicationVersion();
|
||||
}
|
||||
|
||||
async ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes.icon) {
|
||||
const theme = await firstValueFrom(this.themeStateService.selectedTheme$);
|
||||
await this.updateIcon(theme);
|
||||
}
|
||||
}
|
||||
|
||||
private async updateIcon(theme: string) {
|
||||
if (this.icon == null) {
|
||||
if (theme === "dark") {
|
||||
this.icon = BitwardenShieldWhite;
|
||||
}
|
||||
|
||||
if (theme !== "dark") {
|
||||
this.icon = BitwardenShieldPrimary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ export default {
|
||||
subtitle: "The subtitle (optional)",
|
||||
showReadonlyHostname: true,
|
||||
icon: LockIcon,
|
||||
hideLogo: false,
|
||||
},
|
||||
} as Meta;
|
||||
|
||||
@@ -144,7 +145,7 @@ export const WithThinPrimaryContent: Story = {
|
||||
}),
|
||||
};
|
||||
|
||||
export const WithIcon: Story = {
|
||||
export const WithCustomIcon: Story = {
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template:
|
||||
@@ -159,3 +160,35 @@ export const WithIcon: Story = {
|
||||
`,
|
||||
}),
|
||||
};
|
||||
|
||||
export const HideLogo: Story = {
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template:
|
||||
// Projected content (the <div>) and styling is just a sample and can be replaced with any content/styling.
|
||||
`
|
||||
<auth-anon-layout [title]="title" [subtitle]="subtitle" [showReadonlyHostname]="showReadonlyHostname" [hideLogo]="true">
|
||||
<div>
|
||||
<div class="tw-font-bold">Primary Projected Content Area (customizable)</div>
|
||||
<div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Necessitatibus illum vero, placeat recusandae esse ratione eius minima veniam nemo, quas beatae! Impedit molestiae alias sapiente explicabo. Sapiente corporis ipsa numquam?</div>
|
||||
</div>
|
||||
</auth-anon-layout>
|
||||
`,
|
||||
}),
|
||||
};
|
||||
|
||||
export const HideFooter: Story = {
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template:
|
||||
// Projected content (the <div>) and styling is just a sample and can be replaced with any content/styling.
|
||||
`
|
||||
<auth-anon-layout [title]="title" [subtitle]="subtitle" [showReadonlyHostname]="showReadonlyHostname" [hideFooter]="true">
|
||||
<div>
|
||||
<div class="tw-font-bold">Primary Projected Content Area (customizable)</div>
|
||||
<div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Necessitatibus illum vero, placeat recusandae esse ratione eius minima veniam nemo, quas beatae! Impedit molestiae alias sapiente explicabo. Sapiente corporis ipsa numquam?</div>
|
||||
</div>
|
||||
</auth-anon-layout>
|
||||
`,
|
||||
}),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user