From b1020fde6499e9d65289ad8cf689827a5f3d1f36 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Wed, 28 Dec 2022 20:38:57 +0100 Subject: [PATCH] web/elements: render ak-seach-select dropdown correctly in modals Signed-off-by: Jens Langhammer --- authentik/core/templates/base/skeleton.html | 1 + web/rollup.config.js | 4 + web/src/common/styles/authentik.css | 12 +++ web/src/elements/SearchSelect.ts | 113 +++++++++++++------- 4 files changed, 94 insertions(+), 36 deletions(-) diff --git a/authentik/core/templates/base/skeleton.html b/authentik/core/templates/base/skeleton.html index 97235f986..f763941a1 100644 --- a/authentik/core/templates/base/skeleton.html +++ b/authentik/core/templates/base/skeleton.html @@ -13,6 +13,7 @@ + {% block head_before %} {% endblock %} diff --git a/web/rollup.config.js b/web/rollup.config.js index 18ae58cb0..ad4982bbb 100644 --- a/web/rollup.config.js +++ b/web/rollup.config.js @@ -24,6 +24,10 @@ export const resources = [ src: "node_modules/@patternfly/patternfly/patternfly-base.css", dest: "dist/", }, + { + src: "node_modules/@patternfly/patternfly/components/Dropdown/dropdown.css", + dest: "dist/", + }, { src: "node_modules/@patternfly/patternfly/components/Page/page.css", dest: "dist/", diff --git a/web/src/common/styles/authentik.css b/web/src/common/styles/authentik.css index 161d03932..c829003e6 100644 --- a/web/src/common/styles/authentik.css +++ b/web/src/common/styles/authentik.css @@ -310,6 +310,18 @@ html > form > input { .pf-c-dropdown__toggle::before { border-color: transparent; } + .pf-c-dropdown__menu { + --pf-c-dropdown__menu--BackgroundColor: var(--ak-dark-background); + } + .pf-c-dropdown__menu-item { + --pf-c-dropdown__menu-item--BackgroundColor: var(--ak-dark-background); + --pf-c-dropdown__menu-item--Color: var(--ak-dark-foreground); + } + .pf-c-dropdown__menu-item:hover, + .pf-c-dropdown__menu-item:focus { + --pf-c-dropdown__menu-item--BackgroundColor: var(--ak-dark-background-light-ish); + --pf-c-dropdown__menu-item--Color: var(--ak-dark-foreground); + } .pf-c-toggle-group__button { color: var(--ak-dark-foreground) !important; } diff --git a/web/src/elements/SearchSelect.ts b/web/src/elements/SearchSelect.ts index 7b54adee4..07a6365f0 100644 --- a/web/src/elements/SearchSelect.ts +++ b/web/src/elements/SearchSelect.ts @@ -2,7 +2,7 @@ import { AKElement } from "@goauthentik/elements/Base"; import { t } from "@lingui/macro"; -import { CSSResult, TemplateResult, html } from "lit"; +import { CSSResult, TemplateResult, html, render } from "lit"; import { customElement, property } from "lit/decorators.js"; import AKGlobal from "@goauthentik/common/styles/authentik.css"; @@ -61,7 +61,81 @@ export class SearchSelect extends AKElement { }); } + menuId: string; + + constructor() { + super(); + this.menuId = btoa(Math.random().toString()).substring(10, 15); + } + + disconnectedCallback(): void { + super.disconnectedCallback(); + document.querySelectorAll(`#${this.menuId}`).forEach((e) => e.remove()); + } + + /* + * This is a little bit hacky. Because we mainly want to use this field in modal-based forms, + * rendering this menu inline makes the menu not overlay over top of the modal, and cause + * the modal to scroll. + * Hence, we render the menu into the document root, hide it when this menu isn't open + * and remove it on disconnect + * Also to move it to the correct position we're getting this elements's position and use that + * to position the menu + * The other downside this has is that, since we're rendering outside of a shadow root, + * the pf-c-dropdown CSS needs to be loaded on the body. + */ + renderMenu(): void { + const pos = this.getBoundingClientRect(); + render( + html`
+
    + ${this.blankable + ? html` +
  • + +
  • + ` + : html``} + ${this.objects.map((obj) => { + return html` +
  • + +
  • + `; + })} +
+
`, + document.body, + { host: this }, + ); + } + render(): TemplateResult { + this.renderMenu(); return html`
@@ -75,51 +149,18 @@ export class SearchSelect extends AKElement { }} @focus=${() => { this.open = true; + this.renderMenu(); }} @blur=${() => { setTimeout(() => { this.open = false; + this.renderMenu(); }, 200); }} .value=${this.selectedObject ? this.renderElement(this.selectedObject) : ""} />
- -
    - ${this.blankable - ? html` -
  • - -
  • - ` - : html``} - ${this.objects.map((obj) => { - return html` -
  • - -
  • - `; - })} -
`; } }