Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Responsive full view #17

Merged
merged 7 commits into from
Sep 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class App extends Component {
export default App;
```

4- Customize the widget to match your app design! You can add both props to manage the title of the widget, the avatar it will use and of course, you can change, from the CSS, the styles the widget will have.
4- Customize the widget to match your app design! You can add both props to manage the title of the widget and the avatar it will use. Of course, feel free to change the styles the widget will have in the CSS

```js
import React, { Component } from 'react';
Expand Down Expand Up @@ -141,11 +141,12 @@ export default App;

#### Props

- **handleNewUserMessage:** (PropTypes.func.isRequired) Function to handle the user input, will receive the full text message when submitted
- **title:** (PropTypes.string) Title of the widget
- **subtitle:** (PropTypes.string) Subtitle of the widget
- **senderPlaceHolder:** (PropTypes.string) The placeholder of the message input
- **profileAvatar:** (PropTypes.string.isRequired) The profile image that will be set on the responses
- **handleNewUserMessage:** (PropTypes.func.isRequired) Function to handle the user input, will receive the full text message when submitted
- **profileAvatar:** (PropTypes.string) The profile image that will be set on the responses
- **showCloseButton:** (PropTypes.bool) Show or hide the close button in full screen mode

#### Styles

Expand Down Expand Up @@ -198,6 +199,18 @@ In order to add new messages, you are provided with the following methods:

**Markdown is supported for the responses and user messages.**

#### Widget behavior

You can also control certain actions of the widget:

- **toggleWidget**
- params: No params expected
- This method is to toggle the widget at will without the need to trigger the click event on the launcher

- **toggleInputDisabled**
- params: No params expected
- Method to toggle the availability of the message input for the user to write on

## About

This project is maintained by [Martín Callegari](https://github.com/mcallegari10) and it was written by [Wolox](http://www.wolox.com.ar).
Expand Down
6 changes: 4 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
addResponseMessage,
addLinkSnippet,
renderCustomComponent,
toggleWidget
toggleWidget,
toggleInputDisabled
} from './src/store/actions/dispatcher';

export {
Expand All @@ -13,5 +14,6 @@ export {
addResponseMessage,
addLinkSnippet,
renderCustomComponent,
toggleWidget
toggleWidget,
toggleInputDisabled
};
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
import React from 'react';
import PropTypes from 'prop-types';

import close from 'assets/clear-button.svg';
import './style.scss';

const Header = ({ title, subtitle }) =>
const Header = ({ title, subtitle, toggleChat, showCloseButton }) =>
<div className="header">
{
showCloseButton &&
<button className="close-button" onClick={toggleChat}>
<img src={close} className="close" alt="close" />
</button>
}
<h4 className="title">{title}</h4>
<span>{subtitle}</span>
</div>;

Header.propTypes = {
title: PropTypes.string,
subtitle: PropTypes.string
subtitle: PropTypes.string,
toggleChat: PropTypes.func,
showCloseButton: PropTypes.bool
};

export default Header;
Original file line number Diff line number Diff line change
@@ -1,15 +1,48 @@
@import "variables.scss";

.header {
text-align: center;
background-color: $turqois-1;
border-radius: 10px 10px 0 0;
color: $white;
display: flex;
flex-direction: column;
text-align: center;
padding: 15px 0 25px;
}

.title {
font-size: 24px;
margin: 0;
padding: 15px 0;
}

.close-button {
display: none;
}

@media screen and (max-width: 800px) {
.header {
border-radius: 0;
flex-shrink: 0;
position: relative;
}

.title {
font-size: 24px;
margin: 0;
padding: 15px;
padding: 0 0 15px 0;
}

.close-button {
background-color: $turqois-1;
border: 0;
display: block;
position: absolute;
right: 10px;
top: 20px;
width: 40px;
}

.close {
width: 20px;
height: 20px;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ class Snippet extends PureComponent {
return (
<div className="snippet">
<h5 className="snippet-title">
{this.props.message.get('title')}
{ this.props.message.get('title') }
</h5>
<div className="snippet-details">
<a href={this.props.message.get('link')} className="link">
{this.props.message.get('link')}
{ this.props.message.get('link') }
</a>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,19 @@ class Messages extends Component {
render() {
return (
<div id="messages" className="messages-container">
{this.props.messages.map((message, index) =>
<div className="message" key={index}>
{message.get('showAvatar') &&
<img src={this.props.profileAvatar} className="avatar" alt="profile" />
}
{ this.getComponentToRender(message) }
</div>
)}
{
this.props.messages.map((message, index) =>
<div className="message" key={index}>
{
message.get('showAvatar') &&
<img src={this.props.profileAvatar} className="avatar" alt="profile" />
}
{
this.getComponentToRender(message)
}
</div>
)
}
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@
overflow-y: scroll;
padding-top: 10px;
}

@media screen and (max-width: 800px) {
.messages-container {
height: 100%;
max-height: none;
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import React from 'react';
import PropTypes from 'prop-types';

import send from 'assets/send_button.svg';
import './style.scss';

const Sender = ({ sendMessage, placeholder }) =>
const Sender = ({ sendMessage, placeholder, disabledInput }) =>
<form className="sender" onSubmit={sendMessage}>
<input type="text" className="new-message" name="message" placeholder={placeholder} autoFocus autoComplete="off" />
<input type="text" className="new-message" name="message" placeholder={placeholder} disabled={disabledInput} autoFocus autoComplete="off" />
<button type="submit" className="send">
<img src={send} className="send-icon" alt="send" />
</button>
</form>;

Sender.propTypes = {
sendMessage: PropTypes.func,
placeholder: PropTypes.string
placeholder: PropTypes.string,
disabledInput: PropTypes.bool
};

export default Sender;
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@import "variables.scss";

.sender {
align-items: center;
display: flex;
background-color: $grey-2;
height: 45px;
Expand All @@ -11,7 +12,6 @@
.new-message {
width: 100%;
border: 0;
align-self: center;
background-color: $grey-2;
height: 30px;
padding-left: 15px;
Expand All @@ -29,3 +29,10 @@
height: 25px;
}
}

@media screen and (max-width: 800px) {
.sender {
border-radius: 0;
flex-shrink: 0;
}
}
15 changes: 7 additions & 8 deletions src/components/Widget/components/Conversation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ const Conversation = props =>
<Header
title={props.title}
subtitle={props.subtitle}
toggleChat={props.toggleChat}
showCloseButton={props.showCloseButton}
/>
<Messages
profileAvatar={props.profileAvatar}
/>
<Sender
sendMessage={props.sendMessage}
placeholder={props.senderPlaceHolder}
disabledInput={props.disabledInput}
/>
</div>;

Expand All @@ -26,14 +29,10 @@ Conversation.propTypes = {
subtitle: PropTypes.string,
sendMessage: PropTypes.func,
senderPlaceHolder: PropTypes.string,
profileAvatar: PropTypes.string
};

Conversation.defaultProps = {
headerStyles: {},
messageStyles: {},
responsesStyles: {},
snippetStyles: {}
profileAvatar: PropTypes.string,
toggleChat: PropTypes.func,
showCloseButton: PropTypes.bool,
disabledInput: PropTypes.bool
};

export default Conversation;
8 changes: 8 additions & 0 deletions src/components/Widget/components/Conversation/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,11 @@
.slide-out {
@include animation(0, 0.5s, slide-out);
}

@media screen and (max-width: 800px) {
.conversation-container {
display: flex;
flex-direction: column;
height: 100%;
}
}
9 changes: 5 additions & 4 deletions src/components/Widget/components/Launcher/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import close from 'assets/clear-button.svg';
import './style.scss';

const Launcher = ({ toggle, chatOpened }) =>
<button type="button" className="launcher" onClick={toggle}>
{chatOpened ?
<img src={close} className="close-launcher" alt="" /> :
<img src={openLauncher} className="open-launcher" alt="" />
<button type="button" className={chatOpened ? 'launcher hide-sm' : 'launcher'} onClick={toggle}>
{
chatOpened ?
<img src={close} className="close-launcher" alt="" /> :
<img src={openLauncher} className="open-launcher" alt="" />
}
</button>;

Expand Down
13 changes: 13 additions & 0 deletions src/components/Widget/components/Launcher/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,16 @@
width: 20px;
@include animation(0, 0.5s, rotation-lr);
}

@media screen and (max-width: 800px){
.launcher {
bottom: 0;
margin: 20px;
position: fixed;
right: 0;
}

.hide-sm {
display: none;
}
}
9 changes: 6 additions & 3 deletions src/components/Widget/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,26 @@ class Widget extends Component {
subtitle={this.props.subtitle}
senderPlaceHolder={this.props.senderPlaceHolder}
profileAvatar={this.props.profileAvatar}
showCloseButton={this.props.showCloseButton}
/>
);
}
}

Widget.propTypes = {
handleNewUserMessage: PropTypes.func.isRequired,
title: PropTypes.string,
subtitle: PropTypes.string,
handleNewUserMessage: PropTypes.func.isRequired,
senderPlaceHolder: PropTypes.string,
profileAvatar: PropTypes.string
profileAvatar: PropTypes.string,
showCloseButton: PropTypes.bool
};

Widget.defaultProps = {
title: 'Welcome',
subtitle: 'This is your chat subtitle',
senderPlaceHolder: 'Type a message...'
senderPlaceHolder: 'Type a message...',
showCloseButton: true
};

export default connect()(Widget);
14 changes: 11 additions & 3 deletions src/components/Widget/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ import './style.scss';

const WidgetLayout = props =>
<div className="widget-container">
{props.showChat &&
{
props.showChat &&
<Conversation
title={props.title}
subtitle={props.subtitle}
sendMessage={props.onSendMessage}
senderPlaceHolder={props.senderPlaceHolder}
profileAvatar={props.profileAvatar}
toggleChat={props.onToggleConversation}
showChat={props.showChat}
showCloseButton={props.showCloseButton}
disabledInput={props.disabledInput}
/>
}
<Launcher
Expand All @@ -29,9 +34,12 @@ WidgetLayout.propTypes = {
onToggleConversation: PropTypes.func,
showChat: PropTypes.bool,
senderPlaceHolder: PropTypes.string,
profileAvatar: PropTypes.string
profileAvatar: PropTypes.string,
showCloseButton: PropTypes.bool,
disabledInput: PropTypes.bool
};

export default connect(store => ({
showChat: store.behavior.get('showChat')
showChat: store.behavior.get('showChat'),
disabledInput: store.behavior.get('disabledInput')
}))(WidgetLayout);
Loading