Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't lose focus due to autofocus when morphing pages #1267

Merged
merged 1 commit into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading