@linktr.ee/messaging-react 3.12.1 → 3.13.0-rc-1783924547

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.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-CxYkk8Bd.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.MessageBubble=e.MessageBubble;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-DJwZVg6y.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.MessageBubble=e.MessageBubble;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.d.ts CHANGED
@@ -206,7 +206,7 @@ export declare const ChannelView: default_2.NamedExoticComponent<ChannelViewProp
206
206
  * Props that MessagingShell passes through to ChannelView.
207
207
  * ChannelViewProps is the source of truth for these props.
208
208
  */
209
- declare type ChannelViewPassthroughProps = Pick<ChannelViewProps, 'renderMessageInputActions' | 'renderConversationFooter' | 'CustomChannelEmptyState' | 'onBlockParticipantClick' | 'onReportParticipantClick' | 'dmAgentEnabled' | 'onMessageSent' | 'chatbotVotingEnabled' | 'viewerLanguage' | 'renderHeaderTitleBadges' | 'renderChannelBanner' | 'customChannelActions' | 'renderChannelActions' | 'onParticipantNameClick' | 'renderMessage' | 'onMessageLinkClick' | 'showChannelInfo' | 'composerInput'>;
209
+ declare type ChannelViewPassthroughProps = Pick<ChannelViewProps, 'renderMessageInputActions' | 'renderConversationFooter' | 'CustomChannelEmptyState' | 'onBlockParticipantClick' | 'onReportParticipantClick' | 'dmAgentEnabled' | 'onMessageSent' | 'chatbotVotingEnabled' | 'viewerLanguage' | 'renderChannelBanner' | 'customChannelActions' | 'renderChannelActions' | 'onParticipantNameClick' | 'renderMessage' | 'onMessageLinkClick' | 'showChannelInfo' | 'composerInput'>;
210
210
 
211
211
  /**
212
212
  * ChannelView component props
@@ -309,8 +309,8 @@ export declare interface ChannelViewProps {
309
309
  */
310
310
  showStarButton?: boolean;
311
311
  /**
312
- * Custom badges rendered inline after the participant name in the channel
313
- * header title.
312
+ * @deprecated No longer rendered. The redesigned header shows built-in paid
313
+ * and starred badges instead. Kept temporarily so existing call sites type-check.
314
314
  */
315
315
  renderHeaderTitleBadges?: (context: {
316
316
  channel: Channel;
@@ -425,10 +425,9 @@ export declare interface ChannelViewProps {
425
425
  */
426
426
  composerInput?: ComponentType;
427
427
  /**
428
- * Fired when the participant's name in the channel header is clicked. When
429
- * provided, the name renders as a button with a trailing caret (an affordance
430
- * for opening participant details / thread content); when omitted, the name
431
- * renders as plain text.
428
+ * Fired when the participant identity in the channel header is clicked. When
429
+ * provided, the avatar + name pill render as a button with a trailing caret;
430
+ * when omitted, they render as non-interactive chrome.
432
431
  *
433
432
  * @example
434
433
  * onParticipantNameClick={() => openThreadContentDialog()}
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 u, i as c, 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 b, u as P, v as f, w as x, x as y, y as B, z as S, B as q, D as z, E as D, G as E, H as V } from "./index-thS5zrVb.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 u, i as c, 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 b, u as P, v as f, w as x, x as y, y as B, z as S, B as q, D as z, E as D, G as E, H as V } from "./index-C-dn7Ime.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.12.1",
3
+ "version": "3.13.0-rc-1783924547",
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-1783924547",
54
54
  "@phosphor-icons/react": "^2.1.10"
55
55
  },
56
56
  "devDependencies": {
@@ -58,7 +58,7 @@ interface ChannelHeaderRedesignProps {
58
58
  customChannelActions?: React.ReactNode
59
59
  renderChannelActions?: React.ReactNode
60
60
  showChannelInfo?: boolean
61
- onParticipantNameClick: () => void
61
+ onParticipantNameClick?: () => void
62
62
  }
63
63
 
64
64
  export const ChannelHeaderRedesign: React.FC<ChannelHeaderRedesignProps> = ({
@@ -113,6 +113,58 @@ export const ChannelHeaderRedesign: React.FC<ChannelHeaderRedesignProps> = ({
113
113
  }
114
114
  }
115
115
 
116
+ const identityContent = (
117
+ <>
118
+ <Avatar
119
+ id={participant?.user?.id || channel.id || 'unknown'}
120
+ name={participantName}
121
+ image={participantImage}
122
+ dmAgentEnabled={dmAgentEnabled}
123
+ shape="circle"
124
+ size={48}
125
+ className="-mb-2"
126
+ />
127
+ <span className="relative z-10 flex max-w-full flex-col items-center justify-center rounded-full border border-white/10 bg-white/65 py-1.5 pl-3 pr-2 shadow-[0px_0px_0px_0px_rgba(0,0,0,0.04),0px_1px_2px_0px_rgba(0,0,0,0.04),0px_8px_32px_0px_rgba(0,0,0,0.1)] backdrop-blur-[2px] transition-filter duration-150 group-hover:brightness-95">
128
+ <span className="flex max-w-full items-center justify-center">
129
+ <span className="min-w-0 truncate text-sm font-bold leading-[1.43] tracking-[0.28px] text-black/90">
130
+ {participantName}
131
+ </span>
132
+ <span className="ml-2 flex gap-1">
133
+ {isPaidCustomer && (
134
+ <span
135
+ aria-label="Paid customer"
136
+ className="flex size-4 shrink-0 items-center justify-center rounded-full bg-[#34C759] text-white"
137
+ >
138
+ <CurrencyDollarIcon className="size-2.5" weight="bold" />
139
+ </span>
140
+ )}
141
+ {showStarButton && isStarred && (
142
+ <span
143
+ aria-label="Starred conversation"
144
+ className="flex size-4 shrink-0 items-center justify-center rounded-full bg-[#FFD60A] text-white"
145
+ >
146
+ <StarIcon className="size-2.5" weight="fill" />
147
+ </span>
148
+ )}
149
+ {onParticipantNameClick && (
150
+ <CaretRightIcon
151
+ aria-hidden="true"
152
+ className="size-4 shrink-0 text-black/65"
153
+ weight="bold"
154
+ />
155
+ )}
156
+ </span>
157
+ </span>
158
+ {dmAgentEnabled && (
159
+ <span className="mt-1 flex items-center gap-1 px-1 pb-0.5 text-[10px] leading-3 text-black/55">
160
+ <SparkleIcon className="size-3 shrink-0 text-black/55" />
161
+ <span>{DM_AGENT_HEADER_HELPER_TEXT}</span>
162
+ </span>
163
+ )}
164
+ </span>
165
+ </>
166
+ )
167
+
116
168
  return (
117
169
  <div
118
170
  className={classNames(
@@ -138,58 +190,20 @@ export const ChannelHeaderRedesign: React.FC<ChannelHeaderRedesignProps> = ({
138
190
  </div>
139
191
 
140
192
  <div className="flex min-w-0 justify-center" data-dd-privacy="mask">
141
- <button
142
- type="button"
143
- onClick={onParticipantNameClick}
144
- aria-label={`View details for ${participantName}`}
145
- className="group flex min-w-0 max-w-full appearance-none flex-col items-center border-0 bg-transparent px-2 focus-ring focus-visible:outline-none"
146
- >
147
- <Avatar
148
- id={participant?.user?.id || channel.id || 'unknown'}
149
- name={participantName}
150
- image={participantImage}
151
- dmAgentEnabled={dmAgentEnabled}
152
- shape="circle"
153
- size={48}
154
- className="-mb-2"
155
- />
156
- <span className="relative z-10 flex max-w-full flex-col items-center justify-center rounded-full border border-white/10 bg-white/65 py-1.5 pl-3 pr-2 shadow-[0px_0px_0px_0px_rgba(0,0,0,0.04),0px_1px_2px_0px_rgba(0,0,0,0.04),0px_8px_32px_0px_rgba(0,0,0,0.1)] backdrop-blur-[2px] transition-filter duration-150 group-hover:brightness-95">
157
- <span className="flex max-w-full items-center justify-center">
158
- <span className="min-w-0 truncate text-sm font-bold leading-[1.43] tracking-[0.28px] text-black/90">
159
- {participantName}
160
- </span>
161
- <span className="ml-2 flex gap-1">
162
- {isPaidCustomer && (
163
- <span
164
- aria-label="Paid customer"
165
- className="flex size-4 shrink-0 items-center justify-center rounded-full bg-[#34C759] text-white"
166
- >
167
- <CurrencyDollarIcon className="size-2.5" weight="bold" />
168
- </span>
169
- )}
170
- {showStarButton && isStarred && (
171
- <span
172
- aria-label="Starred conversation"
173
- className="flex size-4 shrink-0 items-center justify-center rounded-full bg-[#FFD60A] text-white"
174
- >
175
- <StarIcon className="size-2.5" weight="fill" />
176
- </span>
177
- )}
178
- <CaretRightIcon
179
- aria-hidden="true"
180
- className="size-4 shrink-0 text-black/65"
181
- weight="bold"
182
- />
183
- </span>
184
- </span>
185
- {dmAgentEnabled && (
186
- <span className="mt-1 flex items-center gap-1 px-1 pb-0.5 text-[10px] leading-3 text-black/55">
187
- <SparkleIcon className="size-3 shrink-0 text-black/55" />
188
- <span>{DM_AGENT_HEADER_HELPER_TEXT}</span>
189
- </span>
190
- )}
191
- </span>
192
- </button>
193
+ {onParticipantNameClick ? (
194
+ <button
195
+ type="button"
196
+ onClick={onParticipantNameClick}
197
+ aria-label={`View details for ${participantName}`}
198
+ className="group flex min-w-0 max-w-full appearance-none flex-col items-center border-0 bg-transparent px-2 focus-ring focus-visible:outline-none"
199
+ >
200
+ {identityContent}
201
+ </button>
202
+ ) : (
203
+ <div className="flex min-w-0 max-w-full flex-col items-center px-2">
204
+ {identityContent}
205
+ </div>
206
+ )}
193
207
  </div>
194
208
 
195
209
  <div className="flex items-start justify-end gap-2">
@@ -215,72 +215,77 @@ type TemplateProps = ComponentProps & {
215
215
  image?: string
216
216
  }
217
217
  participantCustomerTag?: string
218
- hasScrollableMessages?: boolean
219
- }
220
-
221
- const Template: StoryFn<TemplateProps> = (args) => {
222
- const {
223
- hasMessages = true,
224
- followerStatus,
225
- isFrozen = false,
226
- participantCustomerTag,
227
- hasScrollableMessages,
228
- typingUser,
229
- ...channelViewProps
230
- } = args
231
- const [client] = React.useState(() => createMockStreamChatClient(mockUser))
232
-
233
- const [channel, setChannel] = React.useState<ChannelType | null>(null)
218
+ }
234
219
 
235
- useEffect(() => {
236
- createMockChannel(
220
+ const createTemplate = (
221
+ options: { hasScrollableMessages?: boolean } = {}
222
+ ): StoryFn<TemplateProps> => {
223
+ const Template: StoryFn<TemplateProps> = (args) => {
224
+ const {
225
+ hasMessages = true,
226
+ followerStatus,
227
+ isFrozen = false,
228
+ participantCustomerTag,
229
+ typingUser,
230
+ ...channelViewProps
231
+ } = args
232
+ const [client] = React.useState(() => createMockStreamChatClient(mockUser))
233
+
234
+ const [channel, setChannel] = React.useState<ChannelType | null>(null)
235
+
236
+ useEffect(() => {
237
+ createMockChannel(
238
+ client,
239
+ hasMessages,
240
+ followerStatus,
241
+ isFrozen,
242
+ participantCustomerTag,
243
+ options.hasScrollableMessages
244
+ ).then((mockChannel) => {
245
+ setChannel(mockChannel)
246
+ })
247
+ }, [
237
248
  client,
238
249
  hasMessages,
239
250
  followerStatus,
240
251
  isFrozen,
241
252
  participantCustomerTag,
242
- hasScrollableMessages
243
- ).then((mockChannel) => {
244
- setChannel(mockChannel)
245
- })
246
- }, [
247
- client,
248
- hasMessages,
249
- followerStatus,
250
- isFrozen,
251
- participantCustomerTag,
252
- hasScrollableMessages,
253
- ])
253
+ ])
254
254
 
255
- useEffect(() => {
256
- if (!channel || !typingUser) {
257
- return
258
- }
255
+ useEffect(() => {
256
+ if (!channel || !typingUser) {
257
+ return
258
+ }
259
259
 
260
- const timer = setTimeout(() => {
261
- client.dispatchEvent({
262
- type: 'typing.start',
263
- cid: channel.cid,
264
- user: typingUser,
265
- })
266
- }, 0)
260
+ const timer = setTimeout(() => {
261
+ client.dispatchEvent({
262
+ type: 'typing.start',
263
+ cid: channel.cid,
264
+ user: typingUser,
265
+ })
266
+ }, 0)
267
267
 
268
- return () => clearTimeout(timer)
269
- }, [channel, client, typingUser])
268
+ return () => clearTimeout(timer)
269
+ }, [channel, client, typingUser])
270
270
 
271
- if (!channel) {
272
- return <div>Loading...</div>
271
+ if (!channel) {
272
+ return <div>Loading...</div>
273
+ }
274
+
275
+ return (
276
+ <Chat client={client}>
277
+ <div className="h-screen w-full bg-[#FBFAF9]">
278
+ <ChannelView {...channelViewProps} channel={channel} />
279
+ </div>
280
+ </Chat>
281
+ )
273
282
  }
274
283
 
275
- return (
276
- <Chat client={client}>
277
- <div className="h-screen w-full bg-[#FBFAF9]">
278
- <ChannelView {...channelViewProps} channel={channel} />
279
- </div>
280
- </Chat>
281
- )
284
+ return Template
282
285
  }
283
286
 
287
+ const Template = createTemplate()
288
+
284
289
  export const Default: StoryFn<TemplateProps> = Template.bind({})
285
290
  Default.args = {
286
291
  showBackButton: false,
@@ -294,7 +299,7 @@ Default.args = {
294
299
  Default.parameters = {
295
300
  docs: {
296
301
  description: {
297
- story: 'Default channel view with messages and conversation header.',
302
+ story: 'Default channel view with messages and the redesigned header.',
298
303
  },
299
304
  },
300
305
  }
@@ -306,7 +311,6 @@ ParticipantIdentityTrigger.args = {
306
311
  showBackButton: false,
307
312
  showStarButton: true,
308
313
  participantCustomerTag: 'CUSTOMER_PAID',
309
- hasScrollableMessages: true,
310
314
  onParticipantNameClick: () =>
311
315
  // eslint-disable-next-line no-alert
312
316
  window.alert('Participant details clicked — open Thread content'),
@@ -315,7 +319,22 @@ ParticipantIdentityTrigger.parameters = {
315
319
  docs: {
316
320
  description: {
317
321
  story:
318
- 'Header with `onParticipantNameClick` set: the redesigned floating header centers the avatar and name pill, shows paid/star badges when present, and fires the callback when clicked (shows an alert here). With the prop omitted (see Default) the previous header remains in use.',
322
+ 'Header with `onParticipantNameClick` set: the avatar and name pill become a button with a trailing caret, and the callback fires on click (shows an alert here).',
323
+ },
324
+ },
325
+ }
326
+
327
+ export const WithScrollableMessageList: StoryFn<TemplateProps> = createTemplate({
328
+ hasScrollableMessages: true,
329
+ }).bind({})
330
+ WithScrollableMessageList.args = {
331
+ showBackButton: false,
332
+ }
333
+ WithScrollableMessageList.parameters = {
334
+ docs: {
335
+ description: {
336
+ story:
337
+ 'Long thread that scrolls under the sticky redesigned header.',
319
338
  },
320
339
  },
321
340
  }
@@ -339,27 +358,6 @@ DmAgentHeader.parameters = {
339
358
  },
340
359
  }
341
360
 
342
- export const WithHeaderTitleBadges: StoryFn<TemplateProps> = Template.bind({})
343
- WithHeaderTitleBadges.args = {
344
- showBackButton: false,
345
- renderHeaderTitleBadges: ({ participant }) => (
346
- <span
347
- aria-label={`${participant?.user?.name ?? 'Participant'} is a customer`}
348
- className="flex size-4 items-center justify-center rounded-full bg-[#E8F8EF] text-[10px] font-semibold text-[#136C3A]"
349
- >
350
- $
351
- </span>
352
- ),
353
- }
354
- WithHeaderTitleBadges.parameters = {
355
- docs: {
356
- description: {
357
- story:
358
- 'Renders custom badges inline after the participant name in the channel header via renderHeaderTitleBadges.',
359
- },
360
- },
361
- }
362
-
363
361
  export const RestrictedOfficialChannel: StoryFn<TemplateProps> = Template.bind(
364
362
  {}
365
363
  )
@@ -190,24 +190,18 @@ describe('ChannelView', () => {
190
190
  expect(lastActionsMenuProps().showReportParticipant).toBe(false)
191
191
  })
192
192
 
193
- it('renders the participant name without an info trigger', () => {
193
+ it('renders the redesigned header without a participant click trigger by default', () => {
194
194
  renderWithProviders(<ChannelView channel={createChannel()} />)
195
195
 
196
- // The info sidebar was removed, so the participant name is plain text on
197
- // both headers — there is no clickable affordance to open a profile
198
- // dialog anymore.
199
196
  expect(
200
- screen.queryByRole('button', { name: /view info for/i })
197
+ screen.queryByRole('button', { name: /view details for linker/i })
201
198
  ).not.toBeInTheDocument()
202
199
  expect(screen.getAllByText('Linker').length).toBeGreaterThanOrEqual(1)
203
200
 
204
201
  const avatars = screen.getAllByTestId('avatar')
205
202
  expect(avatars.length).toBeGreaterThanOrEqual(1)
206
- expect(avatars[0].parentElement).toHaveClass(
207
- 'rounded-[12px]',
208
- 'px-1',
209
- 'py-0.5'
210
- )
203
+ expect(avatars[0].closest('button')).toBeNull()
204
+ expect(screen.getByTestId('channel-actions-menu')).toBeInTheDocument()
211
205
  })
212
206
 
213
207
  it('renders the redesigned header button when onParticipantNameClick is provided', () => {
@@ -246,7 +240,6 @@ describe('ChannelView', () => {
246
240
  channel={createChannel({
247
241
  otherMemberCustomerTag: 'CUSTOMER_PAID',
248
242
  })}
249
- onParticipantNameClick={vi.fn()}
250
243
  showStarButton={true}
251
244
  />
252
245
  )
@@ -266,14 +259,10 @@ describe('ChannelView', () => {
266
259
  } as Channel['state']['messages'][number],
267
260
  ],
268
261
  })}
269
- onParticipantNameClick={vi.fn()}
270
262
  />
271
263
  )
272
264
 
273
- const button = screen.getByRole('button', {
274
- name: /view details for linker/i,
275
- })
276
- expect(button.closest('[data-testid="message-list"]')).toBeNull()
265
+ expect(screen.getByText('Linker').closest('[data-testid="message-list"]')).toBeNull()
277
266
  })
278
267
 
279
268
  it('renders the actions menu by default', () => {
@@ -350,38 +339,36 @@ describe('ChannelView', () => {
350
339
  expect(screen.queryByTestId('conversation-footer')).not.toBeInTheDocument()
351
340
  })
352
341
 
353
- it('does not pass starred to avatar when showStarButton is false', () => {
342
+ it('does not show a starred badge when showStarButton is false', () => {
354
343
  mockIsStarred = true
355
- const channel = createChannel()
356
344
 
357
345
  renderWithProviders(
358
- <ChannelView channel={channel} showStarButton={false} />
346
+ <ChannelView channel={createChannel()} showStarButton={false} />
359
347
  )
360
348
 
361
- expect(avatarRenderCalls.length).toBeGreaterThan(0)
362
- expect(avatarRenderCalls.every((call) => call.starred === false)).toBe(true)
349
+ expect(
350
+ screen.queryByLabelText('Starred conversation')
351
+ ).not.toBeInTheDocument()
363
352
  })
364
353
 
365
- it('passes starred to avatar when showStarButton is true and channel is starred', () => {
354
+ it('shows a starred badge when showStarButton is true and channel is starred', () => {
366
355
  mockIsStarred = true
367
- const channel = createChannel()
368
356
 
369
357
  renderWithProviders(
370
- <ChannelView channel={channel} showStarButton={true} />
358
+ <ChannelView channel={createChannel()} showStarButton={true} />
371
359
  )
372
360
 
373
- expect(avatarRenderCalls.length).toBeGreaterThan(0)
374
- expect(avatarRenderCalls.every((call) => call.starred === true)).toBe(true)
361
+ expect(screen.getByLabelText('Starred conversation')).toBeInTheDocument()
375
362
  })
376
363
 
377
- it('does not pass starred to avatar by default (showStarButton defaults to false)', () => {
364
+ it('does not show a starred badge by default (showStarButton defaults to false)', () => {
378
365
  mockIsStarred = true
379
- const channel = createChannel()
380
366
 
381
- renderWithProviders(<ChannelView channel={channel} />)
367
+ renderWithProviders(<ChannelView channel={createChannel()} />)
382
368
 
383
- expect(avatarRenderCalls.length).toBeGreaterThan(0)
384
- expect(avatarRenderCalls.every((call) => call.starred === false)).toBe(true)
369
+ expect(
370
+ screen.queryByLabelText('Starred conversation')
371
+ ).not.toBeInTheDocument()
385
372
  })
386
373
 
387
374
  it('passes dmAgentEnabled to avatar when dmAgentEnabled is true for visitor view', () => {