This commit is contained in:
rr-bw 2024-04-25 22:52:00 +00:00 committed by GitHub
commit 212b72b748
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 122 additions and 1 deletions

View File

@ -4,6 +4,7 @@ import remarkGfm from "remark-gfm";
const config: StorybookConfig = {
stories: [
"../libs/auth/src/**/*.mdx",
"../libs/auth/src/**/*.stories.@(js|jsx|ts|tsx)",
"../libs/components/src/**/*.mdx",
"../libs/components/src/**/*.stories.@(js|jsx|ts|tsx)",

View File

@ -8,6 +8,7 @@ import {
tdeDecryptionRequiredGuard,
UnauthGuard,
} from "@bitwarden/angular/auth/guards";
import { AnonLayoutWrapperComponent } from "@bitwarden/auth/angular";
import { flagEnabled, Flags } from "../utils/flags";
@ -195,6 +196,34 @@ const routes: Routes = [
},
],
},
// TODO: remove this example
{
path: "",
component: AnonLayoutWrapperComponent,
children: [
{
path: "sample-route",
children: [
{
path: "",
component: LoginComponent, // replace with your component
},
{
path: "",
component: HintComponent, // just an example that shows secondary content. Replace with your component (or remove this secondary outlet entirely if not needed)
outlet: "secondary",
},
],
data: {
pageTitle: "The Page Title",
pageSubtitle: "The Page Subtitle",
},
},
],
},
// TODO: remove this example
{
path: "",
component: UserLayoutComponent,

View File

@ -0,0 +1,4 @@
<auth-anon-layout [title]="pageTitle" [subtitle]="pageSubtitle">
<router-outlet></router-outlet>
<router-outlet slot="secondary" name="secondary"></router-outlet>
</auth-anon-layout>

View File

@ -0,0 +1,26 @@
import { Component, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute, RouterModule } from "@angular/router";
import { AnonLayoutComponent } from "./anon-layout.component";
@Component({
standalone: true,
templateUrl: "anon-layout-wrapper.component.html",
imports: [AnonLayoutComponent, RouterModule],
})
export class AnonLayoutWrapperComponent implements OnInit, OnDestroy {
pageTitle: string;
pageSubtitle: string;
constructor(private route: ActivatedRoute) {
this.pageTitle = this.route.snapshot.firstChild.data["pageTitle"];
this.pageSubtitle = this.route.snapshot.firstChild.data["pageSubtitle"];
}
async ngOnInit() {
document.body.classList.add("layout_frontend");
}
ngOnDestroy() {
document.body.classList.remove("layout_frontend");
}
}

View File

@ -1,5 +1,5 @@
<main
class="tw-flex tw-min-h-screen tw-max-w-xl tw-w-full tw-mx-auto tw-flex-col tw-gap-9 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-9 tw-px-4 tw-pb-4 tw-pt-14 tw-text-main"
>
<div class="tw-text-center">
<div class="tw-px-8">

View File

@ -0,0 +1,59 @@
import { Meta, Story, Controls } from "@storybook/addon-docs";
import * as stories from "./anon-layout.stories";
<Meta of={stories} />
# AnonLayout Component
The Auth-owned AnonLayoutComponent is to be used for unauthenticated pages, where we don't know who
the user is (this includes viewing a Send).
The AnonLayoutComponent is not to be implemented by every component that uses it in the component's
template directly. Instead the AnonLayoutComponent is implemented via routable composition, which
gives us the advantages of nested routes in Angular.
To allow for routable composition, Web has an AnonLayoutWrapperComponent which embeds the Auth-owned
AnonLayoutComponent.
For clarity:
- AnonLayoutComponent = Auth-owned library component - `<auth-anon-layout>`
- AnonLayoutWrapperComponent = Web component -
`apps/web/src/app/auth/anon-layout-wrapper.component.ts`
The AnonLayoutWrapperComponent (Web) embeds the AnonLayoutComponent (Auth-owned) along with the
router outlets:
```html
<!-- File: anon-layout-wrapper.component.html (Web component)-->
<auth-anon-layout>
<router-outlet></router-outlet>
<router-outlet slot="secondary" name="secondary"></router-outlet>
</auth-anon-layout>
```
To implement, the developer should not even need to work with the AnonLayoutComponent (Auth-owned)
directly. The devoloper simply uses the AnonLayoutWrapperComponent (Web) in `oss-routing.module.ts`
to construct the page via routable composition:
```javascript
{
path: "",
component: AnonLayoutWrapperComponent, // Web component (not the Auth-owned component)
children: [
{
path: "sample-route", // replace with your route
component: MyPrimaryComponent, // replace with your component
},
{
path: "",
component: MySecondaryComponent, // replace with your component (or remove this secondary outlet object entirely if not needed)
outlet: "secondary",
},
],
},
```
<Story of={stories.WithSecondaryContent} />

View File

@ -5,6 +5,8 @@
// icons
export * from "./icons";
export * from "./anon-layout/anon-layout.component";
export * from "./anon-layout/anon-layout-wrapper.component";
export * from "./fingerprint-dialog/fingerprint-dialog.component";
export * from "./password-callout/password-callout.component";