Customization
You can fully customize pretty much any aspect of the look and behavior of your TalkJS chat. This page gives you an overview of different ways to customize your chat if you're building with web components, such as t-chatbox
and t-conversation-list
.
Method | Description |
---|---|
Component props and events | Use the props and events that components expose to customize the component’s styling and behavior. |
Custom styles | Change the look and feel of your chat with custom styles. |
Custom theme components | Modify the styles, markup, and behavior of individual theme components. |
Custom theme | Take 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 themes | Attach plain JavaScript event handlers to change a theme's behavior. |
A TalkJS theme is a collection of React components that make up the chat interface. The default theme works beautifully out of the box. Even though TalkJS themes are implemented with React components, you can easily customize them in any framework, as described in the following sections.
The easiest way to customize TalkJS is using the props that the components expose. See each component’s reference documentation for a list of available props:
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:
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 works because there's no shadow root, which means you can easily apply styles anywhere you like.
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. See the examples to learn how to use the html
helper provided to specify markup.
Here are examples for different frameworks that show how to override a single theme component, for example the ChatHeader
component in this case.
1import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; // Import the custom elements schema2import { defaultTheme } from '@talkjs/web-components';3import '@talkjs/web-components/default.css';4import { html } from "@talkjs/web-components/theming";56// Define your custom theme component, and make the theme object.78@Component({9 selector: 'app-root',10 standalone: true,11 templateUrl: './app.component.html',12 styleUrl: './app.component.css',13 schemas: [CUSTOM_ELEMENTS_SCHEMA] // Add the custom elements schema to 'schemas'14})15export class AppComponent {16 title = 'angular';1718 appId = '<APP_ID>';19 theme = {ChatHeader: MyChatHeader};20}2122// Custom theme components need to be React components.23// TalkJS exposes a `html` helper that lets you create component functions that return React elements.24function MyChatHeader(props) {25 // You can grab other components from the default theme, and use them in your own component.26 const { ConversationImage } = defaultTheme;27 return html`28 <div class="my-chat-header">29 <${ConversationImage} common=${props.common} />30 {/* ... Any other markup you may want */}31 </div>32 `;33}3435// Then in your component template:36<t-chatbox37 [app-id]="appId"38 user-id="sample_user_alice"39 conversation-id="sample_conversation"40 [theme]="theme"41/>
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 { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; // Import the custom elements schema2import { defaultTheme } from '@talkjs/web-components';3import '@talkjs/web-components/default.css';4import * as myTheme from './my-theme';56// Define your custom theme component, and make the theme object.78@Component({9 selector: 'app-root',10 standalone: true,11 templateUrl: './app.component.html',12 styleUrl: './app.component.css',13 schemas: [CUSTOM_ELEMENTS_SCHEMA] // Add the custom elements schema to 'schemas'14})15export class AppComponent {16 title = 'angular';17 appId = '<APP_ID>';18 theme = myTheme;19}2021// Then in your component template:22<t-chatbox23 [app-id]="appId"24 user-id="sample_user_alice"25 conversation-id="sample_conversation"26 [theme]="theme"27/>
The theme folder contains a number of JavaScript files, each of which exports a React component. TalkJS exposes a html
helper that lets you create component functions that return React elements, without having to set up build tooling for JSX, while still using readable markup. It's a slightly modified version of the htm
library.
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:
1// Given HTML that looks like this:2//3// <t-chatbox conversation-id="..."></t-chatbox>45const chatbox = document.querySelector('t-chatbox');6chatbox.addEventListener('click', async (event) => {7 if (event.target.matches('.t-theme-message .t-theme-avatar')) {8 const messageEl = event.target.closest('.t-theme-message');9 const messageId = messageEl.getAttribute('t-message-id');10 console.log('Clicked on avatar for message ' + messageId);11 // Do something with messageId, for example, fetch the sender with12 // the JavaScript Data API, or perform another action.13 }14});
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.