feat: chat shell

This commit is contained in:
cha0s 2020-07-13 02:26:56 -05:00
parent 2dee78cdef
commit 645763c828
9 changed files with 303 additions and 1 deletions

View File

@ -1,14 +1,26 @@
import './app.scss';
import {hot} from 'react-hot-loader';
import {Route, Switch} from 'react-router-dom';
import React from 'react';
import Chat from './chat';
import Home from './home';
const App = () => (
<div className="app">
<Home />
<Switch>
<Route
component={Home}
exact
path="/"
/>
<Route
component={Chat}
path="/chat"
/>
</Switch>
</div>
);

25
src/client/bar.jsx Normal file
View File

@ -0,0 +1,25 @@
import './bar.scss';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
export default function Bar(props) {
const {children, isHorizontal} = props;
return (
<div
className={classnames(['bar', isHorizontal ? 'bar--horizontal' : 'bar--vertical'])}
>
{children}
</div>
);
}
Bar.defaultProps = {
isHorizontal: true,
};
Bar.propTypes = {
children: PropTypes.node.isRequired,
isHorizontal: PropTypes.bool,
};

16
src/client/bar.scss Normal file
View File

@ -0,0 +1,16 @@
.bar--horizontal {
height: 4em;
width: 100%;
}
.bar--vertical {
height: 100%;
width: 4em;
}
.bar__items {
display: flex;
.channels--closed & {
flex-direction: column;
}
}

View File

@ -0,0 +1,62 @@
import './chat--channels.scss';
import classnames from 'classnames';
import React, {useState} from 'react';
import Bar from './bar';
export default function ChatChannels() {
const [isOpen, setIsOpen] = useState(false);
const [active, setActive] = useState(0);
const toggleOpen = () => setIsOpen(!isOpen);
const buttons = [
{
emoji: '🏠',
label: 'Home',
},
{
emoji: '📜',
label: 'Chats',
},
{
emoji: '😁',
label: 'Frens',
},
];
return (
<div
className={classnames(
'channels',
'chat--flexed',
isOpen ? 'channels--open' : 'channels--closed',
)}
>
<Bar isHorizontal={isOpen}>
<ul className="channels__buttons">
<li className="channels__brandItem">reddichat</li>
{
buttons.map(({emoji, label}, i) => (
<li className="channels__buttonItem">
<button
className={classnames('channels__button', {active: isOpen && i === active})}
onClick={() => {
if (i === active || !isOpen) {
toggleOpen();
}
setActive(i);
}}
type="button"
>
<span role="img" aria-label={label}>{emoji}</span>
<span className="channels__buttonText">{label}</span>
</button>
</li>
))
}
</ul>
</Bar>
</div>
);
}
ChatChannels.propTypes = {};

View File

@ -0,0 +1,58 @@
.channels {
background-color: #373737;
}
.channels--open {
flex-basis: 18em;
}
.channels__buttons {
display: flex;
.channels--closed & {
flex-direction: column;
}
}
.channels__brandItem {
display: flex;
flex-direction: column;
justify-content: space-around;
font-family: var(--thick-title-font-family);
font-size: 0.95em;
padding: 1em;
user-select: none;
.channels--closed & {
font-size: 0.9em;
text-align: center;
padding: 1em 0 0.5em;
}
}
.channels__buttonItem {
padding: 0.25em;
.channels--closed & {
padding-bottom: 0;
}
.channels--open & {
padding-right: 0;
}
}
.channels__button {
background-color: #2a2a2a;
border: none;
height: 3.5em;
transition: 0.1s background-color;
width: 3.5em;
&:hover {
background-color: #272727;
}
&.active {
background-color: #555555;
}
}
.channels__buttonText {
font-size: 0.7em;
}

View File

@ -0,0 +1,53 @@
import './chat--users.scss';
import classnames from 'classnames';
import React, {useState} from 'react';
import Bar from './bar';
export default function ChatUsers() {
const [isOpen, setIsOpen] = useState(false);
const [active, setActive] = useState(0);
const toggleOpen = () => setIsOpen(!isOpen);
const buttons = [
{
emoji: '🙃',
label: 'Folks',
},
];
return (
<div
className={classnames(
'users',
'chat--flexed',
isOpen ? 'users--open' : 'users--closed',
)}
>
<Bar isHorizontal={isOpen}>
<ul className="users__buttons">
{
buttons.map(({emoji, label}, i) => (
<li className="users__buttonItem">
<button
className={classnames('users__button', {active: isOpen && i === active})}
onClick={() => {
if (i === active || !isOpen) {
toggleOpen();
}
setActive(i);
}}
type="button"
>
<span role="img" aria-label={label}>{emoji}</span>
<span className="users__buttonText">{label}</span>
</button>
</li>
))
}
</ul>
</Bar>
</div>
);
}
ChatUsers.propTypes = {};

View File

@ -0,0 +1,44 @@
.users {
background-color: #373737;
}
.users--open {
flex-basis: 18em;
}
.users__buttons {
display: flex;
flex-direction: row-reverse;
.users--closed & {
flex-direction: column;
}
}
.users__buttonItem {
padding: 0.25em;
.users--closed & {
padding-bottom: 0;
}
.users--open & {
padding-left: 0;
}
}
.users__button {
background-color: #2a2a2a;
border: none;
height: 3.5em;
transition: 0.1s background-color;
width: 3.5em;
&:hover {
background-color: #272727;
}
&.active {
background-color: #555555;
}
}
.users__buttonText {
font-size: 0.7em;
}

18
src/client/chat.jsx Normal file
View File

@ -0,0 +1,18 @@
import './chat.scss';
import React from 'react';
import ChatChannels from './chat--channels';
import ChatUsers from './chat--users';
export default function Chat() {
return (
<div className="chat">
<ChatChannels />
<div className="chat__messages chat--flexed"></div>
<ChatUsers />
</div>
);
}
Chat.propTypes = {};

14
src/client/chat.scss Normal file
View File

@ -0,0 +1,14 @@
.chat {
display: flex;
height: 100%;
width: 100%;
}
.chat--flexed {
height: 100%;
flex-basis: 4em;
}
.chat__messages {
flex-grow: 1;
}