Customization

You can render custom components in the KendoReact Chat component by using the built-in properties of the ChatProps interface and any custom properties.

Setting Custom Behavior

You can display any valid HTML and fully customize the behavior of the rendered component by using the additional properties of the Chat component.

The following example demonstrates how to render additional buttons for uploading file, image, folder and camera. Also, send button is moved on the far left.

import React from 'react';
import ReactDOM from 'react-dom';
import { Chat } from '@progress/kendo-react-conversational-ui';

const AttachmentTemplate = (props) => {
    let attachment = props.item;
    return (
        <div className="k-card k-card-type-rich">
            <div className="k-card-body quoteCard">
                <img style={{ maxHeight: '120px' }} src={attachment.content} draggable={false} />
            </div>
        </div>
    )
};

class App extends React.Component {
    constructor(props) {
        super(props);
        this.user = {
            id: 1,
            avatarUrl: "https://via.placeholder.com/24/008000/008000.png"
        };
        this.state = {
            messages: []
        };
    }

    addNewMessage = (event) => {
        this.setState((prevState) => {
            return { messages: [ ...prevState.messages, event.message ] };
        });
    }

    handleInputChange = (e) => {
        let file = e.target.files[0];
        let reader = new FileReader();
        reader.onloadend = (event) => {
            let message = {
                author: this.user,
                text: '',
                attachments: [{
                    content: event.target.result,
                    contentType: 'image'
                }]
            }
            this.setState((prevState) => ({
                messages: [
                    ...prevState.messages,
                    message
                ],
            }));
        };
        reader.readAsDataURL(file);
    }

    uploadButton = (props) => {
        return (
            <React.Fragment>
                <input type='file' onChange={this.handleInputChange} style={{display: 'none'}} ref={el => this.fileUpload = el}/>
                <button className={'k-button k-flat k-button-icon'}  onClick={() => this.fileUpload.click()}>
                    <span className={'k-icon ' + props.icon} style={{fontSize: '20px'}}/>
                </button>
            </React.Fragment>
        )
    }

    customMessage = (props) => {
        return <React.Fragment>
            {props.sendButton}
            {props.messageInput}
            {this.uploadButton({icon: 'k-i-image-insert'})}
        </React.Fragment>;
    }

    render() {
        return (
            <Chat
                messages={this.state.messages}
                user={this.user}
                onMessageSend={this.addNewMessage}
                placeholder={'Type a message...'}
                width={400}
                messageBox={this.customMessage}
                attachmentTemplate={AttachmentTemplate}
            />
        );
    }
}

ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);

Customizing the Message

You can customize chat message using the message prop of the Chat component which is from type 'ChatMessage'. The following example demonstrates how to set different date format, which by default is set to general date and time pattern - "M/d/y h:mm:ss a". You can change the type by setting new value to the dateFormat property of the ChatMessage component and pass it to the message prop of the Chat.

The following example demonstrates how to set different date format.

import React from 'react';
import ReactDOM from 'react-dom';
import { Chat, ChatMessage } from '@progress/kendo-react-conversational-ui';

const CustomChatMessage = (props) => <ChatMessage {...props} dateFormat={'t'} />;

class App extends React.Component {
    constructor(props) {
        super(props);
        this.user = {
            id: 1,
            avatarUrl: "https://via.placeholder.com/24/008000/008000.png"
        };
        this.bot = { id: 0 };
        this.state = {
            messages: [
                {
                    author: this.bot,
                    suggestedActions: [
                        {
                            type: 'reply',
                            value: 'Oh, really?'
                        }, {
                            type: 'reply',
                            value: 'Thanks, but this is boring.'
                        }
                    ],
                    timestamp: new Date(),
                    text: "Hello, this is a demo bot. I don't do much, but I can count symbols!"
                }
            ]
        };
    }

    addNewMessage = (event) => {
        let botResponce = Object.assign({}, event.message);
        botResponce.text = this.countReplayLength(event.message.text);
        botResponce.author = this.bot;
        this.setState((prevState) => ({
            messages: [
                ...prevState.messages,
                event.message
            ]
        }));
        setTimeout(() => {
            this.setState(prevState => ({
                messages: [
                    ...prevState.messages,
                    botResponce
                ]
            }));
        }, 1000);
    };

    countReplayLength = (question) => {
        let length = question.length;
        let answer = question + " contains exactly " + length + " symbols.";
        return answer;
    }

    render() {
        return (
            <div>
                <Chat
                    user={this.user}
                    messages={this.state.messages}
                    onMessageSend={this.addNewMessage}
                    placeholder={"Type a message..."}
                    width={400}
                    message={CustomChatMessage}>
                </Chat>
            </div>
        );
    }
}

ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);