Provide documentation and tests for the LoadingOverlay.
This commit is contained in:
@ -6,8 +6,26 @@ import { customElement, property } from "lit/decorators.js";
|
|||||||
|
|
||||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||||
|
|
||||||
|
export interface ILoadingOverlay {
|
||||||
|
topMost?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class LoadingOverlay
|
||||||
|
* @element ak-loading-overlay
|
||||||
|
*
|
||||||
|
* The LoadingOverlay is meant to cover the container element completely, hiding the content behind
|
||||||
|
* a dimming filter, while content loads.
|
||||||
|
*
|
||||||
|
* @slot "body" - [Optional] message content to display while the overlay is visible.
|
||||||
|
*/
|
||||||
@customElement("ak-loading-overlay")
|
@customElement("ak-loading-overlay")
|
||||||
export class LoadingOverlay extends AKElement {
|
export class LoadingOverlay extends AKElement implements ILoadingOverlay {
|
||||||
|
/**
|
||||||
|
* When true, forces the overlay onto the top layer of the display stack.
|
||||||
|
*
|
||||||
|
* @attr
|
||||||
|
*/
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
topMost = false;
|
topMost = false;
|
||||||
|
|
||||||
@ -38,3 +56,9 @@ export class LoadingOverlay extends AKElement {
|
|||||||
</ak-empty-state>`;
|
</ak-empty-state>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ak-loading-overlay": LoadingOverlay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
36
web/src/elements/stories/LoadingOverlay.docs.mdx
Normal file
36
web/src/elements/stories/LoadingOverlay.docs.mdx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { Canvas, Description, Meta, Story, Title } from "@storybook/blocks";
|
||||||
|
|
||||||
|
import * as LoadingOverlayStories from "./LoadingOverlay.stories";
|
||||||
|
|
||||||
|
<Meta of={LoadingOverlayStories} />
|
||||||
|
|
||||||
|
# LoadingOverlay
|
||||||
|
|
||||||
|
The LoadingOverlay is meant to cover the container element completely, hiding the content behind a
|
||||||
|
dimming filter, while content loads.
|
||||||
|
|
||||||
|
It has a single named slot, "body" into which messages about the loading process can be included.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```Typescript
|
||||||
|
import "@goauthentik/elements/LoadingOverlay.js";
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the content of an alert _must_ be a valid HTML component; plain text does not work here.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<ak-loading-overlay topMost>
|
||||||
|
><span slot="body">This would display in the "body" slot</span></ak-loading-overlay
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demo
|
||||||
|
|
||||||
|
### Default
|
||||||
|
|
||||||
|
<Story of={LoadingOverlayStories.DefaultStory} />
|
||||||
|
|
||||||
|
### With a message
|
||||||
|
|
||||||
|
<Story of={LoadingOverlayStories.WithAMessage} />
|
||||||
73
web/src/elements/stories/LoadingOverlay.stories.ts
Normal file
73
web/src/elements/stories/LoadingOverlay.stories.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import type { Meta, StoryObj } from "@storybook/web-components";
|
||||||
|
|
||||||
|
import { LitElement, TemplateResult, css, html } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators.js";
|
||||||
|
|
||||||
|
import { type ILoadingOverlay, LoadingOverlay } from "../LoadingOverlay.js";
|
||||||
|
import "../LoadingOverlay.js";
|
||||||
|
|
||||||
|
const metadata: Meta<LoadingOverlay> = {
|
||||||
|
title: "Elements/<ak-loading-overlay>",
|
||||||
|
component: "ak-loading-overlay",
|
||||||
|
parameters: {
|
||||||
|
docs: {
|
||||||
|
description: "Our empty state spinner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
topMost: { control: "boolean" },
|
||||||
|
message: { control: "text" },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default metadata;
|
||||||
|
|
||||||
|
@customElement("ak-storybook-demo-container")
|
||||||
|
export class Container extends LitElement {
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
height: 25vh;
|
||||||
|
width: 75vw;
|
||||||
|
}
|
||||||
|
#main-container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property({ type: Object, attribute: false })
|
||||||
|
content!: TemplateResult;
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html` <div id="main-container">${this.content}</div>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DefaultStory: StoryObj = {
|
||||||
|
args: {
|
||||||
|
topMost: undefined,
|
||||||
|
// @ts-ignore
|
||||||
|
message: undefined,
|
||||||
|
},
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
render: ({ topMost, message }: ILoadingOverlay) => {
|
||||||
|
message = typeof message === "string" ? html`<span slot="body">${message}</span>` : message;
|
||||||
|
const content = html` <ak-loading-overlay ?topMost=${topMost}
|
||||||
|
>${message ?? ""}
|
||||||
|
</ak-loading-overlay>`;
|
||||||
|
return html`<ak-storybook-demo-container
|
||||||
|
.content=${content}
|
||||||
|
></ak-storybook-demo-container>`;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WithAMessage: StoryObj = {
|
||||||
|
...DefaultStory,
|
||||||
|
args: { ...DefaultStory.args, message: html`<p slot="body">Overlay with a message</p>` },
|
||||||
|
};
|
||||||
41
web/src/elements/stories/LoadingOverlay.test.ts
Normal file
41
web/src/elements/stories/LoadingOverlay.test.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { ensureCSSStyleSheet } from "@goauthentik/elements/utils/ensureCSSStyleSheet.js";
|
||||||
|
import { $, expect } from "@wdio/globals";
|
||||||
|
|
||||||
|
import { msg } from "@lit/localize";
|
||||||
|
import { TemplateResult, html, render as litRender } from "lit";
|
||||||
|
|
||||||
|
import AKGlobal from "@goauthentik/common/styles/authentik.css";
|
||||||
|
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||||
|
|
||||||
|
import "../LoadingOverlay.js";
|
||||||
|
|
||||||
|
const render = (body: TemplateResult) => {
|
||||||
|
document.adoptedStyleSheets = [
|
||||||
|
...document.adoptedStyleSheets,
|
||||||
|
ensureCSSStyleSheet(PFBase),
|
||||||
|
ensureCSSStyleSheet(AKGlobal),
|
||||||
|
];
|
||||||
|
return litRender(body, document.body);
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("ak-loading-overlay", () => {
|
||||||
|
it("should render the default loader", async () => {
|
||||||
|
render(
|
||||||
|
html`<ak-loading-overlay></ak-loading-overlay>`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const empty = await $("ak-loading-overlay");
|
||||||
|
await expect(empty).toExist();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render a slotted message", async () => {
|
||||||
|
render(
|
||||||
|
html`<ak-loading-overlay>
|
||||||
|
<p slot="body">Try again with a different filter</p>
|
||||||
|
</ak-loading-overlay>`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const message = await $("ak-loading-overlay").$(">>>p");
|
||||||
|
await expect(message).toHaveText("Try again with a different filter");
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user