Customization

You can fully customize almost any aspect of the look and behavior of your TalkJS chat. This page gives you an overview of different ways to customize your chat when using React components, such as Chatbox and ConversationList.

MethodDescription
Component props and eventsUse the props and events that components expose to customize the component’s styling and behavior.
Custom stylesChange the look and feel of your chat with custom styles.
Custom theme componentsModify the styles, markup, and behavior of individual theme components.
Custom themeTake complete control over how your chat looks and behaves. You can fork the default theme as a starting point and change anything you want.
Change behavior without modifying themesAttach plain JavaScript event handlers to change a theme's behavior.

What's a theme?

A TalkJS theme is a collection of React components that make up the chat interface. The default theme works beautifully out of the box, but you can extend or replace parts of it to better fit your own styles and desired behavior.

Component props and events

The easiest way to customize TalkJS is using the props and events that the components expose. See each component’s reference documentation for a list of available props:

Custom styles

You can inspect any component using your browser's developer tools to inspect the markup and see which styles are applied. You can add CSS to your own page to override the styles that are applied by the theme.

You'll want to ensure that your CSS selectors have the same or higher specificity as the selectors of the theme. The easiest way to do so is to just copy a selector from the developer tools, and then ensure that these styles are loaded after TalkJS components. When multiple CSS selectors have the same specificity, the last one wins.

For example, if you want messages sent by the current user to have an orange background that matches your brand, inspect the message element in the developer tools. You’ll get something like the following:

The browser developer tools showing the styles for a message

You can now copy the selector, and modify the properties you want. For example, add some CSS to your page to set the message background and border:

1.t-chatbox .t-theme-message[t-sender='currentUser'] .t-message-body {
2 background-color: rgb(255, 98, 0);
3 border-color: rgb(255, 98, 0);
4}

This approach works for all TalkJS React components, since they render into the regular DOM and can be styled with standard CSS overrides.

Custom theme components

The components let you pass in a theme. You can import the default theme, and then override just the components you want to customize. A theme is just an object mapping component names to React components.

Customizing a theme component allows you to override specific parts of the UI without forking the entire theme.

Here's an example that shows how to override a single theme component, in this case the ChatHeader component:

1import { useMemo } from 'react';
2import { Chatbox, defaultTheme } from '@talkjs/react-components';
3import '@talkjs/react-components/default.css';
4
5function MyChatbox() {
6 // Create an object with components to override, memoized so that it doesn't cause unnecessary re-renders.
7 const theme = useMemo(() => ({ ChatHeader: MyChatHeader }), []);
8
9 // Now use the modified theme when rendering the chatbox.
10 return (
11 <Chatbox
12 appId="YOUR_APP_ID"
13 theme={theme}
14 userId="sample_user_alice"
15 conversationId="sample_conversation"
16 />
17 );
18}
19
20// Your own ChatHeader component. You can also style this with CSS, just like you would any other component in your app.
21function MyChatHeader(props) {
22 // You can grab other components from the default theme, and use them in your own component.
23 const { ConversationImage } = defaultTheme;
24 return (
25 <div className="my-chat-header">
26 <ConversationImage common={props.common} />
27 {/* ... any other markup you want */}
28 </div>
29 );
30}

Custom theme

If you'd like to make extensive changes to the theme, to fully make it your own, you can grab a copy of the default theme, and copy it into your app.

Download the latest version's zip archive from GitHub, and copy the contents into your project.

Assuming you've placed the theme files in a folder called my-theme, you can import it and pass it to the theme prop when rendering the chatbox:

1import { Chatbox } from '@talkjs/react-components';
2import '@talkjs/react-components/default.css';
3
4import * as myTheme from './my-theme';
5
6function MyChatbox() {
7 // Now use the modified theme when rendering the chatbox.
8 return (
9 <Chatbox
10 appId="YOUR_APP_ID"
11 theme={myTheme}
12 userId="sample_user_alice"
13 conversationId="sample_conversation"
14 />
15 );
16}

The theme folder contains a number of JavaScript files. Each of these files exports a React component that represents a part of the chat interface. You can freely modify these components or add your own to create a fully customized theme.

Change behavior without modifying themes

The recommended ways to change a component's behavior are to modify its external props and events, customize specific theme components, or to fork and customize the theme entirely. However, if that doesn't work for your use case, you can use plain JavaScript to change a theme's behavior. This approach goes a bit against the spirit of most frontend frameworks, but it can be very effective for specific cases.

Add a global event listener for clicks on the root UI element, and inside it, filter it down to the clicks you're interested in. For example, if you want to capture clicks on a message avatar picture, you can do something like the following:

1function Chat({conversationId}) {
2 const ref = useRef();
3
4 useEffect(() => {
5 async function click(event) {
6 const target = event.target;
7 if(target.matches(".t-theme-message .t-theme-avatar")) {
8 const messageId = target
9 .closest(".t-theme-message")
10 .getAttribute("t-message-id");
11
12 console.log("Clicked on avatar for message " + messageId);
13 // Do something with messageId, for example, fetch the sender with
14 // the JavaScript Data API, or perform another action.
15 }
16 }
17 ref.current.addEventListener("click", click);
18 return () => ref.current.removeEventListener("click", click);
19 }, []);
20
21 return <Chatbox ref={ref} conversationId={...}/>;
22}

The trick is to use event.target.matches() to narrow down which clicks you want to handle. This lets you listen for clicks on any matching element, even elements that appear later.