From 9a25521586e29b9ad982665e47254710e5b95948 Mon Sep 17 00:00:00 2001 From: Cheng-Hsuan Tsai Date: Mon, 20 Oct 2025 17:18:28 +0000 Subject: [PATCH] fix(aria/ui-patterns): enable overwriting `preventDefault` to allow triggering hyperlinks using enter key --- .../event-manager/keyboard-event-manager.ts | 21 +++- src/aria/ui-patterns/tree/tree.ts | 4 +- .../tree-configurable-example.html | 105 +++++++++++++----- 3 files changed, 97 insertions(+), 33 deletions(-) diff --git a/src/aria/ui-patterns/behaviors/event-manager/keyboard-event-manager.ts b/src/aria/ui-patterns/behaviors/event-manager/keyboard-event-manager.ts index 86cf3329ade5..a088f744dda3 100644 --- a/src/aria/ui-patterns/behaviors/event-manager/keyboard-event-manager.ts +++ b/src/aria/ui-patterns/behaviors/event-manager/keyboard-event-manager.ts @@ -35,32 +35,41 @@ export class KeyboardEventManager extends EventManager< }; /** Configures this event manager to handle events with a specific key and no modifiers. */ - on(key: KeyCode, handler: EventHandler): this; + on(key: KeyCode, handler: EventHandler, options?: Partial): this; /** Configures this event manager to handle events with a specific modifer and key combination. */ - on(modifiers: ModifierInputs, key: KeyCode, handler: EventHandler): this; + on( + modifiers: ModifierInputs, + key: KeyCode, + handler: EventHandler, + options?: Partial, + ): this; on(...args: any[]) { - const {modifiers, key, handler} = this._normalizeInputs(...args); + const {modifiers, key, handler, options} = this._normalizeInputs(...args); this.configs.push({ handler: handler, matcher: event => this._isMatch(event, key, modifiers), ...this.options, + ...options, }); return this; } private _normalizeInputs(...args: any[]) { - const key = args.length === 3 ? args[1] : args[0]; - const handler = args.length === 3 ? args[2] : args[1]; - const modifiers = args.length === 3 ? args[0] : Modifier.None; + const withModifiers = Array.isArray(args[0]) || args[0] in Modifier; + const modifiers = withModifiers ? args[0] : Modifier.None; + const key = withModifiers ? args[1] : args[0]; + const handler = withModifiers ? args[2] : args[1]; + const options = withModifiers ? args[3] : args[2]; return { key: key as KeyCode, handler: handler as EventHandler, modifiers: modifiers as ModifierInputs, + options: (options ?? {}) as Partial, }; } diff --git a/src/aria/ui-patterns/tree/tree.ts b/src/aria/ui-patterns/tree/tree.ts index 0f17ff45b7df..3be3c1201c11 100644 --- a/src/aria/ui-patterns/tree/tree.ts +++ b/src/aria/ui-patterns/tree/tree.ts @@ -275,13 +275,13 @@ export class TreePattern { if (!this.followFocus() && this.inputs.multi()) { manager .on(this.dynamicSpaceKey, () => list.toggle()) - .on('Enter', () => list.toggle()) + .on('Enter', () => list.toggle(), {preventDefault: !this.nav()}) .on([Modifier.Ctrl, Modifier.Meta], 'A', () => list.toggleAll()); } if (!this.followFocus() && !this.inputs.multi()) { manager.on(this.dynamicSpaceKey, () => list.selectOne()); - manager.on('Enter', () => list.selectOne()); + manager.on('Enter', () => list.selectOne(), {preventDefault: !this.nav()}); } if (this.inputs.multi() && this.followFocus()) { diff --git a/src/components-examples/aria/tree/tree-configurable/tree-configurable-example.html b/src/components-examples/aria/tree/tree-configurable/tree-configurable-example.html index 7a308eabebc9..3db40d2d0aef 100644 --- a/src/components-examples/aria/tree/tree-configurable/tree-configurable-example.html +++ b/src/components-examples/aria/tree/tree-configurable/tree-configurable-example.html @@ -47,31 +47,86 @@ @for (node of nodes; track node.value) { -
  • - - - {{ node.name }} - -
  • + @if (nav.value) { +
  • + + + + {{ node.name }} + + +
  • - @if (node.children) { -
      - - - -
    - } + @if (node.children) { +
      + + + +
    + } + } @else { +
  • + + + {{ node.name }} + +
  • + + @if (node.children) { +
      + + + +
    + } + } }