@@ -1286,6 +1286,291 @@ describe("List Tests", () => {
12861286 cy . get ( "[ui5-li-custom]" ) . first ( ) . should ( "be.focused" ) ;
12871287 } ) ;
12881288
1289+ it ( "keyboard handling on F7" , ( ) => {
1290+ cy . mount (
1291+ < List >
1292+ < ListItemCustom >
1293+ < Button > First</ Button >
1294+ < Button > Second</ Button >
1295+ </ ListItemCustom >
1296+ </ List >
1297+ ) ;
1298+
1299+ cy . get ( "[ui5-li-custom]" ) . realClick ( ) ;
1300+ cy . get ( "[ui5-li-custom]" ) . should ( "be.focused" ) ;
1301+
1302+ // F7 goes to first focusable element
1303+ cy . realPress ( "F7" ) ;
1304+ cy . get ( "[ui5-button]" ) . first ( ) . should ( "be.focused" ) ;
1305+
1306+ // Tab to second button
1307+ cy . realPress ( "Tab" ) ;
1308+ cy . get ( "[ui5-button]" ) . last ( ) . should ( "be.focused" ) ;
1309+
1310+ // F7 returns to list item
1311+ cy . realPress ( "F7" ) ;
1312+ cy . get ( "[ui5-li-custom]" ) . should ( "be.focused" ) ;
1313+
1314+ // F7 remembers last focused element (second button)
1315+ cy . realPress ( "F7" ) ;
1316+ cy . get ( "[ui5-button]" ) . last ( ) . should ( "be.focused" ) ;
1317+ } ) ;
1318+
1319+ it ( "keyboard handling on F7 after TAB navigation" , ( ) => {
1320+ cy . mount (
1321+ < div >
1322+ < button > Before</ button >
1323+ < List >
1324+ < ListItemCustom >
1325+ < Button > First</ Button >
1326+ < Button > Second</ Button >
1327+ </ ListItemCustom >
1328+ </ List >
1329+ </ div >
1330+ ) ;
1331+
1332+ cy . get ( "button" ) . realClick ( ) ;
1333+ cy . get ( "button" ) . should ( "be.focused" ) ;
1334+
1335+ // Tab into list item
1336+ cy . realPress ( "Tab" ) ;
1337+ cy . get ( "[ui5-li-custom]" ) . should ( "be.focused" ) ;
1338+
1339+ // Tab into internal elements (goes to first button)
1340+ cy . realPress ( "Tab" ) ;
1341+ cy . get ( "[ui5-button]" ) . first ( ) . should ( "be.focused" ) ;
1342+
1343+ // Tab to second button
1344+ cy . realPress ( "Tab" ) ;
1345+ cy . get ( "[ui5-button]" ) . last ( ) . should ( "be.focused" ) ;
1346+
1347+ // F7 should store current element and return to list item
1348+ cy . realPress ( "F7" ) ;
1349+ cy . get ( "[ui5-li-custom]" ) . should ( "be.focused" ) ;
1350+
1351+ // F7 should remember the second button (not go to first)
1352+ cy . realPress ( "F7" ) ;
1353+ cy . get ( "[ui5-button]" ) . last ( ) . should ( "be.focused" ) ;
1354+ } ) ;
1355+
1356+ it ( "keyboard handling on F7 maintains focus position across list items" , ( ) => {
1357+ cy . mount (
1358+ < List >
1359+ < ListItemCustom >
1360+ < Button > Item 1 - First</ Button >
1361+ < Button > Item 1 - Second</ Button >
1362+ < Button > Item 1 - Third</ Button >
1363+ </ ListItemCustom >
1364+ < ListItemCustom >
1365+ < Button > Item 2 - First</ Button >
1366+ < Button > Item 2 - Second</ Button >
1367+ < Button > Item 2 - Third</ Button >
1368+ </ ListItemCustom >
1369+ </ List >
1370+ ) ;
1371+
1372+ // Focus first list item
1373+ cy . get ( "[ui5-li-custom]" ) . first ( ) . realClick ( ) ;
1374+ cy . get ( "[ui5-li-custom]" ) . first ( ) . should ( "be.focused" ) ;
1375+
1376+ // F7 to enter (should go to first button)
1377+ cy . realPress ( "F7" ) ;
1378+ cy . get ( "[ui5-button]" ) . eq ( 0 ) . should ( "be.focused" ) ;
1379+
1380+ // Tab to second button
1381+ cy . realPress ( "Tab" ) ;
1382+ cy . get ( "[ui5-button]" ) . eq ( 1 ) . should ( "be.focused" ) ;
1383+
1384+ // F7 to exit back to list item
1385+ cy . realPress ( "F7" ) ;
1386+ cy . get ( "[ui5-li-custom]" ) . first ( ) . should ( "be.focused" ) ;
1387+
1388+ // Navigate to second list item with ArrowDown
1389+ cy . realPress ( "ArrowDown" ) ;
1390+ cy . get ( "[ui5-li-custom]" ) . last ( ) . should ( "be.focused" ) ;
1391+
1392+ // F7 should focus the second button (same index as previous item)
1393+ cy . realPress ( "F7" ) ;
1394+ cy . get ( "[ui5-button]" ) . eq ( 4 ) . should ( "be.focused" ) . and ( "contain" , "Item 2 - Second" ) ;
1395+ } ) ;
1396+
1397+ it ( "arrow down navigates to same-index element in next custom item" , ( ) => {
1398+ cy . mount (
1399+ < List >
1400+ < ListItemCustom >
1401+ < Button > Item 1 - First</ Button >
1402+ < Button > Item 1 - Second</ Button >
1403+ </ ListItemCustom >
1404+ < ListItemCustom >
1405+ < Button > Item 2 - First</ Button >
1406+ < Button > Item 2 - Second</ Button >
1407+ </ ListItemCustom >
1408+ < ListItemCustom >
1409+ < Button > Item 3 - First</ Button >
1410+ < Button > Item 3 - Second</ Button >
1411+ </ ListItemCustom >
1412+ </ List >
1413+ ) ;
1414+
1415+ // Focus first button in first item
1416+ cy . get ( "[ui5-button]" ) . first ( ) . realClick ( ) ;
1417+ cy . get ( "[ui5-button]" ) . first ( ) . should ( "be.focused" ) ;
1418+
1419+ // Arrow down should move to first button in second item
1420+ cy . realPress ( "ArrowDown" ) ;
1421+ cy . get ( "[ui5-button]" ) . eq ( 2 ) . should ( "be.focused" ) . and ( "contain" , "Item 2 - First" ) ;
1422+
1423+ // Arrow down again should move to first button in third item
1424+ cy . realPress ( "ArrowDown" ) ;
1425+ cy . get ( "[ui5-button]" ) . eq ( 4 ) . should ( "be.focused" ) . and ( "contain" , "Item 3 - First" ) ;
1426+ } ) ;
1427+
1428+ it ( "arrow up navigates to same-index element in previous custom item" , ( ) => {
1429+ cy . mount (
1430+ < List >
1431+ < ListItemCustom >
1432+ < Button > Item 1 - First</ Button >
1433+ < Button > Item 1 - Second</ Button >
1434+ </ ListItemCustom >
1435+ < ListItemCustom >
1436+ < Button > Item 2 - First</ Button >
1437+ < Button > Item 2 - Second</ Button >
1438+ </ ListItemCustom >
1439+ < ListItemCustom >
1440+ < Button > Item 3 - First</ Button >
1441+ < Button > Item 3 - Second</ Button >
1442+ </ ListItemCustom >
1443+ </ List >
1444+ ) ;
1445+
1446+ // Focus second button in last item
1447+ cy . get ( "[ui5-button]" ) . eq ( 5 ) . realClick ( ) ;
1448+ cy . get ( "[ui5-button]" ) . eq ( 5 ) . should ( "be.focused" ) ;
1449+
1450+ // Arrow up should move to second button in second item
1451+ cy . realPress ( "ArrowUp" ) ;
1452+ cy . get ( "[ui5-button]" ) . eq ( 3 ) . should ( "be.focused" ) . and ( "contain" , "Item 2 - Second" ) ;
1453+
1454+ // Arrow up again should move to second button in first item
1455+ cy . realPress ( "ArrowUp" ) ;
1456+ cy . get ( "[ui5-button]" ) . eq ( 1 ) . should ( "be.focused" ) . and ( "contain" , "Item 1 - Second" ) ;
1457+ } ) ;
1458+
1459+ it ( "arrow navigation skips standard list items" , ( ) => {
1460+ cy . mount (
1461+ < List >
1462+ < ListItemCustom >
1463+ < Button > Custom 1</ Button >
1464+ </ ListItemCustom >
1465+ < ListItemStandard > Standard Item</ ListItemStandard >
1466+ < ListItemStandard > Another Standard</ ListItemStandard >
1467+ < ListItemCustom >
1468+ < Button > Custom 2</ Button >
1469+ </ ListItemCustom >
1470+ </ List >
1471+ ) ;
1472+
1473+ // Focus button in first custom item
1474+ cy . get ( "[ui5-button]" ) . first ( ) . realClick ( ) ;
1475+ cy . get ( "[ui5-button]" ) . first ( ) . should ( "be.focused" ) ;
1476+
1477+ // Arrow down should skip standard items and focus button in second custom item
1478+ cy . realPress ( "ArrowDown" ) ;
1479+ cy . get ( "[ui5-button]" ) . last ( ) . should ( "be.focused" ) . and ( "contain" , "Custom 2" ) ;
1480+
1481+ // Arrow up should skip standard items and return to first custom item
1482+ cy . realPress ( "ArrowUp" ) ;
1483+ cy . get ( "[ui5-button]" ) . first ( ) . should ( "be.focused" ) . and ( "contain" , "Custom 1" ) ;
1484+ } ) ;
1485+
1486+ it ( "arrow navigation works across groups" , ( ) => {
1487+ cy . mount (
1488+ < List >
1489+ < ListItemCustom >
1490+ < Button > Before Group</ Button >
1491+ </ ListItemCustom >
1492+ < ListItemGroup headerText = "Group 1" >
1493+ < ListItemCustom >
1494+ < Button > In Group 1</ Button >
1495+ </ ListItemCustom >
1496+ </ ListItemGroup >
1497+ < ListItemGroup headerText = "Group 2" >
1498+ < ListItemCustom >
1499+ < Button > In Group 2</ Button >
1500+ </ ListItemCustom >
1501+ </ ListItemGroup >
1502+ < ListItemCustom >
1503+ < Button > After Group</ Button >
1504+ </ ListItemCustom >
1505+ </ List >
1506+ ) ;
1507+
1508+ // Focus button before groups
1509+ cy . get ( "[ui5-button]" ) . first ( ) . realClick ( ) ;
1510+
1511+ // Navigate down through groups
1512+ cy . realPress ( "ArrowDown" ) ;
1513+ cy . get ( "[ui5-button]" ) . eq ( 1 ) . should ( "be.focused" ) . and ( "contain" , "In Group 1" ) ;
1514+
1515+ cy . realPress ( "ArrowDown" ) ;
1516+ cy . get ( "[ui5-button]" ) . eq ( 2 ) . should ( "be.focused" ) . and ( "contain" , "In Group 2" ) ;
1517+
1518+ cy . realPress ( "ArrowDown" ) ;
1519+ cy . get ( "[ui5-button]" ) . last ( ) . should ( "be.focused" ) . and ( "contain" , "After Group" ) ;
1520+ } ) ;
1521+
1522+ it ( "arrow navigation handles items with different element counts" , ( ) => {
1523+ cy . mount (
1524+ < List >
1525+ < ListItemCustom >
1526+ < Button > Item 1 - A</ Button >
1527+ < Button > Item 1 - B</ Button >
1528+ < Button > Item 1 - C</ Button >
1529+ < Button > Item 1 - D</ Button >
1530+ </ ListItemCustom >
1531+ < ListItemCustom >
1532+ < Button > Item 2 - A</ Button >
1533+ < Button > Item 2 - B</ Button >
1534+ </ ListItemCustom >
1535+ </ List >
1536+ ) ;
1537+
1538+ // Focus fourth button (index 3) in first item
1539+ cy . get ( "[ui5-button]" ) . eq ( 3 ) . realClick ( ) ;
1540+ cy . get ( "[ui5-button]" ) . eq ( 3 ) . should ( "be.focused" ) ;
1541+
1542+ // Arrow down should focus last button in second item (index clamped to 1)
1543+ cy . realPress ( "ArrowDown" ) ;
1544+ cy . get ( "[ui5-button]" ) . eq ( 5 ) . should ( "be.focused" ) . and ( "contain" , "Item 2 - B" ) ;
1545+ } ) ;
1546+
1547+ it ( "arrow navigation does nothing at list boundaries" , ( ) => {
1548+ cy . mount (
1549+ < List >
1550+ < ListItemCustom >
1551+ < Button > First Item</ Button >
1552+ </ ListItemCustom >
1553+ < ListItemCustom >
1554+ < Button > Last Item</ Button >
1555+ </ ListItemCustom >
1556+ </ List >
1557+ ) ;
1558+
1559+ // Focus first button
1560+ cy . get ( "[ui5-button]" ) . first ( ) . realClick ( ) ;
1561+
1562+ // Arrow up should do nothing (at top boundary)
1563+ cy . realPress ( "ArrowUp" ) ;
1564+ cy . get ( "[ui5-button]" ) . first ( ) . should ( "be.focused" ) ;
1565+
1566+ // Focus last button
1567+ cy . get ( "[ui5-button]" ) . last ( ) . realClick ( ) ;
1568+
1569+ // Arrow down should do nothing (at bottom boundary)
1570+ cy . realPress ( "ArrowDown" ) ;
1571+ cy . get ( "[ui5-button]" ) . last ( ) . should ( "be.focused" ) ;
1572+ } ) ;
1573+
12891574 it ( "keyboard handling on TAB when 2 level nested UI5Element is focused" , ( ) => {
12901575 cy . mount (
12911576 < div >
0 commit comments