Refine mobile tone/theme controls in discover header
This commit is contained in:
@@ -83,8 +83,14 @@
|
||||
<i data-lucide="search" class="w-5 h-5"></i>
|
||||
</div>
|
||||
<input id="q" type="text" placeholder="Search emojis by keyword, mood, meaning..." class="w-full bg-transparent text-white placeholder-gray-500 focus:outline-none font-medium h-full text-sm sm:text-base">
|
||||
<div class="hidden md:flex items-center pr-3">
|
||||
<kbd class="hidden sm:inline-block px-2 py-0.5 text-[10px] font-mono text-gray-500 bg-white/5 border border-white/10 rounded-md">⌘K</kbd>
|
||||
<div class="flex md:hidden items-center gap-2 pr-2">
|
||||
<button id="tone-toggle-mobile" class="w-8 h-8 rounded-full theme-surface border border-white/10 flex items-center justify-center text-gray-300 hover:text-white transition-colors shrink-0" title="Tone: Default">
|
||||
<span id="tone-dot-mobile" class="w-3 h-3 rounded-full bg-white/80 border border-white/30"></span>
|
||||
</button>
|
||||
<button id="theme-toggle-mobile" class="w-8 h-8 rounded-full theme-surface border border-white/10 flex items-center justify-center text-gray-300 hover:text-white transition-colors shrink-0">
|
||||
<span class="sr-only">Toggle theme</span>
|
||||
<i data-lucide="sun-moon" class="w-4 h-4"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -96,15 +102,10 @@
|
||||
<select id="subcategory" class="bg-[#151518] border border-white/10 rounded-xl px-4 text-sm text-gray-300 focus:outline-none focus:border-brand-ocean hover:bg-white/5 transition-colors h-11 cursor-pointer appearance-none theme-surface" disabled>
|
||||
<option value="">All Subcategories</option>
|
||||
</select>
|
||||
<select id="skin-tone" class="bg-[#151518] border border-white/10 rounded-xl px-4 text-sm text-gray-300 focus:outline-none focus:border-brand-ocean hover:bg-white/5 transition-colors h-11 cursor-pointer appearance-none theme-surface">
|
||||
<option value="off">Default tone</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="medium-light">Medium light</option>
|
||||
<option value="medium">Medium</option>
|
||||
<option value="medium-dark">Medium dark</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
<button id="theme-toggle" class="w-10 h-10 rounded-full theme-surface border border-white/10 shadow-lg flex items-center justify-center text-gray-300 hover:text-white transition-colors">
|
||||
<button id="tone-toggle" class="hidden md:flex w-10 h-10 rounded-full theme-surface border border-white/10 shadow-lg items-center justify-center text-gray-300 hover:text-white transition-colors" title="Tone: Default">
|
||||
<span id="tone-dot-desktop" class="w-4 h-4 rounded-full bg-white/80 border border-white/30"></span>
|
||||
</button>
|
||||
<button id="theme-toggle" class="hidden md:flex w-10 h-10 rounded-full theme-surface border border-white/10 shadow-lg items-center justify-center text-gray-300 hover:text-white transition-colors">
|
||||
<span class="sr-only">Toggle theme</span>
|
||||
<i data-lucide="moon" class="w-4 h-4" data-theme-icon="dark"></i>
|
||||
<i data-lucide="sun" class="w-4 h-4 hidden" data-theme-icon="light"></i>
|
||||
@@ -234,7 +235,12 @@
|
||||
const qEl = document.getElementById('q');
|
||||
const catEl = document.getElementById('category');
|
||||
const subEl = document.getElementById('subcategory');
|
||||
const toneEl = document.getElementById('skin-tone');
|
||||
const toneDesktopBtn = document.getElementById('tone-toggle');
|
||||
const toneMobileBtn = document.getElementById('tone-toggle-mobile');
|
||||
const toneDotDesktop = document.getElementById('tone-dot-desktop');
|
||||
const toneDotMobile = document.getElementById('tone-dot-mobile');
|
||||
const themeMobileBtn = document.getElementById('theme-toggle-mobile');
|
||||
const themeDesktopBtn = document.getElementById('theme-toggle');
|
||||
const grid = document.getElementById('grid');
|
||||
const count = document.getElementById('count');
|
||||
const more = document.getElementById('more');
|
||||
@@ -260,6 +266,24 @@
|
||||
const keywordEditText = document.getElementById('keyword-edit-text');
|
||||
const keywordEditLang = document.getElementById('keyword-edit-lang');
|
||||
const toneStorageKey = 'dewemoji_skin_tone';
|
||||
const toneOrder = ['off', 'light', 'medium-light', 'medium', 'medium-dark', 'dark'];
|
||||
const toneLabelMap = {
|
||||
off: 'Default',
|
||||
light: 'Light',
|
||||
'medium-light': 'Medium light',
|
||||
medium: 'Medium',
|
||||
'medium-dark': 'Medium dark',
|
||||
dark: 'Dark',
|
||||
};
|
||||
const toneColorMap = {
|
||||
off: '#ffd155',
|
||||
light: '#f6d7c3',
|
||||
'medium-light': '#e8bc95',
|
||||
medium: '#c68a62',
|
||||
'medium-dark': '#8f5f45',
|
||||
dark: '#5b3b2f',
|
||||
};
|
||||
let currentTone = 'off';
|
||||
const toneIndexMap = {
|
||||
light: 0,
|
||||
'medium-light': 1,
|
||||
@@ -328,7 +352,23 @@
|
||||
}
|
||||
|
||||
function selectedTone() {
|
||||
return String(toneEl?.value || 'off');
|
||||
return currentTone;
|
||||
}
|
||||
|
||||
function setToneControlValue(value) {
|
||||
const normalized = toneOrder.includes(String(value)) ? String(value) : 'off';
|
||||
currentTone = normalized;
|
||||
const bg = toneColorMap[normalized] || toneColorMap.off;
|
||||
const title = `Tone: ${toneLabelMap[normalized] || 'Default'}`;
|
||||
[toneDotDesktop, toneDotMobile].forEach((dot) => {
|
||||
if (!dot) return;
|
||||
dot.style.backgroundColor = bg;
|
||||
});
|
||||
[toneDesktopBtn, toneMobileBtn].forEach((btn) => {
|
||||
if (!btn) return;
|
||||
btn.title = title;
|
||||
btn.setAttribute('aria-label', title);
|
||||
});
|
||||
}
|
||||
|
||||
function emojiWithTone(item) {
|
||||
@@ -568,9 +608,27 @@
|
||||
});
|
||||
|
||||
subEl.addEventListener('change', () => fetchEmojis(true));
|
||||
toneEl?.addEventListener('change', () => {
|
||||
localStorage.setItem(toneStorageKey, selectedTone());
|
||||
const onToneChange = (nextTone = null) => {
|
||||
const tone = nextTone || selectedTone();
|
||||
setToneControlValue(tone);
|
||||
localStorage.setItem(toneStorageKey, tone);
|
||||
fetchEmojis(true);
|
||||
};
|
||||
const cycleTone = () => {
|
||||
const idx = toneOrder.indexOf(selectedTone());
|
||||
const next = toneOrder[(idx + 1) % toneOrder.length];
|
||||
onToneChange(next);
|
||||
};
|
||||
toneDesktopBtn?.addEventListener('click', cycleTone);
|
||||
toneMobileBtn?.addEventListener('click', cycleTone);
|
||||
|
||||
themeMobileBtn?.addEventListener('click', () => {
|
||||
themeDesktopBtn?.click();
|
||||
});
|
||||
|
||||
// keep mobile icon synced when desktop toggle flips theme
|
||||
themeDesktopBtn?.addEventListener('click', () => {
|
||||
setTimeout(() => lucide.createIcons(), 0);
|
||||
});
|
||||
|
||||
more.addEventListener('click', async () => {
|
||||
@@ -644,9 +702,7 @@
|
||||
}
|
||||
|
||||
(async () => {
|
||||
if (toneEl) {
|
||||
toneEl.value = localStorage.getItem(toneStorageKey) || 'off';
|
||||
}
|
||||
setToneControlValue(localStorage.getItem(toneStorageKey) || 'off');
|
||||
await loadCategories();
|
||||
if (initialCategory && state.categories[initialCategory]) {
|
||||
catEl.value = initialCategory;
|
||||
|
||||
Reference in New Issue
Block a user