web: Make viewing the in-page documentation optional

# What

1. Adds a new component, 'ak-sidebar-help-toggle', which creates a vertical button that reads
   "Documentation" by default.  When clicked, will display a sidebar entry of the markdown
   documentation sent to it.

2. Updates the ApplicationList page to demonstrate how this might look in practice.

This feature does not memoize; it returns to the default condition every time you return to the
page. Long-term memoization may be by-device (using LocalStorage) or by user (using attributes), but
these changes are not part of this proposal.

# Testing

Run the thing and click on the button.

# User documentation changes required.

This changes the look and feel of the application to a small degree. Screenshots may need to be
updated.

# Developer documentation changes required.

None.
This commit is contained in:
Ken Sternberg
2025-01-22 15:09:49 -08:00
parent 457b61c5b4
commit 246423b2be
2 changed files with 130 additions and 7 deletions

View File

@ -4,6 +4,7 @@ import MDApplication from "@goauthentik/docs/add-secure-apps/applications/index.
import "@goauthentik/elements/AppIcon.js";
import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider";
import "@goauthentik/elements/Markdown";
import "@goauthentik/elements/SidebarHelpToggle.js";
import "@goauthentik/elements/buttons/SpinnerButton";
import "@goauthentik/elements/forms/DeleteBulkForm";
import "@goauthentik/elements/forms/ModalForm";
@ -38,6 +39,21 @@ export const applicationListStyle = css`
.pf-c-sidebar.pf-m-gutter > .pf-c-sidebar__main > * + * {
margin-left: calc(var(--pf-c-sidebar__main--child--MarginLeft) / 2);
}
ak-sidebar-help-toggle {
display: none;
}
@media screen and (min-width: 768px) {
ak-sidebar-help-toggle {
display: block;
}
}
ak-sidebar-help-toggle.pf-m-width-default {
background-color: inherit;
max-width: 3rem;
}
`;
@customElement("ak-application-list")
@ -90,13 +106,12 @@ export class ApplicationListPage extends WithBrandConfig(TablePage<Application>)
}
renderSidebarAfter(): TemplateResult {
return html`<div class="pf-c-sidebar__panel pf-m-width-25">
<div class="pf-c-card">
<div class="pf-c-card__body">
<ak-markdown .md=${MDApplication} meta="applications/index.md"></ak-markdown>
</div>
</div>
</div>`;
return html`<ak-sidebar-help-toggle
label=${msg("Applications Documentation")}
.content=${MDApplication}
class="pf-c-sidebar__panel"
active-style="pf-m-width-25"
></ak-sidebar-help-toggle>`;
}
renderToolbarSelected(): TemplateResult {

View File

@ -0,0 +1,108 @@
import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/Markdown";
import { msg } from "@lit/localize";
import { css, html } from "lit";
import { customElement, property, query, state } from "lit/decorators.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFCard from "@patternfly/patternfly/components/Card/card.css";
import PFDisplay from "@patternfly/patternfly/utilities/Display/display.css";
import PFFlex from "@patternfly/patternfly/utilities/Flex/flex.css";
import PFSpacing from "@patternfly/patternfly/utilities/Spacing/spacing.css";
import { bound } from "./decorators/bound";
@customElement("ak-sidebar-help-toggle")
export class ToggledSidebarHelp extends AKElement {
static get styles() {
return [
PFCard,
PFButton,
PFDisplay,
PFFlex,
PFSpacing,
css`
.vert {
transform-origin: bottom left;
rotate: 90deg;
translate: 0 -100%;
}
.ak-fit-text {
width: fit-content;
}
`,
];
}
@property({ attribute: false })
content: string = "";
@property({ attribute: "active-style" })
activeStyle = "pf-m-width-25";
@property()
label: string = msg("Documentation");
@state()
showing = false;
@query("#toggle")
button!: HTMLButtonElement;
@bound
toggle() {
this.showing = !this.showing;
}
render() {
if (!this.showing) {
// eslint-disable-next-line wc/no-self-class
this.classList.remove(this.activeStyle);
// eslint-disable-next-line wc/no-self-class
this.classList.add("pf-m-width-default");
return html`<button
type="button"
id="toggle"
class="pf-c-button pf-m-primary vert"
@click=${this.toggle}
>
${this.label}
</button>`;
}
// eslint-disable-next-line wc/no-self-class
this.classList.remove("pf-m-width-default");
// eslint-disable-next-line wc/no-self-class
this.classList.add(this.activeStyle);
return html`
<div class="pf-c-card">
<div class="pf-u-display-flex pf-u-justify-content-flex-end">
<button
type="button"
class=" pf-c-button pf-m-secondary pf-u-m-md ak-fit-text"
@click=${this.toggle}
>
${msg("Hide")}
</button>
</div>
<div class="pf-c-card__body">
<ak-markdown .md=${this.content} meta="applications/index.md"></ak-markdown>
</div>
</div>
`;
}
updated() {
requestAnimationFrame(() => {
if (this.showing) {
this.style.removeProperty("width");
} else {
if (this.button) {
const { width } = this.button.getBoundingClientRect();
this.style.setProperty("width", `${width}px`);
}
}
});
}
}