Lesson 10: Styling the JavaScript Widget

To style our widget, create a new file called assets.js and add the following code that does the following:

  • Exports styles constant, which we will use to inject styles into the head of the document
  • Exports MESSAGE_ICON constant, which is an SVG icon for the message icon
  • Exports CLOSE_ICON constant, which is an SVG icon for the close icon

You can later change the styles however you want, but for now, this is the default styling we will use.

assets.js

export const styles = `
.widget__container * {
box-sizing: border-box;
}
h3, p, input {
margin: 0;
padding: 0;
}
.widget__container {
box-shadow: 0 0 18px 8px rgba(0, 0, 0, 0.1), 0 0 32px 32px rgba(0, 0, 0, 0.08);
width: 400px;
overflow: auto;
right: -25px;
bottom: 75px;
position: absolute;
transition: max-height .2s ease;
font-family: Helvetica, Arial ,sans-serif;
background-color: #e6e6e6a6;
border-radius: 10px;
box-sizing: border-box;
}
.widget__icon {
cursor: pointer;
width: 60%;
position: absolute;
top: 18px;
left: 16px;
transition: transform .3s ease;
}
.widget__hidden {
transform: scale(0);
}
.button__container {
border: none;
background-color: #0f172a;
width: 60px;
height: 60px;
border-radius: 50%;
cursor: pointer;
}
.widget__container.hidden {
max-height: 0px;
}
.widget__header {
padding: 1rem 2rem 1.5rem;
background-color: #000;
color: #fff;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
text-align: center;
}
.widget__header h3 {
font-size: 24px;
font-weight: 400;
margin-bottom: 8px;
}
form {
padding: 2rem 1rem 1.5rem;
}
form .form__field {
margin-bottom: 1.5rem;
display: flex;
flex-direction: column;
}
.form__field label {
margin-bottom: 8px;
font-size: 14px;
}
.form__field input,
.form__field textarea {
border: 1px solid #000000ad;
border-radius: 3px;
padding: 8px 10px;
background-color: #fff;
}
.form__field input {
height: 48px;
}
.form__field textarea::placeholder {
font-family: Helvetica, Arial ,sans-serif;
}
form button {
height: 48px;
border-radius: 6px;
font-size: 18px;
background-color: #000;
color: #fff;
border: 0;
width: 100%;
cursor: pointer;
}
form button:hover {
background-color: rgba(0, 0, 0, 95%);
}
 
/* Chat containers */
.container {
border: 2px solid #dedede;
background-color: #f1f1f1;
border-radius: 5px;
padding: 10px;
margin: 10px 0;
}
 
/* Darker chat container */
.darker {
border-color: #ccc;
background-color: #ddd;
}
 
/* Clear floats */
.container::after {
content: "";
clear: both;
display: table;
}
 
/* Style images */
.container img {
float: left;
max-width: 60px;
width: 100%;
margin-right: 20px;
border-radius: 50%;
}
 
/* Style the right image */
.container img.right {
float: right;
margin-left: 20px;
margin-right:0;
}
 
/* Style time text */
.time-right {
float: right;
color: #aaa;
}
 
/* Style time text */
.time-left {
float: left;
color: #999;
}
 
.widget__messages_box {
margin: 0px 15px;
height: 400px;
overflow-y: scroll;
}
`;
 
export const MESSAGE_ICON = `
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-mail">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
`;
 
export const CLOSE_ICON = `
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-x">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
`;

Next, we need to open our main.js file and add the following code:

  • Import of styling
  • Uncomment few lines

So, let's add the injection:

main.js

import {CLOSE_ICON, MESSAGE_ICON, styles} from "./assets.js";
 
class MessageWidget {
// ...
injectStyles() {
const styleTag = document.createElement("style");
styleTag.innerHTML = styles.replace(/^\s+|\n/gm, "");
document.head.appendChild(styleTag);
}
 
// ...
}

Then, we can uncomment the injectStyles method in the construct method:

main.js

class MessageWidget {
// ...
constructor() {
// ...
// this.injectStyles(); //
this.injectStyles();
}
// ...
}

And uncomment the SVG icons in the createWidgetContent method:

main.js

class MessageWidget {
// ...
createWidgetContent() {
// ...
// this.widgetIcon.innerHTML = MESSAGE_ICON; //
this.widgetIcon.innerHTML = MESSAGE_ICON;
// this.closeIcon.innerHTML = CLOSE_ICON; //
this.closeIcon.innerHTML = CLOSE_ICON;
// ...
}
// ...
}

Now, if we launch our project with npm run dev, we should see the widget with the new styles applied:

And if we click on it, we should see that it opens and closes as expected:

That's it. Next, we will test the widget to see if it works as expected.


No comments or questions yet...