Skip to content

Commit

Permalink
style(esl-toggleable): fix focus behavior for chain focus flow
Browse files Browse the repository at this point in the history
  • Loading branch information
ala-n committed Nov 15, 2024
1 parent 8c338c6 commit cf1ed1b
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 13 deletions.
3 changes: 2 additions & 1 deletion src/modules/esl-popup/core/esl-popup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,11 @@ export class ESLPopup extends ESLToggleable {
/**
* Focus behavior. Available values:
* - 'none' - no focus management
* - 'grab' - focus on the first focusable element
* - 'chain' (default) - focus on the first focusable element first and return focus to the activator after the last focusable element
* - 'loop' - focus on the first focusable element and loop through the focusable elements
*/
@attr({defaultValue: 'none'})
@attr({defaultValue: 'chain'})
public override focusBehavior: FocusFlowType;

public $placeholder: ESLPopupPlaceholder | null;
Expand Down
3 changes: 2 additions & 1 deletion src/modules/esl-toggleable/core/esl-toggleable.shape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ export interface ESLToggleableTagShape<T extends ESLToggleable = ESLToggleable>
/**
* Define focus behavior
* - 'none' - no focus management
* - 'grab' - focus on the first focusable element
* - 'chain' - focus on the first focusable element first and return focus to the activator after the last focusable element
* - 'loop' - focus on the first focusable element and loop through the focusable elements
*/
'focus-behaviour'?: 'none' | 'chain' | 'loop';
'focus-behavior'?: 'none' | 'chain' | 'loop';

/** Define Toggleable group meta information to organize groups */
'group'?: string;
Expand Down
19 changes: 10 additions & 9 deletions src/modules/esl-toggleable/core/esl-toggleable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export class ESLToggleable extends ESLBaseElement {
/**
* Focus behavior. Available values:
* - 'none' - no focus management
* - 'grab' - focus on the first focusable element
* - 'chain' - focus on the first focusable element first and return focus to the activator after the last focusable element
* - 'loop' - focus on the first focusable element and loop through the focusable elements
*/
Expand Down Expand Up @@ -284,7 +285,7 @@ export class ESLToggleable extends ESLBaseElement {
/**
* Actions to execute on show toggleable.
* Inner state and 'open' attribute are not affected and updated before `onShow` execution.
* Adds CSS classes, update a11y and fire {@link ESLToggleable.REFRESH_EVENT} event by default.
* Adds CSS classes, update a11y and fire {@link ESLBaseElement.REFRESH_EVENT} event by default.
*/
protected onShow(params: ESLToggleableActionParams): void {
this.open = true;
Expand Down Expand Up @@ -417,15 +418,15 @@ export class ESLToggleable extends ESLBaseElement {
@listen('focusout')
protected _onFocusOut(e: FocusEvent): void {
if (!this.open) return;
if (this.focusBehavior === 'chain') {
afterNextRender(() => {
if (this.hasFocus) return;
afterNextRender(() => {
if (this.hasFocus) return;
if (this.focusBehavior === 'chain') {
this.hide({initiator: 'focusout', event: e});
});
}
if (this.focusBehavior === 'loop') {
this.focus({preventScroll: true});
}
}
if (this.focusBehavior === 'loop') {
this.focus({preventScroll: true});
}
});
}

@listen({auto: false, event: 'mouseenter'})
Expand Down
1 change: 1 addition & 0 deletions src/modules/esl-tooltip/core/esl-tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export class ESLTooltip extends ESLPopup {
this.dir = params.dir || '';
this.lang = params.lang || '';
this.parentNode !== document.body && document.body.appendChild(this);

super.onShow(params);
}

Expand Down
4 changes: 2 additions & 2 deletions src/modules/esl-utils/dom/focus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export const handleFocusFlow = (

if (type === 'loop') return handleFocusChain(e, $first, $last);

if (type === 'chain' && $last && $fallback) {
if (e.target !== (e.shiftKey ? $first : $last)) return;
if (type === 'chain' && $fallback) {
if ($last && e.target !== (e.shiftKey ? $first : $last)) return;
$fallback.focus();
e.preventDefault();
}
Expand Down

0 comments on commit cf1ed1b

Please sign in to comment.