@linktr.ee/messaging-react 3.8.0 → 3.8.1-rc-1783410975

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 (38) hide show
  1. package/dist/{Card-BJ1ttS3d.js → Card-BRvcFjsq.js} +2 -2
  2. package/dist/{Card-BJ1ttS3d.js.map → Card-BRvcFjsq.js.map} +1 -1
  3. package/dist/{Card-DvZ0INEN.cjs → Card-BuXkok0A.cjs} +2 -2
  4. package/dist/{Card-DvZ0INEN.cjs.map → Card-BuXkok0A.cjs.map} +1 -1
  5. package/dist/{Card-VcM0VofY.js → Card-CvNHv3me.js} +2 -2
  6. package/dist/{Card-VcM0VofY.js.map → Card-CvNHv3me.js.map} +1 -1
  7. package/dist/{Card-B34_3dxf.cjs → Card-DOSuQdnk.cjs} +2 -2
  8. package/dist/{Card-B34_3dxf.cjs.map → Card-DOSuQdnk.cjs.map} +1 -1
  9. package/dist/{Card-BDzTCHou.cjs → Card-NnQw99XE.cjs} +2 -2
  10. package/dist/{Card-BDzTCHou.cjs.map → Card-NnQw99XE.cjs.map} +1 -1
  11. package/dist/{Card-Dm-jfetA.js → Card-jGOcSN1O.js} +3 -3
  12. package/dist/{Card-Dm-jfetA.js.map → Card-jGOcSN1O.js.map} +1 -1
  13. package/dist/{LockedThumbnail-BDf9eBov.js → LockedThumbnail-EsjaAqLR.js} +3 -3
  14. package/dist/{LockedThumbnail-BDf9eBov.js.map → LockedThumbnail-EsjaAqLR.js.map} +1 -1
  15. package/dist/{LockedThumbnail-DYz11nhd.cjs → LockedThumbnail-uAauUd5c.cjs} +2 -2
  16. package/dist/{LockedThumbnail-DYz11nhd.cjs.map → LockedThumbnail-uAauUd5c.cjs.map} +1 -1
  17. package/dist/assets/index.css +1 -1
  18. package/dist/{index-27SEkKTJ.js → index-BCgRoF_u.js} +10 -9
  19. package/dist/index-BCgRoF_u.js.map +1 -0
  20. package/dist/index-DRurVQ0-.cjs +2 -0
  21. package/dist/index-DRurVQ0-.cjs.map +1 -0
  22. package/dist/index.cjs +1 -1
  23. package/dist/index.js +1 -1
  24. package/package.json +2 -2
  25. package/src/components/AttachmentCard/index.tsx +1 -1
  26. package/src/components/CustomLinkPreviewList/CustomLinkPreviewCard.tsx +1 -1
  27. package/src/components/CustomMessage/CustomMessage.stories.tsx +27 -0
  28. package/src/components/CustomMessage/MessageAttachmentConversations.stories.tsx +2 -2
  29. package/src/components/CustomMessage/MessageTag.stories.tsx +2 -2
  30. package/src/components/LinkAttachment/components/_shared/CardShell.tsx +1 -1
  31. package/src/components/LockedAttachment/components/_shared/LockedCardShell.tsx +1 -1
  32. package/src/components/MediaMessage/index.tsx +8 -1
  33. package/src/components/MessageAttachment/_shared/Bubble.tsx +7 -7
  34. package/src/components/MessageAttachment/_shared/CompactDocumentRow.tsx +3 -3
  35. package/src/styles.css +101 -9
  36. package/dist/index-27SEkKTJ.js.map +0 -1
  37. package/dist/index-DupFGSXr.cjs +0 -2
  38. package/dist/index-DupFGSXr.cjs.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-DupFGSXr.cjs");exports.ActionButton=e.ActionButton;exports.Avatar=e.Avatar;exports.ChannelEmptyState=e.ChannelEmptyState;exports.ChannelList=e.ChannelList;exports.ChannelView=e.ChannelView;exports.CustomMessageProvider=e.CustomMessageProvider;exports.FaqList=e.FaqList;exports.FaqListItem=e.FaqListItem;exports.LinkAttachment=e.LinkAttachment;exports.LockedAttachment=e.LockedAttachment;exports.MediaMessage=e.MediaMessage;exports.MessageAttachment=e.MessageAttachment;exports.MessageVoteButtons=e.MessageVoteButtons;exports.MessagingProvider=e.MessagingProvider;exports.MessagingShell=e.MessagingShell;exports.buildCompactMetaLabel=e.buildCompactMetaLabel;exports.formatFileSize=e.formatFileSize;exports.formatRelativeTime=e.formatRelativeTime;exports.getFileExtensionLabel=e.getFileExtensionLabel;exports.getMessageDisplayText=e.getMessageDisplayText;exports.isLinkAttachment=e.isLinkAttachment;exports.isUuidLike=e.isUuidLike;exports.messageAttachmentGroupPositionFromStream=e.bubbleGroupPositionFromStream;exports.normalizeLanguageCode=e.normalizeLanguageCode;exports.resolveConversationParticipant=e.resolveConversationParticipant;exports.resolveLinkAttachment=e.resolveLinkAttachment;exports.resolveMediaFromMessage=e.resolveMediaFromMessage;exports.resolveParticipantDisplayName=e.resolveParticipantDisplayName;exports.useComposerLocked=e.useComposerLocked;exports.useCustomMessage=e.useCustomMessage;exports.useMessageVote=e.useMessageVote;exports.useMessaging=e.useMessaging;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-DRurVQ0-.cjs");exports.ActionButton=e.ActionButton;exports.Avatar=e.Avatar;exports.ChannelEmptyState=e.ChannelEmptyState;exports.ChannelList=e.ChannelList;exports.ChannelView=e.ChannelView;exports.CustomMessageProvider=e.CustomMessageProvider;exports.FaqList=e.FaqList;exports.FaqListItem=e.FaqListItem;exports.LinkAttachment=e.LinkAttachment;exports.LockedAttachment=e.LockedAttachment;exports.MediaMessage=e.MediaMessage;exports.MessageAttachment=e.MessageAttachment;exports.MessageVoteButtons=e.MessageVoteButtons;exports.MessagingProvider=e.MessagingProvider;exports.MessagingShell=e.MessagingShell;exports.buildCompactMetaLabel=e.buildCompactMetaLabel;exports.formatFileSize=e.formatFileSize;exports.formatRelativeTime=e.formatRelativeTime;exports.getFileExtensionLabel=e.getFileExtensionLabel;exports.getMessageDisplayText=e.getMessageDisplayText;exports.isLinkAttachment=e.isLinkAttachment;exports.isUuidLike=e.isUuidLike;exports.messageAttachmentGroupPositionFromStream=e.bubbleGroupPositionFromStream;exports.normalizeLanguageCode=e.normalizeLanguageCode;exports.resolveConversationParticipant=e.resolveConversationParticipant;exports.resolveLinkAttachment=e.resolveLinkAttachment;exports.resolveMediaFromMessage=e.resolveMediaFromMessage;exports.resolveParticipantDisplayName=e.resolveParticipantDisplayName;exports.useComposerLocked=e.useComposerLocked;exports.useCustomMessage=e.useCustomMessage;exports.useMessageVote=e.useMessageVote;exports.useMessaging=e.useMessaging;
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as e, b as t, C as i, c as o, d as n, e as m, F as r, f as g, L as l, h as M, M as c, i as u, j as L, k as h, l as d, m as p, n as v, o as C, p as A, q as k, s as F, t as P, u as b, v as f, w as x, x as y, y as S, z as q, B as z, D as B, E as D, G as E } from "./index-27SEkKTJ.js";
1
+ import { a as e, b as t, C as i, c as o, d as n, e as m, F as r, f as g, L as l, h as M, M as c, i as u, j as L, k as h, l as d, m as p, n as v, o as C, p as A, q as k, s as F, t as P, u as b, v as f, w as x, x as y, y as S, z as q, B as z, D as B, E as D, G as E } from "./index-BCgRoF_u.js";
2
2
  export {
3
3
  e as ActionButton,
4
4
  t as Avatar,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "3.8.0",
3
+ "version": "3.8.1-rc-1783410975",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -50,7 +50,7 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@linktr.ee/component-library": "11.8.6",
53
- "@linktr.ee/messaging-core": "^2.2.0",
53
+ "@linktr.ee/messaging-core": "2.3.0-rc-1783410975",
54
54
  "@phosphor-icons/react": "^2.1.10"
55
55
  },
56
56
  "devDependencies": {
@@ -57,7 +57,7 @@ const AttachmentCard: React.FC<AttachmentCardProps> = ({
57
57
  data-testid={dataTestId}
58
58
  className={classNames(
59
59
  'relative w-[280px] select-none overflow-hidden rounded-[24px] shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_4px_8px_rgba(0,0,0,0.06)]',
60
- isDark ? 'bg-[#121110]' : 'bg-white'
60
+ isDark ? 'bg-[#1e2330]' : 'bg-white'
61
61
  )}
62
62
  >
63
63
  {topLeft ? (
@@ -23,7 +23,7 @@ const CustomLinkPreviewCard: React.FC<CustomLinkPreviewCardProps> = ({
23
23
  href={og_scrape_url}
24
24
  target="_blank"
25
25
  rel="noopener noreferrer"
26
- className="relative block w-full rounded-[24px] bg-[#121110] p-2 no-underline transition-opacity hover:opacity-90"
26
+ className="relative block w-full rounded-[24px] bg-[#1e2330] p-2 no-underline transition-opacity hover:opacity-90"
27
27
  >
28
28
  {image_url && (
29
29
  <img
@@ -278,6 +278,33 @@ WithTipTag.args = {
278
278
  ],
279
279
  }
280
280
 
281
+ export const ThreeConsecutiveSentMessages: StoryFn<TemplateProps> =
282
+ Template.bind({})
283
+ ThreeConsecutiveSentMessages.args = {
284
+ messages: [
285
+ {
286
+ id: 'msg-1',
287
+ text: 'why is it that the sun',
288
+ user: storyUsers.visitor,
289
+ },
290
+ {
291
+ id: 'msg-2',
292
+ text: 'has rays',
293
+ user: storyUsers.creator,
294
+ },
295
+ {
296
+ id: 'msg-3',
297
+ text: 'how how how',
298
+ user: storyUsers.creator,
299
+ },
300
+ {
301
+ id: 'msg-4',
302
+ text: 'thanks for the note',
303
+ user: storyUsers.visitor,
304
+ },
305
+ ],
306
+ }
307
+
281
308
  export const TipOnly: StoryFn<TemplateProps> = Template.bind({})
282
309
  TipOnly.args = {
283
310
  messages: [
@@ -42,8 +42,8 @@ interface ChatNode {
42
42
  }
43
43
 
44
44
  const TEXT_BG_BY_ROLE: Record<ChatRole, string> = {
45
- sender: 'bg-[#121110] text-white',
46
- receiver: 'bg-[#e9eaed] text-[#080707]',
45
+ sender: 'bg-[#1e2330] text-white',
46
+ receiver: 'bg-[#f2f1ef] text-[#000000]',
47
47
  }
48
48
 
49
49
  const TextBubble: React.FC<{ role: ChatRole; children: React.ReactNode }> = ({
@@ -83,7 +83,7 @@ ChatbotReceiverText.parameters = skipInChromatic
83
83
  export const ChatbotSenderText: StoryFn<ComponentProps> = (args) => {
84
84
  return (
85
85
  <div className="p-12">
86
- <div className="bg-[#121110] rounded-[24px] px-4 py-3 w-[280px]">
86
+ <div className="bg-[#1e2330] rounded-[24px] px-4 py-3 w-[280px]">
87
87
  <MessageTag {...args} />
88
88
  </div>
89
89
  </div>
@@ -150,7 +150,7 @@ export const AllVariants: StoryFn = () => {
150
150
  </div>
151
151
  <div className="flex items-center gap-4">
152
152
  <span className="text-sm w-32">Chatbot (sender):</span>
153
- <div className="bg-[#121110] rounded-[24px] px-4 py-3 w-[280px]">
153
+ <div className="bg-[#1e2330] rounded-[24px] px-4 py-3 w-[280px]">
154
154
  <MessageTag
155
155
  message={createMockMessage({
156
156
  metadata: { custom_type: 'MESSAGE_CHATBOT' },
@@ -64,7 +64,7 @@ const CardShell: React.FC<CardShellProps> = ({
64
64
  const isInteractive = href != null || onClick != null
65
65
  const className = classNames(
66
66
  SHELL_CLASS,
67
- bgClassName ?? (variant === 'dark' ? 'bg-[#121110]' : 'bg-white'),
67
+ bgClassName ?? (variant === 'dark' ? 'bg-[#1e2330]' : 'bg-white'),
68
68
  // `focus-ring` is a design-system utility from the component-library
69
69
  // tailwind preset — outline-none + a black 2px focus-visible ring
70
70
  // with offset, so keyboard users can see the focused card.
@@ -26,7 +26,7 @@ const LockedCardShell: React.FC<LockedCardShellProps> = ({
26
26
  className={classNames(
27
27
  'relative w-[280px] select-none overflow-hidden rounded-md',
28
28
  'shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_1px_2px_rgba(0,0,0,0.04),0_8px_32px_rgba(0,0,0,0.1)]',
29
- variant === 'dark' ? 'bg-[#121110]' : 'bg-white'
29
+ variant === 'dark' ? 'bg-[#1e2330]' : 'bg-white'
30
30
  )}
31
31
  >
32
32
  {children}
@@ -15,7 +15,7 @@ function formatBytes(bytes: number): string {
15
15
  }
16
16
 
17
17
  function linkCardShellClass(isMyMessage: boolean) {
18
- const bg = isMyMessage ? 'bg-[#121110]' : 'bg-[#F3F3F1]'
18
+ const bg = isMyMessage ? 'bg-[#1e2330]' : 'bg-[#F3F3F1]'
19
19
  return `w-[280px] select-none overflow-hidden rounded-[24px] ${bg} shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_4px_8px_rgba(0,0,0,0.06)]`
20
20
  }
21
21
 
@@ -318,6 +318,13 @@ const MediaMessageRoot: React.FC<MediaMessageProps> = ({
318
318
  <div className="str-chat__message-bubble-wrapper">
319
319
  <div
320
320
  className="str-chat__message-bubble"
321
+ // The visible child is a self-contained AttachmentCard (white /
322
+ // #1e2330 card with its own shadow + radius), not a speech
323
+ // bubble, and this wrapper is transparent. Mark it so the
324
+ // received/sent tail in `styles.css` skips it — otherwise a
325
+ // tail tinted from the text-bubble surface (#f2f1ef) hangs off
326
+ // a white card and reads as a detached grey nub.
327
+ data-attachment-bubble="true"
321
328
  style={{ padding: 0, borderRadius: 0, overflow: 'visible', background: 'transparent' }}
322
329
  >
323
330
  {linkAttachment ? (
@@ -29,8 +29,8 @@ export interface BubbleProps {
29
29
  // Colors and metrics tracked from `stream-chat-react`'s default
30
30
  // `.str-chat__message-bubble` token set so attachments visually drop
31
31
  // into a normal `CustomMessage` thread without any seams:
32
- // - light → `--str-chat__secondary-surface-color` = grey200 (#e9eaed)
33
- // - dark → `.str-chat__message--me` override in `styles.css` (#121110)
32
+ // - light → `--str-chat__message-bubble-background-color` in `styles.css` (#f2f1ef)
33
+ // - dark → `.str-chat__message--me` override in `styles.css` (#1e2330)
34
34
  // - text padding → `--str-chat__spacing-2 --str-chat__spacing-4` = 8px 16px
35
35
  // - border-radius → `--str-chat__border-radius-md` = 18px
36
36
  //
@@ -41,13 +41,13 @@ export interface BubbleProps {
41
41
  // rebrand would need to touch every site. A central token would
42
42
  // collapse the migration to one definition.
43
43
  const BUBBLE_BG_BY_VARIANT: Record<BubbleVariant, string> = {
44
- dark: 'bg-[#121110]',
45
- light: 'bg-[#e9eaed]',
44
+ dark: 'bg-[#1e2330]',
45
+ light: 'bg-[#f2f1ef]',
46
46
  }
47
47
 
48
48
  const BUBBLE_TEXT_BY_VARIANT: Record<BubbleVariant, string> = {
49
49
  dark: 'text-white',
50
- light: 'text-[#080707]',
50
+ light: 'text-[#000000]',
51
51
  }
52
52
 
53
53
  const BUBBLE_BORDER_BY_VARIANT: Record<BubbleVariant, string> = {
@@ -104,8 +104,8 @@ const CORNER_CLASSES_BY_SIDE_AND_POSITION: Record<
104
104
  * is the file', 'Here is the image').
105
105
  *
106
106
  * Two visual variants:
107
- * - `dark` — sender-side (Composer / Sent), white text on `#121110`.
108
- * - `light` — recipient-side (Received), dark text on `#e9eaed`.
107
+ * - `dark` — sender-side (Composer / Sent), white text on `#1e2330`.
108
+ * - `light` — recipient-side (Received), dark text on `#f2f1ef`.
109
109
  *
110
110
  * Background colors, padding, border-radius, and inherited font come
111
111
  * from the stream-chat-react `.str-chat__message-bubble` token set so
@@ -41,11 +41,11 @@ export interface CompactDocumentRowProps {
41
41
  // so they stay variant-aware. The title inherits the bubble's text
42
42
  // color (set on the parent `Bubble`).
43
43
  //
44
- // `text-black/55` on the `#e9eaed` light bubble lands right at the
44
+ // `text-black/55` on the `#f2f1ef` light bubble lands right at the
45
45
  // WCAG AA 4.5:1 small-text threshold (≈4.5:1) — bump to `/65` so
46
46
  // the meta line has a comfortable margin on the light bubble. The
47
- // dark variant (`text-white/55` on `#121110`) already passes AA at
48
- // ~6:1, so we leave it alone.
47
+ // dark variant (`text-white/55` on `#1e2330`) already passes AA,
48
+ // so we leave it alone.
49
49
  const META_CLASS_BY_VARIANT: Record<BubbleVariant, string> = {
50
50
  dark: 'text-white/55',
51
51
  light: 'text-black/65',
package/src/styles.css CHANGED
@@ -8,10 +8,10 @@
8
8
  --str-chat__font-family: inherit;
9
9
 
10
10
  --str-chat__message-bubble-border-radius: 1.5rem;
11
- --str-chat__message-bubble-background-color: #f1f0ee;
12
- --str-chat__message-bubble-color: #181818;
11
+ --str-chat__message-bubble-background-color: #f2f1ef;
12
+ --str-chat__message-bubble-color: #000000;
13
13
 
14
- --str-chat__own-message-bubble-background-color: #121110;
14
+ --str-chat__own-message-bubble-background-color: #1e2330;
15
15
  --str-chat__own-message-bubble-color: #fff;
16
16
  }
17
17
 
@@ -593,7 +593,36 @@
593
593
 
594
594
  .str-chat__message .str-chat__message-bubble {
595
595
  font-size: 0.875rem;
596
- line-height: 1.25rem;
596
+ line-height: 1.3125rem;
597
+ letter-spacing: 0.14px;
598
+ }
599
+
600
+ /* Keep every bubble a full pill regardless of its position in a same-author
601
+ run. stream-chat-react's default theme flattens the inner corners of
602
+ grouped bubbles (bottom-/top-inline-end for `--me`, inline-start for
603
+ `--other`) via `.str-chat__li--{top,middle,bottom} .str-chat__message--{me,other}
604
+ .str-chat__message-bubble` rules at specificity (0,3,0). We prepend the
605
+ `.str-chat` root class to reach (0,4,0) so this wins independently of
606
+ stylesheet load order and restores the fully-rounded pill from the Figma
607
+ spec — only the trailing bubble's tail (`::after`, below) breaks the pill. */
608
+ .str-chat .str-chat__li--single .str-chat__message--me .str-chat__message-bubble,
609
+ .str-chat .str-chat__li--top .str-chat__message--me .str-chat__message-bubble,
610
+ .str-chat .str-chat__li--middle .str-chat__message--me .str-chat__message-bubble,
611
+ .str-chat .str-chat__li--bottom .str-chat__message--me .str-chat__message-bubble,
612
+ .str-chat
613
+ .str-chat__li--single
614
+ .str-chat__message--other
615
+ .str-chat__message-bubble,
616
+ .str-chat .str-chat__li--top .str-chat__message--other .str-chat__message-bubble,
617
+ .str-chat
618
+ .str-chat__li--middle
619
+ .str-chat__message--other
620
+ .str-chat__message-bubble,
621
+ .str-chat
622
+ .str-chat__li--bottom
623
+ .str-chat__message--other
624
+ .str-chat__message-bubble {
625
+ border-radius: var(--str-chat__message-bubble-border-radius);
597
626
  }
598
627
 
599
628
  /* Chatbot reply markdown — restore semantics that consumer Tailwind preflight
@@ -706,15 +735,78 @@
706
735
  margin-block-end: 0.875rem;
707
736
  }
708
737
 
709
- .str-chat__message--other .str-chat__message-bubble {
710
- border-end-start-radius: var(--str-chat__message-bubble-border-radius);
738
+ /* `:not([data-attachment-bubble])` keeps the tail off self-contained
739
+ attachment/media cards (see `MediaMessage`): those render their own
740
+ shadowed card inside a transparent bubble, so a tail tinted from the
741
+ text-bubble surface would hang off the card rather than read as part
742
+ of it. Only genuine text/message bubbles get a tail. */
743
+ .str-chat__message--other
744
+ .str-chat__message-bubble-wrapper
745
+ > .str-chat__message-bubble:last-child:not([data-attachment-bubble]) {
746
+ position: relative;
747
+ /* Form a stacking context so the `z-index: -1` tail below paints
748
+ *after* this bubble's own (opaque, same-color) background but
749
+ *behind* its in-flow content. Without this the tail would either
750
+ sit on top of content (a positioned pseudo-element paints above
751
+ in-flow siblings — switching to `::before` would NOT change that)
752
+ or drop behind the whole bubble. This matters most for the
753
+ zero-padding `MediaMessageRoot` bubble, whose media card reaches
754
+ the corner: the tail must tuck behind the card, not cover it. */
755
+ isolation: isolate;
756
+
757
+ &::after {
758
+ content: '';
759
+ position: absolute;
760
+ inset-block-end: 0;
761
+ inset-inline-start: calc(-1 * 0.25rem);
762
+ z-index: -1;
763
+ width: 1.25rem;
764
+ height: 1.4375rem;
765
+ /* Inherit the bubble's own background rather than reading the theme var
766
+ directly: the tail is visually part of the bubble, so it must track any
767
+ consumer override of the bubble surface (e.g. the Spotlight / "priority
768
+ by AI" treatment repaints `.str-chat__message-bubble` white). Reading
769
+ the var would leave the tail the default grey against a white bubble. */
770
+ background-color: inherit;
771
+ pointer-events: none;
772
+ transform: scaleX(-1);
773
+ transform-origin: center;
774
+ -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='23' fill='none'%3E%3Cpath fill='black' d='M0 0H15C15 10.1934 15.859 15.2345 19.168 21.4893C19.527 22.168 19.039 22.9917 18.274 22.9178C5.176 21.6506 0.32 6.0737 0 0Z'/%3E%3C/svg%3E")
775
+ no-repeat center / 100% 100%;
776
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='23' fill='none'%3E%3Cpath fill='black' d='M0 0H15C15 10.1934 15.859 15.2345 19.168 21.4893C19.527 22.168 19.039 22.9917 18.274 22.9178C5.176 21.6506 0.32 6.0737 0 0Z'/%3E%3C/svg%3E")
777
+ no-repeat center / 100% 100%;
778
+ }
711
779
  }
712
780
 
713
- .str-chat__message--me .str-chat__message-bubble {
714
- border-end-end-radius: var(--str-chat__message-bubble-border-radius);
781
+ .str-chat__message--me
782
+ .str-chat__message-bubble-wrapper
783
+ > .str-chat__message-bubble:last-child:not([data-attachment-bubble]) {
784
+ position: relative;
785
+ /* See the `--other` rule above: stacking context so the tail tucks
786
+ behind in-flow content (e.g. the corner of a zero-padding
787
+ `MediaMessageRoot` card) instead of painting over it. */
788
+ isolation: isolate;
789
+
790
+ &::after {
791
+ content: '';
792
+ position: absolute;
793
+ inset-block-end: 0;
794
+ inset-inline-end: calc(-1 * 0.25rem);
795
+ z-index: -1;
796
+ width: 1.25rem;
797
+ height: 1.4375rem;
798
+ /* Inherit the bubble's own background (see the `--other` tail above) so
799
+ the sent tail tracks any consumer override of the bubble surface. */
800
+ background-color: inherit;
801
+ pointer-events: none;
802
+ -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='23' fill='none'%3E%3Cpath fill='black' d='M0 0H15C15 10.1934 15.859 15.2345 19.168 21.4893C19.527 22.168 19.039 22.9917 18.274 22.9178C5.176 21.6506 0.32 6.0737 0 0Z'/%3E%3C/svg%3E")
803
+ no-repeat center / 100% 100%;
804
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='23' fill='none'%3E%3Cpath fill='black' d='M0 0H15C15 10.1934 15.859 15.2345 19.168 21.4893C19.527 22.168 19.039 22.9917 18.274 22.9178C5.176 21.6506 0.32 6.0737 0 0Z'/%3E%3C/svg%3E")
805
+ no-repeat center / 100% 100%;
806
+ }
715
807
  }
716
- }
717
808
 
809
+ }
718
810
  /* Locked attachment wrapper: stack card + text bubble in the correct direction */
719
811
  .str-chat__li .str-chat__message--me .str-chat__message-bubble-wrapper {
720
812
  display: flex;