Feature: Widget design update (#426)

This commit is contained in:
Nithin David Thomas 2020-01-17 13:36:05 +05:30 committed by Pranav Raj S
parent cc180b77ce
commit f7f7a6b9c7
18 changed files with 186 additions and 66 deletions

View file

@ -21,7 +21,7 @@ table {
tr { tr {
.show-if-hover { .show-if-hover {
opacity: 0; opacity: 0;
transition: all .2s $ease-in-out-cubic; transition: all 0.2s $ease-in-out-cubic;
} }
&:hover { &:hover {

View file

@ -140,19 +140,21 @@ const IFrameHelper = {
'*' '*'
); );
}, },
events: {
loaded: message => {
Cookies.set('cw_conversation', message.config.authToken);
IFrameHelper.sendMessage('config-set', {});
IFrameHelper.onLoad(message.config.channelConfig);
IFrameHelper.setCurrentUrl();
},
set_auth_token: message => {
Cookies.set('cw_conversation', message.authToken);
},
toggleBubble: () => {
bubbleClickCallback();
},
},
initPostMessageCommunication: () => { initPostMessageCommunication: () => {
const events = {
loaded: message => {
Cookies.set('cw_conversation', message.config.authToken);
IFrameHelper.sendMessage('config-set', {});
IFrameHelper.onLoad(message.config.channelConfig);
IFrameHelper.setCurrentUrl();
},
set_auth_token: message => {
Cookies.set('cw_conversation', message.authToken);
},
};
window.onmessage = e => { window.onmessage = e => {
if ( if (
typeof e.data !== 'string' || typeof e.data !== 'string' ||
@ -161,8 +163,8 @@ const IFrameHelper = {
return; return;
} }
const message = JSON.parse(e.data.replace('chatwoot-widget:', '')); const message = JSON.parse(e.data.replace('chatwoot-widget:', ''));
if (typeof events[message.event] === 'function') { if (typeof IFrameHelper.events[message.event] === 'function') {
events[message.event](message); IFrameHelper.events[message.event](message);
} }
}; };
}, },

View file

@ -6,17 +6,8 @@
<script> <script>
import { mapActions } from 'vuex'; import { mapActions } from 'vuex';
import { setHeader } from './helpers/axios'; import { setHeader } from 'widget/helpers/axios';
import { IFrameHelper } from 'widget/helpers/utils';
export const IFrameHelper = {
isIFrame: () => window.self !== window.top,
sendMessage: msg => {
window.parent.postMessage(
`chatwoot-widget:${JSON.stringify({ ...msg })}`,
'*'
);
},
};
export default { export default {
name: 'App', name: 'App',

View file

@ -4,6 +4,11 @@ $shadow-color-2: rgba(0, 0, 0, 0.07);
$shadow-color-3: rgba(50, 50, 93, .08); $shadow-color-3: rgba(50, 50, 93, .08);
$shadow-color-4: rgba(0, 0, 0, .05); $shadow-color-4: rgba(0, 0, 0, .05);
$color-shadow-medium: rgba(0, 0, 0, 0.1);
$color-shadow-light: rgba(0, 0, 0, 0.06);
$color-shadow-large: rgba(0, 0, 0, 0.25);
$color-shadow-outline: rgba(66, 153, 225, 0.5);
@mixin normal-shadow { @mixin normal-shadow {
box-shadow: 0 $space-small $space-normal $shadow-color-1, 0 $space-smaller $space-slab $shadow-color-2; box-shadow: 0 $space-small $space-normal $shadow-color-1, 0 $space-smaller $space-slab $shadow-color-2;
} }
@ -13,8 +18,59 @@ $shadow-color-4: rgba(0, 0, 0, .05);
} }
@mixin placeholder { @mixin placeholder {
&::-webkit-input-placeholder {@content} &::-webkit-input-placeholder {
&:-moz-placeholder {@content} @content
&::-moz-placeholder {@content} }
&:-ms-input-placeholder {@content}
&:-moz-placeholder {
@content
}
&::-moz-placeholder {
@content
}
&:-ms-input-placeholder {
@content
}
}
@mixin shadow {
box-shadow: 0 1px 10px -4 $color-shadow-medium,
0 1px 5px 2px $color-shadow-light;
}
@mixin shadow-medium {
box-shadow: 0 4px 6px -8px $color-shadow-medium,
0 2px 4px -4px $color-shadow-light;
}
@mixin shadow-large {
box-shadow: 0 10px 15px -16px $color-shadow-medium,
0 4px 6px -8px $color-shadow-light;
}
@mixin shadow-big {
box-shadow: 0 20px 25px -20px $color-shadow-medium,
0 10px 10px -10px $color-shadow-light;
}
@mixin shadow-mega {
box-shadow: 0 25px 50px -12px $color-shadow-big;
}
@mixin shadow-inner {
box-shadow: inset 0 2px 4px 0 $color-shadow-light;
}
@mixin shadow-outline {
box-shadow: 0 0 0 3px $color-shadow-outline;
}
@mixin shadow-none {
box-shadow: none;
} }

View file

@ -91,9 +91,20 @@ $line-height: 1;
$footer-height: 11.2rem; $footer-height: 11.2rem;
$header-expanded-height: $space-medium * 10; $header-expanded-height: $space-medium * 10;
$font-family: 'Inter', -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; $font-family: 'Inter',
-apple-system,
system-ui,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
"Helvetica Neue",
Arial,
sans-serif;
$ionicons-font-path: '~ionicons/fonts'; $ionicons-font-path: '~ionicons/fonts';
$spinkit-spinner-color: $color-white !default; $spinkit-spinner-color: $color-white !default;
$spinkit-spinner-margin: 0 0 0 1.6rem !default; $spinkit-spinner-margin: 0 0 0 1.6rem !default;
$spinkit-size: 1.6rem !default; $spinkit-size: 1.6rem !default;
// Break points
$break-point-medium: 667px;

View file

@ -55,10 +55,10 @@ export const SDK_CSS = ` .woot-widget-holder {
} }
.woot--close:before, .woot--close:after { .woot--close:before, .woot--close:after {
position: absolute; position: absolute;
left: 30px; left: 32px;
top: 15px; top: 20px;
content: ' '; content: ' ';
height: 33px; height: 24px;
width: 2px; width: 2px;
background-color: white; background-color: white;
} }
@ -86,17 +86,10 @@ export const SDK_CSS = ` .woot-widget-holder {
} }
.woot-widget-bubble.woot--close { .woot-widget-bubble.woot--close {
top: 8px; visibility: hidden !important;
right: 8px; z-index: -1 !important;
box-shadow: none !important; opacity: 0;
-moz-box-shadow: none !important; bottom: 60px;
-o-box-shadow: none !important;
-webkit-box-shadow: none !important;
background: transparent !important;
}
.woot--close:before, .woot--close:after {
background-color: black;
} }
} }

View file

@ -71,7 +71,7 @@ export default {
max-width: 88%; max-width: 88%;
& + .agent-message { & + .agent-message {
margin-bottom: $space-smaller; margin-bottom: $space-micro;
.chat-bubble { .chat-bubble {
border-top-left-radius: $space-smaller; border-top-left-radius: $space-smaller;
@ -101,10 +101,10 @@ export default {
.agent-name { .agent-name {
color: $color-body; color: $color-body;
font-size: $font-size-default; font-size: $font-size-small;
font-weight: $font-weight-medium; font-weight: $font-weight-medium;
margin-bottom: $space-small; margin: $space-small 0;
margin-top: $space-small; padding-left: $space-micro;
} }
} }
</style> </style>

View file

@ -24,7 +24,7 @@
justify-content: center; justify-content: center;
text-align: center; text-align: center;
text-decoration: none; text-decoration: none;
padding: $space-slab 0; padding: $space-normal 0 $space-slab;
cursor: pointer; cursor: pointer;
&:hover { &:hover {

View file

@ -27,6 +27,7 @@ export default {
<!-- Add "scoped" attribute to limit CSS to this component only --> <!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss"> <style scoped lang="scss">
@import '~widget/assets/scss/variables.scss'; @import '~widget/assets/scss/variables.scss';
@import '~widget/assets/scss/mixins.scss';
.footer { .footer {
background: $color-white; background: $color-white;
@ -34,8 +35,7 @@ export default {
padding: $space-small $space-slab; padding: $space-small $space-slab;
width: 100%; width: 100%;
border-radius: 7px; border-radius: 7px;
box-shadow: 0 20px 25px -10px rgba(0, 0, 0, 0.1), @include shadow-big;
0 10px 10px -10px rgba(0, 0, 0, 0.04) !important;
} }
.branding { .branding {

View file

@ -1,15 +1,15 @@
<template> <template>
<header class="header-collapsed" :style="{ background: widgetColor }"> <header class="header-collapsed">
<div> <h2 class="title">
<h2 class="title"> {{ title }}
{{ title }} </h2>
</h2> <span class="close" @click="closeWindow"></span>
</div>
</header> </header>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import { IFrameHelper } from 'widget/helpers/utils';
export default { export default {
name: 'ChatHeader', name: 'ChatHeader',
@ -24,22 +24,60 @@ export default {
default: '', default: '',
}, },
}, },
methods: {
closeWindow() {
if (IFrameHelper.isIFrame()) {
IFrameHelper.sendMessage({
event: 'toggleBubble',
});
}
},
},
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import '~widget/assets/scss/variables.scss'; @import '~widget/assets/scss/variables.scss';
@import '~widget/assets/scss/mixins.scss';
.header-collapsed { .header-collapsed {
background: $color-woot; display: flex;
justify-content: space-between;
background: $color-white;
padding: $space-two $space-medium; padding: $space-two $space-medium;
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
color: $color-white; color: $color-white;
border-bottom-left-radius: $space-small;
border-bottom-right-radius: $space-small;
@include shadow-large;
.title { .title {
font-size: $font-size-big; font-size: $font-size-large;
font-weight: $font-weight-medium; font-weight: $font-weight-medium;
color: $color-heading;
}
.close {
position: relative;
margin-right: $space-small;
&:before,
&:after {
position: absolute;
left: 0;
top: $space-smaller;
content: ' ';
height: $space-normal;
width: 2px;
background-color: $color-heading;
}
&:before {
transform: rotate(45deg);
}
&:after {
transform: rotate(-45deg);
}
} }
} }
</style> </style>

View file

@ -41,15 +41,15 @@ export default {
<style scoped lang="scss"> <style scoped lang="scss">
@import '~widget/assets/scss/variables.scss'; @import '~widget/assets/scss/variables.scss';
@import '~widget/assets/scss/mixins.scss';
.header-expanded { .header-expanded {
background: $color-white; background: $color-white;
padding: $space-larger $space-medium $space-large; padding: $space-larger $space-medium $space-large;
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
border-radius: 1.6rem; border-radius: $space-normal;
box-shadow: 0 10px 15px -16px rgba(0, 0, 0, 0.1), @include shadow-large;
0 4px 6px -8px rgba(0, 0, 0, 0.05) !important;
@media only screen and (min-device-width: 320px) and (max-device-width: 480px) { @media only screen and (min-device-width: 320px) and (max-device-width: 480px) {
border-radius: 0; border-radius: 0;

View file

@ -46,6 +46,7 @@ export default {
} }
& + .agent-message { & + .agent-message {
margin-top: $space-normal; margin-top: $space-normal;
margin-bottom: $space-micro;
} }
.message-wrap { .message-wrap {
margin-right: $space-small; margin-right: $space-small;

View file

@ -44,7 +44,7 @@ export default {
font-size: $font-size-default; font-size: $font-size-default;
line-height: 1.5; line-height: 1.5;
max-width: 80%; max-width: 80%;
padding: $space-small $space-two; padding: $space-small $space-normal;
text-align: left; text-align: left;
a { a {

View file

@ -17,7 +17,7 @@
:disabled="$v.email.$invalid" :disabled="$v.email.$invalid"
:style="{ background: widgetColor, borderColor: widgetColor }" :style="{ background: widgetColor, borderColor: widgetColor }"
> >
<i v-if="!uiFlags.isUpdating" class="ion-android-arrow-forward" /> <i v-if="!uiFlags.isUpdating" class="ion-ios-arrow-forward" />
<spinner v-else /> <spinner v-else />
</button> </button>
</form> </form>

View file

@ -8,3 +8,13 @@ export const arrayToHashById = array =>
newMap[obj.id] = obj; newMap[obj.id] = obj;
return newMap; return newMap;
}, {}); }, {});
export const IFrameHelper = {
isIFrame: () => window.self !== window.top,
sendMessage: msg => {
window.parent.postMessage(
`chatwoot-widget:${JSON.stringify({ ...msg })}`,
'*'
);
},
};

View file

@ -75,6 +75,21 @@ export default {
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative;
&:before {
content: '';
position: absolute;
top: -$space-normal;
left: 0;
width: 100%;
height: $space-normal;
background: linear-gradient(
to top,
$color-background,
rgba($color-background, 0)
);
}
} }
.input-wrap { .input-wrap {

View file

@ -1,3 +1,5 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
<script> <script>
(function(d,t) { (function(d,t) {
var BASE_URL = ''; var BASE_URL = '';

View file

@ -8,7 +8,8 @@
"test": "jest --no-cache", "test": "jest --no-cache",
"test:watch": "jest --watch --no-cache", "test:watch": "jest --watch --no-cache",
"test:coverage": "jest --no-cache --collectCoverage", "test:coverage": "jest --no-cache --collectCoverage",
"webpacker-start": "webpack-dev-server -d --config webpack.dev.config.js --content-base public/ --progress --colors" "webpacker-start": "webpack-dev-server -d --config webpack.dev.config.js --content-base public/ --progress --colors",
"start:dev": "foreman start -f ./Procfile.dev"
}, },
"dependencies": { "dependencies": {
"@babel/polyfill": "^7.6.0", "@babel/polyfill": "^7.6.0",