Close the menu cleanly when changing locale
Dismiss the user menu on language pick, and update the URL together with an optimistic identity write so the mismatch callout does not flash mid-switch. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -58,7 +58,6 @@ const topBarUserMenuFragment = graphql`
|
||||
fragment TopBarUserMenu_identity on Identity {
|
||||
fullName
|
||||
email
|
||||
locale
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -136,7 +135,12 @@ export function TopBarUserMenu({ identityKey }: TopBarUserMenuProps) {
|
||||
}}
|
||||
>
|
||||
{URL_LOCALES.map(code => (
|
||||
<DropdownRadioItem key={code} value={code} disabled={isChangingLocale}>
|
||||
<DropdownRadioItem
|
||||
key={code}
|
||||
value={code}
|
||||
closeOnClick
|
||||
disabled={isChangingLocale}
|
||||
>
|
||||
{URL_LOCALE_LABELS[code]}
|
||||
</DropdownRadioItem>
|
||||
))}
|
||||
|
||||
@@ -44,11 +44,18 @@ export function useChangeLocale() {
|
||||
locale: UrlLocale,
|
||||
options: ChangeLocaleOptions = {},
|
||||
) => {
|
||||
// Persist and navigate without sequencing them: awaiting the mutation
|
||||
// before navigation left a frame where Identity.locale already matched
|
||||
// the new choice but the URL still had the old prefix, flashing the
|
||||
// mismatch callout. updateLocale writes the store optimistically, and
|
||||
// flushSync applies the URL change in the same paint.
|
||||
if (options.persist) {
|
||||
await updateLocale(locale);
|
||||
void updateLocale(locale);
|
||||
}
|
||||
if (locale !== currentLocale) {
|
||||
void navigate(replaceLocaleInPathname(pathname, locale) + search);
|
||||
void navigate(replaceLocaleInPathname(pathname, locale) + search, {
|
||||
flushSync: true,
|
||||
});
|
||||
}
|
||||
}, [currentLocale, navigate, pathname, search, updateLocale]);
|
||||
|
||||
|
||||
@@ -53,6 +53,11 @@ export function useUpdateLocale() {
|
||||
await commit(
|
||||
{
|
||||
variables: { input: { locale } },
|
||||
// Keep the Relay store in sync with the URL during locale switches so
|
||||
// the mismatch callout never paints a one-frame desync.
|
||||
optimisticUpdater: (store) => {
|
||||
store.getRoot().getLinkedRecord("viewer")?.setValue(locale, "locale");
|
||||
},
|
||||
},
|
||||
feedback,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user