Feature: Update design for web widget (#408)

This commit is contained in:
Nithin David Thomas 2020-01-13 12:10:40 +05:30 committed by Pranav Raj S
parent 655c585358
commit 7cf19e0b52
11 changed files with 184 additions and 77 deletions

View file

@ -4,8 +4,6 @@ import { SDK_CSS } from '../widget/assets/scss/sdk';
/* eslint-disable no-param-reassign */
const bubbleImg =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAAUVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////8IN+deAAAAGnRSTlMAAwgJEBk0TVheY2R5eo+ut8jb5OXs8fX2+cjRDTIAAADsSURBVHgBldZbkoMgFIThRgQv8SKKgGf/C51UnJqaRI30/9zfe+NQUQ3TvG7bOk9DVeCmshmj/CuOTYnrdBfkUOg0zlOtl9OWVuEk4+QyZ3DIevmSt/ioTvK1VH/s5bY3YdM9SBZ/mUUyWgx+U06ycgp7D8msxSvtc4HXL9BLdj2elSEfhBJAI0QNgJEBI1BEBsQClVBVGDgwYOLAhJkDM1YOrNg4sLFAsLJgZsHEgoEFFQt0JAFGFjQsKAMJ0LFAexKgZYFyJIDxJIBNJEDNAtSJBLCeBDCOBFAPzwFA94ED+zmhwDO9358r8ANtIsMXi7qVAwAAAABJRU5ErkJggg==';
const closeImg =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAP1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////9Du/pqAAAAFHRSTlMACBstLi8wMVB+mcbT2err7O3w8n+sjtQAAAEuSURBVHgBtNLdcoMgGITh1SCGH9DId//X2mnTg7hYxj0oh8w8r+MqgDnmlsIE6UwhtRxnAHge9n2KV7wvP+h4AvPbm73W+359/aJjRjQTCuTNIrJJBfKW0UwqkLeGZJ8Ff2O/T28JwZQCewuYilJgX6buavdDv188br1RIE+jc2H5yy+9VwrXXij0nsflwth7YFRw7N3Y88BcYL+z7wubO/lt6AcFwQMLF9irP8r2eF8/ei8VLrxUkDzguMDejX03WK3dsGJB9lxgrxd0T8PTRxUL5OUCealQz76KXg/or/CvI36VXgcEAAAgCMP6t16IZVDg3zPuI+0rb5g2zlsoW2lbqlvrOyw7bTuuO+8LGIs4C1mLeQuai7oL2437LRytPC1drX0tnq2+Ld+r/wDPIIIJkfdlbQAAAABJRU5ErkJggg==';
const body = document.getElementsByTagName('body')[0];
const holder = document.createElement('div');
@ -189,11 +187,8 @@ const IFrameHelper = {
target: chatBubble,
});
const closeIcon = createBubbleIcon({
className: 'woot-widget-bubble woot--close woot--hide',
src: closeImg,
target: closeBubble,
});
const closeIcon = closeBubble;
closeIcon.className = 'woot-widget-bubble woot--close woot--hide';
chatIcon.style.background = widgetColor;
closeIcon.style.background = widgetColor;

View file

@ -1,44 +1,47 @@
export const SDK_CSS = `
.woot-widget-holder {
z-index: 2147483000!important;
position: fixed!important;
-moz-box-shadow: 0 5px 40px rgba(0,0,0,.16)!important;
-o-box-shadow: 0 5px 40px rgba(0,0,0,.16)!important;
-webkit-box-shadow: 0 5px 40px rgba(0,0,0,.16)!important;
box-shadow: 0 5px 40px rgba(0,0,0,.16)!important;
overflow: hidden!important;
export const SDK_CSS = ` .woot-widget-holder {
z-index: 2147483000 !important;
position: fixed !important;
-moz-box-shadow: 0 5px 40px rgba(0, 0, 0, .16) !important;
-o-box-shadow: 0 5px 40px rgba(0, 0, 0, .16) !important;
-webkit-box-shadow: 0 5px 40px rgba(0, 0, 0, .16) !important;
box-shadow: 0 5px 40px rgba(0, 0, 0, .16) !important;
overflow: hidden !important;
opacity: 1;
transition-property: opacity, bottom;
transition-duration: 0.5s, 0.5s;
}
.woot-widget-holder iframe { width: 100% !important; height: 100% !important; border: 0; }
.woot-widget-holder iframe {
width: 100% !important;
height: 100% !important;
border: 0;
}
.woot-widget-bubble {
z-index: 2147483000!important;
-moz-box-shadow: 0 8px 24px rgba(0,0,0,.16)!important;
-o-box-shadow: 0 8px 24px rgba(0,0,0,.16)!important;
-webkit-box-shadow: 0 8px 24px rgba(0,0,0,.16)!important;
box-shadow: 0 8px 24px rgba(0,0,0,.16)!important;
-o-border-radius: 100px!important;
-moz-border-radius: 100px!important;
-webkit-border-radius: 100px!important;
border-radius: 100px!important;
z-index: 2147483000 !important;
-moz-box-shadow: 0 8px 24px rgba(0, 0, 0, .16) !important;
-o-box-shadow: 0 8px 24px rgba(0, 0, 0, .16) !important;
-webkit-box-shadow: 0 8px 24px rgba(0, 0, 0, .16) !important;
box-shadow: 0 8px 24px rgba(0, 0, 0, .16) !important;
-o-border-radius: 100px !important;
-moz-border-radius: 100px !important;
-webkit-border-radius: 100px !important;
border-radius: 100px !important;
background: #1f93ff;
position: fixed;
cursor: pointer;
right: 20px;
bottom: 20px;
width: 64px!important;
height: 64px!important;
width: 64px !important;
height: 64px !important;
}
.woot-widget-bubble:hover {
background: #1f93ff;
-moz-box-shadow: 0 8px 32px rgba(0,0,0,.4)!important;
-o-box-shadow: 0 8px 32px rgba(0,0,0,.4)!important;
-webkit-box-shadow: 0 8px 32px rgba(0,0,0,.4)!important;
box-shadow: 0 8px 32px rgba(0,0,0,.4)!important;
-moz-box-shadow: 0 8px 32px rgba(0, 0, 0, .4) !important;
-o-box-shadow: 0 8px 32px rgba(0, 0, 0, .4) !important;
-webkit-box-shadow: 0 8px 32px rgba(0, 0, 0, .4) !important;
box-shadow: 0 8px 32px rgba(0, 0, 0, .4) !important;
}
.woot-widget-bubble img {
@ -47,15 +50,29 @@ export const SDK_CSS = `
margin: 20px;
}
.woot-widget-bubble.woot--close img {
width: 16px;
height: 16px;
margin: 24px;
.woot--close:hover {
opacity: 1;
}
.woot--close:before, .woot--close:after {
position: absolute;
left: 30px;
top: 15px;
content: ' ';
height: 33px;
width: 2px;
background-color: white;
}
.woot--close:before {
transform: rotate(45deg);
}
.woot--close:after {
transform: rotate(-45deg);
}
.woot--hide {
visibility: hidden !important;
z-index: -1!important;
z-index: -1 !important;
opacity: 0;
bottom: 60px;
}
@ -69,12 +86,17 @@ export const SDK_CSS = `
}
.woot-widget-bubble.woot--close {
top: 0;
right: 0;
top: 8px;
right: 8px;
box-shadow: none !important;
-moz-box-shadow: none !important;
-o-box-shadow: none !important;
-webkit-box-shadow: none !important;
background: transparent !important;
}
.woot--close:before, .woot--close:after {
background-color: black;
}
}
@ -83,13 +105,13 @@ export const SDK_CSS = `
bottom: 104px;
right: 20px;
height: calc(85% - 64px - 20px);
width: 370px!important;
min-height: 250px!important;
max-height: 590px!important;
-o-border-radius: 8px!important;
-moz-border-radius: 8px!important;
-webkit-border-radius: 8px!important;
border-radius: 8px!important;
width: 400px !important;
min-height: 250px !important;
max-height: 590px !important;
-o-border-radius: 8px !important;
-moz-border-radius: 8px !important;
-webkit-border-radius: 8px !important;
border-radius: 8px !important;
}
}

View file

@ -16,22 +16,26 @@
.branding {
align-items: center;
color: $color-gray;
color: $color-light-gray;
opacity: 0.9;
display: flex;
filter: grayscale(1);
font-size: $font-size-default;
font-size: $font-size-small;
justify-content: center;
padding: $space-one;
text-align: center;
text-decoration: none;
padding: $space-slab 0;
cursor: pointer;
&:hover {
filter: grayscale(0);
opacity: 1;
color: $color-gray;
}
img {
margin-right: $space-small;
max-width: $space-two;
margin-right: $space-smaller;
max-width: $space-slab;
}
}
</style>

View file

@ -12,8 +12,14 @@ export default {
ChatInputWrap,
},
props: {
msg: String,
onSendMessage: Function,
msg: {
type: String,
default: '',
},
onSendMessage: {
type: Function,
default: () => {},
},
},
};
</script>
@ -24,11 +30,12 @@ export default {
.footer {
background: $color-white;
box-shadow: 0 -$space-micro 3px rgba(50, 50, 93, 0.04),
0 -1px 2px rgba(0, 0, 0, 0.03);
box-sizing: border-box;
padding: $space-small;
padding: $space-small $space-slab;
width: 100%;
border-radius: 7px;
box-shadow: 0 20px 25px -10px rgba(0, 0, 0, 0.1),
0 10px 10px -10px rgba(0, 0, 0, 0.04) !important;
}
.branding {

View file

@ -1,6 +1,10 @@
<template>
<header class="header-expanded" :style="{ background: widgetColor }">
<header class="header-expanded">
<div>
<!-- <img
class="logo"
src="http://www.hennigcompany.com/wp-content/uploads/2014/06/starbucks-logo.png"
/> -->
<h2 class="title">
{{ introHeading }}
</h2>
@ -39,21 +43,35 @@ export default {
@import '~widget/assets/scss/variables.scss';
.header-expanded {
background: $color-woot;
padding: $space-large;
background: $color-white;
padding: $space-larger $space-medium $space-large;
width: 100%;
box-sizing: border-box;
color: $color-white;
border-radius: 1.6rem;
box-shadow: 0 10px 15px -16px rgba(0, 0, 0, 0.1),
0 4px 6px -8px rgba(0, 0, 0, 0.05) !important;
@media only screen and (min-device-width: 320px) and (max-device-width: 480px) {
border-radius: 0;
}
.logo {
width: 64px;
height: 64px;
}
.title {
color: $color-heading;
font-size: $font-size-mega;
font-weight: $font-weight-medium;
margin-bottom: $space-two;
font-weight: $font-weight-normal;
margin-bottom: $space-slab;
margin-top: $space-large;
}
.body {
font-size: $font-size-medium;
line-height: 1.5;
color: $color-body;
font-size: 1.8rem;
line-height: 1.6;
}
}
</style>

View file

@ -1,14 +1,21 @@
<template>
<textarea
class="form-input user-message-input"
:placeholder="placeholder"
:value="value"
@input="$emit('input', $event.target.value)"
/>
<resizable-textarea>
<textarea
class="form-input user-message-input"
:placeholder="placeholder"
:value="value"
@input="$emit('input', $event.target.value)"
/>
</resizable-textarea>
</template>
<script>
import ResizableTextarea from 'widget/components/ResizableTextarea.vue';
export default {
components: {
ResizableTextarea,
},
props: {
placeholder: String,
value: String,
@ -24,5 +31,6 @@ export default {
border: 0;
height: $space-large;
resize: none;
padding-top: $space-small;
}
</style>

View file

@ -4,11 +4,13 @@
<ChatSendButton
:on-click="handleButtonClick"
:disabled="!userInput.length"
:color="widgetColor"
/>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import ChatSendButton from 'widget/components/ChatSendButton.vue';
import ChatInputArea from 'widget/components/ChatInputArea.vue';
@ -42,6 +44,11 @@ export default {
document.addEventListener('keypress', this.handleEnterKeyPress);
},
computed: {
...mapGetters({
widgetColor: 'appConfig/getWidgetColor',
}),
},
methods: {
handleButtonClick() {
if (this.userInput && this.userInput.trim()) {

View file

@ -5,9 +5,11 @@
class="send-button"
@click="onClick"
>
<span v-if="!loading" class="icon-holder">
<i class="ion-android-send" />
</span>
<span
v-if="!loading"
:style="`background-color: ${color}`"
class="icon-holder"
></span>
<spinner v-else size="small" />
</button>
</template>
@ -32,6 +34,10 @@ export default {
type: Function,
default: () => {},
},
color: {
type: String,
default: '#6e6f73',
},
},
};
</script>
@ -45,6 +51,7 @@ export default {
border: 0;
cursor: pointer;
position: relative;
padding-right: $space-smaller;
.icon-holder {
display: flex;
@ -53,6 +60,10 @@ export default {
fill: $color-white;
font-size: $font-size-big;
font-weight: $font-weight-medium;
width: $space-two;
height: $space-two;
-webkit-mask-image: url("data:image/svg+xml;charset=utf8,%3Csvg width='20' height='20' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M18.34 7.32l-14-7a3 3 0 00-4.08 3.9l2.4 5.37c.11.262.11.558 0 .82l-2.4 5.37A3 3 0 003 20a3.14 3.14 0 001.35-.32l14-7a3 3 0 000-5.36h-.01zm-.89 3.57l-14 7a1 1 0 01-1.35-1.3l2.39-5.37a2 2 0 00.08-.22h6.89a1 1 0 000-2H4.57a2 2 0 00-.08-.22L2.1 3.41a1 1 0 011.35-1.3l14 7a1 1 0 010 1.78z' fill='%23999A9B' fill-rule='nonzero'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml;charset=utf8,%3Csvg width='20' height='20' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M18.34 7.32l-14-7a3 3 0 00-4.08 3.9l2.4 5.37c.11.262.11.558 0 .82l-2.4 5.37A3 3 0 003 20a3.14 3.14 0 001.35-.32l14-7a3 3 0 000-5.36h-.01zm-.89 3.57l-14 7a1 1 0 01-1.35-1.3l2.39-5.37a2 2 0 00.08-.22h6.89a1 1 0 000-2H4.57a2 2 0 00-.08-.22L2.1 3.41a1 1 0 011.35-1.3l14 7a1 1 0 010 1.78z' fill='%23999A9B' fill-rule='nonzero'/%3E%3C/svg%3E");
}
}
</style>

View file

@ -13,12 +13,10 @@
/>
</div>
</div>
<branding></branding>
</div>
</template>
<script>
import Branding from 'widget/components/Branding.vue';
import ChatMessage from 'widget/components/ChatMessage.vue';
import DateSeparator from 'shared/components/DateSeparator.vue';
import Spinner from 'shared/components/Spinner.vue';
@ -27,7 +25,6 @@ import { mapActions, mapGetters } from 'vuex';
export default {
name: 'ConversationWrap',
components: {
Branding,
ChatMessage,
DateSeparator,
Spinner,

View file

@ -0,0 +1,26 @@
<script>
export default {
mounted() {
this.$nextTick(() => {
this.$el.setAttribute(
'style',
`height: ${this.$el.scrollHeight}px;overflow-y:hidden;`
);
});
this.$el.addEventListener('input', this.resizeTextarea);
},
beforeDestroy() {
this.$el.removeEventListener('input', this.resizeTextarea);
},
methods: {
resizeTextarea(event) {
event.target.style.height = '3.2rem';
event.target.style.height = `${event.target.scrollHeight}px`;
},
},
render() {
return this.$slots.default[0];
},
};
</script>

View file

@ -6,7 +6,10 @@
</div>
<ConversationWrap :grouped-messages="groupedMessages" />
<div class="footer-wrap">
<ChatFooter :on-send-message="handleSendMessage" />
<div class="input-wrap">
<ChatFooter :on-send-message="handleSendMessage" />
</div>
<branding></branding>
</div>
</div>
</template>
@ -14,6 +17,7 @@
<script>
import { mapActions, mapGetters } from 'vuex';
import Branding from 'widget/components/Branding.vue';
import ChatFooter from 'widget/components/ChatFooter.vue';
import ChatHeaderExpanded from 'widget/components/ChatHeaderExpanded.vue';
import ChatHeader from 'widget/components/ChatHeader.vue';
@ -26,6 +30,7 @@ export default {
ChatHeaderExpanded,
ConversationWrap,
ChatHeader,
Branding,
},
methods: {
...mapActions('conversation', ['sendMessage']),
@ -67,6 +72,13 @@ export default {
.footer-wrap {
flex-shrink: 0;
width: 100%;
display: flex;
flex-direction: column;
}
.input-wrap {
padding: 0 $space-medium;
}
}
</style>