Add skin tone support for discover grid and emoji detail
This commit is contained in:
@@ -96,6 +96,14 @@
|
||||
<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">
|
||||
<span class="sr-only">Toggle theme</span>
|
||||
<i data-lucide="moon" class="w-4 h-4" data-theme-icon="dark"></i>
|
||||
@@ -226,6 +234,7 @@
|
||||
const qEl = document.getElementById('q');
|
||||
const catEl = document.getElementById('category');
|
||||
const subEl = document.getElementById('subcategory');
|
||||
const toneEl = document.getElementById('skin-tone');
|
||||
const grid = document.getElementById('grid');
|
||||
const count = document.getElementById('count');
|
||||
const more = document.getElementById('more');
|
||||
@@ -250,6 +259,14 @@
|
||||
const keywordEditSlug = document.getElementById('keyword-edit-slug');
|
||||
const keywordEditText = document.getElementById('keyword-edit-text');
|
||||
const keywordEditLang = document.getElementById('keyword-edit-lang');
|
||||
const toneStorageKey = 'dewemoji_skin_tone';
|
||||
const toneIndexMap = {
|
||||
light: 0,
|
||||
'medium-light': 1,
|
||||
medium: 2,
|
||||
'medium-dark': 3,
|
||||
dark: 4,
|
||||
};
|
||||
|
||||
if (initialQuery) qEl.value = initialQuery;
|
||||
|
||||
@@ -310,6 +327,20 @@
|
||||
return String(s || '').replace(/[&<>"']/g, (c) => ({ '&':'&','<':'<','>':'>','"':'"',"'":''' }[c]));
|
||||
}
|
||||
|
||||
function selectedTone() {
|
||||
return String(toneEl?.value || 'off');
|
||||
}
|
||||
|
||||
function emojiWithTone(item) {
|
||||
const tone = selectedTone();
|
||||
if (tone === 'off') return item.emoji;
|
||||
if (!item?.supports_skin_tone) return item.emoji;
|
||||
const variants = Array.isArray(item?.variants) ? item.variants : [];
|
||||
const idx = toneIndexMap[tone];
|
||||
if (typeof idx === 'number' && variants[idx]) return variants[idx];
|
||||
return item.emoji_base || item.emoji;
|
||||
}
|
||||
|
||||
function applyGridDensity(level) {
|
||||
const sizes = [
|
||||
{ min: 90, emoji: '2.2rem' },
|
||||
@@ -484,12 +515,12 @@
|
||||
}
|
||||
|
||||
items.forEach((item) => {
|
||||
const isPrivate = item.source === 'private';
|
||||
const renderedEmoji = emojiWithTone(item);
|
||||
const card = document.createElement('div');
|
||||
card.className = 'emoji-card relative aspect-square rounded-lg bg-white/5 hover:bg-white/10 transition-transform hover:scale-[1.02] border border-transparent hover:border-white/20 overflow-hidden group';
|
||||
card.innerHTML = `
|
||||
<a href="/emoji/${encodeURIComponent(item.slug)}" class="absolute inset-0 flex items-center justify-center pb-10">
|
||||
<span class="leading-none" style="font-size:var(--emoji-size)">${esc(item.emoji)}</span>
|
||||
<span class="leading-none" style="font-size:var(--emoji-size)">${esc(renderedEmoji)}</span>
|
||||
</a>
|
||||
<div class="emoji-card-bar absolute bottom-0 left-0 right-0 border-t border-white/10 bg-black/20 px-2 py-1.5 flex items-start gap-1">
|
||||
<span class="emoji-name-clamp text-[10px] text-gray-300 text-left flex-1">${esc(item.name)}</span>
|
||||
@@ -501,17 +532,17 @@
|
||||
copyBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
navigator.clipboard.writeText(item.emoji).then(() => {
|
||||
showToast('Copied ' + item.emoji);
|
||||
addRecent(item.emoji);
|
||||
navigator.clipboard.writeText(renderedEmoji).then(() => {
|
||||
showToast('Copied ' + renderedEmoji);
|
||||
addRecent(renderedEmoji);
|
||||
});
|
||||
});
|
||||
}
|
||||
card.addEventListener('contextmenu', (e) => {
|
||||
e.preventDefault();
|
||||
navigator.clipboard.writeText(item.emoji).then(() => {
|
||||
showToast('Copied ' + item.emoji);
|
||||
addRecent(item.emoji);
|
||||
navigator.clipboard.writeText(renderedEmoji).then(() => {
|
||||
showToast('Copied ' + renderedEmoji);
|
||||
addRecent(renderedEmoji);
|
||||
});
|
||||
});
|
||||
grid.appendChild(card);
|
||||
@@ -537,6 +568,10 @@
|
||||
});
|
||||
|
||||
subEl.addEventListener('change', () => fetchEmojis(true));
|
||||
toneEl?.addEventListener('change', () => {
|
||||
localStorage.setItem(toneStorageKey, selectedTone());
|
||||
fetchEmojis(true);
|
||||
});
|
||||
|
||||
more.addEventListener('click', async () => {
|
||||
state.page += 1;
|
||||
@@ -609,6 +644,9 @@
|
||||
}
|
||||
|
||||
(async () => {
|
||||
if (toneEl) {
|
||||
toneEl.value = localStorage.getItem(toneStorageKey) || 'off';
|
||||
}
|
||||
await loadCategories();
|
||||
if (initialCategory && state.categories[initialCategory]) {
|
||||
catEl.value = initialCategory;
|
||||
|
||||
Reference in New Issue
Block a user