Skip to content

Commit ee9ab73

Browse files
committed
refactor(expansion-panel): Expansion panel cleanups
Unify open state logic and event behavior
1 parent ebfc92f commit ee9ab73

File tree

1 file changed

+39
-46
lines changed

1 file changed

+39
-46
lines changed

src/components/expansion-panel/expansion-panel.ts

Lines changed: 39 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ export default class IgcExpansionPanelComponent extends EventEmitterMixin<
6767

6868
private _panelId = `${IgcExpansionPanelComponent.tagName}-${nextId++}`;
6969
private readonly _headerRef = createRef<HTMLElement>();
70-
private readonly _contentRef = createRef<HTMLElement>();
70+
private readonly _panelRef = createRef<HTMLElement>();
7171

72-
private readonly _player = addAnimationController(this, this._contentRef);
72+
private readonly _player = addAnimationController(this, this._panelRef);
7373
private readonly _slots = addSlotController(this, {
7474
slots: setSlots('title', 'subtitle', 'indicator', 'indicator-expanded'),
7575
});
@@ -104,60 +104,59 @@ export default class IgcExpansionPanelComponent extends EventEmitterMixin<
104104
ref: this._headerRef,
105105
skip: () => this.disabled,
106106
})
107-
.setActivateHandler(this._toggleWithEvent)
108-
.set([altKey, arrowDown], this._openWithEvent)
109-
.set([altKey, arrowUp], this._closeWithEvent);
107+
.setActivateHandler(this._toggle)
108+
.set([altKey, arrowDown], this._show)
109+
.set([altKey, arrowUp], this._hide);
110110
}
111111

112+
/** @internal */
112113
public override connectedCallback(): void {
113114
super.connectedCallback();
114115
this._panelId = this.id || this._panelId;
115116
}
116117

117118
private _handleClick(): void {
118-
this._headerRef.value!.focus();
119-
this._toggleWithEvent();
119+
this._headerRef.value?.focus();
120+
this._toggle();
120121
}
121122

122-
private _toggleWithEvent(): void {
123-
this.open ? this._closeWithEvent() : this._openWithEvent();
124-
}
123+
private async _setOpenState({
124+
state,
125+
withEvent,
126+
}: {
127+
state: boolean;
128+
withEvent?: boolean;
129+
}): Promise<void> {
130+
if (this.open === state) return;
125131

126-
private async _toggleAnimation(dir: 'open' | 'close'): Promise<boolean> {
127-
const animation = dir === 'open' ? growVerIn : growVerOut;
128-
return this._player.playExclusive(animation());
129-
}
132+
const args = { detail: this };
133+
const event = state ? 'igcOpening' : 'igcClosing';
134+
const eventDone = state ? 'igcOpened' : 'igcClosed';
135+
const animation = state ? growVerIn : growVerOut;
130136

131-
private async _openWithEvent(): Promise<void> {
132-
if (
133-
this.open ||
134-
!this.emitEvent('igcOpening', { cancelable: true, detail: this })
135-
) {
137+
if (withEvent && !this.emitEvent(event, { cancelable: true, ...args })) {
136138
return;
137139
}
138140

139-
this.open = true;
141+
this.open = state;
140142

141-
if (await this._toggleAnimation('open')) {
142-
this.emitEvent('igcOpened', { detail: this });
143+
if (await this._player.playExclusive(animation())) {
144+
if (withEvent) {
145+
this.emitEvent(eventDone, args);
146+
}
143147
}
144148
}
145149

146-
private async _closeWithEvent(): Promise<void> {
147-
if (
148-
!(
149-
this.open &&
150-
this.emitEvent('igcClosing', { cancelable: true, detail: this })
151-
)
152-
) {
153-
return;
154-
}
150+
private async _toggle(): Promise<void> {
151+
this.open ? await this._hide() : await this._show();
152+
}
155153

156-
this.open = false;
154+
private async _show(): Promise<void> {
155+
await this._setOpenState({ state: true, withEvent: true });
156+
}
157157

158-
if (await this._toggleAnimation('close')) {
159-
this.emitEvent('igcClosed', { detail: this });
160-
}
158+
private async _hide(): Promise<void> {
159+
await this._setOpenState({ state: false, withEvent: true });
161160
}
162161

163162
/** Toggles the panel open/close state. */
@@ -167,23 +166,17 @@ export default class IgcExpansionPanelComponent extends EventEmitterMixin<
167166

168167
/** Hides the panel content. */
169168
public async hide(): Promise<boolean> {
170-
if (!this.open) {
171-
return false;
172-
}
169+
if (!this.open) return false;
173170

174-
this.open = false;
175-
await this._toggleAnimation('close');
171+
await this._setOpenState({ state: false });
176172
return true;
177173
}
178174

179175
/** Shows the panel content. */
180176
public async show(): Promise<boolean> {
181-
if (this.open) {
182-
return false;
183-
}
177+
if (this.open) return false;
184178

185-
this.open = true;
186-
await this._toggleAnimation('open');
179+
await this._setOpenState({ state: true });
187180
return true;
188181
}
189182

@@ -227,7 +220,7 @@ export default class IgcExpansionPanelComponent extends EventEmitterMixin<
227220
private _renderPanel() {
228221
return html`
229222
<div
230-
${ref(this._contentRef)}
223+
${ref(this._panelRef)}
231224
part="content"
232225
role="region"
233226
id="${this._panelId}-content"

0 commit comments

Comments
 (0)