@@ -6,6 +6,7 @@ import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
66import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js" ;
77import getActiveElement from "@ui5/webcomponents-base/dist/util/getActiveElement.js" ;
88import { getFirstFocusableElement } from "@ui5/webcomponents-base/dist/util/FocusableElements.js" ;
9+ import { getTabbableElements } from "@ui5/webcomponents-base/dist/util/TabbableElements.js" ;
910import type { AccessibilityAttributes , AriaRole , AriaHasPopup } from "@ui5/webcomponents-base" ;
1011import property from "@ui5/webcomponents-base/dist/decorators/property.js" ;
1112import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js" ;
@@ -21,6 +22,7 @@ import ListItemBase from "./ListItemBase.js";
2122import type RadioButton from "./RadioButton.js" ;
2223import type CheckBox from "./CheckBox.js" ;
2324import type { IButton } from "./Button.js" ;
25+ import type List from "./List.js" ;
2426import {
2527 DELETE ,
2628 ARIA_LABEL_LIST_ITEM_CHECKBOX ,
@@ -200,12 +202,6 @@ abstract class ListItem extends ListItemBase {
200202 @property ( )
201203 mediaRange = "S" ;
202204
203- /**
204- * Stores the last focused element within the list item when navigating with F7.
205- * @private
206- */
207- _lastInnerFocusedElement ?: HTMLElement ;
208-
209205 /**
210206 * Defines the delete button, displayed in "Delete" mode.
211207 * **Note:** While the slot allows custom buttons, to match
@@ -521,24 +517,21 @@ abstract class ListItem extends ListItemBase {
521517 return this . shadowRoot ! . querySelector ( "li" ) ;
522518 }
523519
524- async _handleF7 ( e : KeyboardEvent ) {
525- e . preventDefault ( ) ; // Prevent browser default behavior (F7 = Caret Browsing toggle)
520+ _handleF7 ( e : KeyboardEvent ) {
521+ e . preventDefault ( ) ;
526522
527523 const focusDomRef = this . getFocusDomRef ( ) ! ;
528524 const activeElement = getActiveElement ( ) ;
525+ const list = this . _getList ( ) ;
529526
530527 if ( activeElement === focusDomRef ) {
531- // On list item - restore to stored element or go to first focusable
532- if ( this . _lastInnerFocusedElement ) {
533- this . _lastInnerFocusedElement . focus ( ) ;
534- } else {
535- const firstFocusable = await getFirstFocusableElement ( focusDomRef ) ;
536- firstFocusable ?. focus ( ) ;
537- this . _lastInnerFocusedElement = firstFocusable || undefined ;
538- }
528+ // Navigate from list item into content
529+ this . _focusInternalElement ( list ) ;
539530 } else {
540- // On internal element - store it and go back to list item
541- this . _lastInnerFocusedElement = activeElement as HTMLElement ;
531+ // Navigate from content back to list item
532+ if ( activeElement ) {
533+ this . _updateStoredFocusIndex ( list , activeElement as HTMLElement ) ;
534+ }
542535 focusDomRef . focus ( ) ;
543536 }
544537 }
@@ -556,6 +549,45 @@ abstract class ListItem extends ListItemBase {
556549 focusDomRef . focus ( ) ;
557550 }
558551 }
552+
553+ _getList ( ) : List | null {
554+ return this . closest ( "[ui5-list]" ) ;
555+ }
556+
557+ _getFocusableElements ( ) : HTMLElement [ ] {
558+ const focusDomRef = this . getFocusDomRef ( ) ! ;
559+ return getTabbableElements ( focusDomRef ) ;
560+ }
561+
562+ _focusInternalElement ( list : List | null ) {
563+ const focusables = this . _getFocusableElements ( ) ;
564+ if ( ! focusables . length ) {
565+ return ;
566+ }
567+
568+ const targetIndex = list ?. _lastFocusedElementIndex ?? 0 ;
569+ const safeIndex = Math . min ( targetIndex , focusables . length - 1 ) ;
570+ const elementToFocus = focusables [ safeIndex ] ;
571+
572+ elementToFocus . focus ( ) ;
573+
574+ if ( list ) {
575+ list . _lastFocusedElementIndex = safeIndex ;
576+ }
577+ }
578+
579+ _updateStoredFocusIndex ( list : List | null , activeElement : HTMLElement ) {
580+ if ( ! list ) {
581+ return ;
582+ }
583+
584+ const focusables = this . _getFocusableElements ( ) ;
585+ const currentIndex = focusables . indexOf ( activeElement ) ;
586+
587+ if ( currentIndex !== - 1 ) {
588+ list . _lastFocusedElementIndex = currentIndex ;
589+ }
590+ }
559591}
560592
561593export default ListItem ;
0 commit comments