(core) Fix missing placeholder flag icon

Summary:
Shows a placeholder flag icon for the language picker button when a country flag
isn't available.

The country flag icon is displayed on top of the placeholder icon. For countries
where an icon isn't available, the placeholder will then become visible.

This fixes a bug where no icon was shown for languages that didn't have a flag
icon available.

Test Plan: Tested manually.

Reviewers: jarek

Reviewed By: jarek

Subscribers: jarek

Differential Revision: https://phab.getgrist.com/D3805
This commit is contained in:
George Gevoian 2023-02-23 02:50:34 -05:00
parent 17569561bf
commit 788a223f13
4 changed files with 45 additions and 27 deletions

View File

@ -1,7 +1,8 @@
import {detectCurrentLang, makeT, setAnonymousLocale} from 'app/client/lib/localization';
import {AppModel} from 'app/client/models/AppModel';
import {hoverTooltip} from 'app/client/ui/tooltips';
import {cssHoverCircle, cssTopBarBtn} from 'app/client/ui/TopBarCss';
import {cssHoverCircle} from 'app/client/ui/TopBarCss';
import {theme} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {menu, menuItem} from 'app/client/ui2018/menus';
import {getCountryCode} from 'app/common/Locales';
@ -29,13 +30,10 @@ export function buildLanguageMenu(appModel: AppModel) {
setAnonymousLocale(lng);
window.location.reload();
};
// Try to convert locale setting to the emoji flag, fallback to plain flag icon.
const emojiFlag = buildEmoji(userLanguage);
return cssHoverCircle(
// Margin is common for all hover buttons on TopBar.
{style: `margin: 5px;`},
const flagIcon = buildFlagIcon(userLanguage);
return cssFlagButton(
// Flag or emoji flag if we have it.
emojiFlag ?? cssTopBarBtn('Flag'),
cssFlagIconWrapper(flagIcon),
// Expose for test the current language use.
testId(`current-` + userLanguage),
menu(
@ -56,15 +54,16 @@ export function buildLanguageMenu(appModel: AppModel) {
);
}
// Unfortunately, Windows doesn't support emoji flags, so we need to use SVG icons.
function buildEmoji(locale: string) {
function buildFlagIcon(locale: string) {
const countryCode = getCountryCode(locale);
if (!countryCode) { return null; }
return [
cssSvgIcon({
style: `background-image: url("icons/locales/${countryCode}.svg")`
}),
dom.cls(cssSvgIconWrapper.className)
// Try to show an icon of the country's flag. (The icon may not exist.)
!countryCode ? null : cssFlagIcon({
// Unfortunately, Windows doesn't support emoji flags, so we need to use SVG icons.
style: `background-image: url("icons/locales/${countryCode}.svg");`,
}, testId('button-icon')),
// Display a placeholder icon behind the one above, to act as a fallback.
cssPlaceholderFlagIcon('Flag'),
];
}
@ -84,24 +83,38 @@ const cssWrapper = styled('div', `
display: inline-block;
`);
const cssSvgIconWrapper = styled('div', `
display: grid;
place-content: center;
cursor: pointer;
user-select: none;
const cssFirstUpper = styled('span', `
&::first-letter {
text-transform: capitalize;
}
`);
const cssSvgIcon = styled('div', `
const cssFlagButton = styled(cssHoverCircle, `
display: flex;
align-items: center;
justify-content: center;
margin: 5px;
cursor: pointer;
`);
const cssFlagIconWrapper = styled('div', `
position: relative;
width: 16px;
height: 16px;
`);
const cssFlagIcon = styled('div', `
position: absolute;
width: 16px;
height: 16px;
background-repeat: no-repeat;
background-position: center;
background-color: transparent;
background-size: contain;
z-index: 1;
`);
const cssFirstUpper = styled('span', `
&::first-letter {
text-transform: capitalize;
}
const cssPlaceholderFlagIcon = styled(icon, `
position: absolute;
--icon-color: ${theme.topBarButtonPrimaryFg};
`);

View File

@ -62,7 +62,7 @@
--icon-Filter: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTIuNSw0IEwxLjUsNCBDMS4yMjQsNCAxLDMuNzc2IDEsMy41IEMxLDMuMjI0IDEuMjI0LDMgMS41LDMgTDIuNSwzIEMyLjc3NiwzIDMsMy4yMjQgMywzLjUgQzMsMy43NzYgMi43NzYsNCAyLjUsNCBaIE00LjUsNyBMMS41LDcgQzEuMjI0LDcgMSw2Ljc3NiAxLDYuNSBDMSw2LjIyNCAxLjIyNCw2IDEuNSw2IEw0LjUsNiBDNC43NzYsNiA1LDYuMjI0IDUsNi41IEM1LDYuNzc2IDQuNzc2LDcgNC41LDcgWiBNNi41LDEwIEwxLjUsMTAgQzEuMjI0LDEwIDEsOS43NzYgMSw5LjUgQzEsOS4yMjQgMS4yMjQsOSAxLjUsOSBMNi41LDkgQzYuNzc2LDkgNyw5LjIyNCA3LDkuNSBDNyw5Ljc3NiA2Ljc3NiwxMCA2LjUsMTAgWiBNOC41LDEzIEwxLjUsMTMgQzEuMjI0LDEzIDEsMTIuNzc2IDEsMTIuNSBDMSwxMi4yMjQgMS4yMjQsMTIgMS41LDEyIEw4LjUsMTIgQzguNzc2LDEyIDksMTIuMjI0IDksMTIuNSBDOSwxMi43NzYgOC43NzYsMTMgOC41LDEzIFogTTE0Ljk3Mjg4OCwyLjI4NDkwODg1IEMxNS4wMjY1MzgyLDIuNDU3MzYxNzggMTQuOTk2ODg2NCwyLjY1NTk2NzI1IDE0Ljg5Nzg5MzIsMi43ODc4MDY4MyBMMTEuNjgxMzA2OCw3LjA3NjY2OTY1IEMxMS42MTE3MzQ3LDcuMTY5NTg4MDkgMTEuNTM4MDA5LDcuNDA2ODA3MDIgMTEuNTM4MDA5LDcuNTM4MTg1MDggTDExLjUzODAwOSwxMy41Mzc4ODU2IEMxMS41MzgwMDksMTMuNzI0NjQ1NSAxMS40NTM3ODQsMTMuODkyOTQ0OCAxMS4zMjQzMzE0LDEzLjk2NDE3MiBDMTEuMjgxNTI2NiwxMy45ODgwMTcgMTEuMjM2NTI5NywxMy45OTk0MDEgMTEuMTkxOTk0MywxMy45OTk0MDEgQzExLjEwMTg4NTEsMTMuOTk5NDAxIDExLjAxMzI3NTgsMTMuOTUyNDgwMyAxMC45NDcxNjUsMTMuODY0MTc3IEw5LjU2MjY0NDg2LDEyLjAxODExNTMgQzkuNDk3Njg3NzksMTEuOTMxNjU4MSA5LjQ2MTIyODc2LDExLjgxNDI3OTMgOS40NjEyMjg3NiwxMS42OTE4MjM5IEw5LjQ2MTIyODc2LDcuNTM4MTg1MDggQzkuNDYxMjI4NzYsNy40MDY4MDcwMiA5LjM4NzYxODQ0LDcuMTY5NTg4MDkgOS4zMTc5MzA5Miw3LjA3Njk3NzMzIEw2LjEwMTM0NDUyLDIuNzg3OTYwNjcgQzYuMDAyMzUxMzMsMi42NTU5NjcyNSA1Ljk3MjgxNDksMi40NTc1MTU2MiA2LjAyNjM0OTY4LDIuMjg0OTA4ODUgQzYuMDc5ODg0NDUsMi4xMTIzMDIwOSA2LjIwNjEwNjU0LDIgNi4zNDYwNTg0NSwyIEwxNC42NTMxNzkzLDIgQzE0Ljc5MzI0NjYsMiAxNC45MTk0Njg2LDIuMTEyMzAyMDkgMTQuOTcyODg4LDIuMjg0OTA4ODUgWiIgZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJub256ZXJvIi8+PC9zdmc+');
--icon-FilterSimple: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTkuOTUwODMzMzMsMC4yMiBDOS44NzgyODY2NywwLjA4NDQ5NzcxMDggOS43MzcwMzQsLTYuMTY5Njc5NTFlLTA1IDkuNTgzMzMzMzMsLTQuNjI1OTMyOGUtMTcgTDAuNDE2NjY2NjY3LC00LjYyNTkzMjhlLTE3IEMwLjI2MzEwMzQ1NCw3LjkzMjczNDM1ZS0wNSAwLjEyMjAzMTQsMC4wODQ2MTg0ODc1IDAuMDQ5NTQ5NDAxMiwwLjIxOTk5OTUyOSBDLTAuMDIyOTMyNTk3OCwwLjM1NTM4MDU3MSAtMC4wMTUwNzQwNTE3LDAuNTE5NjU2MDYyIDAuMDcsMC42NDc1IEwzLjMzMzMzMzMzLDUuNTQyNSBMMy4zMzMzMzMzMyw5LjU4MzMzMzMzIEMzLjMzMzMzMzMzLDkuODEzNDUyIDMuNTE5ODgxMzYsMTAgMy43NSwxMCBMNi4yNSwxMCBDNi40ODAxMTg2NCwxMCA2LjY2NjY2NjY3LDkuODEzNDUyIDYuNjY2NjY2NjcsOS41ODMzMzMzMyBMNi42NjY2NjY2Nyw1LjU0MjUgTDkuOTMsMC42NDc1IEMxMC4wMTUxOTU2LDAuNTE5NzI3OTkxIDEwLjAyMzIwMTMsMC4zNTU0NTA1NDcgOS45NTA4MzMzMywwLjIyIFoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMgMykiIGZpbGw9IiMwMDAiIGZpbGwtcnVsZT0ibm9uemVybyIvPjwvc3ZnPg==');
--icon-Fireworks: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTguNjY2NDcgMTUuMzMzM0g3LjMzMzE0QzcuMzMzMTQgOS44NDc5NyA0LjQ0NzggOC42MzA2MyA0LjQxODQ3IDguNjE5M0wzLjc5OTggOC4zNzEzIDQuMjk1MTQgNy4xMzMzIDQuOTE0NDcgNy4zODA2M0M1LjAyNTE0IDcuNDI1OTcgNi45NTE4IDguMjM1MyA3Ljk5OTggMTEuMTE0IDkuMDQ3OCA4LjIzNTk3IDEwLjk3NDUgNy40MjY2MyAxMS4wODUxIDcuMzgwNjNMMTEuNzA0NSA3LjEzMzMgMTIuMTk5OCA4LjM3MTMgMTEuNTg0NSA4LjYxNzNDMTEuNDM5OCA4LjY3OTk3IDguNjY2NDcgOS45NDE5NyA4LjY2NjQ3IDE1LjMzMzN6TTEwLjQ1MzEgMS43OTA1NEw4Ljc1NzcyIDEuNTQ0NTQgNy45OTk3Mi4wMDg1NDQ5MiA3LjI0MTcyIDEuNTQ0NTQgNS41NDYzOSAxLjc5MDU0IDYuNzczMDUgMi45ODY1NCA2LjQ4MzcyIDQuNjc1MjEgNy45OTk3MiAzLjg3Nzg4IDkuNTE1NzIgNC42NzUyMSA5LjIyNjM5IDIuOTg2NTQgMTAuNDUzMSAxLjc5MDU0ek01LjI5OTE3IDEyLjM1OEwzLjY5ODUgMTIuMTI1MyAyLjk4MzE3IDEwLjY3NTMgMi4yNjcxNyAxMi4xMjUzLjY2NjUwNCAxMi4zNTggMS44MjQ1IDEzLjQ4NjYgMS41NTExNyAxNS4wODA2IDIuOTgzMTcgMTQuMzI4NiA0LjQxNDUgMTUuMDgwNiA0LjE0MTE3IDEzLjQ4NjYgNS4yOTkxNyAxMi4zNTh6TTE1LjMzMzMgMTIuMzU4TDEzLjczMjcgMTIuMTI1MyAxMy4wMTY3IDEwLjY3NTMgMTIuMzAxMyAxMi4xMjUzIDEwLjcwMDcgMTIuMzU4IDExLjg1ODcgMTMuNDg2NiAxMS41ODUzIDE1LjA4MDYgMTMuMDE2NyAxNC4zMjg2IDE0LjQ0ODcgMTUuMDgwNiAxNC4xNzUzIDEzLjQ4NjYgMTUuMzMzMyAxMi4zNTh6IiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTguNjY2MzQgNy41MzMxM1Y1LjM0MThINy4zMzMwMVY3LjUyMDQ2QzcuNTc2MjEgNy43NjgxMSA3LjgwMjUgOC4wMzE4MSA4LjAxMDM0IDguMzA5OCA4LjIxMjIgOC4wMzcxNyA4LjQzMTMyIDcuNzc3NzUgOC42NjYzNCA3LjUzMzEzek0xLjY2NjUgNy4zMzMyNUMyLjIxODc5IDcuMzMzMjUgMi42NjY1IDYuODg1NTQgMi42NjY1IDYuMzMzMjUgMi42NjY1IDUuNzgwOTcgMi4yMTg3OSA1LjMzMzI1IDEuNjY2NSA1LjMzMzI1IDEuMTE0MjIgNS4zMzMyNS42NjY1MDQgNS43ODA5Ny42NjY1MDQgNi4zMzMyNS42NjY1MDQgNi44ODU1NCAxLjExNDIyIDcuMzMzMjUgMS42NjY1IDcuMzMzMjV6TTE0LjMzMyA3LjMzMzI1QzE0Ljg4NTMgNy4zMzMyNSAxNS4zMzMgNi44ODU1NCAxNS4zMzMgNi4zMzMyNSAxNS4zMzMgNS43ODA5NyAxNC44ODUzIDUuMzMzMjUgMTQuMzMzIDUuMzMzMjUgMTMuNzgwNyA1LjMzMzI1IDEzLjMzMyA1Ljc4MDk3IDEzLjMzMyA2LjMzMzI1IDEzLjMzMyA2Ljg4NTU0IDEzLjc4MDcgNy4zMzMyNSAxNC4zMzMgNy4zMzMyNXoiIGZpbGw9IiNmZmYiLz48L3N2Zz4=');
--icon-Flag: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLWZsYWciPjxwYXRoIGQ9Ik00IDE1czEtMSA0LTEgNSAyIDggMiA0LTEgNC0xVjNzLTEgMS00IDEtNS0yLTgtMi00IDEtNCAxek00IDIyTDQgMTUiLz48L3N2Zz4=');
--icon-Flag: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9ImZlYXRoZXIgZmVhdGhlci1mbGFnIj48cGF0aCBkPSJtMC40NzEzNiwxMC43MzIxMXMwLjk0MDU0LC0wLjc4Nzg3IDMuNzYyMTYsLTAuNzg3ODdzNC43MDI2OSwxLjU3NTc0IDcuNTI0MzIsMS41NzU3NHMzLjc2MjE2LC0wLjc4Nzg3IDMuNzYyMTYsLTAuNzg3ODdsMCwtOS40NTQ0OHMtMC45NDA1NCwwLjc4Nzg3IC0zLjc2MjE2LDAuNzg3ODdzLTQuNzAyNjksLTEuNTc1NzQgLTcuNTI0MzIsLTEuNTc1NzRzLTMuNzYyMTYsMC43ODc4NyAtMy43NjIxNiwwLjc4Nzg3bDAsOS40NTQ0OHoiIHN0cm9rZT0ibnVsbCIvPjwvc3ZnPg==');
--icon-Folder: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTMsNSBMMTMsNSBDMTMuNTUyMjg0Nyw1IDE0LDUuNDQ3NzE1MjUgMTQsNiBMMTQsMTMgQzE0LDEzLjU1MjI4NDcgMTMuNTUyMjg0NywxNCAxMywxNCBMMywxNCBDMi40NDc3MTUyNSwxNCAyLDEzLjU1MjI4NDcgMiwxMyBMMiw2IEMyLDUuNDQ3NzE1MjUgMi40NDc3MTUyNSw1IDMsNSBaIE00LDIgTDEyLDIgTDEyLDQgTDQsNCBMNCwyIFoiIGZpbGw9IiMwMDAiIGZpbGwtcnVsZT0ibm9uemVybyIvPjwvc3ZnPg==');
--icon-FontBold: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZD0iTTMuMTk1MDk4OCAxLjgzNTQxOTloNS42OTAzODE4Yy43NTQ1OTUyIDAgMS40NzgyNzI0LjI5OTc1NjcgMi4wMTE4NTM0LjgzMzMzNzUuNTMzNTgxLjUzMzU4MDguODMzMzM3IDEuMjU3MjU4Mi44MzMzMzcgMi4wMTE4NTM1IDAgLjc1NDU5NTItLjI5OTc1NiAxLjQ3ODI3MjctLjgzMzMzNyAyLjAxMTg1MzVDMTAuMzYzNzUzIDcuMjI2MDQ1MSA5LjY0MDA3NTggNy41MjU4MDE4IDguODg1NDgwNiA3LjUyNTgwMThINS4wOTE4OTI3TTUuMDkxODkyNyA3LjUyNTgwMThoNS4yMTYxODMzYy44ODAzNTIgMCAxLjcyNDY1My4zNDk3MTgyIDIuMzQ3MTY5Ljk3MjIyMDcuNjIyNTAyLjYyMjUxNTIuOTcyMjIgMS40NjY4MTYxLjk3MjIyIDIuMzQ3MTY4NXYwYzAgLjg4MDM1My0uMzQ5NzE4IDEuNzI0NjU0LS45NzIyMiAyLjM0NzIxOS0uNjIyNTE2LjYyMjQwMi0xLjQ2NjgxNy45NzIxNy0yLjM0NzE2OS45NzIxN0gzLjE5NTA5ODhNNS4wOTE4OTI3IDEuODM1NDE5OVYxNC4xNjQ1OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDMwMDAwIiBzdHJva2Utd2lkdGg9IjEuMjY1IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=');
--icon-FontItalic: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PGRlZnM+PGNsaXBQYXRoIGlkPSJhIj48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMCAwSDEyVjEySDB6Ii8+PC9jbGlwUGF0aD48L2RlZnM+PGcgdHJhbnNmb3JtPSJtYXRyaXgoMS4xMzU2IDAgMCAxLjEzNTYgLjk4MyAxLjM5KSIgY2xpcC1wYXRoPSJ1cmwoI2EpIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0ibSA0Ljg3NSwwLjM3NSBoIDQuNSIgc3Ryb2tlPSIjMDAwIi8+PHBhdGggZD0ibSAyLjYyNSwxMS42MjUgaCA0LjUiIHN0cm9rZT0iIzA2MDAwMCIvPjxwYXRoIGQ9Im0gNy4xMjUsMC4zNzUgLTIuMjUsMTEuMjUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9Ii45OSIvPjwvZz48L3N2Zz4=');

View File

@ -1 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-flag"><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"></path><line x1="4" y1="22" x2="4" y2="15"></line></svg>
<svg width="16" height="12" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" class="feather feather-flag">
<g>
<title>Layer 1</title>
<path d="m0.47136,10.73211s0.94054,-0.78787 3.76216,-0.78787s4.70269,1.57574 7.52432,1.57574s3.76216,-0.78787 3.76216,-0.78787l0,-9.45448s-0.94054,0.78787 -3.76216,0.78787s-4.70269,-1.57574 -7.52432,-1.57574s-3.76216,0.78787 -3.76216,0.78787l0,9.45448z" id="svg_1" stroke="null"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 334 B

After

Width:  |  Height:  |  Size: 500 B

View File

@ -34,7 +34,7 @@ describe("LanguageSettings", function() {
const button = await langButton();
assert.isTrue(await button.isDisplayed());
// Make sure correct flag is shown.
const flag = await button.find("div").getCssValue("background-image");
const flag = await button.find(".test-language-button-icon").getCssValue("background-image");
assert.isTrue(flag.endsWith(countryCode + '.svg")'), `Flag is ${flag} search for ${countryCode}`);
// Make sure we see the all languages in the menu.
await button.click();