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

Fix language selector invalid value #2635

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

HiDeoo
Copy link
Member

@HiDeoo HiDeoo commented Nov 25, 2024

This issue fixes an issue where the language selector could have an invalid value when the user navigates back to a page in a different language.

Repro:

  1. Visit http://localhost:4321/
  2. Change the language to French
  3. Press the back button

At expected at this point, the page is in English however the language selector is still set to French.

In Chrome & Safari, a refresh of the page would fix the issue. However, in Firefox, a refresh of the page is not enough to fix the issue, you have to manually focus the address bar and press enter again.

This is not something visible with the theme selector as we have some JS code to update the picker when the page is loaded.

Setting the to autocomplete attribute to off on the select element prvent the browser to automatically select a cached value for this field based on the last user input. Our <Select> component is only used for the theme and theme selector so I applied the change to the component itself.

Copy link

changeset-bot bot commented Nov 25, 2024

🦋 Changeset detected

Latest commit: 210079f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@astrojs/starlight Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added the 🌟 core Changes to Starlight’s main package label Nov 25, 2024
Copy link

netlify bot commented Nov 25, 2024

Deploy Preview for astro-starlight ready!

Name Link
🔨 Latest commit 210079f
🔍 Latest deploy log https://app.netlify.com/sites/astro-starlight/deploys/67472162e9e5830008509df3
😎 Deploy Preview https://deploy-preview-2635--astro-starlight.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 100 (no change from production)
Accessibility: 100 (no change from production)
Best Practices: 100 (no change from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Member

@delucis delucis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, nice fix! Would have assumed we needed a bit of extra JS for this.

Are we sure it works? I just tried in Chrome (v131 on macOS 15) and still saw the old behaviour:

picker.mov

@HiDeoo
Copy link
Member Author

HiDeoo commented Nov 25, 2024

Oh, interesting, I did not checked the deploy preview yet but indeed, this works in dev but not in the production version. I wonder why the difference 🤔 I'll investigate a bit more as it would be nice to avoid JS for this if possible somehow.

@HiDeoo HiDeoo marked this pull request as draft November 25, 2024 11:03
@trueberryless
Copy link
Contributor

I think that the production preview works properly, because it works on my machine :)

I'm using Arc v1.29.0 on Windows 11 and here you can see the comparison between current Starlight (left) and preview of this PR (right).

Production.works.I.think.mp4

PS: I'm sorry that my screen recorder didn't capture the dropdown menu, what are you guys using for recording?

@HiDeoo
Copy link
Member Author

HiDeoo commented Nov 25, 2024

After investigating a bit more and finding so many cases/bug reports regarding how the autocomplete attribute is behaving, and considering the explicit value we provide can be ignored, domain-dependent, markup dependant, change based on user's settings or browser, I think it's safe to say that we sadly can't rely on it even tho, per spec, it should work…

I'll have to update this PR to use a JS based approach instead when I get the time.

PS: I'm sorry that my screen recorder didn't capture the dropdown menu, what are you guys using for recording?

Depending on the machine I use, I'll either use ScreenFlow or the built-in macOS screen recording tool.

@HiDeoo
Copy link
Member Author

HiDeoo commented Nov 27, 2024

Turns out after more investigation that in this specific case, autocomplete="off" works in all browsers but what's making the difference in production is the back/forward cache (or bfcache) (that's also why autocomplete="off" is still present in the changes and works in dev where the bfcache does not work).

I updated the PR with some code to hook to the pageshow event which has a persisted property, which is true if the page was restored from bfcache. If this is the case, we ensure that the selected value is the correct one.

I made an E2E test for it while adding the code but I did not submit it:

  • By default, the bfcache is disabled in playwright.
  • We can change that but due to a Chrome limitation, this does not work in headless mode.
  • The new headless implementation available in Playwright v1.49.0 removes that limitation but it felt a bit too new to switch to it as there are still some issues with it.

@@ -46,4 +46,18 @@ function localizedPathname(locale: string | undefined): string {
}
}
customElements.define('starlight-lang-select', StarlightLanguageSelect);
window.addEventListener('pageshow', (event) => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A better event would be resume from the Document API but it's not available in Safari at the moment.

@HiDeoo HiDeoo marked this pull request as ready for review November 27, 2024 13:45
Copy link
Contributor

@trueberryless trueberryless left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🎉

But I have a question regarding the fallback if no selected index could be determined (see comment 👇)

const markupSelectedIndex =
select.querySelector<HTMLOptionElement>('option[selected]')?.index;
if (markupSelectedIndex !== select.selectedIndex) {
select.selectedIndex = markupSelectedIndex ?? 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
select.selectedIndex = markupSelectedIndex ?? 0;
select.selectedIndex = markupSelectedIndex ?? select.selectedIndex;

Please correct me if I'm wrong, but wouldn't it be better to leave the dropdown as it is if markupSelectedIndex is undefined?

Or formulated differently: Why did you fallback to the default locale in this case, HiDeoo?

This is just another option to consider, you are probably right to default to 0...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the selected index from the markup is not defined, we're in the case of the default locale with no selected attribute in the markup. For example, if you check the markup on https://starlight.astro.build/, you can see that there is no selected attribute for "English" which makes the first option automatically selected.

image

Falling back to 0 ensures that the first option is selected in this case even if select.selectedIndex has a different value due to a cache restoration.

Basically, when a cache is restored, the markup is always the source of truth and we never fallback to select.selectedIndex which may not be reliable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🌟 core Changes to Starlight’s main package
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants