Skip to content

Commit ae01b21

Browse files
committed
feat: Add visual highlight for selected language in dropdown
1 parent 66db267 commit ae01b21

File tree

3 files changed

+106
-4
lines changed

3 files changed

+106
-4
lines changed

css/themes.css

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@
143143
.dark #confirmation-message {
144144
color: #e2e2e2;
145145
}
146+
146147
body {
147148
--border: #cccccc;
148149
--bg: #ffffff;
@@ -159,4 +160,16 @@ body.dark {
159160
--accent: #3fe0d1;
160161
}
161162

162-
/* Your Custom Theme can go here if you don't want to modify the existing dark mode */
163+
/* Your Custom Theme can go here if you don't want to modify the existing dark mode */
164+
165+
/* Selected language highlight in language dropdown */
166+
#languagedropdown li a.selected-language {
167+
background-color: rgba(33, 150, 243, 0.15);
168+
border-left: 3px solid #2196F3;
169+
font-weight: 600;
170+
}
171+
172+
.dark #languagedropdown li a.selected-language {
173+
background-color: rgba(33, 150, 243, 0.25);
174+
border-left: 3px solid #64B5F6;
175+
}

js/__tests__/toolbar.test.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -886,8 +886,25 @@ describe("Toolbar Class", () => {
886886

887887
test("renderLanguageSelectIcon sets onclick and updates language selection", () => {
888888
const languageSelectIcon = { onclick: null };
889-
const languageBox = { setAttribute: jest.fn() };
890-
global.docById.mockReturnValue(languageSelectIcon);
889+
const languageBox = { enUS_onclick: jest.fn() };
890+
891+
// Mock elements for all language IDs with classList
892+
const mockLangElement = {
893+
onclick: null,
894+
classList: {
895+
add: jest.fn(),
896+
remove: jest.fn()
897+
}
898+
};
899+
900+
global.docById.mockImplementation(id => {
901+
if (id === "languageSelectIcon") return languageSelectIcon;
902+
// Return mock element with classList for any language ID
903+
return mockLangElement;
904+
});
905+
906+
global.localStorage.languagePreference = "enUS";
907+
891908
toolbar.renderLanguageSelectIcon(languageBox);
892909
expect(languageSelectIcon.onclick).toBeInstanceOf(Function);
893910
languageSelectIcon.onclick();

js/toolbar.js

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1175,9 +1175,81 @@ class Toolbar {
11751175
"ur"
11761176
];
11771177

1178+
/**
1179+
* Updates the selected-language class to highlight the currently selected language.
1180+
* @param {string} selectedLang - The language code to highlight.
1181+
*/
1182+
const updateSelectedLanguageHighlight = selectedLang => {
1183+
// Remove existing selection from all language items
1184+
languages.forEach(lang => {
1185+
const langElem = docById(lang);
1186+
if (langElem) {
1187+
langElem.classList.remove("selected-language");
1188+
}
1189+
});
1190+
1191+
// Handle special cases for language preference storage values and browser language codes
1192+
let langToHighlight = selectedLang;
1193+
1194+
// Map browser language codes to dropdown IDs
1195+
const browserLangMap = {
1196+
"en-US": "enUS",
1197+
"en-GB": "enUK",
1198+
"en-UK": "enUK",
1199+
"zh-CN": "zhCN",
1200+
"zh": "zhCN"
1201+
};
1202+
1203+
// Check if it's a browser language code that needs mapping
1204+
if (selectedLang && browserLangMap[selectedLang]) {
1205+
langToHighlight = browserLangMap[selectedLang];
1206+
}
1207+
1208+
// Handle Japanese variants (ja-kanji, ja-kana stored vs ja/kana displayed)
1209+
if (selectedLang && selectedLang.startsWith("ja")) {
1210+
if (selectedLang === "ja-kana" || localStorage.kanaPreference === "kana") {
1211+
langToHighlight = "kana";
1212+
} else {
1213+
langToHighlight = "ja";
1214+
}
1215+
}
1216+
1217+
// Handle zh_CN to zhCN mapping (stored preference format)
1218+
if (selectedLang === "zh_CN") {
1219+
langToHighlight = "zhCN";
1220+
}
1221+
1222+
// Fallback: if language starts with "en" but not mapped, default to enUS
1223+
if (
1224+
selectedLang &&
1225+
selectedLang.startsWith("en") &&
1226+
!languages.includes(langToHighlight)
1227+
) {
1228+
langToHighlight = "enUS";
1229+
}
1230+
1231+
const selectedElem = docById(langToHighlight);
1232+
if (selectedElem) {
1233+
selectedElem.classList.add("selected-language");
1234+
}
1235+
};
1236+
11781237
languageSelectIcon.onclick = () => {
1238+
// Get current language preference
1239+
const currentLang = localStorage.languagePreference || navigator.language;
1240+
1241+
// Highlight the currently selected language
1242+
updateSelectedLanguageHighlight(currentLang);
1243+
1244+
// Set up click handlers for each language
11791245
languages.forEach(lang => {
1180-
docById(lang).onclick = () => languageBox[`${lang}_onclick`](this.activity);
1246+
docById(lang).onclick = () => {
1247+
// Update highlight to newly selected language
1248+
updateSelectedLanguageHighlight(lang);
1249+
1250+
// Call the original language change handler
1251+
languageBox[`${lang}_onclick`](this.activity);
1252+
};
11811253
});
11821254
};
11831255
}

0 commit comments

Comments
 (0)