import { AKElement } from "@goauthentik/elements/Base"; import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, css, html } from "lit"; import { customElement, property } from "lit/decorators.js"; import { createRef, ref } from "lit/directives/ref.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFForm from "@patternfly/patternfly/components/Form/form.css"; import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; /** * Form Group * * Mostly visual effects, with a single interaction for opening/closing the view. * * @todo Listen for custom events from its children about 'invalidation' events, and * trigger the `expanded` property as needed. */ @customElement("ak-form-group") export class FormGroup extends AKElement { @property({ type: Boolean, reflect: true }) expanded = false; @property({ type: String, attribute: "aria-label", reflect: true }) ariaLabel = msg("Details"); static get styles(): CSSResult[] { return [ PFBase, PFForm, PFButton, PFFormControl, css` /** * Workaround to trigger the hover effect on the button when the header is hovered. * * Alternatively, we group the expander button and header, but the grid would have to be * restructured to allow for this. */ .pf-c-form__field-group:has(.pf-c-form__field-group-header:hover) .pf-c-button { color: var(--pf-c-button--m-plain--hover--Color) !important; } /** * Transition ensuring a smooth animation when the body is expanded/collapsed. */ slot[name="body"] { transition-behavior: allow-discrete; transition-property: opacity, display, transform; transition-duration: var(--pf-global--TransitionDuration); transition-timing-function: var(--pf-global--TimingFunction); display: block; opacity: 1; transform: scaleY(1); transform-origin: top left; will-change: opacity, display, transform; } slot[name="body"][hidden] { opacity: 0 !important; display: none !important; transform: scaleY(0) !important; } @media (prefers-reduced-motion) { slot[name="body"] { transition-duration: 0s; } } `, ]; } formRef = createRef(); scrollAnimationFrame = -1; scrollIntoView = (): void => { this.formRef.value?.scrollIntoView({ behavior: "smooth", }); }; toggleExpanded = (): void => { cancelAnimationFrame(this.scrollAnimationFrame); this.expanded = !this.expanded; if (this.expanded) { this.scrollAnimationFrame = requestAnimationFrame(this.scrollIntoView); } }; render(): TemplateResult { return html`
`; } } declare global { interface HTMLElementTagNameMap { "ak-form-group": FormGroup; } }