Skip to content

Commit

Permalink
Merge pull request #5 from krksgbr/prevent-scroll
Browse files Browse the repository at this point in the history
Allow preventing scroll when an element is focused
  • Loading branch information
knuton authored Feb 20, 2024
2 parents 0f9ad4b + aa75672 commit 7996fb7
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ focus-shift is a lightweight, zero-dependency JavaScript library designed for ke
- Declare groups with custom focus strategies
- Mark subtrees of the DOM that should trap focus
- Mark subtrees of the DOM that should be skipped
- Mark elements to not trigger scrolling when receiving focus
- Dispatches events which allow canceling individual focus shifts

## Usage
Expand Down Expand Up @@ -39,6 +40,7 @@ The following attributes may be added in the markup to guide the moving of focus
- `data-focus-active`: Marks an element as the currently active element within a group.
- `data-focus-skip`: Skips the element and its descendants in navigation.
- `data-focus-trap`: Only allows elements within the annotated layer to receive focus.
- `data-focus-prevent-scroll`: Prevents scrolling when the element receives focus.

Setting `window.FOCUS_SHIFT_DEBUG = true` lets the library log processing steps to the browser's console.

Expand Down
20 changes: 20 additions & 0 deletions cypress/e2e/spec.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,24 @@ describe("focus-shift spec", () => {
{ eventType: "keydown", selector: "#button-3", options: keyevent({ key: "ArrowDown", repeat: false }) }
])
)

it("allows preventing scroll", function () {
cy.visit("./cypress/fixtures/scroll.html")
const getScrollLeft = () => cy.document().then((doc) => doc.scrollingElement.scrollLeft)
function testScroll(id, assert) {
getScrollLeft().then((scrollLeftBefore) => {
const firstButton = cy.get(id)
firstButton.focus()
firstButton.trigger("keydown", keyevent({ key: "ArrowRight" }))
cy.wait(50)
getScrollLeft().then((scrollLeftAfter) => assert(scrollLeftBefore, scrollLeftAfter))
})
}
testScroll("#prevent", function (before, after) {
expect(before).to.equal(after)
})
testScroll("#no-prevent", function (before, after) {
expect(before).to.not.equal(after)
})
})
})
19 changes: 19 additions & 0 deletions cypress/fixtures/scroll.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div class="nav-group" style="display: flex; gap: 100vw">
<div><button id="prevent">First Button</button></div>
<div><button data-focus-prevent-scroll>Don't scroll here</button></div>
</div>

<div class="nav-group" style="display: flex; gap: 100vw" id="no-prevent-scroll">
<div><button id="no-prevent">First Button</button></div>
<div><button>Scroll Here</button></div>
</div>
<script src="../../index.js"></script>
</body>
</html>
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,8 @@ function applyFocus(direction, origin, target) {
if (isGroup(target)) {
dispatchGroupFocus(direction, origin, target)
} else if ("focus" in target && typeof target.focus === "function") {
target.focus()
const preventScroll = target.hasAttribute("data-focus-prevent-scroll")
target.focus({ preventScroll: preventScroll })
}
}

Expand Down

0 comments on commit 7996fb7

Please sign in to comment.