web: Enhance accordion header interactions for better UX (#12813)
web: Refine accordion headers for pressability. - Allows user to click or tap anywhere on a accordion header to expand or collapse. - Adds transition to collapse.
This commit is contained in:
		| @ -125,6 +125,11 @@ html > form > input { | |||||||
|     margin-bottom: 6px; |     margin-bottom: 6px; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .pf-m-pressable { | ||||||
|  |     cursor: pointer; | ||||||
|  |     user-select: none; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Flow-card adjustments for static pages */ | /* Flow-card adjustments for static pages */ | ||||||
| .pf-c-brand { | .pf-c-brand { | ||||||
|     padding-top: calc( |     padding-top: calc( | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ import { AKElement } from "@goauthentik/elements/Base"; | |||||||
| import { msg } from "@lit/localize"; | import { msg } from "@lit/localize"; | ||||||
| import { CSSResult, TemplateResult, css, html } from "lit"; | import { CSSResult, TemplateResult, css, html } from "lit"; | ||||||
| import { customElement, property } from "lit/decorators.js"; | 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 PFButton from "@patternfly/patternfly/components/Button/button.css"; | ||||||
| import PFForm from "@patternfly/patternfly/components/Form/form.css"; | import PFForm from "@patternfly/patternfly/components/Form/form.css"; | ||||||
| @ -14,13 +15,9 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css"; | |||||||
|  * |  * | ||||||
|  * Mostly visual effects, with a single interaction for opening/closing the view. |  * Mostly visual effects, with a single interaction for opening/closing the view. | ||||||
|  * |  * | ||||||
|  */ |  * @todo Listen for custom events from its children about 'invalidation' events, and | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * TODO: Listen for custom events from its children about 'invalidation' events, and |  | ||||||
|  * trigger the `expanded` property as needed. |  * trigger the `expanded` property as needed. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| @customElement("ak-form-group") | @customElement("ak-form-group") | ||||||
| export class FormGroup extends AKElement { | export class FormGroup extends AKElement { | ||||||
|     @property({ type: Boolean, reflect: true }) |     @property({ type: Boolean, reflect: true }) | ||||||
| @ -36,15 +33,68 @@ export class FormGroup extends AKElement { | |||||||
|             PFButton, |             PFButton, | ||||||
|             PFFormControl, |             PFFormControl, | ||||||
|             css` |             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-global--Color--100) !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] { |                 slot[name="body"][hidden] { | ||||||
|  |                     opacity: 0 !important; | ||||||
|                     display: none !important; |                     display: none !important; | ||||||
|  |                     transform: scaleY(0) !important; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 @media (prefers-reduced-motion) { | ||||||
|  |                     slot[name="body"] { | ||||||
|  |                         transition-duration: 0s; | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|             `, |             `, | ||||||
|         ]; |         ]; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     formRef = createRef<HTMLFormElement>(); | ||||||
|  |  | ||||||
|  |     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 { |     render(): TemplateResult { | ||||||
|         return html` <div class="pf-c-form"> |         return html`<div class="pf-c-form" ${ref(this.formRef)}> | ||||||
|             <div class="pf-c-form__field-group ${this.expanded ? "pf-m-expanded" : ""}"> |             <div class="pf-c-form__field-group ${this.expanded ? "pf-m-expanded" : ""}"> | ||||||
|                 <div class="pf-c-form__field-group-toggle"> |                 <div class="pf-c-form__field-group-toggle"> | ||||||
|                     <div class="pf-c-form__field-group-toggle-button"> |                     <div class="pf-c-form__field-group-toggle-button"> | ||||||
| @ -53,9 +103,7 @@ export class FormGroup extends AKElement { | |||||||
|                             type="button" |                             type="button" | ||||||
|                             aria-expanded="${this.expanded}" |                             aria-expanded="${this.expanded}" | ||||||
|                             aria-label=${this.ariaLabel} |                             aria-label=${this.ariaLabel} | ||||||
|                             @click=${() => { |                             @click=${this.toggleExpanded} | ||||||
|                                 this.expanded = !this.expanded; |  | ||||||
|                             }} |  | ||||||
|                         > |                         > | ||||||
|                             <span class="pf-c-form__field-group-toggle-icon"> |                             <span class="pf-c-form__field-group-toggle-icon"> | ||||||
|                                 <i class="fas fa-angle-right" aria-hidden="true"></i> |                                 <i class="fas fa-angle-right" aria-hidden="true"></i> | ||||||
| @ -63,7 +111,12 @@ export class FormGroup extends AKElement { | |||||||
|                         </button> |                         </button> | ||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div> | ||||||
|                 <div class="pf-c-form__field-group-header"> |                 <div | ||||||
|  |                     class="pf-c-form__field-group-header pf-m-pressable" | ||||||
|  |                     @click=${this.toggleExpanded} | ||||||
|  |                     aria-expanded=${this.expanded} | ||||||
|  |                     aria-role="button" | ||||||
|  |                 > | ||||||
|                     <div class="pf-c-form__field-group-header-main"> |                     <div class="pf-c-form__field-group-header-main"> | ||||||
|                         <div class="pf-c-form__field-group-header-title"> |                         <div class="pf-c-form__field-group-header-title"> | ||||||
|                             <div class="pf-c-form__field-group-header-title-text"> |                             <div class="pf-c-form__field-group-header-title-text"> | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Teffen Ellis
					Teffen Ellis