Switching to a proper emojii picker
This commit is contained in:
parent
3757454f3a
commit
15d98fe19a
4 changed files with 46 additions and 81 deletions
|
|
@ -0,0 +1 @@
|
|||
Emojii picker element - https://github.com/nolanlawson/emoji-picker-element
|
||||
15
index.html
15
index.html
|
|
@ -57,21 +57,11 @@
|
|||
role="button"
|
||||
tabindex="0"
|
||||
aria-label="Current emoji — click to change"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span id="emoji-show">💬</span>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
id="emoji-input"
|
||||
class="emoji-picker-input"
|
||||
placeholder="Type or paste an emoji…"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
autocapitalize="none"
|
||||
spellcheck="false"
|
||||
aria-label="Emoji input"
|
||||
/>
|
||||
<span class="emoji-hint" id="emoji-hint">Click to change emoji</span>
|
||||
<emoji-picker id="emoji-picker"></emoji-picker>
|
||||
</div>
|
||||
|
||||
<!-- Status text -->
|
||||
|
|
@ -269,6 +259,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/emoji-picker-element@^1/index.js"></script>
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
63
script.js
63
script.js
|
|
@ -6,9 +6,7 @@ let settings = { username: "", apiKey: "", theme: "auto", mastodonPost: false };
|
|||
const $ = (id) => document.getElementById(id);
|
||||
const emojiDisplay = $("emoji-display");
|
||||
const emojiShow = $("emoji-show");
|
||||
const emojiInput = $("emoji-input");
|
||||
const emojiSection = emojiDisplay.closest(".emoji-section");
|
||||
const emojiHint = $("emoji-hint");
|
||||
const statusText = $("status-text");
|
||||
const statusUrl = $("status-url");
|
||||
const charCount = $("char-count");
|
||||
|
|
@ -31,6 +29,11 @@ function applyTheme(theme) {
|
|||
} else {
|
||||
document.documentElement.dataset.theme = theme;
|
||||
}
|
||||
const picker = document.getElementById("emoji-picker");
|
||||
if (picker) {
|
||||
picker.classList.remove("light", "dark");
|
||||
if (theme !== "auto") picker.classList.add(theme);
|
||||
}
|
||||
}
|
||||
|
||||
function updateThemeToggle(theme) {
|
||||
|
|
@ -135,65 +138,43 @@ eyeBtn.addEventListener("click", () => {
|
|||
});
|
||||
|
||||
// ── Emoji picker ─────────────────────────────────────────────────────────────
|
||||
function extractFirstEmoji(str) {
|
||||
if (!str) return null;
|
||||
if (typeof Intl?.Segmenter === "function") {
|
||||
const seg = new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
||||
for (const { segment } of seg.segment(str)) {
|
||||
if (/\p{Emoji}/u.test(segment) && segment.trim() !== "") return segment;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
const m = str.match(/\p{Emoji_Presentation}[\p{Emoji}\u{FE0F}\u{20E3}]*/u);
|
||||
return m ? m[0] : null;
|
||||
}
|
||||
|
||||
// Detect platform for hint text
|
||||
const isMac =
|
||||
/Mac/.test(navigator.userAgent) && !/iPhone|iPad/.test(navigator.userAgent);
|
||||
const osHint = isMac
|
||||
? " · or ⌃⌘Space"
|
||||
: navigator.userAgent.includes("Win")
|
||||
? " · or Win+."
|
||||
: "";
|
||||
const emojiPicker = $("emoji-picker");
|
||||
|
||||
function openEmojiPicker() {
|
||||
emojiSection.classList.add("picking");
|
||||
emojiInput.value = "";
|
||||
emojiInput.focus();
|
||||
emojiHint.textContent = `Type, paste, or use your emoji keyboard${osHint}`;
|
||||
emojiDisplay.setAttribute("aria-expanded", "true");
|
||||
}
|
||||
|
||||
function closeEmojiPicker() {
|
||||
emojiSection.classList.remove("picking");
|
||||
emojiHint.textContent = "Click to change emoji";
|
||||
emojiDisplay.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
|
||||
emojiDisplay.addEventListener("click", openEmojiPicker);
|
||||
emojiDisplay.addEventListener("click", () => {
|
||||
if (emojiSection.classList.contains("picking")) closeEmojiPicker();
|
||||
else openEmojiPicker();
|
||||
});
|
||||
|
||||
emojiDisplay.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
openEmojiPicker();
|
||||
if (emojiSection.classList.contains("picking")) closeEmojiPicker();
|
||||
else openEmojiPicker();
|
||||
}
|
||||
});
|
||||
|
||||
emojiInput.addEventListener("input", () => {
|
||||
const found = extractFirstEmoji(emojiInput.value);
|
||||
if (found) {
|
||||
emoji = found;
|
||||
emojiShow.textContent = found;
|
||||
emojiPicker.addEventListener("emoji-click", (e) => {
|
||||
emoji = e.detail.unicode;
|
||||
emojiShow.textContent = emoji;
|
||||
closeEmojiPicker();
|
||||
});
|
||||
|
||||
document.addEventListener("click", (e) => {
|
||||
if (emojiSection.classList.contains("picking") && !emojiSection.contains(e.target)) {
|
||||
closeEmojiPicker();
|
||||
}
|
||||
});
|
||||
|
||||
emojiInput.addEventListener("blur", () => {
|
||||
// Small delay so a click on the emoji-display doesn't flicker
|
||||
setTimeout(() => {
|
||||
if (document.activeElement !== emojiInput) closeEmojiPicker();
|
||||
}, 150);
|
||||
});
|
||||
|
||||
// ── Keyboard shortcuts ────────────────────────────────────────────────────────
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape") {
|
||||
|
|
|
|||
48
style.css
48
style.css
|
|
@ -199,6 +199,7 @@ main {
|
|||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.emoji-display {
|
||||
|
|
@ -229,39 +230,30 @@ main {
|
|||
background: var(--accent-dim);
|
||||
}
|
||||
|
||||
/* Visible emoji text input — slides in when picking */
|
||||
.emoji-picker-input {
|
||||
width: 200px;
|
||||
text-align: center;
|
||||
font-size: 1.5rem;
|
||||
/* collapse when hidden */
|
||||
max-height: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
overflow: hidden;
|
||||
emoji-picker {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
border-color: transparent;
|
||||
transition:
|
||||
max-height 0.2s ease,
|
||||
padding 0.18s ease,
|
||||
opacity 0.15s ease,
|
||||
border-color 0.15s ease;
|
||||
position: absolute;
|
||||
top: calc(100% + 8px);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 20;
|
||||
width: min(340px, calc(100vw - 40px));
|
||||
border-radius: var(--r);
|
||||
--background: var(--surface);
|
||||
--border-color: var(--border);
|
||||
--indicator-color: var(--accent);
|
||||
--input-border-color: var(--border);
|
||||
--input-font-color: var(--text);
|
||||
--input-placeholder-color: var(--muted);
|
||||
--outline-color: var(--accent);
|
||||
}
|
||||
|
||||
.emoji-section.picking .emoji-picker-input {
|
||||
max-height: 60px;
|
||||
padding-top: 9px;
|
||||
padding-bottom: 9px;
|
||||
.emoji-section.picking emoji-picker {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.emoji-hint {
|
||||
font-size: 0.8rem;
|
||||
color: var(--muted);
|
||||
transition: opacity 0.15s;
|
||||
visibility: visible;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* ── Form fields ───────────────────────────────────────────────────────── */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue