Merge a112d21f17
into c21a58f2fb
This commit is contained in:
commit
212b72b748
|
@ -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)",
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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">
|
||||
|
|
|
@ -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} />
|
|
@ -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";
|
||||
|
||||
|
|
Loading…
Reference in New Issue