@linktr.ee/messaging-react 1.5.3 → 1.6.0
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/assets/index.css +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +532 -510
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ChannelView.tsx +1 -1
- package/src/components/FaqList/FaqList.stories.tsx +49 -0
- package/src/components/FaqList/FaqListItem.tsx +3 -2
- package/src/components/FaqList/index.tsx +38 -10
- package/src/components/MessagingShell/index.tsx +9 -4
- package/src/types.ts +7 -0
package/package.json
CHANGED
|
@@ -433,7 +433,7 @@ const ChannelViewInner: React.FC<{
|
|
|
433
433
|
|
|
434
434
|
{/* Show custom empty state when no messages */}
|
|
435
435
|
{!hasMessages && CustomChannelEmptyState && (
|
|
436
|
-
<div className="absolute inset-0 flex
|
|
436
|
+
<div className="absolute inset-0 flex bg-white">
|
|
437
437
|
<CustomChannelEmptyState />
|
|
438
438
|
</div>
|
|
439
439
|
)}
|
|
@@ -49,6 +49,8 @@ Default.args = {
|
|
|
49
49
|
],
|
|
50
50
|
onFaqClick: (id) => console.log('FAQ clicked:', id),
|
|
51
51
|
headerText: 'Tap to send a suggested question by Brie Parson:',
|
|
52
|
+
avatarName: 'Brie Parson',
|
|
53
|
+
avatarImage: 'https://i.pravatar.cc/150?img=47',
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
export const WithoutHeader: StoryFn<ComponentProps> = Template.bind({})
|
|
@@ -135,3 +137,50 @@ Empty.args = {
|
|
|
135
137
|
faqs: [],
|
|
136
138
|
onFaqClick: (id) => console.log('FAQ clicked:', id),
|
|
137
139
|
}
|
|
140
|
+
|
|
141
|
+
export const WithAvatarOnly: StoryFn<ComponentProps> = Template.bind({})
|
|
142
|
+
WithAvatarOnly.args = {
|
|
143
|
+
faqs: [
|
|
144
|
+
{
|
|
145
|
+
id: '1',
|
|
146
|
+
question: 'Book club slots',
|
|
147
|
+
answer: 'We ship worldwide...',
|
|
148
|
+
enabled: true,
|
|
149
|
+
order: 1,
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
id: '2',
|
|
153
|
+
question: 'Refunds',
|
|
154
|
+
answer: 'You can track...',
|
|
155
|
+
enabled: true,
|
|
156
|
+
order: 2,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
onFaqClick: (id) => console.log('FAQ clicked:', id),
|
|
160
|
+
headerText: 'Frequently Asked Questions',
|
|
161
|
+
avatarName: 'Account Owner',
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export const WithAvatarAndImage: StoryFn<ComponentProps> = Template.bind({})
|
|
165
|
+
WithAvatarAndImage.args = {
|
|
166
|
+
faqs: [
|
|
167
|
+
{
|
|
168
|
+
id: '1',
|
|
169
|
+
question: 'How do I contact support?',
|
|
170
|
+
answer: 'You can reach us...',
|
|
171
|
+
enabled: true,
|
|
172
|
+
order: 1,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
id: '2',
|
|
176
|
+
question: 'What are your hours?',
|
|
177
|
+
answer: 'We are available...',
|
|
178
|
+
enabled: true,
|
|
179
|
+
order: 2,
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
onFaqClick: (id) => console.log('FAQ clicked:', id),
|
|
183
|
+
headerText: 'Questions for Sarah',
|
|
184
|
+
avatarName: 'Sarah Johnson',
|
|
185
|
+
avatarImage: 'https://i.pravatar.cc/150?img=28',
|
|
186
|
+
}
|
|
@@ -19,10 +19,11 @@ export const FaqListItem: React.FC<FaqListItemProps> = ({
|
|
|
19
19
|
type="button"
|
|
20
20
|
onClick={onClick}
|
|
21
21
|
disabled={loading}
|
|
22
|
+
style={{ backgroundColor: '#E6E5E3' }}
|
|
22
23
|
className={classNames(
|
|
23
|
-
'w-full text-center p-4 rounded-xl
|
|
24
|
+
'w-full text-center p-4 rounded-xl text-charcoal font-medium transition-colors',
|
|
24
25
|
{
|
|
25
|
-
'hover:
|
|
26
|
+
'hover:brightness-95 active:brightness-90': !loading,
|
|
26
27
|
'opacity-50 cursor-not-allowed': loading,
|
|
27
28
|
},
|
|
28
29
|
className
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import classNames from 'classnames'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
|
+
import { Avatar } from '../Avatar'
|
|
5
|
+
|
|
4
6
|
import { FaqListItem } from './FaqListItem'
|
|
5
7
|
|
|
6
8
|
export interface Faq {
|
|
@@ -17,6 +19,8 @@ export interface FaqListProps {
|
|
|
17
19
|
loadingFaqId?: string | null
|
|
18
20
|
headerText?: string
|
|
19
21
|
className?: string
|
|
22
|
+
avatarImage?: string
|
|
23
|
+
avatarName?: string
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
export const FaqList: React.FC<FaqListProps> = ({
|
|
@@ -25,6 +29,8 @@ export const FaqList: React.FC<FaqListProps> = ({
|
|
|
25
29
|
loadingFaqId,
|
|
26
30
|
headerText,
|
|
27
31
|
className,
|
|
32
|
+
avatarImage,
|
|
33
|
+
avatarName,
|
|
28
34
|
}) => {
|
|
29
35
|
const enabledFaqs = faqs
|
|
30
36
|
.filter((faq) => faq.enabled)
|
|
@@ -35,16 +41,38 @@ export const FaqList: React.FC<FaqListProps> = ({
|
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
return (
|
|
38
|
-
<div className={classNames('px-4 py-6
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
<div className={classNames('px-4 py-6', className)}>
|
|
45
|
+
<div className="flex gap-3 items-end">
|
|
46
|
+
{/* Avatar at bottom-left, outside grey background */}
|
|
47
|
+
{(avatarImage || avatarName) && (
|
|
48
|
+
<div className="flex-none">
|
|
49
|
+
<Avatar
|
|
50
|
+
id={avatarName || 'account'}
|
|
51
|
+
name={avatarName || 'Account'}
|
|
52
|
+
image={avatarImage}
|
|
53
|
+
size={24}
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
)}
|
|
57
|
+
|
|
58
|
+
{/* FAQs with grey background */}
|
|
59
|
+
<div
|
|
60
|
+
className="flex-1 rounded-lg p-4 space-y-3"
|
|
61
|
+
style={{ backgroundColor: '#F1F0EE' }}
|
|
62
|
+
>
|
|
63
|
+
{headerText && (
|
|
64
|
+
<p className="text-md text-charcoal mb-4">{headerText}</p>
|
|
65
|
+
)}
|
|
66
|
+
{enabledFaqs.map((faq) => (
|
|
67
|
+
<FaqListItem
|
|
68
|
+
key={faq.id}
|
|
69
|
+
question={faq.question}
|
|
70
|
+
onClick={() => onFaqClick(faq.id)}
|
|
71
|
+
loading={loadingFaqId === faq.id}
|
|
72
|
+
/>
|
|
73
|
+
))}
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
48
76
|
</div>
|
|
49
77
|
)
|
|
50
78
|
}
|
|
@@ -24,6 +24,7 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
24
24
|
initialParticipantFilter,
|
|
25
25
|
initialParticipantData,
|
|
26
26
|
CustomChannelEmptyState,
|
|
27
|
+
showChannelList = true,
|
|
27
28
|
}) => {
|
|
28
29
|
const {
|
|
29
30
|
service,
|
|
@@ -386,14 +387,18 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
386
387
|
className={classNames(
|
|
387
388
|
'messaging-channel-list-sidebar min-h-0 min-w-0 bg-white lg:bg-chalk lg:flex lg:flex-col lg:border-r lg:border-sand',
|
|
388
389
|
{
|
|
389
|
-
//
|
|
390
|
-
'!hidden': directConversationMode,
|
|
390
|
+
// Explicitly hidden via prop or in direct conversation mode
|
|
391
|
+
'!hidden': showChannelList === false || directConversationMode,
|
|
391
392
|
// Normal mode: hide on mobile when channel selected, show on desktop
|
|
392
393
|
'hidden lg:flex lg:w-80 lg:min-w-[280px] lg:max-w-[360px]':
|
|
393
|
-
|
|
394
|
+
showChannelList !== false &&
|
|
395
|
+
!directConversationMode &&
|
|
396
|
+
isChannelSelected,
|
|
394
397
|
// Normal mode: show when no channel selected
|
|
395
398
|
'flex flex-col w-full lg:flex-1 lg:max-w-2xl':
|
|
396
|
-
|
|
399
|
+
showChannelList !== false &&
|
|
400
|
+
!directConversationMode &&
|
|
401
|
+
!isChannelSelected,
|
|
397
402
|
}
|
|
398
403
|
)}
|
|
399
404
|
>
|
package/src/types.ts
CHANGED
|
@@ -87,6 +87,13 @@ export interface MessagingShellProps {
|
|
|
87
87
|
* Useful for showing FAQs or other contextual information in empty channels.
|
|
88
88
|
*/
|
|
89
89
|
CustomChannelEmptyState?: React.ComponentType
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Controls whether the channel list is shown. When false, the channel list
|
|
93
|
+
* is immediately hidden. Useful for direct conversation mode where you want
|
|
94
|
+
* to show only the channel view without the list.
|
|
95
|
+
*/
|
|
96
|
+
showChannelList?: boolean
|
|
90
97
|
}
|
|
91
98
|
|
|
92
99
|
/**
|