Skip to content

Commit

Permalink
Update post-collapsible-trigger.tsx
Browse files Browse the repository at this point in the history
  • Loading branch information
alizedebray committed Jul 15, 2024
1 parent 269d522 commit 2723c96
Showing 1 changed file with 52 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { PostCollapsibleCustomEvent } from '@/components';
tag: 'post-collapsible-trigger',
})
export class PostCollapsibleTrigger {
private trigger?: HTMLElement;
private trigger?: HTMLButtonElement;
private observer = new MutationObserver(() => this.setTrigger());

@Element() host: HTMLPostCollapsibleTriggerElement;

Expand All @@ -16,50 +17,75 @@ export class PostCollapsibleTrigger {
*/
@Prop() for: string;

/**
* Set the "aria-controls" and "aria-expanded" attributes on the trigger to match the state of the controlled post-collapsible
*/
@Watch('for')
setAriaAttributes() {
checkNonEmpty(this.for, 'The post-collapsible-trigger "for" prop is required.');
checkType(this.for, 'string', 'The post-collapsible-trigger "for" prop should be a id.');

if (!this.trigger) return;

const controlledCollapsible = this.collapsible;
if (controlledCollapsible) {
this.trigger.setAttribute('aria-controls', this.for);
this.trigger.setAttribute('aria-expanded', `${!controlledCollapsible.collapsed}`);
} else {
this.trigger.removeAttribute('aria-controls');
this.trigger.removeAttribute('aria-expanded');
// add the provided id to the aria-controls list
const ariaControls = this.trigger.getAttribute('aria-controls');
if (!ariaControls.includes(this.for)) {
const newAriaControls = ariaControls ? `${ariaControls} ${this.for}` : this.for;
this.trigger.setAttribute('aria-controls', newAriaControls);
}

// set the aria-expanded to `false` if the controlled collapsible is collapsed or undefined, set it to `true` otherwise
const isCollapsed = this.collapsible?.collapsed;
const newAriaExpanded = isCollapsed || isCollapsed === undefined ? 'false' : 'true';
this.trigger.setAttribute('aria-expanded', newAriaExpanded);
}

/**
* Initiate a mutation observer that updates the trigger whenever necessary
*/
connectedCallback() {
this.observer.observe(this.host, { childList: true, subtree: true });
}

/**
* Add the "data-version" to the host element and set the trigger
*/
componentDidLoad() {
this.host.setAttribute('data-version', version);
this.trigger = this.host.querySelector('button');
this.setTrigger();

if (!this.trigger) {
console.error('The post-collapsible-trigger must contain a button.');
console.warn('The post-collapsible-trigger must contain a button.');
return;
}
}

this.trigger.addEventListener('click', () => this.toggleCollapsible());
this.setAriaAttributes();
/**
* Disconnect the mutation observer
*/
disconnectedCallback() {
this.observer.disconnect();
}

/**
* Update the "aria-expanded" attribute on the trigger anytime the controlled post-collapsible is toggled
* @param e
*/
@Listen('postToggle', { target: 'document' })
setAriaExpanded(e: PostCollapsibleCustomEvent<boolean>) {
if (!this.trigger || !e.target.isEqualNode(this.collapsible)) return;
this.trigger.setAttribute('aria-expanded', `${e.detail}`);
}

/**
* Toggle the post-collapsible controlled by the trigger
*/
private async toggleCollapsible() {
await this.collapsible?.toggle();
}

/**
* Retrieve the post-collapsible controlled by the trigger
*/
private get collapsible(): HTMLPostCollapsibleElement | null {
const ref = document.getElementById(this.for);
if (ref && ref.localName === 'post-collapsible') {
Expand All @@ -68,4 +94,17 @@ export class PostCollapsibleTrigger {

return null;
}

/**
* Find the button and add the proper event listener and ARIA attributes to it
*/
private setTrigger() {
const trigger = this.host.querySelector('button');
if (!trigger || (this.trigger && trigger.isEqualNode(this.trigger))) return;

this.trigger = trigger;

this.trigger.addEventListener('click', () => this.toggleCollapsible());
this.setAriaAttributes();
}
}

0 comments on commit 2723c96

Please sign in to comment.