aboutsummaryrefslogtreecommitdiffstats
path: root/src/style.css
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-15 09:27:45 -0700
committerAdam Soltys <[email protected]>2026-09-15 09:27:45 -0700
commitc90d0f3c600802b5b4b43959df5fd2d02f78012c (patch)
tree0bb36a804eda41415e2d3e871bc6475836f8f99e /src/style.css
parentfeadbb008de9b2fe2332a7f0e190955ae545f07d (diff)
downloadcoinosv3-c90d0f3c600802b5b4b43959df5fd2d02f78012c.tar.gz
coinosv3-c90d0f3c600802b5b4b43959df5fd2d02f78012c.zip
Custom emoji in chat: :shortcodes: render as pictures, packs sync with Vector.
A message from Vector says :pika_wave: and carries a NIP-30 ["emoji", code, url] tag for it; coinos showed the bare shortcode. Now the bubble shows the picture (in rooms, DMs, the feed and the public /chat page), a bubble that is only one to three of them shows them big, and a :code: reaction chip is a picture too. Sending: every :code: you type that resolves travels with its tag, so the other side renders it whether or not they hold the pack. Shortcodes come from packs you hold (NIP-51 kind 30030 sets) and from what you've seen in chat, so anyone can answer a :pika_wave: with one. The composer autocompletes on ":pi" (Tab/Enter takes the first), the reaction picker lists custom emoji first, and Vector's pack share link renders with an Add button; a pasted naddr works too. Packs live on your kind 10030 list — the one Vector reads and writes — so a pack added in either app appears in both. tools/emoji-test.js drives the real coinos room headlessly and checks all of the above. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
Diffstat (limited to 'src/style.css')
-rw-r--r--src/style.css29
1 files changed, 29 insertions, 0 deletions
diff --git a/src/style.css b/src/style.css
index 4bb7c5b..f969cee 100644
--- a/src/style.css
+++ b/src/style.css
@@ -1014,3 +1014,32 @@ body::after {
.emoji-grid button.on { border-color: var(--accent); }
.hub-list { max-height: 360px; overflow-y: auto; }
.hub-icon { object-fit: cover; }
+
+/* custom emoji (NIP-30): an inline picture the height of a capital, sat on
+ the baseline like the character it stands for */
+.cemoji { display: inline-block; height: 1.4em; width: auto; max-width: 3em; vertical-align: -0.35em; object-fit: contain; }
+/* a bubble that is nothing but one to three of them shows them big */
+.chat-bubble.jumbo .cemoji { height: 2.8em; max-width: 5em; vertical-align: middle; }
+.chat-react .cemoji { height: 1.25em; vertical-align: -0.3em; }
+.emoji-grid .cemoji { height: 28px; max-width: 36px; vertical-align: middle; }
+.msg-sheet-emojis .cemoji { height: 22px; vertical-align: middle; }
+/* the :shortcode: strip above the composer */
+.emoji-ac { display: flex; flex-wrap: wrap; gap: 4px; }
+.emoji-ac:empty { display: none; }
+.emoji-ac button {
+ display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; font-size: 18px; line-height: 1;
+ border: 1px solid var(--line); border-radius: 10px; background: var(--paper);
+}
+.emoji-ac button .small { font-size: 12px; color: var(--muted); }
+.emoji-ac .cemoji { height: 22px; vertical-align: middle; }
+/* the packs behind the picker, and the add box */
+.emoji-packs { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
+.emoji-pack { display: inline-flex; align-items: center; gap: 2px; }
+.emoji-pack .linklike { padding: 0 2px; font-size: 14px; color: var(--muted); }
+/* Vector's pack share link: named, with its Add button */
+.pack-link { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
+.pack-link .btn-sm { padding: 3px 10px; }
+/* a custom emoji whose picture won't load falls back to its :code: alt text;
+ in the 40px grid cell that text must not spill into the next cell */
+.emoji-grid button { overflow: hidden; }
+.emoji-grid .cemoji { font-size: 8px; }