diff --git a/modules/web-common b/modules/web-common
index 00f99acb..e3e2a7d5 160000
--- a/modules/web-common
+++ b/modules/web-common
@@ -1 +1 @@
-Subproject commit 00f99acb4b5e5319a3700114ced2df02db52fd70
+Subproject commit e3e2a7d59dd14ca91977f063248dd75daa72dc1e
diff --git a/src/js/component/item/items/table.jsx b/src/js/component/item/items/table.jsx
index 5e1a63f6..6956a3db 100644
--- a/src/js/component/item/items/table.jsx
+++ b/src/js/component/item/items/table.jsx
@@ -347,6 +347,11 @@ const Table = () => {
}, [dispatch, isEmbedded, focusBySelector]);
const handleTableFocus = useCallback(ev => {
+ // The overflow list is made focusable by default in most browsers and to prevent this we
+ // need to set `tabIndex` to -1. However, since this element is rendered by react-window, we
+ // cannot pass it as a prop. As a workaround, we set the tabIndex attribute directly here.
+ // This fixes issue #519.
+ outerRef.current?.setAttribute?.('tabindex', '-1');
const hasChangedFocused = receiveFocus(ev);
if(hasChangedFocused) {
dispatch(triggerFocus('items-table', true));
diff --git a/src/js/component/tag-selector/tag-selector-items.jsx b/src/js/component/tag-selector/tag-selector-items.jsx
index 6f18ea95..f5816ca2 100644
--- a/src/js/component/tag-selector/tag-selector-items.jsx
+++ b/src/js/component/tag-selector/tag-selector-items.jsx
@@ -186,6 +186,7 @@ const TagSelectorItems = () => {
return (
{
+ delete window.location;
+ window.location = new URL('http://localhost/testuser/collections/WTTJ2J56/items/VR82JUX8/item-details');
+ const user = userEvent.setup()
+ renderWithProviders(, { preloadedState: state, includeStyles: true });
+
+ await waitForPosition();
+ await user.click(screen.getByRole('textbox', { name: 'Title' }));
+ expect(screen.getByRole('textbox', { name: 'Title' })).toHaveFocus();
+
+ await user.keyboard('{shift>}{tab}{/shift}');
+ const inputTypeCombo = screen.getByRole('combobox', { name: 'Item Type' });
+ expect(getByRole(inputTypeCombo, 'textbox')).toHaveFocus();
+
+ await user.keyboard('{shift>}{tab}{/shift}');
+ expect(screen.getByRole('tab', { name: 'Info' })).toHaveFocus();
+
+ await user.keyboard('{shift>}{tab}{/shift}');
+ expect(screen.getByRole('row', { name: 'Effects of diet restriction on life span and age-related changes in dogs' })).toHaveFocus();
+
+ await user.keyboard('{shift>}{tab}{/shift}');
+ expect(screen.getByRole('button', { name: 'New Item' })).toHaveFocus();
+
+ await user.keyboard('{shift>}{tab}{/shift}');
+ expect(screen.getByRole('searchbox', { name: 'Filter Tags' })).toHaveFocus();
+
+ await user.keyboard('{shift>}{tab}{/shift}');
+ expect(screen.getByRole('button', { name: 'cute' })).toHaveFocus();
+
+ await user.keyboard('{shift>}{tab}{/shift}');
+ expect(screen.getByRole('button', { name: 'Collapse Tag Selector' })).toHaveFocus();
+
+ await user.keyboard('{shift>}{tab}{/shift}');
+ expect(screen.getByRole('treeitem', { name: 'My Library' })).toHaveFocus();
+
+ await user.keyboard('{shift>}{tab}{/shift}');
+ expect(screen.getByRole('searchbox', { name: 'Title, Creator, Year' })).toHaveFocus();
+});
+
+
diff --git a/test/keyboard-ui.test.jsx b/test/keyboard-ui.test.jsx
index b29176c6..2eff0a99 100644
--- a/test/keyboard-ui.test.jsx
+++ b/test/keyboard-ui.test.jsx
@@ -57,4 +57,16 @@ test('Tabulate through the UI', async () => {
expect(screen.getAllByRole('combobox', { name: 'Creator Type' }).shift()).toHaveFocus();
});
+test('Tabbing back to item details tabs should focus on the last selected tab', async () => {
+ delete window.location;
+ window.location = new URL('http://localhost/testuser/collections/WTTJ2J56/items/VR82JUX8/item-details');
+ const user = userEvent.setup()
+ renderWithProviders(, { preloadedState: state, includeStyles: true });
+ await user.click(screen.getByRole('tab', { name: 'Tags' }));
+ await user.keyboard('{tab}');
+ expect(screen.getByRole('button', { name: 'Add Tag' })).toHaveFocus();
+
+ await user.keyboard('{shift>}{tab}{/shift}');
+ expect(screen.getByRole('tab', { name: 'Tags' })).toHaveFocus();
+});