Skip to content

Commit

Permalink
Merge pull request #1267 from hotwired/morph-autofocus
Browse files Browse the repository at this point in the history
Don't lose focus due to autofocus when morphing pages
  • Loading branch information
jorgemanrubia committed May 30, 2024
2 parents 89be8e4 + c818307 commit c339144
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 4 deletions.
4 changes: 4 additions & 0 deletions src/core/drive/morph_renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export class MorphRenderer extends PageRenderer {
return "morph"
}

get shouldAutofocus() {
return false
}

// Private

async #morphBody() {
Expand Down
12 changes: 9 additions & 3 deletions src/core/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export class Renderer {
return true
}

get shouldAutofocus() {
return true
}

get reloadReason() {
return
}
Expand All @@ -40,9 +44,11 @@ export class Renderer {
}

focusFirstAutofocusableElement() {
const element = this.connectedSnapshot.firstAutofocusableElement
if (element) {
element.focus()
if (this.shouldAutofocus) {
const element = this.connectedSnapshot.firstAutofocusableElement
if (element) {
element.focus()
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/tests/fixtures/autofocus.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<title>Autofocus</title>
<script src="/dist/turbo.es2017-umd.js" data-turbo-track="reload"></script>
<script src="/src/tests/fixtures/test.js"></script>
<meta name="turbo-refresh-method" content="morph">
<meta name="turbo-refresh-scroll" content="preserve">
</head>
<body>
<h1>Autofocus</h1>
Expand All @@ -22,5 +24,12 @@ <h1>Autofocus</h1>
<turbo-frame id="drives-frame" target="frame">
<a id="drives-frame-target-link" href="/src/tests/fixtures/frames/form.html">#drives-frame link to frames/form.html</a>
</turbo-frame>

<form id="form" action="/__turbo/refresh" method="post" class="redirect">
<input id="form-text" type="text" name="text" value="" autofocus>
<input type="hidden" name="path" value="/src/tests/fixtures/autofocus.html">
<input type="hidden" name="sleep" value="50">
<input id="form-submit" type="submit" value="form[method=post]">
</form>
</body>
</html>
22 changes: 22 additions & 0 deletions src/tests/functional/autofocus_tests.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect, test } from "@playwright/test"
import { nextEventNamed, nextPageRefresh } from "../helpers/page"

test.beforeEach(async ({ page }) => {
await page.goto("/src/tests/fixtures/autofocus.html")
Expand Down Expand Up @@ -74,3 +75,24 @@ test("receiving a Turbo Stream message with an [autofocus] element when an eleme
})
await expect(page.locator("#first-autofocus-element")).toBeFocused()
})

test("don't focus on [autofocus] elements on page refreshes with morphing", async ({ page }) => {
const input = await page.locator("#form input[autofocus]")

const button = page.locator("#first-autofocus-element")
await button.click()

await nextPageRefresh(page)

await expect(button).toBeFocused()
await expect(input).not.toBeFocused()

await page.evaluate(() => {
document.querySelector("#form").requestSubmit()
})

await nextEventNamed(page, "turbo:render", { renderMethod: "morph" })
await nextPageRefresh(page)

await expect(button).toBeFocused()
})
2 changes: 1 addition & 1 deletion src/tests/functional/page_refresh_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ test("renders a page refresh with morphing when the paths are the same but searc
await nextEventNamed(page, "turbo:render", { renderMethod: "morph" })
})

test("renders a page refresh with morphing when the GET form paths are the same but search params are diferent", async ({ page }) => {
test("renders a page refresh with morphing when the GET form paths are the same but search params are different", async ({ page }) => {
await page.goto("/src/tests/fixtures/page_refresh.html")

const input = page.locator("form[method=get] input[name=query]")
Expand Down

0 comments on commit c339144

Please sign in to comment.