1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[CL-613] Support non-card primary content in anon-layout (#15273)

This commit is contained in:
Vicki League
2025-06-26 17:09:25 -04:00
committed by GitHub
parent 04d82a59be
commit 34a338930a
8 changed files with 66 additions and 9 deletions

View File

@@ -27,6 +27,7 @@
[maxWidth]="maxWidth"
[hideFooter]="hideFooter"
[hideIcon]="hideIcon"
[hideCardWrapper]="hideCardWrapper"
>
<router-outlet></router-outlet>
<router-outlet slot="secondary" name="secondary"></router-outlet>

View File

@@ -60,6 +60,7 @@ export class ExtensionAnonLayoutWrapperComponent implements OnInit, OnDestroy {
protected maxWidth: "md" | "3xl";
protected hasLoggedInAccount: boolean = false;
protected hideFooter: boolean;
protected hideCardWrapper: boolean = false;
protected theme: string;
protected logo = Icons.ExtensionBitwardenLogo;
@@ -137,6 +138,10 @@ export class ExtensionAnonLayoutWrapperComponent implements OnInit, OnDestroy {
if (firstChildRouteData["hideIcon"] !== undefined) {
this.hideIcon = Boolean(firstChildRouteData["hideIcon"]);
}
if (firstChildRouteData["hideCardWrapper"] !== undefined) {
this.hideCardWrapper = Boolean(firstChildRouteData["hideCardWrapper"]);
}
}
private listenForServiceDataChanges() {
@@ -177,6 +182,10 @@ export class ExtensionAnonLayoutWrapperComponent implements OnInit, OnDestroy {
this.showReadonlyHostname = data.showReadonlyHostname;
}
if (data.hideCardWrapper !== undefined) {
this.hideCardWrapper = data.hideCardWrapper;
}
if (data.showAcctSwitcher !== undefined) {
this.showAcctSwitcher = data.showAcctSwitcher;
}
@@ -214,6 +223,7 @@ export class ExtensionAnonLayoutWrapperComponent implements OnInit, OnDestroy {
this.showLogo = null;
this.maxWidth = null;
this.hideFooter = null;
this.hideCardWrapper = null;
}
ngOnDestroy() {

View File

@@ -5,6 +5,7 @@
[showReadonlyHostname]="showReadonlyHostname"
[maxWidth]="maxWidth"
[titleAreaMaxWidth]="titleAreaMaxWidth"
[hideCardWrapper]="hideCardWrapper"
>
<router-outlet></router-outlet>
<router-outlet slot="secondary" name="secondary"></router-outlet>

View File

@@ -41,6 +41,10 @@ export interface AnonLayoutWrapperData {
* Optional flag to set the max-width of the title area. Defaults to null if not provided.
*/
titleAreaMaxWidth?: "md";
/**
* Hide the card that wraps the default content. Defaults to false.
*/
hideCardWrapper?: boolean;
}
@Component({
@@ -56,6 +60,7 @@ export class AnonLayoutWrapperComponent implements OnInit, OnDestroy {
protected showReadonlyHostname: boolean;
protected maxWidth: "md" | "3xl";
protected titleAreaMaxWidth: "md";
protected hideCardWrapper: boolean;
constructor(
private router: Router,
@@ -107,6 +112,7 @@ export class AnonLayoutWrapperComponent implements OnInit, OnDestroy {
this.showReadonlyHostname = Boolean(firstChildRouteData["showReadonlyHostname"]);
this.maxWidth = firstChildRouteData["maxWidth"];
this.titleAreaMaxWidth = firstChildRouteData["titleAreaMaxWidth"];
this.hideCardWrapper = Boolean(firstChildRouteData["hideCardWrapper"]);
}
private listenForServiceDataChanges() {
@@ -143,6 +149,10 @@ export class AnonLayoutWrapperComponent implements OnInit, OnDestroy {
this.showReadonlyHostname = data.showReadonlyHostname;
}
if (data.hideCardWrapper !== undefined) {
this.hideCardWrapper = data.hideCardWrapper;
}
// Manually fire change detection to avoid ExpressionChangedAfterItHasBeenCheckedError
// when setting the page data from a service
this.changeDetectorRef.detectChanges();
@@ -165,6 +175,7 @@ export class AnonLayoutWrapperComponent implements OnInit, OnDestroy {
this.showReadonlyHostname = null;
this.maxWidth = null;
this.titleAreaMaxWidth = null;
this.hideCardWrapper = null;
}
ngOnDestroy() {

View File

@@ -87,6 +87,7 @@ const decorators = (options: {
appLogoLabel: "app logo label",
finishCreatingYourAccountBySettingAPassword:
"Finish creating your account by setting a password",
enterpriseSingleSignOn: "Enterprise Single Sign-On",
});
},
},

View File

@@ -39,11 +39,17 @@
class="tw-grow 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-2xl tw-mb-6 sm:tw-mb-10 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>
@if (hideCardWrapper) {
<div class="tw-mb-6 sm:tw-mb-10">
<ng-container *ngTemplateOutlet="defaultContent"></ng-container>
</div>
} @else {
<div
class="tw-rounded-2xl tw-mb-6 sm:tw-mb-10 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-container *ngTemplateOutlet="defaultContent"></ng-container>
</div>
}
<ng-content select="[slot=secondary]"></ng-content>
</div>
@@ -60,3 +66,7 @@
</ng-container>
</footer>
</main>
<ng-template #defaultContent>
<ng-content></ng-content>
</ng-template>

View File

@@ -33,6 +33,7 @@ export class AnonLayoutComponent implements OnInit, OnChanges {
@Input() hideLogo: boolean = false;
@Input() hideFooter: boolean = false;
@Input() hideIcon: boolean = false;
@Input() hideCardWrapper: boolean = false;
/**
* Max width of the title area content

View File

@@ -61,6 +61,7 @@ export default {
showReadonlyHostname: true,
icon: LockIcon,
hideLogo: false,
hideCardWrapper: false,
},
} as Meta;
@@ -95,7 +96,7 @@ export const WithSecondaryContent: Story = {
<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>
<div slot="secondary" class="text-center">
<div slot="secondary" class="tw-text-center">
<div class="tw-font-bold tw-mb-2">Secondary Projected Content (optional)</div>
<button bitButton>Perform Action</button>
</div>
@@ -116,7 +117,7 @@ export const WithLongContent: Story = {
<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? Lorem ipsum dolor sit amet consectetur adipisicing elit. Lorem ipsum dolor sit amet consectetur adipisicing elit. Lorem ipsum dolor sit amet consectetur adipisicing elit. Lorem ipsum dolor sit amet consectetur adipisicing elit. Lorem ipsum dolor sit amet consectetur adipisicing elit. Lorem ipsum dolor sit amet consectetur adipisicing elit. Lorem ipsum dolor sit amet consectetur adipisicing elit. Lorem ipsum dolor sit amet consectetur adipisicing elit. Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
</div>
<div slot="secondary" class="text-center">
<div slot="secondary" class="tw-text-center">
<div class="tw-font-bold tw-mb-2">Secondary Projected Content (optional)</div>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestias laborum nostrum natus. Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestias laborum nostrum natus. Expedita, quod est? </p>
<button bitButton>Perform Action</button>
@@ -133,9 +134,9 @@ export const WithThinPrimaryContent: Story = {
// Projected content (the <div>'s) and styling is just a sample and can be replaced with any content/styling.
`
<auth-anon-layout [title]="title" [subtitle]="subtitle" [showReadonlyHostname]="showReadonlyHostname" [hideLogo]="hideLogo" >
<div class="text-center">Lorem ipsum</div>
<div class="tw-text-center">Lorem ipsum</div>
<div slot="secondary" class="text-center">
<div slot="secondary" class="tw-text-center">
<div class="tw-font-bold tw-mb-2">Secondary Projected Content (optional)</div>
<button bitButton>Perform Action</button>
</div>
@@ -160,6 +161,27 @@ export const WithCustomIcon: Story = {
}),
};
export const HideCardWrapper: Story = {
render: (args) => ({
props: {
...args,
hideCardWrapper: true,
},
template: `
<auth-anon-layout [title]="title" [subtitle]="subtitle" [showReadonlyHostname]="showReadonlyHostname" [hideLogo]="hideLogo" [hideCardWrapper]="hideCardWrapper">
<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>
<div slot="secondary" class="tw-text-center">
<div class="tw-font-bold tw-mb-2">Secondary Projected Content (optional)</div>
<button bitButton>Perform Action</button>
</div>
</auth-anon-layout>
`,
}),
};
export const HideIcon: Story = {
render: (args) => ({
props: args,