mevrick
mevrick

Reputation: 1045

How to make chat like UI with chat bubbles in React JS

I have some JSON data in dummyData. I am not sure how can I place the chat bubbles on left and right according to the direction. I am using Material UI and context API. Image for the reference. I don't want to use any library other than material UI.

enter image description here

Currently, every chat bubble is positioned to the left. How to position bubbles according to the direction. Code so far (CodeSandbox):

    import React from 'react';
import makeStyles from '@material-ui/core/styles/makeStyles';

const useStyles = makeStyles(theme => ({
    container: {
        bottom: 0,
        position: 'fixed'
    },
    bubbleContainer: {
        width: '100%'
    },
    bubble: {
        border: '0.5px solid black',
        borderRadius: '10px',
        margin: '5px',
        padding: '10px',
        display: 'inline-block'
    }
}));

const ChatLayout = () => {
    const classes = useStyles();
    const dummyData = [
        {
            message: '1: This should be in left',
            direction: 'left'
        },
        {
            message: '2: This should be in right',
            direction: 'right'
        },
        {
            message: '3: This should be in left again',
            direction: 'left'
        }
    ];

    const chatBubbles = dummyData.map((obj, i = 0) => (
        <div className={classes.bubbleContainer}>
            <div key={i++} className={classes.bubble}>
                <div className={classes.button}>{obj.message}</div>
            </div>
        </div>
    ));
    return <div className={classes.container}>{chatBubbles}</div>;
};

export default ChatLayout;

Upvotes: 4

Views: 19526

Answers (1)

Nicolas Othmar
Nicolas Othmar

Reputation: 773

To achieve the result you want, you need to use flexbox. Here is the updated code with comments noting added or updated lines (CodeSandbox):

import React from "react";
import makeStyles from "@material-ui/core/styles/makeStyles";

const useStyles = makeStyles(theme => ({
  container: {
    bottom: 0,
    position: "fixed", // added line
    display: "flex", // added line
    flexDirection: "column" // added line
  },
  bubbleContainerLeft: {
    marginRight: "auto" // updated line
  },
  bubbleContainerRight: {
    marginLeft: "auto" // updated line
  },
  bubble: {
    border: "0.5px solid black",
    borderRadius: "10px",
    margin: "5px",
    padding: "10px",
    display: "inline-block"
  }
}));

const ChatLayout = () => {
  const classes = useStyles();
  const dummyData = [
    {
      message: "1: This should be in left",
      direction: "left"
    },
    {
      message: "2: This should be in right",
      direction: "right"
    },
    {
      message: "3: This should be in left again",
      direction: "left"
    }
  ];

  const chatBubbles = dummyData.map((obj, i = 0) => (
    // updated line
    <div className={obj.direction === "left" ? classes.bubbleContainerLeft : classes.bubbleContainerRight}> 
      <div key={i++} className={classes.bubble}>
        <div className={classes.button}>{obj.message}</div>
      </div>
    </div>
  ));
  return <div className={classes.container}>{chatBubbles}</div>;
};

export default ChatLayout;

Explanation for the changes:

I set the parent container as a flexbox. To move the child to the left, set marginRight to auto. This will make it so this child has the maximum possible right margin, thus making it left-aligned. We do a similar thing to move the child to the right, but reversed: marginLeft set to auto.

Upvotes: 0

Related Questions