feat: kaomoji picker with full kaomojikuma.com library

34 categories, 3300+ kaomoji from kaomojikuma.com.
Data in web/src/lib/kaomojiData.ts (exported KAOMOJI_CATEGORIES).
EmojiPicker refactored to import from external data file.
Categories: Greetings, Joy, Sad, Mad, Stress, Love, Animals,
Action, Shy, OwO, OMG, Neutral, Kawaii, Wave, Bodily, Table,
Fight, Magic, Dance, Sleep, Run, Music, Hugs, Kiss, Wink,
Heart, Rage, Thumbs, Cheer, Drink, Write, Comfort, Flourishes.
Search by emoji text or tags. Tabbed browsing.
This commit is contained in:
2026-07-02 12:04:22 -04:00
parent 59f6a40882
commit 3a04eff42b
3 changed files with 3575 additions and 128 deletions
+4 -127
View File
@@ -1,128 +1,5 @@
import { useState, useMemo } from 'react'; import { useState, useMemo } from 'react';
import { KAOMOJI_CATEGORIES, type KaomojiItem } from '../lib/kaomojiData';
interface KaomojiItem {
emoji: string;
tags: string[];
}
interface Category {
name: string;
tabLabel: string;
items: KaomojiItem[];
}
const KAOMOJI_CATEGORIES: Category[] = [
{
name: 'Bear (Kuma)',
tabLabel: 'Bear',
items: [
{ emoji: 'ʕ•ᴥ•ʔ', tags: ['bear', 'kuma', 'animal', 'happy', 'neutral', 'cute'] },
{ emoji: 'ʕっ•ᴥ•ʔっ', tags: ['bear', 'kuma', 'hug', 'love', 'happy', 'cute'] },
{ emoji: 'ʕ•ᴥ•ʔノ♡', tags: ['bear', 'kuma', 'love', 'wave', 'happy', 'cute'] },
{ emoji: 'ʕ º ᴥ º ʔ', tags: ['bear', 'kuma', 'surprised', 'shocked', 'gasp'] },
{ emoji: 'ʕ◕ᴥ◕ʔ', tags: ['bear', 'kuma', 'cute', 'happy', 'smile'] },
{ emoji: 'ʕ ; ᴥ ; ʔ', tags: ['bear', 'kuma', 'sad', 'crying', 'tear'] },
{ emoji: 'ʕಠᴥಠʔ', tags: ['bear', 'kuma', 'angry', 'mad', 'glare'] },
{ emoji: 'ʕ*ノᴥノʔ', tags: ['bear', 'kuma', 'shy', 'blush', 'cute'] },
{ emoji: 'ʕ⊙ᴥ⊙ʔ', tags: ['bear', 'kuma', 'shocked', 'surprised', 'gasp'] },
{ emoji: 'ʕ/•ᴥ•ʔ/', tags: ['bear', 'kuma', 'happy', 'celebrate', 'dance'] },
{ emoji: 'ʕ·ᴥ·ʔ', tags: ['bear', 'kuma', 'small', 'cute', 'neutral'] },
{ emoji: '⊂( ̄(エ) ̄)⊃', tags: ['bear', 'kuma', 'big', 'hug', 'animal'] },
{ emoji: '(● ̄(エ) ̄●)', tags: ['bear', 'kuma', 'chubby', 'cute', 'neutral'] },
{ emoji: 'ʕ •ᴥ•ʔゝ☆', tags: ['bear', 'kuma', 'magic', 'star', 'happy'] },
{ emoji: 'ʕ•ᴥ•ʔ/', tags: ['bear', 'kuma', 'wave', 'hello', 'happy'] },
{ emoji: 'ʕっ•ᴥ•ʔ', tags: ['bear', 'kuma', 'reach', 'cute'] },
{ emoji: 'ʕ ⊃・ ェ ・ ʔ⊃', tags: ['bear', 'kuma', 'hug', 'reach'] },
{ emoji: 'ʕ ꈍ ᴥ ꈍ ʔ', tags: ['bear', 'kuma', 'shy', 'happy', 'smug'] },
{ emoji: 'ʕ ·(ェ)· ʔ', tags: ['bear', 'kuma', 'classic', 'neutral'] },
]
},
{
name: 'Happy / Laughing',
tabLabel: 'Joy',
items: [
{ emoji: '(^_^)', tags: ['happy', 'smile', 'classic', 'joy'] },
{ emoji: '(^o^)', tags: ['happy', 'laugh', 'excited', 'joy'] },
{ emoji: '(*^ω^*)', tags: ['happy', 'cute', 'smile', 'blush'] },
{ emoji: '(≧▽≦)', tags: ['happy', 'laugh', 'excited', 'joy', 'grin'] },
{ emoji: '(✿◠‿◠)', tags: ['happy', 'flower', 'cute', 'smile', 'peace'] },
{ emoji: '(•‿•)', tags: ['happy', 'smile', 'cute'] },
{ emoji: '(o^^o)', tags: ['happy', 'cute', 'blush', 'smile'] },
{ emoji: '( ‘‿’ )', tags: ['happy', 'smile', 'cute'] },
{ emoji: '(〇‿〇)', tags: ['happy', 'celebrate', 'excited', 'dance'] },
{ emoji: '(◕‿◕)', tags: ['happy', 'smile', 'cute'] },
{ emoji: '(>ω<)', tags: ['happy', 'excited', 'cute', 'joy'] },
{ emoji: '(★ω★)', tags: ['happy', 'excited', 'star', 'sparkle', 'eyes'] },
{ emoji: '(*^.^*)', tags: ['happy', 'smile', 'cute', 'shy'] },
]
},
{
name: 'Sad / Crying',
tabLabel: 'Sad',
items: [
{ emoji: '(T_T)', tags: ['sad', 'crying', 'tear', 'classic'] },
{ emoji: '(ಥ﹏ಥ)', tags: ['sad', 'crying', 'tear', 'cute', 'pity'] },
{ emoji: '(;_;)', tags: ['sad', 'crying', 'tear'] },
{ emoji: '(._.)', tags: ['sad', 'depressed', 'down', 'neutral'] },
{ emoji: '(._. )', tags: ['sad', 'depressed', 'down', 'shy'] },
{ emoji: '(╥﹏╥)', tags: ['sad', 'crying', 'tear', 'heavy'] },
{ emoji: '((>_<))', tags: ['sad', 'worried', 'frustrated', 'nervous'] },
{ emoji: '(#>_<)', tags: ['sad', 'frustrated', 'mad', 'angry'] },
{ emoji: '(;;)', tags: ['sad', 'crying', 'tear'] },
]
},
{
name: 'Angry / Glaring',
tabLabel: 'Mad',
items: [
{ emoji: '(ಠ_ಠ)', tags: ['angry', 'mad', 'glare', 'disapproval', 'look'] },
{ emoji: '(╯°□°)╯︵ ┻━┻', tags: ['angry', 'mad', 'table', 'flip', 'rage'] },
{ emoji: '┬─┬ノ( º _ ºノ)', tags: ['neutral', 'table', 'put', 'back', 'calm'] },
{ emoji: '(#`д´)ノ', tags: ['angry', 'mad', 'yell', 'shake'] },
{ emoji: '(¬_¬)', tags: ['suspicious', 'glare', 'annoyed', 'side-eye'] },
{ emoji: '( ̄︿ ̄)', tags: ['annoyed', 'disappointed', 'unhappy'] },
{ emoji: '(╬ಠ益ಠ)', tags: ['angry', 'mad', 'rage', 'furious'] },
{ emoji: '(凸ಠ益ಠ)凸', tags: ['angry', 'mad', 'middle', 'finger', 'rage'] },
]
},
{
name: 'Shy / Cute',
tabLabel: 'Shy',
items: [
{ emoji: '(*n_n*)', tags: ['shy', 'blush', 'cute', 'smile'] },
{ emoji: '(*ノ∀`*)', tags: ['shy', 'blush', 'embarrassed', 'cute'] },
{ emoji: '(ノωヽ)', tags: ['shy', 'blush', 'embarrassed', 'hide', 'cute'] },
{ emoji: '( ꈍ ꈍ )', tags: ['cute', 'shy', 'blush', 'happy'] },
{ emoji: '( ⁄•⁄ω⁄•⁄ )', tags: ['cute', 'shy', 'blush', 'super', 'embarrassed'] },
{ emoji: '(❤ω❤)', tags: ['love', 'cute', 'excited', 'heart'] },
]
},
{
name: 'Cats & Animals',
tabLabel: 'Pets',
items: [
{ emoji: '(=^·^=)', tags: ['cat', 'animal', 'cute', 'happy'] },
{ emoji: '(=^·ェ·^=)', tags: ['cat', 'animal', 'cute'] },
{ emoji: '(=^ ◡ ^=)', tags: ['cat', 'animal', 'happy', 'smile'] },
{ emoji: '(=^·^=)ノ', tags: ['cat', 'animal', 'wave', 'hello'] },
{ emoji: '(◕ᴥ◕)', tags: ['animal', 'cute', 'seal'] },
{ emoji: '(=^ ᆺ ^=)', tags: ['cat', 'animal', 'cute'] },
]
},
{
name: 'Action & Funny',
tabLabel: 'Misc',
items: [
{ emoji: '¯\\_(ツ)_/¯', tags: ['funny', 'shrug', 'meh', 'whatever'] },
{ emoji: '( ͡° ͜ʖ ͡°)', tags: ['funny', 'lenny', 'smug', 'face'] },
{ emoji: '(ง •̀_•́)ง', tags: ['action', 'fight', 'determined', 'fist'] },
{ emoji: '(-)(._.)', tags: ['action', 'pat', 'comfort', 'friend'] },
{ emoji: '(/°▽°)/', tags: ['action', 'happy', 'throw', 'hands'] },
{ emoji: '(°ロ°)', tags: ['surprised', 'shocked', 'gasp'] },
{ emoji: 'ヽ(°〇°)ノ', tags: ['surprised', 'shocked', 'amaze'] },
]
}
];
interface EmojiPickerProps { interface EmojiPickerProps {
onSelect: (emoji: string) => void; onSelect: (emoji: string) => void;
@@ -143,7 +20,7 @@ export function EmojiPicker({ onSelect, onClose }: EmojiPickerProps) {
for (const cat of KAOMOJI_CATEGORIES) { for (const cat of KAOMOJI_CATEGORIES) {
for (const item of cat.items) { for (const item of cat.items) {
if (seen.has(item.emoji)) continue; if (seen.has(item.emoji)) continue;
const matchesEmoji = item.emoji.includes(query); const matchesEmoji = item.emoji.toLowerCase().includes(query);
const matchesTags = item.tags.some(tag => tag.includes(query)); const matchesTags = item.tags.some(tag => tag.includes(query));
if (matchesEmoji || matchesTags) { if (matchesEmoji || matchesTags) {
results.push(item); results.push(item);
@@ -174,7 +51,7 @@ export function EmojiPicker({ onSelect, onClose }: EmojiPickerProps) {
}, [activeTab]); }, [activeTab]);
return ( return (
<div className="absolute bottom-full left-0 mb-1 bg-gb-bg border border-gb-bg-t p-2 w-[340px] max-h-[340px] overflow-y-auto z-50 shadow-lg font-mono"> <div className="absolute bottom-full left-0 mb-1 bg-gb-bg border border-gb-bg-t p-2 w-[420px] max-h-[400px] overflow-y-auto z-50 shadow-lg font-mono">
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
<span className="text-xs text-gb-fg-f">KAOMOJI PICKER</span> <span className="text-xs text-gb-fg-f">KAOMOJI PICKER</span>
<button onClick={onClose} className="text-xs text-gb-red hover:text-gb-orange font-mono">[x]</button> <button onClick={onClose} className="text-xs text-gb-red hover:text-gb-orange font-mono">[x]</button>
@@ -211,7 +88,7 @@ export function EmojiPicker({ onSelect, onClose }: EmojiPickerProps) {
)} )}
{/* Emoticons grid */} {/* Emoticons grid */}
<div className="flex flex-wrap gap-1.5 max-h-56 overflow-y-auto"> <div className="flex flex-wrap gap-1.5 max-h-64 overflow-y-auto">
{search ? ( {search ? (
searchResults.map((item) => ( searchResults.map((item) => (
<button <button
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
{"root":["./src/App.tsx","./src/main.tsx","./src/components/BotManager.tsx","./src/components/CalendarView.tsx","./src/components/ChannelList.tsx","./src/components/ChannelSettingsModal.tsx","./src/components/ChatArea.tsx","./src/components/CommandManager.tsx","./src/components/ContextMenu.tsx","./src/components/ConversationList.tsx","./src/components/CreateChannelModal.tsx","./src/components/CreateServerModal.tsx","./src/components/DMChat.tsx","./src/components/DocsView.tsx","./src/components/EmojiPicker.tsx","./src/components/ForgotPasswordPage.tsx","./src/components/ForumView.tsx","./src/components/GiphyPicker.tsx","./src/components/InstallPrompt.tsx","./src/components/InviteModal.tsx","./src/components/JoinServer.tsx","./src/components/JoinServerModal.tsx","./src/components/Layout.tsx","./src/components/ListView.tsx","./src/components/LoginForm.tsx","./src/components/MemberContextMenu.tsx","./src/components/MemberList.tsx","./src/components/MemberRoleAssign.tsx","./src/components/MentionDropdown.tsx","./src/components/MentionPopup.tsx","./src/components/MessageSearch.tsx","./src/components/MobileDrawer.tsx","./src/components/MobileNav.tsx","./src/components/NewConversationModal.tsx","./src/components/PinnedMessages.tsx","./src/components/ReactionBar.tsx","./src/components/ReplyBar.tsx","./src/components/ResetPasswordPage.tsx","./src/components/RoleManager.tsx","./src/components/ServerBar.tsx","./src/components/ServerSettingsModal.tsx","./src/components/SlashCommandPopup.tsx","./src/components/ThemeToggle.tsx","./src/components/ThreadListPanel.tsx","./src/components/ThreadPanel.tsx","./src/components/TypingIndicator.tsx","./src/components/UserProfileModal.tsx","./src/components/UserSettings.tsx","./src/components/VideoGrid.tsx","./src/components/VoiceChannel.tsx","./src/components/VoiceControls.tsx","./src/components/VoicePanel.tsx","./src/lib/api.ts","./src/lib/usePermissions.ts","./src/stores/auth.ts","./src/stores/bot.ts","./src/stores/channel.ts","./src/stores/conversation.ts","./src/stores/layout.ts","./src/stores/member.ts","./src/stores/message.ts","./src/stores/moderation.ts","./src/stores/notificationSettings.ts","./src/stores/permissions.ts","./src/stores/presence.ts","./src/stores/push.ts","./src/stores/readStates.ts","./src/stores/role.ts","./src/stores/server.ts","./src/stores/thread.ts","./src/stores/typing.ts","./src/stores/voice.ts","./src/stores/ws.ts"],"version":"5.9.3"} {"root":["./src/App.tsx","./src/main.tsx","./src/components/BotManager.tsx","./src/components/CalendarView.tsx","./src/components/ChannelList.tsx","./src/components/ChannelSettingsModal.tsx","./src/components/ChatArea.tsx","./src/components/CommandManager.tsx","./src/components/ContextMenu.tsx","./src/components/ConversationList.tsx","./src/components/CreateChannelModal.tsx","./src/components/CreateServerModal.tsx","./src/components/DMChat.tsx","./src/components/DocsView.tsx","./src/components/EmojiPicker.tsx","./src/components/ForgotPasswordPage.tsx","./src/components/ForumView.tsx","./src/components/GiphyPicker.tsx","./src/components/InstallPrompt.tsx","./src/components/InviteModal.tsx","./src/components/JoinServer.tsx","./src/components/JoinServerModal.tsx","./src/components/Layout.tsx","./src/components/ListView.tsx","./src/components/LoginForm.tsx","./src/components/MemberContextMenu.tsx","./src/components/MemberList.tsx","./src/components/MemberRoleAssign.tsx","./src/components/MentionDropdown.tsx","./src/components/MentionPopup.tsx","./src/components/MessageSearch.tsx","./src/components/MobileDrawer.tsx","./src/components/MobileNav.tsx","./src/components/NewConversationModal.tsx","./src/components/PinnedMessages.tsx","./src/components/ReactionBar.tsx","./src/components/ReplyBar.tsx","./src/components/ResetPasswordPage.tsx","./src/components/RoleManager.tsx","./src/components/ServerBar.tsx","./src/components/ServerSettingsModal.tsx","./src/components/SlashCommandPopup.tsx","./src/components/ThemeToggle.tsx","./src/components/ThreadListPanel.tsx","./src/components/ThreadPanel.tsx","./src/components/TypingIndicator.tsx","./src/components/UserProfileModal.tsx","./src/components/UserSettings.tsx","./src/components/VideoGrid.tsx","./src/components/VoiceChannel.tsx","./src/components/VoiceControls.tsx","./src/components/VoicePanel.tsx","./src/lib/api.ts","./src/lib/kaomojiData.ts","./src/lib/usePermissions.ts","./src/stores/auth.ts","./src/stores/bot.ts","./src/stores/channel.ts","./src/stores/conversation.ts","./src/stores/layout.ts","./src/stores/member.ts","./src/stores/message.ts","./src/stores/moderation.ts","./src/stores/notificationSettings.ts","./src/stores/permissions.ts","./src/stores/presence.ts","./src/stores/push.ts","./src/stores/readStates.ts","./src/stores/role.ts","./src/stores/server.ts","./src/stores/thread.ts","./src/stores/typing.ts","./src/stores/voice.ts","./src/stores/ws.ts"],"version":"5.9.3"}