@hliejun/react-chat
v0.0.1-alpha.7
Published
Presentational chat components for ReactJS
Downloads
1
Maintainers
Readme
React Chat
React Chat is presently in alpha and is not meant to be a viable substitute to delicate native chat frameworks.
React Chat currently does not support pagination of messages or rooms, hence might have performance issues when loading huge volume of chat data. Handles for pagination such as scroll pagination will be added soon.
Intro
React Chat is an extensible set of presentational chat components for mobile-first ReactJS web applications. It facilitates simple messaging interactions on-the-go.
React Chat is inspired by the designs at GiftedChat, Slack, WhatsApp and Telegram.
Besides this README, you may find documentation of the design and behaviours of components in Storybook.
Examples and demos will be provided through Storybook and the Examples page in the future. This is a work in progress.
Getting Started
React Chat requires at least React 16.3.0
as a peer dependency.
To install using npm
:
npm install @hliejun/react-chat
To install using yarn
:
yarn add @hliejun/react-chat
To opt-in to alpha versions, please explicitly state the version. Check on the latest version here.
Usage
React Chat comprises of:
ChatList
ChatRoom
ChatList
ChatList
is a component used for interacting with a list of chat rooms or message groups. As a presentational component, it exposes the handles for various tasks such as displaying chat rooms, refreshing the view, filtering the list and more.
For instance, you can invoke ChatList
with the following:
import { ChatList } from '@hliejun/react-chat';
class MyContainer extends React.Component {
// ...
render = () => {
//...
const { rooms } = this.state;
//...
return (
<ChatList
onItem={this.segueToChatRoom}
rooms={this.parseRooms(rooms)}
title='Chats'
/>
);
};
// ...
parseRooms = (rooms) => {
// Fetch and parse data into shape of room objects
};
segueToChatRoom = (id) => {
// Navigate to chat room of id when room is selected
};
}
The following table indicates the props
that ChatList accepts.
Name | Type | Description
--- | --- | ---
className
| string
| Style classes passed down from container component
hideAvatar
| bool
| Flag to opt out from showing Avatar
in ListItem
hideChevron
| bool
| Flag to opt out from showing chevron indicator as affordance to segueing
hideTitleBar
| bool
| Flag to opt out from showing the TitleBar
isLoading
| bool
| Flag to display loading animations while the ChatList
is not readily populated
layout
| see AppContext | Styling enumeration to match ChatRoom
layout
liveSearch
| bool
| Flag to indicate the intended search behaviour
menuActions
| see Actions | Action handlers and metadata to populate chat ListItem
menu
onAvatar
| func
| Handler for interaction with the Avatar
in a ListItem
onInfo
| func
| Handler for interaction with the identity Avatar
in TitleBar
onItem
| func
| Handler for selecting a ListItem
of a specific room
onMenu
| func
| Handler for prompting the ListItem
menu of a specific room
onRefresh
| func
| Handler for initiating a fetch or reload to repopulate the ChatList
onResult
| func
| Handler for selecting a search ListItem
in the search results pane
onSearch
| func
| Handler for search or filter logic to fetch or reload searchResults
Placeholder
| React element
| Component to fill the body when rooms
is empty
rooms
| see Rooms | Collection of objects specifying the metadata of a room
searchHint
| string
| Placeholder for empty search field
searchPlaceholder
| React element
| Placeholder for empty search results body
searchResults
| see Search | Collection of objects describing the outcome of onSearch
selectedId
| string
| Unique identifier of the list item that is currently active
sizing
| see AppContext | Device and sizing enumeration for layout responsiveness
subtitle
| string
| Subtitle to display on TitleBar
theme
| see AppContext | Theme enumeration for styling constituent components
title
| string
| Title to display on TitleBar
user
| see Users | Object containing metadata of a user or a user profile
ChatRoom
ChatRoom
is a component used for interacting with a chat group, room, conversation, etc. Regardless of the room size, it offers generic handles for various messaging tasks such as typing, sending, searching, deleting, copying and more.
You can use ChatRoom
this way:
import { ChatRoom } from '@hliejun/react-chat';
class MyContainer extends React.Component {
// ...
render = () => {
//...
const { input, messages, room, userId, users } = this.state;
const { id, name } = room;
//...
return (
<ChatRoom
inputValue={input}
messages={this.parseMessages(messages)}
onInput={this.parseInput}
onSend={this.sendMessage}
roomId={id}
roomName={name}
userId={userId}
users={users}
/>
);
};
// ...
parseMessages = (messages) => {
// Fetch and parse data into shape of message objects
};
parseInput = (nextInput) => {
// Input control to parse HTML string into desirable values
// ...
// When done parsing, reload ChatRoom with new input state
// Pure components will not reload if unaffected by input
this.setState({
input: parsedInput
});
};
sendMessage = (input) => {
// Call API to submit message
};
}
The following table indicates the props
that ChatRoom accepts.
Name | Type | Description
--- | --- | ---
attachOptions
| see Media | Action handlers for media attachments
className
| string
| Style classes passed down from container component
hideAvatar
| bool
| Flag to opt out from showing Avatar
in Message
item
inputData
| see Media | Object describing attached media due for posting
inputHint
| string
| Placeholder for input field
inputValue
| string
| HTML-formatted string for rendering into input field
layout
| see AppContext | Styling enumeration describing layout of messages
liveSearch
| bool
| Flag to indicate the intended search behaviour
menuActions
| see Actions | Action handlers and metadata to populate chat Message
menu
messages
| see Messages | Collection of objects representing Message
content
onAttach
| func
| Handler for attaching media to input
onAvatar
| func
| Handler for interaction with the Avatar
in a Message
onContent
| func
| Handler for selecting a message Content
onInfo
| func
| Handler for interaction with the identity Avatar
in TitleBar
onInput
| func
| Handler for intercepting and updating input field value
onMenu
| func
| Handler for prompting the content Menu
of a specific message
onRefresh
| func
| Handler for initiating a fetch or reload to repopulate the Message
list
onResult
| func
| Handler for selecting a search ListItem
in the search results pane
onReturn
| func
| Handler for interacting with the return button to perform a segue
onSearch
| func
| Handler for search or filter logic to fetch or reload searchResults
onSend
| func
| Handler for submitting input value
roomAvatar
| string
| Link to room avatar image
roomId
| string
| Unique identifier of the room for actions contextual to the room
roomName
| string
| Name or title of the chat room
searchHint
| string
| Placeholder for empty search field
searchPlaceholder
| React element
| Placeholder for empty search results body
searchResults
| see Search | Collection of objects describing the outcome of onSearch
sizing
| see AppContext | Device and sizing enumeration for layout responsiveness
subtitle
| string
| Subtitle to display on TitleBar
theme
| see AppContext | Theme enumeration for styling constituent components
userId
| string
| Unique identifier of the current user
users
| see Users | Indexed collection of objects containing metadata of all users involved in the chat room
Actions
(WIP) Here are the PropTypes declaration for menu actions for the respective components.
{/* ListItem Menu Actions */}
menuActions: PropTypes.arrayOf(PropTypes.shape({
action: PropTypes.func.isRequired,
icon: PropTypes.string,
label: PropTypes.string.isRequired,
type: PropTypes.oneOf([
'archive',
'delete',
'info',
'pin',
'star',
'unread'
]).isRequired
}))
{/* Message Menu Actions */}
menuActions: PropTypes.arrayOf(PropTypes.shape({
action: PropTypes.func.isRequired,
icon: PropTypes.string,
label: PropTypes.string.isRequired,
type: PropTypes.oneOf([
'copy',
'delete',
'forward',
'info',
'pin',
'reply'
]).isRequired
})),
AppContext
(WIP) Here are the PropTypes declaration for app context options.
{/* Layout */}
layout: PropTypes.oneOf([
'aligned',
'staggered'
])
{/* Sizing */}
sizing: PropTypes.oneOf([
'desktop',
'mobile',
'tablet'
])
{/* Theme */}
theme: PropTypes.oneOf([
'dark',
'light'
])
Messages
(WIP) Here are the PropTypes declaration for messages.
{/* Messages */}
messages: PropTypes.arrayOf(PropTypes.shape({
data: PropTypes.shape({
coordinates: PropTypes.shape({
lat: PropTypes.string,
lng: PropTypes.string
}),
galleryId: PropTypes.string,
markdown: PropTypes.string,
metadata: PropTypes.object,
source: PropTypes.string.isRequired,
type: PropTypes.oneOf([
'audio',
'file',
'gif',
'image',
'link',
'location',
'markdown',
'pdf',
'video'
]).isRequired
}),
eventContent: PropTypes.element,
eventName: PropTypes.string,
isDelivered: PropTypes.bool,
isLoading: PropTypes.bool,
isRead: PropTypes.bool,
messageId: PropTypes.string.isRequired,
senderId: PropTypes.string,
text: PropTypes.string,
timeStamp: PropTypes.string.isRequired,
type: PropTypes.oneOf([
'event',
'media',
'system',
'text'
]).isRequired
})).isRequired
Media
(WIP) Here are the PropTypes declaration for media-related objects.
{/* Attach Options */}
attachOptions: PropTypes.arrayOf(PropTypes.shape({
action: PropTypes.func.isRequired,
icon: PropTypes.string,
label: PropTypes.string.isRequired,
type: PropTypes.oneOf([
'audio',
'file',
'gif',
'image',
'link',
'location',
'markdown',
'pdf',
'video'
]).isRequired
}))
{/* Input Data */}
inputData: PropTypes.shape({
coordinates: PropTypes.shape({
lat: PropTypes.string,
lng: PropTypes.string
}),
galleryId: PropTypes.string,
markdown: PropTypes.string,
metadata: PropTypes.object,
source: PropTypes.string.isRequired,
type: PropTypes.oneOf([
'audio',
'file',
'gif',
'image',
'link',
'location',
'markdown',
'pdf',
'video'
]).isRequired
})
Rooms
(WIP) Here are the PropTypes declaration for rooms.
{/* Rooms */}
rooms: PropTypes.arrayOf(PropTypes.shape({
avatar: PropTypes.string,
description: PropTypes.string,
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
status: PropTypes.oneOf([
'archive',
'pin',
'star',
'new'
]),
subtitle: PropTypes.string,
timeStamp: PropTypes.string
})).isRequired
Search
(WIP) Here are the PropTypes declaration for search results.
{/* Search Results */}
PropTypes.arrayOf(PropTypes.shape({
avatar: PropTypes.string,
description: PropTypes.string,
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
timeStamp: PropTypes.string
}))
Users
(WIP) Here are the PropTypes declaration for user(s).
{/* User */}
user: PropTypes.shape({
avatar: PropTypes.string,
description: PropTypes.string,
email: PropTypes.string,
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
phone: PropTypes.string,
website: PropTypes.string
})
{/* Users */}
users: PropTypes.objectOf(PropTypes.shape({
avatar: PropTypes.string,
description: PropTypes.string,
email: PropTypes.string,
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
phone: PropTypes.string,
website: PropTypes.string
})).isRequired
Style Classes
(WIP) Formats and variants off CSS classes.
Development
(WIP) Code Design, Linters, Storybook, RollUp, AppContext, Classnames. DOMPurify.
TODOs
Summary of upcoming TODOs:
Features
- [ ] Animations
- [ ] Children buttons in TitleBar
- [ ] Dividers
- [ ] Expose child components for use
- [ ] Media preview
- [ ] Message markdown
- [ ] Message replies
- [ ] Refresh
- [ ] Scroll pagination
- [ ] Themes and abstract colors usage
Performance
- [ ] Recycle views
- [ ] Reduce bundle size with UglifyJS
- [ ] Split bundles for selective import
- [ ] Switch to PureComponent(s)
- [ ] Trim style classes
Code Quality
- [ ] Add Jest tests
- [ ] Refactor all stories
- [ ] Switch to SCSS for stories
Documentation
- [ ] Add example screenshots
- [ ] Complete README
- [ ] Complete Storybook
- [ ] Examples with ChatKit
Maintenance
- [ ] Setup issues
Credits and Licenses
This project is licensed under the MIT License. See LICENSE for copyright credits to the respective sources. The following people and resources have helped this project greatly in one way or another:
Throttling without Lodash Author: Jhey Tompkins Web: Throttling and Debouncing in Javascript
Default to Polymer SVG Icons Author: PolymerElements and David Francisco Repo (polymerelements): https://github.com/PolymerElements/iron-icons Repo (dmfrancisco): https://github.com/dmfrancisco/react-icons
Web URL Regex Author: Diego Perini Gist: https://gist.github.com/dperini/729294
SASS Mixins Authors: Richard Torres and Engage Interactive Repo (engageinteractive): https://github.com/engageinteractive/core Gist (richardtorres314): https://gist.github.com/richardtorres314/26b18e12958ba418bb37993fdcbfc1bd
SASS Material Colors Author: minusfive Repo: https://github.com/minusfive/sass-material-colors
Support
(WIP) Issues and contact.