paint-brush
"Code over a tile"// React - from sass files to Styled-Components. [PART II]by@rgc
136 reads

"Code over a tile"// React - from sass files to Styled-Components. [PART II]

by RicardoSeptember 11th, 2019
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

In Part I we saw how to move from sass to a Styled component for a simple component. Now we are going to increase the complexity of our controls in the chat app. We're going to create four styled.div components with the styles of the messages. The data is sent to the control when the message is sent and rendered. We need to change the div that with some conditional style to make a difference on the message owner. We then send the attribute data as a boolean and set the correct style for each property.

Company Mentioned

Mention Thumbnail
featured image - "Code over a tile"// React - from sass files to Styled-Components. [PART II]
Ricardo HackerNoon profile picture

In Part I we saw how to move from sass to a Styled Component for a simple component. So this tutorial assume that you have already installed the styled component made your first try with it. Now we are going to increase the complexity of our controls in the chat app moving to styled components the messages in the chat window.

The data

Each chat window has an array of messages where each one has the name of the sender, the time and the message like


{
  from:'rob'
  time:'13:23pm'
  message:'hi'
}

After that when the message is sent the array is updated and the component Messages is rendered.

The Controls

messages.js

import React from 'react';
import './messages.scss';

const Messages = ({
    messages,
    from
}) =>
    messages.map((data, index) =>
        <div className='message-row' key={index}>
            <div className={(from===data.from?' sender':' receiver')}>
                <div className='sender-time'>{data.time}</div>
                <div className='sender-name'>{data.from +":"}</div>
                <div className='sender-message'>{data.message}</div>
            </div>
        </div>
    )

export default Messages

messages.scss

.message-row{
    width:100%;
    float:left;
    .sender-name{
        color:#4e7ea8;
        word-break: initial;
        width:100%;
        margin-right:50px;
        font:18px/20px 'Open Sans',"Lucida Grande","Lucida Sans Unicode",Arial,Helvetica,Verdana,sans-serif;
    }
    .sender-message{
        width:100%;
        margin-left:10px;
        float:left;
        font:12px/18px 'Open Sans',"Lucida Grande","Lucida Sans Unicode",Arial,Helvetica,Verdana,sans-serif;
    }
    .sender-time{
        float: right;
        font: 11px/20px 'Open Sans',"Lucida Grande","Lucida Sans Unicode",Arial,Helvetica,Verdana,sans-serif;
        color: grey;
    }
}

.receiver{
    float:left;
    padding:5px 10px 5px 10px;
    margin-left:30px;
    margin-top:10px;
    position: relative;
    background: #FFFFFF;
    border-radius: .4em;
    max-width: 450px;
    word-break: break-all;
}

.receiver:after {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    width: 0;
    height: 0;
    border: 20px solid transparent;
    border-right-color: #FFFFFF;
    border-left: 0;
    border-bottom: 0;
    margin-top: -10px;
    margin-left: -20px;
}

.sender{
    padding:5px 10px 5px 10px;
    margin-right:30px;
    margin-top:10px;
    float:right;
    position: relative;
    background: #a4e893;
    border-radius: .4em;
    max-width: 450px;
    word-break: break-all;
}

.sender:after {
    content: '';
    position: absolute;
    right: 0;
    top: 50%;
    width: 0;
    height: 0;
    border: 20px solid transparent;
    border-left-color: #a4e893;
    border-right: 0;
    border-bottom: 0;
    margin-top: -10px;
    margin-right: -20px;
}

So as we did it in the Part I, we're going to create styled components, in this case that we have nested divs a good approach is go from bottom to top changing small components first.

First add the Styled components library.

import styled from 'styled-components'

As we see in the messages.js we have three divs: sender name, sender time, and sender message. So we're going to create four styled.div components with the styles.

const MessageRow = styled.div`
    width:100%;
    float:left;
}`

const SenderName =  styled.div`
    color:#4e7ea8;
    word-break: initial;
    width:100%;
    margin-right:50px;
    font:18px/20px 'Open Sans',"Lucida Grande","Lucida Sans Unicode",Arial,Helvetica,Verdana,sans-serif;`

const SenderMessage =  styled.div`
    width:100%;
    margin-left:10px;
    float:left;
    font:12px/18px 'Open Sans',"Lucida Grande","Lucida Sans Unicode",Arial,Helvetica,Verdana,sans-serif;
`
const SenderTime =  styled.div`
    float: right;
    font: 11px/20px 'Open Sans',"Lucida Grande","Lucida Sans Unicode",Arial,Helvetica,Verdana,sans-serif;
    color: grey;
`

Then we can change our code in order to use them and the message render looks like this

messages.map((data, index) =>
        <MessageRow key={index}>
            <div className={(from===data.from?' sender':' receiver')}>
                <SenderTime>{data.time}</SenderTime>
                <SenderName>{data.from +":"}</SenderName>
                <SenderMessage>{data.message}</SenderMessage>
            </div>
        </MessageRow>

Until now the steps are similar to PART I, now we need to change the div that with some conditional style to make a difference on the message owner. (see screenshot)

To do this we create the styled.div component and change it on our renderer then send to the control the attribute data as a boolean.

NOTE: If you send a boolean like (true,false) you will see an error like "Warning: Received `false` for a non-boolean attribute .." So you should send a boolean as an integer.

        <MessageRow key={index}>
            <Message data={from===data.from?1:0}>
                <SenderTime>{data.time}</SenderTime>
                <SenderName>{data.from +":"}</SenderName>
                <SenderMessage>{data.message}</SenderMessage>
            </Message>
        </MessageRow>

For this you can use passed props , and write a function to use the props as variables inside functions like

 background :${ props=>props.data? '#a4e893':'#FFFFFF' }

So the idea is that, we check if the value is the owner or not as a boolean and then you can set the correct style for each css property. So you Message Component should look like.

const Message = styled.div`
    position: relative;
    padding:5px 10px 5px 10px;
    margin-top:10px;
    word-break: break-all;
    max-width: 450px;
    border-radius: .4em;
    background :${ props=>props.data? '#a4e893':'#FFFFFF' }
    float: ${props=> props.data? 'right':'left'};
    margin-left:${props=>props.data?'':'30px'};
    margin-right:${props=>props.data?'30px':''};
    &::after{
        content: '';
        position: absolute;
        top: 50%;
        width: 0;
        height: 0;
        border: 20px solid transparent;
        border-bottom: 0;
        margin-top: -10px;

        //sender
        right: ${props=>props.data? '0':''};
        left: ${props=>props.data? '':'0'};

        border-right-color: ${props=>!props.data? '#FFFFFF':''};
        border-left-color: ${props=>props.data ? '#a4e893':''};
        border-right: ${props=>props.data?'0':''};
        border-left: ${props=>!props.data?'0':''};

        margin-right:${props=>props.data?'-20px':''};
        margin-left:${props=>!props.data?'-20px':''};
    }

IMHO I'll try to keep simple the functions in the styles in order to understand easy what is doing.

I hope this help you to change your code and make it more comprehensive and simple . Feedback is a simple way to share knowledge and is always welcome :)