diff --git a/services/web/frontend/js/features/source-editor/components/tabs/tabs-container.tsx b/services/web/frontend/js/features/source-editor/components/tabs/tabs-container.tsx
index 0fee481727..3415027eb7 100644
--- a/services/web/frontend/js/features/source-editor/components/tabs/tabs-container.tsx
+++ b/services/web/frontend/js/features/source-editor/components/tabs/tabs-container.tsx
@@ -59,6 +59,14 @@ export const TabsContainer = () => {
setHovered(false)
}, [throttledOnDragOver])
+ const onWheel = useCallback((e: React.WheelEvent) => {
+ if (e.deltaY !== 0 && e.deltaX === 0) {
+ // if this is a purely vertical scroll, convert it to a horizontal scroll
+ // instead
+ e.currentTarget.scrollLeft += e.deltaY
+ }
+ }, [])
+
return (
{
onDragOver={onDragOver}
onDrop={onDrop}
onDragLeave={onDragLeave}
+ onWheel={onWheel}
tabIndex={-1}
>
{tabs.map(tab => (
diff --git a/services/web/test/frontend/features/source-editor/components/tabs.spec.tsx b/services/web/test/frontend/features/source-editor/components/tabs.spec.tsx
index e47b46ea34..2075c83244 100644
--- a/services/web/test/frontend/features/source-editor/components/tabs.spec.tsx
+++ b/services/web/test/frontend/features/source-editor/components/tabs.spec.tsx
@@ -731,7 +731,7 @@ describe('File Tabs', function () {
})
})
- describe('Tab scroll into view', function () {
+ describe('Tab scrolling', function () {
it('scrolls the selected tab into view', function () {
const manyDocs = [
{ _id: DOC_IDS.main, name: 'main.tex' },
@@ -761,6 +761,38 @@ describe('File Tabs', function () {
cy.findByRole('tab', { name: /main\.tex/ }).should('be.visible')
})
+
+ it('scrolls horizontally on vertical mouse wheel', function () {
+ const manyDocs = [
+ { _id: DOC_IDS.main, name: 'main.tex' },
+ ...Array.from({ length: 10 }, (_, i) => ({
+ _id: `ch${i + 1}`,
+ name: `chapter-${i + 1}.tex`,
+ })),
+ ]
+ const rootFolder = makeRootFolder(manyDocs)
+ mountTabs({ rootFolder })
+
+ // Open enough tabs to cause overflow
+ cy.then(() => selectDoc(DOC_IDS.main))
+ for (let i = 1; i <= 10; i++) {
+ const id = `ch${i}`
+ cy.then(() => selectEntity(makeDocEntity(id, `chapter-${i}.tex`)))
+ }
+
+ // Scroll back to the start
+ cy.findByRole('tablist').then($el => {
+ $el[0].scrollLeft = 0
+ })
+
+ // Trigger a vertical wheel event on the tablist
+ cy.findByRole('tablist').trigger('wheel', { deltaY: 100, deltaX: 0 })
+
+ // scrollLeft should have increased
+ cy.findByRole('tablist').should($el => {
+ expect($el[0].scrollLeft).to.be.greaterThan(0)
+ })
+ })
})
describe('SplitTestBadge', function () {