feat: chat shell
This commit is contained in:
parent
2dee78cdef
commit
645763c828
|
@ -1,14 +1,26 @@
|
||||||
import './app.scss';
|
import './app.scss';
|
||||||
|
|
||||||
import {hot} from 'react-hot-loader';
|
import {hot} from 'react-hot-loader';
|
||||||
|
import {Route, Switch} from 'react-router-dom';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import Chat from './chat';
|
||||||
import Home from './home';
|
import Home from './home';
|
||||||
|
|
||||||
const App = () => (
|
const App = () => (
|
||||||
<div className="app">
|
<div className="app">
|
||||||
<Home />
|
<Switch>
|
||||||
|
<Route
|
||||||
|
component={Home}
|
||||||
|
exact
|
||||||
|
path="/"
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
component={Chat}
|
||||||
|
path="/chat"
|
||||||
|
/>
|
||||||
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
25
src/client/bar.jsx
Normal file
25
src/client/bar.jsx
Normal 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
16
src/client/bar.scss
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
62
src/client/chat--channels.jsx
Normal file
62
src/client/chat--channels.jsx
Normal 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 = {};
|
58
src/client/chat--channels.scss
Normal file
58
src/client/chat--channels.scss
Normal 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;
|
||||||
|
}
|
||||||
|
|
53
src/client/chat--users.jsx
Normal file
53
src/client/chat--users.jsx
Normal 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 = {};
|
44
src/client/chat--users.scss
Normal file
44
src/client/chat--users.scss
Normal 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
18
src/client/chat.jsx
Normal 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
14
src/client/chat.scss
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
.chat {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat--flexed {
|
||||||
|
height: 100%;
|
||||||
|
flex-basis: 4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat__messages {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user