diff --git a/app/client/ui/LanguageMenu.ts b/app/client/ui/LanguageMenu.ts index a25c1371..c155cefd 100644 --- a/app/client/ui/LanguageMenu.ts +++ b/app/client/ui/LanguageMenu.ts @@ -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; +const cssFirstUpper = styled('span', ` + &::first-letter { + text-transform: capitalize; + } +`); + +const cssFlagButton = styled(cssHoverCircle, ` + display: flex; + align-items: center; + justify-content: center; + margin: 5px; cursor: pointer; - user-select: none; `); -const cssSvgIcon = styled('div', ` +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}; `); diff --git a/static/icons/icons.css b/static/icons/icons.css index 9abc7963..6c960343 100644 --- a/static/icons/icons.css +++ b/static/icons/icons.css @@ -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='); diff --git a/static/ui-icons/UI/Flag.svg b/static/ui-icons/UI/Flag.svg index 037737cb..8dbb1066 100644 --- a/static/ui-icons/UI/Flag.svg +++ b/static/ui-icons/UI/Flag.svg @@ -1 +1,6 @@ - \ No newline at end of file + + + Layer 1 + + + diff --git a/test/nbrowser/LanguageSettings.ts b/test/nbrowser/LanguageSettings.ts index d0ca5ba3..551dca2a 100644 --- a/test/nbrowser/LanguageSettings.ts +++ b/test/nbrowser/LanguageSettings.ts @@ -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();