@ermis-network/ermis-chat-react 1.0.9 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +144 -0
  2. package/dist/index.cjs +8320 -3427
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.css +1277 -291
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.d.mts +1131 -99
  7. package/dist/index.d.ts +1131 -99
  8. package/dist/index.mjs +8168 -3319
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +9 -4
  11. package/src/channelTypeUtils.ts +1 -1
  12. package/src/components/Avatar.tsx +2 -1
  13. package/src/components/Channel.tsx +6 -5
  14. package/src/components/ChannelActions.tsx +67 -3
  15. package/src/components/ChannelHeader.tsx +27 -37
  16. package/src/components/ChannelInfo/AddMemberModal.tsx +12 -2
  17. package/src/components/ChannelInfo/ChannelInfo.tsx +410 -187
  18. package/src/components/ChannelInfo/ChannelInfoTabs.tsx +59 -297
  19. package/src/components/ChannelInfo/ChannelSettingsPanel.tsx +30 -174
  20. package/src/components/ChannelInfo/EditChannelModal.tsx +6 -3
  21. package/src/components/ChannelInfo/MediaGridItem.tsx +215 -68
  22. package/src/components/ChannelInfo/MemberListItem.tsx +2 -3
  23. package/src/components/ChannelInfo/MessageSearchPanel.tsx +27 -126
  24. package/src/components/ChannelInfo/States.tsx +1 -1
  25. package/src/components/ChannelInfo/index.ts +3 -0
  26. package/src/components/ChannelInfo/useChannelInfoTabs.tsx +427 -0
  27. package/src/components/ChannelInfo/useChannelSettings.ts +212 -0
  28. package/src/components/ChannelInfo/useMessageSearch.tsx +141 -0
  29. package/src/components/ChannelList.tsx +247 -301
  30. package/src/components/CreateChannelModal.tsx +290 -93
  31. package/src/components/Dropdown.tsx +1 -16
  32. package/src/components/EditPreview.tsx +1 -0
  33. package/src/components/ErmisCallProvider.tsx +72 -17
  34. package/src/components/ErmisCallUI.tsx +43 -20
  35. package/src/components/FilesPreview.tsx +8 -12
  36. package/src/components/FlatTopicGroupItem.tsx +243 -0
  37. package/src/components/ForwardMessageModal.tsx +43 -81
  38. package/src/components/MediaLightbox.tsx +454 -292
  39. package/src/components/MentionSuggestions.tsx +47 -35
  40. package/src/components/MessageActionsBox.tsx +6 -1
  41. package/src/components/MessageInput.tsx +165 -17
  42. package/src/components/MessageInputDefaults.tsx +127 -1
  43. package/src/components/MessageItem.tsx +155 -43
  44. package/src/components/MessageQuickReactions.tsx +153 -23
  45. package/src/components/MessageReactions.tsx +49 -3
  46. package/src/components/MessageRenderers.tsx +1114 -445
  47. package/src/components/Panel.tsx +1 -14
  48. package/src/components/PinnedMessages.tsx +55 -15
  49. package/src/components/PreviewOverlay.tsx +24 -0
  50. package/src/components/QuotedMessagePreview.tsx +99 -8
  51. package/src/components/ReadReceipts.tsx +2 -1
  52. package/src/components/RecoveryPin/RecoveryPin.tsx +279 -0
  53. package/src/components/RecoveryPin/index.ts +19 -0
  54. package/src/components/TopicList.tsx +236 -0
  55. package/src/components/TopicModal.tsx +4 -1
  56. package/src/components/TypingIndicator.tsx +17 -8
  57. package/src/components/UserPicker.tsx +94 -16
  58. package/src/components/VirtualMessageList.tsx +419 -113
  59. package/src/context/ChatComponentsContext.tsx +14 -0
  60. package/src/context/ChatProvider.tsx +44 -14
  61. package/src/context/ErmisCallContext.tsx +4 -0
  62. package/src/hooks/useChannelCapabilities.ts +7 -4
  63. package/src/hooks/useChannelData.ts +10 -3
  64. package/src/hooks/useChannelListUpdates.ts +94 -21
  65. package/src/hooks/useChannelMessages.ts +391 -42
  66. package/src/hooks/useChannelRowUpdates.ts +36 -5
  67. package/src/hooks/useChatUser.ts +39 -0
  68. package/src/hooks/useContactChannels.ts +45 -0
  69. package/src/hooks/useContactCount.ts +50 -0
  70. package/src/hooks/useDownloadHandler.ts +36 -0
  71. package/src/hooks/useDragAndDrop.ts +79 -0
  72. package/src/hooks/useE2eeAttachmentRenderer.ts +204 -0
  73. package/src/hooks/useE2eeFileUpload.ts +38 -0
  74. package/src/hooks/useFileUpload.ts +25 -5
  75. package/src/hooks/useForwardMessage.ts +309 -0
  76. package/src/hooks/useInviteChannels.ts +88 -0
  77. package/src/hooks/useInviteCount.ts +104 -0
  78. package/src/hooks/useLoadMessages.ts +16 -4
  79. package/src/hooks/useMentions.ts +60 -7
  80. package/src/hooks/useMessageActions.ts +19 -10
  81. package/src/hooks/useMessageSend.ts +64 -12
  82. package/src/hooks/usePendingE2eeSends.ts +29 -0
  83. package/src/hooks/usePendingState.ts +21 -4
  84. package/src/hooks/usePreviewState.ts +69 -0
  85. package/src/hooks/useRecoveryPin.ts +287 -0
  86. package/src/hooks/useScrollToMessage.ts +29 -4
  87. package/src/hooks/useStickerPicker.ts +62 -0
  88. package/src/hooks/useTopicGroupUpdates.ts +235 -0
  89. package/src/index.ts +79 -6
  90. package/src/messageTypeUtils.ts +27 -1
  91. package/src/styles/_base.css +0 -1
  92. package/src/styles/_call-ui.css +59 -2
  93. package/src/styles/_channel-info.css +50 -4
  94. package/src/styles/_channel-list.css +131 -68
  95. package/src/styles/_create-channel-modal.css +10 -0
  96. package/src/styles/_forward-modal.css +16 -1
  97. package/src/styles/_media-lightbox.css +67 -2
  98. package/src/styles/_mentions.css +1 -1
  99. package/src/styles/_message-actions.css +3 -4
  100. package/src/styles/_message-bubble.css +631 -112
  101. package/src/styles/_message-input.css +139 -0
  102. package/src/styles/_message-list.css +91 -18
  103. package/src/styles/_message-quick-reactions.css +105 -32
  104. package/src/styles/_message-reactions.css +22 -32
  105. package/src/styles/_modal.css +2 -1
  106. package/src/styles/_preview-overlay.css +38 -0
  107. package/src/styles/_recovery-pin.css +97 -0
  108. package/src/styles/_tokens.css +22 -20
  109. package/src/styles/_typing-indicator.css +26 -10
  110. package/src/styles/index.css +2 -0
  111. package/src/types.ts +477 -15
  112. package/src/utils/avatarColors.ts +48 -0
  113. package/src/utils.ts +219 -16
@@ -10,6 +10,7 @@
10
10
  background-color: var(--ermis-bg-secondary);
11
11
  font-family: var(--ermis-font-family);
12
12
  position: relative;
13
+ overflow: hidden;
13
14
  }
14
15
 
15
16
  .ermis-message-input__row {
@@ -117,6 +118,56 @@
117
118
  color: var(--ermis-accent);
118
119
  }
119
120
 
121
+ /* --- Voice record button --- */
122
+ .ermis-message-input__voice-btn {
123
+ display: inline-flex;
124
+ align-items: center;
125
+ justify-content: center;
126
+ padding: 4px;
127
+ border: none;
128
+ background: none;
129
+ font-size: 1.25rem;
130
+ cursor: pointer;
131
+ color: var(--ermis-text-secondary);
132
+ transition: color var(--ermis-transition);
133
+ flex-shrink: 0;
134
+ }
135
+
136
+ .ermis-message-input__voice-btn:hover {
137
+ color: var(--ermis-accent);
138
+ }
139
+
140
+ .ermis-message-input__voice-btn--recording {
141
+ color: var(--ermis-color-danger);
142
+ }
143
+
144
+ .ermis-message-input__voice-btn:disabled {
145
+ opacity: 0.4;
146
+ cursor: not-allowed;
147
+ }
148
+
149
+ .ermis-message-input__voice-recording-indicator {
150
+ display: flex;
151
+ align-items: center;
152
+ gap: 6px;
153
+ font-size: var(--ermis-font-size-sm);
154
+ font-weight: 500;
155
+ color: var(--ermis-color-danger);
156
+ }
157
+
158
+ .ermis-message-input__voice-dot {
159
+ width: 8px;
160
+ height: 8px;
161
+ background-color: var(--ermis-color-danger);
162
+ border-radius: 50%;
163
+ animation: ermis-blink 1.5s ease-in-out infinite;
164
+ }
165
+
166
+ @keyframes ermis-blink {
167
+ 0%, 100% { opacity: 1; }
168
+ 50% { opacity: 0.4; }
169
+ }
170
+
120
171
  /* --- Emoji picker container --- */
121
172
  .ermis-message-input__emoji-picker {
122
173
  position: absolute;
@@ -129,6 +180,51 @@
129
180
  overflow: hidden;
130
181
  }
131
182
 
183
+ /* --- Sticker button --- */
184
+ .ermis-message-input__sticker-btn {
185
+ display: inline-flex;
186
+ align-items: center;
187
+ justify-content: center;
188
+ padding: 4px;
189
+ border: none;
190
+ background: none;
191
+ font-size: 1.25rem;
192
+ cursor: pointer;
193
+ color: var(--ermis-text-secondary);
194
+ transition: color var(--ermis-transition);
195
+ flex-shrink: 0;
196
+ }
197
+
198
+ .ermis-message-input__sticker-btn:hover,
199
+ .ermis-message-input__sticker-btn--active {
200
+ color: var(--ermis-accent);
201
+ }
202
+
203
+ .ermis-message-input__sticker-btn:disabled {
204
+ opacity: 0.4;
205
+ cursor: not-allowed;
206
+ }
207
+
208
+ /* --- Sticker picker container --- */
209
+ .ermis-message-input__sticker-picker-container {
210
+ position: absolute;
211
+ bottom: 100%;
212
+ right: 0;
213
+ margin-bottom: var(--ermis-spacing-xs);
214
+ z-index: 100;
215
+ border-radius: var(--ermis-radius-lg);
216
+ box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.15);
217
+ overflow: hidden;
218
+ }
219
+
220
+ .ermis-message-input__sticker-iframe {
221
+ border: none;
222
+ width: 320px;
223
+ height: 400px;
224
+ background: var(--ermis-bg-primary);
225
+ display: block;
226
+ }
227
+
132
228
  /* --- Files preview --- */
133
229
  .ermis-files-preview {
134
230
  display: flex;
@@ -224,6 +320,14 @@
224
320
  justify-content: center;
225
321
  }
226
322
 
323
+ .ermis-files-preview__progress {
324
+ color: #fff;
325
+ font-size: 11px;
326
+ font-weight: 600;
327
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
328
+ z-index: 2;
329
+ }
330
+
227
331
  .ermis-files-preview__spinner {
228
332
  width: 20px;
229
333
  height: 20px;
@@ -411,3 +515,38 @@
411
515
  border-top-left-radius: 0;
412
516
  border-top-right-radius: 0;
413
517
  }
518
+
519
+ /* ----------------------------------------------------------
520
+ Drag & Drop Overlay (Global over channel)
521
+ ---------------------------------------------------------- */
522
+ .ermis-channel__drop-overlay {
523
+ position: fixed;
524
+ inset: 0;
525
+ z-index: 9999;
526
+ background-color: var(--ermis-bg-overlay);
527
+ backdrop-filter: blur(4px);
528
+ display: flex;
529
+ align-items: center;
530
+ justify-content: center;
531
+ pointer-events: none; /* Let the window drag events pass through */
532
+ }
533
+
534
+ .ermis-channel__drop-overlay-content {
535
+ border: 2px dashed var(--ermis-accent);
536
+ border-radius: var(--ermis-radius-lg);
537
+ padding: var(--ermis-spacing-xl) var(--ermis-spacing-xxl);
538
+ display: flex;
539
+ flex-direction: column;
540
+ align-items: center;
541
+ gap: var(--ermis-spacing-md);
542
+ color: var(--ermis-accent);
543
+ background-color: var(--ermis-bg-primary);
544
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
545
+ pointer-events: none;
546
+ }
547
+
548
+ .ermis-channel__drop-overlay-content span {
549
+ font-size: var(--ermis-font-size-lg);
550
+ font-weight: 600;
551
+ font-family: var(--ermis-font-family);
552
+ }
@@ -26,18 +26,26 @@
26
26
  display: flex;
27
27
  flex-direction: column;
28
28
  flex: 1;
29
+ min-height: 0;
30
+ overflow: hidden;
29
31
  font-family: var(--ermis-font-family);
30
- gap: var(--ermis-spacing-xs);
31
32
  position: relative;
32
33
  }
33
34
 
34
35
  .ermis-message-list__vlist {
35
36
  display: flex !important;
36
37
  flex-direction: column !important;
37
- padding-left: 3rem;
38
- padding-right: 3rem;
39
- padding-top: var(--ermis-spacing-lg);
40
- padding-bottom: var(--ermis-spacing-lg);
38
+ flex: 1;
39
+ min-height: 0;
40
+ overflow-anchor: none;
41
+ padding-left: 1rem;
42
+ padding-right: 1rem;
43
+ padding-top: 1rem;
44
+ padding-bottom: 0.5rem;
45
+ }
46
+
47
+ .ermis-message-list__vlist * {
48
+ overflow-anchor: none;
41
49
  }
42
50
 
43
51
  /* Push content to bottom when few messages, margin collapses when content overflows */
@@ -93,25 +101,43 @@
93
101
  .ermis-message-list__date-separator {
94
102
  display: flex;
95
103
  align-items: center;
96
- gap: var(--ermis-spacing-md);
104
+ justify-content: center;
97
105
  padding: var(--ermis-spacing-md) 0;
98
106
  margin: var(--ermis-spacing-xs) 0;
99
107
  align-self: stretch;
100
108
  }
101
109
 
102
110
  .ermis-message-list__date-separator-line {
103
- flex: 1;
104
- height: 1px;
105
- background-color: var(--ermis-border);
111
+ display: none;
106
112
  }
107
113
 
108
114
  .ermis-message-list__date-separator-label {
109
- font-size: var(--ermis-font-size-xs);
110
- color: var(--ermis-text-muted);
115
+ font-size: 11px;
116
+ color: #fff;
117
+ background-color: rgba(0, 0, 0, 0.3);
118
+ padding: 4px 12px;
119
+ border-radius: 12px;
111
120
  white-space: nowrap;
112
121
  font-weight: 500;
113
122
  }
114
123
 
124
+ /* --- Time separator (same user, time gap > 5min) --- */
125
+ .ermis-message-list__time-separator {
126
+ display: flex;
127
+ align-items: center;
128
+ justify-content: center;
129
+ padding: var(--ermis-spacing-xs) 0;
130
+ margin: var(--ermis-spacing-xs) 0;
131
+ align-self: stretch;
132
+ }
133
+
134
+ .ermis-message-list__time-separator-label {
135
+ font-size: 10px;
136
+ color: var(--ermis-text-muted);
137
+ padding: 2px 10px;
138
+ white-space: nowrap;
139
+ font-weight: 400;
140
+ }
115
141
  .ermis-message-list__empty {
116
142
  display: flex;
117
143
  flex-direction: column;
@@ -142,21 +168,55 @@
142
168
  color: var(--ermis-text-muted);
143
169
  }
144
170
 
171
+ /* --- Message group (consecutive messages from same user) --- */
172
+ .ermis-message-group {
173
+ display: flex;
174
+ align-items: flex-end;
175
+ gap: var(--ermis-spacing-sm);
176
+ width: 100%;
177
+ padding-top: 4px;
178
+ }
179
+
180
+ .ermis-message-group--own {
181
+ flex-direction: row-reverse;
182
+ }
183
+
184
+ .ermis-message-group--other {
185
+ flex-direction: row;
186
+ }
187
+
188
+ .ermis-message-group__avatar-col {
189
+ flex-shrink: 0;
190
+ position: sticky;
191
+ bottom: 0;
192
+ align-self: flex-end;
193
+ z-index: 5;
194
+ }
195
+
196
+ .ermis-message-group__messages-col {
197
+ display: flex;
198
+ flex-direction: column;
199
+ min-width: 0;
200
+ max-width: 75%;
201
+ }
202
+
145
203
  /* --- Message item (other = left, own = right) --- */
146
204
  .ermis-message-list__item {
147
205
  display: flex;
148
- align-items: flex-start;
206
+ align-items: flex-end;
149
207
  gap: var(--ermis-spacing-sm);
150
208
  width: 100%;
151
209
  }
152
210
 
153
- /* First message in a group: normal top margin */
154
- .ermis-message-list__item--group-start {
155
- padding-top: var(--ermis-spacing-md);
211
+ /* First message in a group (or standalone): spacing handled by group wrapper */
212
+ .ermis-message-list__item--group-single,
213
+ .ermis-message-list__item--group-top {
214
+ padding-top: 0;
156
215
  }
157
216
 
158
217
  /* Continuation messages in a group: tight spacing */
159
- .ermis-message-list__item--group-cont {
218
+ .ermis-message-list__item--group-middle,
219
+ .ermis-message-list__item--group-bottom {
160
220
  padding-top: 2px;
161
221
  }
162
222
 
@@ -174,6 +234,7 @@
174
234
  0% {
175
235
  background-color: rgba(99, 102, 241, 0.15);
176
236
  }
237
+
177
238
  100% {
178
239
  background-color: transparent;
179
240
  }
@@ -186,6 +247,7 @@
186
247
  0% {
187
248
  opacity: 0;
188
249
  }
250
+
189
251
  100% {
190
252
  opacity: 1;
191
253
  }
@@ -221,6 +283,18 @@
221
283
  border: 1px solid #e74c3c;
222
284
  }
223
285
 
286
+ /* --- Deleted Display Message --- */
287
+
288
+ .ermis-message-list__deleted-text {
289
+ display: inline-flex;
290
+ align-items: center;
291
+ gap: 6px;
292
+ font-style: italic;
293
+ font-size: var(--ermis-font-size-sm);
294
+ user-select: none;
295
+ opacity: 0.5;
296
+ }
297
+
224
298
  /* --- Pinned Message Indicator --- */
225
299
  .ermis-message-list__pinned-indicator {
226
300
  position: absolute;
@@ -329,8 +403,6 @@
329
403
  transform: translateY(0);
330
404
  }
331
405
 
332
-
333
-
334
406
  /* Unblock button inside blocked overlay */
335
407
  .ermis-message-list__unblock-btn {
336
408
  margin-top: var(--ermis-spacing-md);
@@ -456,6 +528,7 @@
456
528
  transform: translateY(-2px);
457
529
  box-shadow: 0 6px 14px rgba(239, 68, 68, 0.3);
458
530
  }
531
+
459
532
  .ermis-message-list__reject-btn:active {
460
533
  transform: translateY(0);
461
534
  }
@@ -1,67 +1,140 @@
1
1
  /* ============================================================
2
- Message Quick Reactions (Hover popup)
2
+ Quick Reactions – Horizontal Strip (In Hover Actions)
3
3
  ============================================================ */
4
4
 
5
- .ermis-message-quick-reactions {
5
+ /* The wrapper is now inline-flex inside the hover actions box */
6
+ .ermis-qr-wrapper {
7
+ position: relative;
8
+ display: inline-flex;
9
+ }
10
+
11
+ /* ---- Horizontal Strip ---- */
12
+ .ermis-qr__strip--horizontal {
6
13
  position: absolute;
7
- bottom: calc(100% - 10px); /* hover right above the bubble */
14
+ bottom: calc(100% + 8px);
15
+ left: 50%;
8
16
  display: flex;
17
+ flex-direction: row;
9
18
  align-items: center;
10
19
  gap: 2px;
11
- background-color: var(--ermis-bg-primary);
20
+ background-color: var(--ermis-bg-primary, #ffffff);
12
21
  border: 1px solid var(--ermis-border);
13
- padding: 4px;
14
22
  border-radius: 20px;
15
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
23
+ padding: 4px;
24
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
25
+ z-index: 101;
26
+ width: max-content;
27
+
28
+ /* Animation */
16
29
  opacity: 0;
17
- visibility: hidden;
18
- pointer-events: none;
19
- transform: translateY(8px);
20
- transition: opacity 0.2s ease, transform 0.2s ease;
21
- z-index: 20;
30
+ transform: translateX(-50%) scale(0.95);
31
+ animation: ermis-qr-pop-centered 0.15s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
22
32
  }
23
33
 
24
- /* Align based on ownership */
25
- .ermis-message-quick-reactions {
34
+ /* Invisible bridge to prevent hover loss when moving mouse from trigger to strip */
35
+ .ermis-qr__strip--horizontal::after {
36
+ content: '';
37
+ position: absolute;
38
+ top: 100%;
26
39
  left: 0;
40
+ width: 100%;
41
+ height: 12px; /* Covers the 8px gap + some extra safe area */
42
+ }
43
+
44
+ @keyframes ermis-qr-pop-centered {
45
+ to {
46
+ opacity: 1;
47
+ transform: translateX(-50%) scale(1);
48
+ }
27
49
  }
28
- .ermis-message-quick-reactions--own {
29
- left: auto;
30
- right: 0;
50
+
51
+ @keyframes ermis-qr-pop {
52
+ to {
53
+ opacity: 1;
54
+ transform: scale(1);
55
+ }
31
56
  }
32
57
 
33
- .ermis-message-list__bubble-wrapper:hover .ermis-message-quick-reactions {
34
- opacity: 1;
35
- visibility: visible;
36
- pointer-events: auto;
37
- transform: translateY(0);
58
+ /* Positioning based on message owner */
59
+ .ermis-message-list__item--own .ermis-qr__strip--horizontal {
60
+ left: 50%; /* Center it relative to the wrapper */
38
61
  }
39
62
 
40
- .ermis-message-list__bubble-wrapper:hover .ermis-message-quick-reactions--disabled {
41
- opacity: 0.5;
42
- pointer-events: none;
63
+ .ermis-message-list__item--other .ermis-qr__strip--horizontal {
64
+ left: 50%; /* Center it relative to the wrapper */
43
65
  }
44
66
 
45
- .ermis-message-quick-reactions__btn {
67
+ /* ---- Emoji Buttons ---- */
68
+ .ermis-qr__emoji {
46
69
  display: flex;
47
70
  align-items: center;
48
71
  justify-content: center;
49
- background: none;
72
+ background: transparent;
50
73
  border: none;
51
- font-size: 18px;
74
+ font-size: 16px;
52
75
  line-height: 1;
53
76
  width: 32px;
54
77
  height: 32px;
55
78
  border-radius: 50%;
56
79
  cursor: pointer;
57
- transition: transform 0.15s cubic-bezier(0.175, 0.885, 0.32, 1.275), background-color 0.15s;
80
+ transition: transform 0.15s cubic-bezier(0.175, 0.885, 0.32, 1.275),
81
+ background-color 0.15s;
82
+ padding: 0;
83
+ outline: none;
84
+ color: inherit;
85
+ flex-shrink: 0;
58
86
  }
59
87
 
60
- .ermis-message-quick-reactions__btn:hover {
88
+ .ermis-qr__emoji:hover {
61
89
  transform: scale(1.2);
62
- background-color: var(--ermis-bg-hover);
90
+ background-color: rgba(0, 0, 0, 0.05);
91
+ }
92
+
93
+ .ermis-qr__emoji--active {
94
+ background-color: rgba(99, 102, 241, 0.1);
95
+ }
96
+
97
+ .ermis-qr__emoji--more {
98
+ color: var(--ermis-text-muted);
99
+ font-size: 14px;
100
+ }
101
+
102
+ .ermis-qr__emoji--more:hover {
103
+ color: var(--ermis-text-primary);
104
+ }
105
+
106
+ /* ---- Full Emoji Picker ---- */
107
+ .ermis-qr__picker {
108
+ position: absolute;
109
+ width: 350px;
110
+ height: 368px;
111
+ border-radius: 16px;
112
+ overflow: hidden;
113
+ background-color: var(--ermis-bg-primary);
114
+ border: 1px solid var(--ermis-border);
115
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1),
116
+ 0 8px 10px -6px rgba(0, 0, 0, 0.1);
117
+ z-index: 102;
118
+
119
+ /* Animation */
120
+ opacity: 0;
121
+ transform: scale(0.95);
122
+ animation: ermis-qr-pop 0.15s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
63
123
  }
64
124
 
65
- .ermis-message-quick-reactions__btn--active {
66
- background-color: var(--ermis-bg-active, rgba(99, 102, 241, 0.12));
125
+ .ermis-qr__picker--top {
126
+ bottom: calc(100% + 8px);
67
127
  }
128
+
129
+ .ermis-qr__picker--bottom {
130
+ top: calc(100% + 8px);
131
+ }
132
+
133
+ .ermis-message-list__item--own .ermis-qr__picker {
134
+ right: -8px;
135
+ }
136
+
137
+ .ermis-message-list__item--other .ermis-qr__picker {
138
+ left: -8px;
139
+ }
140
+
@@ -2,12 +2,12 @@
2
2
  Message Reactions
3
3
  ============================================================ */
4
4
  .ermis-message-reactions {
5
- display: flex;
5
+ display: inline-flex;
6
6
  flex-wrap: wrap;
7
7
  gap: 4px;
8
- margin-bottom: 2px;
9
- margin-top: 2px;
10
- width: 100%;
8
+ margin-top: 4px;
9
+ max-width: 100%;
10
+ vertical-align: middle;
11
11
  }
12
12
 
13
13
  .ermis-message-reactions--disabled {
@@ -15,6 +15,10 @@
15
15
  pointer-events: none;
16
16
  }
17
17
 
18
+ .ermis-message-reactions--own {
19
+ justify-content: flex-end;
20
+ }
21
+
18
22
  .ermis-message-reactions__item {
19
23
  position: relative; /* For tooltip */
20
24
  display: inline-flex;
@@ -22,7 +26,7 @@
22
26
  gap: 4px;
23
27
  padding: 2px 6px;
24
28
  border-radius: 12px;
25
- background-color: var(--ermis-surface);
29
+ background-color: var(--ermis-bg-hover);
26
30
  border: 1px solid var(--ermis-border);
27
31
  font-size: 11px;
28
32
  line-height: 1.2;
@@ -32,39 +36,25 @@
32
36
  user-select: none;
33
37
  }
34
38
 
35
- /* Custom Tooltip */
36
- .ermis-message-reactions__item::after {
37
- content: attr(data-tooltip);
38
- position: absolute;
39
- bottom: 100%;
40
- left: 50%;
41
- transform: translateX(-50%);
42
- background-color: rgba(0, 0, 0, 0.75);
43
- color: #fff;
44
- padding: 4px 8px;
45
- border-radius: 6px;
46
- font-size: 11px;
47
- white-space: pre;
48
- text-align: left;
49
- pointer-events: none;
50
- opacity: 0;
51
- visibility: hidden;
52
- transition: opacity 0.2s, visibility 0.2s;
53
- margin-bottom: 6px;
54
- z-index: 100;
55
- }
56
-
57
- .ermis-message-reactions__item:hover::after {
58
- opacity: 1;
59
- visibility: visible;
60
- }
61
-
62
39
  .ermis-message-reactions__item--active {
63
40
  background-color: var(--ermis-bg-active, rgba(99, 102, 241, 0.12));
64
41
  border-color: var(--ermis-accent);
65
42
  color: var(--ermis-accent);
66
43
  }
67
44
 
45
+ /* Own bubble overrides — pills need contrast against accent bg */
46
+ .ermis-message-bubble--own .ermis-message-reactions__item {
47
+ background-color: rgba(255, 255, 255, 0.2);
48
+ border-color: rgba(255, 255, 255, 0.3);
49
+ color: rgba(255, 255, 255, 0.9);
50
+ }
51
+
52
+ .ermis-message-bubble--own .ermis-message-reactions__item--active {
53
+ background-color: rgba(255, 255, 255, 0.35);
54
+ border-color: rgba(255, 255, 255, 0.6);
55
+ color: #ffffff;
56
+ }
57
+
68
58
  .ermis-message-reactions__emoji {
69
59
  font-size: 14px;
70
60
  }
@@ -85,8 +85,9 @@
85
85
  padding: 20px;
86
86
  display: flex;
87
87
  flex-direction: column;
88
- overflow: hidden;
88
+ overflow-y: auto;
89
89
  flex: 1;
90
+ min-height: 0;
90
91
  }
91
92
 
92
93
  .ermis-modal-footer {
@@ -0,0 +1,38 @@
1
+ /* ----------------------------------------------------------
2
+ PreviewOverlay
3
+ ---------------------------------------------------------- */
4
+ .ermis-preview-overlay {
5
+ display: flex;
6
+ align-items: center;
7
+ justify-content: space-between;
8
+ padding: var(--ermis-spacing-md);
9
+ background-color: var(--ermis-bg-secondary);
10
+ border-top: 1px solid var(--ermis-border);
11
+ font-family: var(--ermis-font-family);
12
+ }
13
+
14
+ .ermis-preview-overlay__text {
15
+ font-size: var(--ermis-font-size-sm);
16
+ color: var(--ermis-text-secondary);
17
+ font-weight: 500;
18
+ }
19
+
20
+ .ermis-preview-overlay__button {
21
+ background-color: var(--ermis-accent);
22
+ color: #ffffff;
23
+ border: none;
24
+ border-radius: var(--ermis-radius-md);
25
+ padding: var(--ermis-spacing-sm) var(--ermis-spacing-md);
26
+ font-size: var(--ermis-font-size-sm);
27
+ font-weight: 600;
28
+ cursor: pointer;
29
+ transition: opacity 0.2s ease, transform 0.1s ease;
30
+ }
31
+
32
+ .ermis-preview-overlay__button:hover {
33
+ opacity: 0.9;
34
+ }
35
+
36
+ .ermis-preview-overlay__button:active {
37
+ transform: scale(0.98);
38
+ }