The popover emoji picker (both quick presets and full picker) was
publishing reactions internally without triggering haptic feedback.
Add impactLight() at the top of publishReaction() so every emoji
selection path gets tactile feedback.
Custom emoji images with natural dimensions <= 16x16 now render with
image-rendering: pixelated to preserve crisp pixels instead of blurring.
Also consolidates 6 direct <img> sites to use the shared CustomEmojiImg
component so all custom emoji rendering benefits from this behavior.
Custom emojis were explicitly excluded from usage tracking, so they could
never accumulate enough count to appear in the quick-react popover. The
bar already handles displaying and filtering custom emojis correctly
(including removing stale ones from deleted packs), so the only missing
piece was the tracking call.
Two bugs prevented NIP-30 custom emoji reactions from working on /i/
pages (e.g. country pages):
1. Publishing: QuickReactMenu's onReact callback discarded the emoji
tag, so kind 17 events were published without the ['emoji', name,
url] tag needed to resolve custom emojis. Now passes emojiTag
through to the callback.
2. Display: The reaction button rendered a plain <span> that showed
raw :shortcode: text. Now uses ReactionEmoji component which
resolves custom emoji images from the event's tags.
Also updated useExternalUserReaction to return the event's tags
alongside the emoji string so custom emojis can be rendered.
Closes#62
- Remove CustomEmojiPicker.tsx and useUserEmojiPacks.ts (replaced by
Derek's useCustomEmojis + emoji-mart custom categories)
- Update EmojiPackContent to use local kind 10030 query
- Update EmojiShortcodeAutocomplete to use useCustomEmojis
- Fix quick reaction buttons to render custom emojis as images
- Fix quick reaction buttons to include emoji tag when reacting
- Filter stale custom emojis from quick reaction row
- Add emoji tags to compose box mock event for preview rendering
Integrate custom emojis from the user's kind 10030 emoji list into
the emoji picker, compose flow, reactions, and DMs:
Hook:
- useCustomEmojis: query kind 10030, extract emoji shortcode/url pairs
EmojiPicker:
- Accept customEmojis prop, render as dedicated 'Custom' tab via
emoji-mart's custom categories feature
- Changed onSelect from string to EmojiSelection union type
(native unicode | custom shortcode+url)
ComposeBox:
- Pass custom emojis to picker, insert :shortcode: on selection
- Scan content on publish for :shortcode: patterns, cross-reference
against user's emoji list, add ['emoji', name, url] tags (NIP-30)
QuickReactMenu:
- Custom emoji reactions: content=':shortcode:', with emoji tag
- Optimistic cache update includes custom emoji URL/name
DMChatArea:
- Pass custom emojis to picker, insert :shortcode: text
Settings:
- Registered as 'Custom Emojis' in Other Stuff > Whimsy section
- showCustomEmojis toggle (default true) gates all custom emoji
features — when disabled, no kind 10030 queries are made
- Fix pre-existing Bot icon missing import in sidebarItems
The accent (secondary) color is now gold/amber which looks wrong for
active nav states, section titles, and interactive backgrounds. Change
these to use foreground or neutral surface colors instead:
- Left sidebar active items: text-accent -> text-foreground
- Right sidebar headings: text-accent -> text-foreground
- Mobile bottom nav active items: text-accent -> text-foreground
- Mobile explore drawer active items: text-accent -> text-foreground
- Quick react emoji picker: hover:bg-accent -> hover:bg-secondary
- Section labels (Explore, Settings, My Themes): text-accent/70 -> text-muted-foreground
- Search page trending heading and Rising tab: text-accent -> text-foreground/text-primary
- Sidebar theme palette icon: text-accent -> text-primary
The popover's mouse-leave timeout was firing during the DOM transition
from the quick-select bar to the full emoji-mart picker, causing it to
close immediately. Added an expanded state flag that disables the
hover-to-close behavior when the full picker is shown.
Close the popover via onClose callback when an emoji is selected from
the full picker. Add a 300ms cooldown (justClosedRef) to prevent the
popover from immediately reopening via hover when the picker disappears
and the cursor lands on the trigger button.
Custom emoji reactions from kind 7 events with emoji tags were displaying
the raw shortcode text (e.g., ':soapbox:') instead of rendering the image.
Add custom emoji resolution throughout the reaction pipeline: data hooks
now extract emoji URLs from event tags, and all rendering locations
(ReactionButton, PostDetailPage stats, InteractionsModal, Notifications)
now display custom emojis as inline images.
The relay needs time to index newly published events. Immediate
invalidation caused a refetch that returned stale counts, overwriting
the optimistic +1 and making the count briefly appear then vanish.
- Add true optimistic updates for reactions and reposts via setQueryData
instead of only invalidating queries after publish
- Track user's own reaction per event and display their emoji in place of
the Heart icon across feed, post details, and notifications
- Strip whitespace around block embeds and skipped media URLs to eliminate
blank lines caused by whitespace-pre-wrap
- Only render link preview cards for standalone URLs; inline URLs in
sentences render as plain clickable links
- Remove border-b separators and use fixed-height object-cover on preview
images to eliminate gaps
- Tighten padding on EmbeddedNote and EmbeddedNaddr cards
- Use fixed-height object-cover for ImageGallery grid images
- Unify RepostMenu to use Popover on all screen sizes instead of Drawer
on mobile
- Clicking "..." now replaces quick menu with full emoji picker
- Removed nested Popover that was causing the menu to close
- Full picker stays open and functional within the same popover
- Simplified state management with showFullPicker boolean
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Created useEmojiUsage hook to track user's most-used emojis
- QuickReactMenu now shows user's top 6 emojis, falling back to defaults
- Default emojis: ❤️, 👍, 👎, 😂, 😮, 😢
- ReactionButton triggers menu on hover for faster access
- Menu aligns to start (left) to begin from the heart icon
- Emoji usage persists per user in localStorage
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Created QuickReactMenu component with horizontal emoji bar
- Quick access to 6 common emojis (❤️, 😂, 💯, 🔥, 👍, 📌)
- "..." button opens full EmojiPicker for more options
- Updated ReactionButton to use QuickReactMenu instead of full picker
- Matches Ditto UX: click shows quick react menu, ... reveals full picker
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>