diff --git a/src/js/picker.js b/src/js/picker.js
index 7d2b747b..0ae515e9 100644
--- a/src/js/picker.js
+++ b/src/js/picker.js
@@ -88,6 +88,7 @@ function openEmojiPanel(e) {
// Load emoji sections with optimized rendering
renderEmojiPanel();
+ initCollapsibleSections();
// Display the picker - use class instead of inline style
picker.classList.add('visible');
@@ -2031,22 +2032,6 @@ function _pcRenderGrid() {
grid.appendChild(cell);
});
- // Trailing "+" upload affordance — placed after the emojis so the
- // editor's reading order matches the picker's actual render order.
- // Hidden when the pack is empty (the big bottom dropzone is the
- // only entry point in that case) and when the cap is hit.
- if (_pc.emojis.length > 0 && _pc.emojis.length < PC_MAX_EMOJIS) {
- const addCell = document.createElement('button');
- addCell.type = 'button';
- addCell.className = 'emoji-creator-cell-add';
- addCell.setAttribute('aria-label', 'Upload emoji');
- addCell.innerHTML = '
';
- addCell.addEventListener('click', () => {
- document.getElementById('emoji-creator-files').click();
- });
- grid.appendChild(addCell);
- }
-
// Bottom dropzone label adapts: first-emoji onboarding tone, normal,
// or cap-reached.
const dz = document.getElementById('emoji-creator-dropzone');
@@ -2476,7 +2461,7 @@ function _pcShowNaming({ src, initial, batch }, mode = 'create') {
errEl.hidden = true;
errEl.textContent = '';
skipBtn.textContent = mode === 'edit' ? 'CANCEL' : 'SKIP';
- titleEl.textContent = mode === 'edit' ? 'Rename emoji' : 'Name this emoji';
+ titleEl.textContent = mode === 'edit' ? 'Rename Emoji' : 'Name This Emoji';
if (batch && batch.total > 1) {
batchEl.textContent = `${batch.current} of ${batch.total}`;
batchEl.hidden = false;
@@ -3102,8 +3087,8 @@ async function _pcDelete() {
// any click on it would trip the outside-close handler, snapping
// the picker shut mid-flow.
const ok = await _pcShowConfirm({
- title: 'Delete pack?',
- detail: 'This removes the emoji files from your media servers and the pack from Nostr. This action cannot be undone.',
+ title: 'Delete This Pack?',
+ detail: 'This action permanently removes the emoji files from your media servers and the pack from Nostr. This action cannot be undone.',
icon: 'vector_warning.svg',
tone: 'danger',
confirmText: 'DELETE',
@@ -3389,7 +3374,7 @@ function renderEmojiPackSections() {
const header = document.createElement('div');
header.className = 'emoji-section-header';
const editPencil = pack.is_own
- ? `
`
+ ? `
`
: '';
// Order: [logo][title][count][collapse-arrow] ... [edit-if-own].
// The pencil uses `margin-left: auto` (in CSS) to float right;
@@ -3617,17 +3602,13 @@ function loadEmojiSections() {
let collapsiblesInitialized = false;
function initCollapsibleSections() {
- if (collapsiblesInitialized) return; // Prevent duplicate initialization
-
- document.querySelectorAll('.emoji-section-header').forEach(header => {
- header.addEventListener('click', (e) => {
- e.stopPropagation(); // Prevent closing the picker
- const section = header.parentElement;
- section.classList.toggle('collapsed');
- });
+ document.querySelector('.emoji-main').addEventListener('click', (e) => {
+ const header = e.target.closest('.emoji-section-header');
+ if (!header) return;
+ e.stopPropagation();
+ const section = header.parentElement;
+ section.classList.toggle('collapsed');
});
-
- collapsiblesInitialized = true;
}
// Function to reset emoji picker state
diff --git a/src/styles.css b/src/styles.css
index 49762139..4e374302 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -1648,8 +1648,8 @@ html, body {
.context-menu-item .icon {
position: relative;
flex-shrink: 0;
- width: 16px;
- height: 16px;
+ width: 18px;
+ height: 18px;
margin: 0;
padding: 0;
border-radius: 0;
@@ -3198,6 +3198,10 @@ body.chat-bg-disabled .chat-messages::before {
opacity: 1;
}
+.emoji-picker:has(.emoji-pack-creator-error:not([hidden])) {
+ border: none;
+}
+
/* Wide screens: anchor the picker to the right edge of the viewport, Discord-style.
* Narrow screens stay centered (the centered position above) so the panel still
* fits comfortably without crowding the input. */
@@ -3387,6 +3391,11 @@ body.chat-bg-disabled .chat-messages::before {
display: none;
}
+.emoji-section.collapsed .emoji-pack-canvas,
+.emoji-section.collapsed canvas {
+ display: none !important;
+}
+
.emoji-grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
@@ -3481,6 +3490,9 @@ body.chat-bg-disabled .chat-messages::before {
.emoji-pack-section .emoji-section-header .emoji-pack-edit-pencil {
margin-left: auto;
}
+.emoji-pack-section .emoji-section-header .icon-chevron-down {
+ margin-left: -2px;
+}
/* Count chip — `.emoji-picker .…` prefix outranks the legacy
`.emoji-picker span { width:30px ... }` so the count is an inline
@@ -3664,8 +3676,8 @@ img.emoji-img-loading {
right: auto;
bottom: auto;
margin: 0;
- width: 14px;
- height: 14px;
+ width: 16px;
+ height: 16px;
padding: 0;
border-radius: 0;
background-color: rgba(255, 255, 255, 0.9);
@@ -3676,9 +3688,12 @@ img.emoji-img-loading {
============================================================================ */
.emoji-creator {
- padding: 4px 0 12px;
+ padding: 4px 0 0;
color: #fff;
position: relative;
+ display: flex;
+ flex-direction: column;
+ height: 100%;
}
.emoji-creator[hidden] { display: none; }
@@ -3705,8 +3720,8 @@ img.emoji-img-loading {
right: auto;
bottom: auto;
margin: 0;
- width: 14px;
- height: 14px;
+ width: 20px;
+ height: 20px;
}
.emoji-picker .emoji-creator-dropzone-label {
white-space: nowrap;
@@ -3729,8 +3744,8 @@ img.emoji-img-loading {
.emoji-creator-head {
display: flex;
align-items: center;
- gap: 8px;
- padding: 4px 0 10px;
+ gap: 6px;
+ padding: 4px 6px 10px 0;
position: sticky;
top: 0;
background-color: #0a0a0a;
@@ -3753,8 +3768,7 @@ img.emoji-img-loading {
}
.emoji-creator-logo:hover { border-color: var(--icon-color-primary); }
.emoji-creator-logo.has-image {
- border-style: solid;
- border-color: rgba(255, 255, 255, 0.08);
+ border: none;
}
.emoji-creator-logo img {
width: 100%;
@@ -3800,6 +3814,7 @@ img.emoji-img-loading {
display: flex;
align-items: center;
justify-content: center;
+ margin-left: 4px;
}
.emoji-creator-done:hover { background-color: rgba(255, 255, 255, 0.06); }
.emoji-creator-done .icon {
@@ -3849,8 +3864,7 @@ img.emoji-img-loading {
padding-top: 8px;
margin-bottom: 12px;
}
-.emoji-creator-cell,
-.emoji-creator-cell-add {
+.emoji-creator-cell {
position: relative;
aspect-ratio: 1 / 1;
border-radius: 8px;
@@ -3862,10 +3876,6 @@ img.emoji-img-loading {
padding: 0;
cursor: pointer;
transition: border-color 0.15s ease, background-color 0.15s ease;
- /* Block the WebView's default touch-handling (vertical scroll,
- pull-to-refresh, tap-to-zoom) so our pointer-driven drag-to-
- reorder gets the gesture instead. The `+` add-cell shares this
- selector but never receives a drag start, so it's harmless. */
touch-action: none;
}
.emoji-creator-cell.is-hovered { border-color: rgba(255, 255, 255, 0.18); }
@@ -3941,26 +3951,6 @@ img.emoji-img-loading {
object-fit: fill;
pointer-events: none;
}
-.emoji-creator-cell-add {
- border-style: dashed;
- border-color: rgba(255, 255, 255, 0.22);
- color: rgba(255, 255, 255, 0.7);
-}
-.emoji-creator-cell-add:hover {
- border-color: var(--icon-color-primary);
- color: var(--icon-color-primary);
-}
-.emoji-creator-cell-add.is-disabled {
- opacity: 0.35;
- pointer-events: none;
-}
-.emoji-creator-cell-add .icon {
- width: 22px;
- height: 22px;
- padding: 0;
- border-radius: 0;
- background-color: currentColor;
-}
.emoji-creator-cell-remove {
position: absolute;
@@ -3991,22 +3981,26 @@ img.emoji-img-loading {
/* Bottom dropzone — second affordance for uploading (mirrors mockup). */
.emoji-creator-dropzone {
width: 100%;
- padding: 28px 12px;
+ flex: 1;
+ min-height: 78px;
+ padding: 0;
+ margin-bottom: 12px;
background-color: rgba(255, 255, 255, 0.02);
border: 1.5px dashed rgba(255, 255, 255, 0.18);
border-radius: 10px;
color: rgba(255, 255, 255, 0.7);
display: flex;
+ flex-direction: row;
align-items: center;
justify-content: center;
- gap: 10px;
+ gap: 4px;
cursor: pointer;
- transition: border-color 0.15s ease, background-color 0.15s ease;
+ transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease;
font-size: 13px;
font-weight: 500;
}
-.emoji-creator-dropzone:hover,
-.emoji-creator-dropzone.is-dragover {
+.emoji-picker .emoji-creator-dropzone:hover,
+.emoji-picker .emoji-creator-dropzone.is-dragover {
border-color: var(--icon-color-primary);
color: var(--icon-color-primary);
background-color: rgba(89, 252, 179, 0.06);
@@ -4029,17 +4023,38 @@ img.emoji-img-loading {
justify-content: flex-end;
padding-top: 12px;
}
+
.emoji-creator-delete {
- background-color: rgba(255, 74, 138, 0.15);
- color: #ff4a8a;
+ flex-shrink: 0;
+ width: 28px;
+ height: 28px;
+ background: none;
border: none;
- padding: 6px 12px;
- border-radius: 8px;
- font-size: 12px;
- font-weight: 600;
+ padding: 0;
cursor: pointer;
+ border-radius: 6px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.emoji-creator-delete:hover {
+ background-color: rgba(255, 255, 255, 0.06);
+}
+
+.emoji-creator-delete.btn:hover {
+ opacity: 1;
+}
+
+.emoji-creator-delete .icon {
+ width: 16px;
+ height: 16px;
+ background-color: #FF2EA9;
+}
+
+.emoji-creator-delete:hover .icon {
+ background-color: #FF2EA9;
}
-.emoji-creator-delete:hover { background-color: rgba(255, 74, 138, 0.3); }
/* Confirm overlay — generalised question modal. Same in-panel chrome
as error/naming/progress (lives inside .emoji-picker so clicks can't
@@ -4049,7 +4064,7 @@ img.emoji-img-loading {
position: absolute;
inset: 0;
border-radius: inherit;
- background: rgba(8, 8, 8, 0.82);
+ background: rgba(8, 8, 8, 0.85);
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
border: 2px solid rgba(255, 255, 255, 0.12);
@@ -4075,8 +4090,8 @@ img.emoji-img-loading {
.emoji-picker .emoji-pack-creator-confirm-icon {
display: block;
margin: 0 auto 10px;
- width: 56px;
- height: 56px;
+ width: 100px;
+ height: 100px;
padding: 0;
border-radius: 0;
background: none;
@@ -4093,7 +4108,7 @@ img.emoji-img-loading {
color: #ff4a8a;
}
.emoji-pack-creator-confirm-detail {
- color: rgba(255, 255, 255, 0.65);
+ color: #fff;
font-size: 12px;
line-height: 1.5;
margin: 0 0 18px;
@@ -4106,26 +4121,33 @@ img.emoji-img-loading {
}
.emoji-pack-creator-confirm-cancel,
.emoji-pack-creator-confirm-ok {
- background-color: rgba(20, 20, 20, 0.85);
+ background-color: #171717;
color: #fff;
- border: 1px solid rgba(255, 255, 255, 0.14);
- padding: 10px 24px;
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ padding: 12px 28px;
border-radius: 10px;
font-weight: 700;
letter-spacing: 0.08em;
- font-size: 12px;
+ font-size: 14px;
cursor: pointer;
transition: border-color 0.15s ease, background-color 0.15s ease;
}
+
.emoji-pack-creator-confirm-ok {
- background-color: rgba(89, 252, 179, 0.18);
- border-color: var(--icon-color-primary);
- color: var(--icon-color-primary);
+ background-color: #58fcb3;
+ border-color: #58fcb3;
+ color: #000;
}
+
.emoji-pack-creator-confirm[data-tone="danger"] .emoji-pack-creator-confirm-ok {
- background-color: rgba(255, 74, 138, 0.18);
- border-color: #ff4a8a;
- color: #ff4a8a;
+ background-color: #ff2ea9;
+ border-color: #ff2ea9;
+ color: #000;
+}
+
+.emoji-pack-creator-confirm-cancel {
+ border-color: #ff2ea9;
+ background-color: #03030390;
}
/* Pack creator cropper overlay — square-crop UX for non-square static
uploads. Mirrors the confirm overlay's chrome (backdrop, body, action
@@ -4269,10 +4291,9 @@ img.emoji-img-loading {
cursor: not-allowed;
}
-.emoji-pack-creator-confirm-cancel:hover { border-color: rgba(255, 255, 255, 0.28); background-color: #2a2a2a; }
-.emoji-pack-creator-confirm-ok:hover { background-color: rgba(89, 252, 179, 0.30); }
-.emoji-pack-creator-confirm[data-tone="danger"] .emoji-pack-creator-confirm-ok:hover {
- background-color: rgba(255, 74, 138, 0.30);
+.emoji-pack-creator-confirm-cancel:active,
+.emoji-pack-creator-confirm-ok:active {
+ opacity: 0.8;
}
/* Progress overlay — in-panel chrome for long async ops (pack delete:
@@ -4334,7 +4355,7 @@ img.emoji-img-loading {
border-radius: inherit;
background:
linear-gradient(to top, rgba(89, 252, 179, 0.18) 0%, rgba(89, 252, 179, 0) 38%),
- rgba(8, 8, 8, 0.82);
+ rgba(8, 8, 8, 0.9);
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
border: 2px solid var(--icon-color-primary);
@@ -4352,6 +4373,9 @@ img.emoji-img-loading {
max-width: 320px;
width: 100%;
}
+.emoji-picker:has(.emoji-pack-creator-naming:not([hidden])) {
+ border: none;
+}
.emoji-pack-creator-naming-batch {
font-size: 11px;
font-weight: 700;
@@ -4402,7 +4426,7 @@ img.emoji-img-loading {
cursor: default;
}
.emoji-pack-creator-naming-input {
- background-color: rgba(255, 255, 255, 0.06);
+ background-color: #03030390;
border: 1px solid rgba(255, 255, 255, 0.14);
border-radius: 8px;
color: #fff;
@@ -4416,7 +4440,7 @@ img.emoji-img-loading {
}
.emoji-pack-creator-naming-input:focus {
border-color: var(--icon-color-primary);
- background-color: rgba(89, 252, 179, 0.06);
+ background-color: #030303;
}
.emoji-pack-creator-naming-input.is-invalid {
border-color: #ff4a8a;
@@ -4438,24 +4462,28 @@ img.emoji-img-loading {
}
.emoji-pack-creator-naming-skip,
.emoji-pack-creator-naming-save {
- background-color: rgba(20, 20, 20, 0.85);
+ background-color: #171717;
color: #fff;
- border: 1px solid rgba(255, 255, 255, 0.14);
- padding: 10px 24px;
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ padding: 12px 28px;
border-radius: 10px;
font-weight: 700;
letter-spacing: 0.08em;
- font-size: 12px;
+ font-size: 14px;
cursor: pointer;
- transition: border-color 0.15s ease, background-color 0.15s ease;
+ transition: opacity 0.15s ease;
}
.emoji-pack-creator-naming-save {
- background-color: rgba(89, 252, 179, 0.16);
- border-color: var(--icon-color-primary);
- color: var(--icon-color-primary);
+ background-color: var(--primary-color);
+ border-color: var(--primary-color);
+ color: #000;
}
-.emoji-pack-creator-naming-skip:hover { border-color: rgba(255, 255, 255, 0.28); background-color: #2a2a2a; }
-.emoji-pack-creator-naming-save:hover { background-color: rgba(89, 252, 179, 0.28); }
+.emoji-pack-creator-naming-skip {
+ border-color: rgba(255, 255, 255, 0.2);
+ background-color: #03030390;
+}
+.emoji-pack-creator-naming-skip:active,
+.emoji-pack-creator-naming-save:active { opacity: 0.8; }
.emoji-pack-creator-naming-save:disabled,
.emoji-pack-creator-naming-skip:disabled { opacity: 0.5; cursor: not-allowed; }
@@ -4466,11 +4494,9 @@ img.emoji-img-loading {
position: absolute;
inset: 0;
border-radius: inherit;
- /* Theme warning pink (#ff4a8a) glows from the bottom edge upward,
- layered on top of the dark scrim. */
background:
linear-gradient(to top, rgba(255, 74, 138, 0.32) 0%, rgba(255, 74, 138, 0) 38%),
- rgba(8, 8, 8, 0.78);
+ rgba(8, 8, 8, 0.85);
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
border: 2px solid #ff4a8a;
@@ -4483,6 +4509,9 @@ img.emoji-img-loading {
box-sizing: border-box;
}
.emoji-pack-creator-error[hidden] { display: none; }
+.emoji-picker:has(.emoji-pack-creator-error:not([hidden])) {
+ border-color: transparent;
+}
.emoji-pack-creator-error-body {
text-align: center;
max-width: 320px;
@@ -4519,20 +4548,20 @@ img.emoji-img-loading {
margin: 0 0 16px;
}
.emoji-pack-creator-error-retry {
- background-color: rgba(20, 20, 20, 0.85);
- color: #fff;
- border: 1px solid rgba(255, 255, 255, 0.14);
+ background-color: #ff2ea9;
+ color: #000;
+ border: none;
padding: 12px 28px;
border-radius: 10px;
font-weight: 700;
letter-spacing: 0.08em;
- font-size: 12px;
+ font-size: 14px;
cursor: pointer;
- transition: border-color 0.15s ease, background-color 0.15s ease;
+ transition: opacity 0.15s ease;
}
-.emoji-pack-creator-error-retry:hover {
- background-color: #2a2a2a;
- border-color: rgba(255, 255, 255, 0.28);
+
+.emoji-pack-creator-error-retry:active {
+ opacity: 0.8;
}
/* ============================================================================