ui overhaul + integrate gateway better
This commit is contained in:
parent
c5210b40c3
commit
118a55fed9
23 changed files with 446 additions and 342 deletions
|
@ -49,7 +49,7 @@ export default function Login() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="login-container" className="card main-card">
|
<div id="login-container" className="main-card">
|
||||||
<label htmlFor="username">Username</label>
|
<label htmlFor="username">Username</label>
|
||||||
<br />
|
<br />
|
||||||
<input type="text" name="username" className="text-input" onChange={ ({ target }) => setUsernameInput(target.value) } />
|
<input type="text" name="username" className="text-input" onChange={ ({ target }) => setUsernameInput(target.value) } />
|
||||||
|
|
|
@ -6,8 +6,8 @@ import { useHistory } from 'react-router-dom';
|
||||||
export default function ChannelButton({ channel, selected }) {
|
export default function ChannelButton({ channel, selected }) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
let buttonClasses = 'button channel-button';
|
let buttonClasses = 'button button-channel';
|
||||||
if (selected) buttonClasses += ' pressed';
|
if (selected) buttonClasses += ' button-pressed';
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (gatewayConnection.handshakeCompleted) {
|
if (gatewayConnection.handshakeCompleted) {
|
||||||
|
|
|
@ -6,9 +6,9 @@ import { connect } from 'react-redux'
|
||||||
function ChannelList({ selectedChannelId, channels }) {
|
function ChannelList({ selectedChannelId, channels }) {
|
||||||
if (!channels) {
|
if (!channels) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<ChannelListLoader />
|
<ChannelListLoader />
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -5,39 +5,39 @@ export default function ChannelListLoader(props) {
|
||||||
const lessThan600 = useMediaPredicate("(max-width: 600px)");
|
const lessThan600 = useMediaPredicate("(max-width: 600px)");
|
||||||
|
|
||||||
if (lessThan600) {
|
if (lessThan600) {
|
||||||
return (
|
return (
|
||||||
<ContentLoader
|
<ContentLoader
|
||||||
speed={1.5}
|
speed={1.5}
|
||||||
width={62}
|
width={100}
|
||||||
height={300}
|
height={250}
|
||||||
viewBox="0 0 62 300"
|
viewBox="0 0 100 250"
|
||||||
backgroundColor="#434c5e"
|
backgroundColor="#423f3f"
|
||||||
foregroundColor="#4c566a"
|
foregroundColor="#4d4a4a"
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<rect x="6" y="5" rx="0" ry="0" width="50" height="25" />
|
<rect x="10" y="10" rx="0" ry="0" width="100" height="40" />
|
||||||
<rect x="6" y="35" rx="0" ry="0" width="50" height="25" />
|
<rect x="10" y="55" rx="0" ry="0" width="100" height="40" />
|
||||||
<rect x="6" y="65" rx="0" ry="0" width="50" height="25" />
|
<rect x="10" y="100" rx="0" ry="0" width="100" height="40" />
|
||||||
<rect x="6" y="95" rx="0" ry="0" width="50" height="25" />
|
<rect x="10" y="145" rx="0" ry="0" width="100" height="40" />
|
||||||
<rect x="6" y="125" rx="0" ry="0" width="50" height="25" />
|
<rect x="10" y="190" rx="0" ry="0" width="100" height="40" />
|
||||||
</ContentLoader>
|
</ContentLoader>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<ContentLoader
|
<ContentLoader
|
||||||
speed={1.5}
|
speed={1.5}
|
||||||
width={112}
|
width={200}
|
||||||
height={300}
|
height={250}
|
||||||
viewBox="0 0 112 300"
|
viewBox="0 0 200 250"
|
||||||
backgroundColor="#434c5e"
|
backgroundColor="#423f3f"
|
||||||
foregroundColor="#4c566a"
|
foregroundColor="#4d4a4a"
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<rect x="6" y="5" rx="0" ry="0" width="100" height="25" />
|
<rect x="10" y="10" rx="0" ry="0" width="180" height="40" />
|
||||||
<rect x="6" y="35" rx="0" ry="0" width="100" height="25" />
|
<rect x="10" y="55" rx="0" ry="0" width="180" height="40" />
|
||||||
<rect x="6" y="65" rx="0" ry="0" width="100" height="25" />
|
<rect x="10" y="145" rx="0" ry="0" width="180" height="40" />
|
||||||
<rect x="6" y="95" rx="0" ry="0" width="100" height="25" />
|
<rect x="10" y="100" rx="0" ry="0" width="180" height="40" />
|
||||||
<rect x="6" y="125" rx="0" ry="0" width="100" height="25" />
|
<rect x="10" y="190" rx="0" ry="0" width="180" height="40" />
|
||||||
</ContentLoader>
|
</ContentLoader>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
25
bfrontend/src/Components/Channels/ChannelUserList.js
Normal file
25
bfrontend/src/Components/Channels/ChannelUserList.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import UserProfileButton from '../Users/UserButton';
|
||||||
|
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
function Sidebar({ channelPresenceClientList }) {
|
||||||
|
const users = [
|
||||||
|
{ username: "thgitrhiorg" },
|
||||||
|
{ username: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" },
|
||||||
|
{ username: "FDGFEGSDFHRFGHNERTYBNRNBTYJMNUM" }
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="main-card sidebar">
|
||||||
|
{ users.map((user) => <UserProfileButton user={ user }></UserProfileButton>) }
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const stateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
channelPresenceClientList: state?.channelPresenceClientList
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(stateToProps)(Sidebar);
|
|
@ -1,28 +1,28 @@
|
||||||
import ChannelViewLoader from './ChannelViewLoader';
|
import ChannelViewLoader from '../UI/ProfileLinkLoader';
|
||||||
import ChannelProfile from './ChannelProfileLink';
|
import ChannelProfile from './ChannelProfileLink';
|
||||||
import Message from '../Messages/Message';
|
import Message from '../Messages/Message';
|
||||||
import gatewayConnection from '../../API/Gateway/globalGatewayConnection';
|
import gatewayConnection from '../../API/Gateway/globalGatewayConnection';
|
||||||
|
import ChannelUserList from "./ChannelUserList";
|
||||||
|
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { connect, useDispatch } from 'react-redux';
|
import { connect, useDispatch } from 'react-redux';
|
||||||
import { useState, useRef, useEffect } from 'react';
|
import { useState, useRef, useEffect } from 'react';
|
||||||
|
|
||||||
function ChannelView({ channels, messages }) {
|
|
||||||
|
const ChannelView = ({ channels, messages, channel, selectedChannelId }) => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const [ textInput, setTextInput ] = useState('');
|
const [ textInput, setTextInput ] = useState('');
|
||||||
const [ channel, setChannel ] = useState();
|
|
||||||
|
|
||||||
const textInputRef = useRef(null);
|
const textInputRef = useRef(null);
|
||||||
const invisibleBottomMessageRef = useRef(null);
|
const invisibleBottomMessageRef = useRef(null);
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const scrollToBottom = () => {
|
useEffect(() => {
|
||||||
if (invisibleBottomMessageRef && invisibleBottomMessageRef.current) {
|
if (invisibleBottomMessageRef && invisibleBottomMessageRef.current) {
|
||||||
invisibleBottomMessageRef.current.scrollIntoView({ behaviour: 'smooth' });
|
invisibleBottomMessageRef.current.scrollIntoView({ behaviour: 'smooth' });
|
||||||
}
|
}
|
||||||
}
|
}, [messages]);
|
||||||
useEffect(scrollToBottom, [messages]);
|
|
||||||
|
|
||||||
const handleTextboxKeydown = (e) => {
|
const handleTextboxKeydown = (e) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
|
@ -34,15 +34,11 @@ function ChannelView({ channels, messages }) {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!channels) return;
|
if (!channels) return;
|
||||||
|
|
||||||
setChannel(channels.find(x => x._id === id));
|
|
||||||
}, [channels, id]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!channel) return;
|
if (!channel) return;
|
||||||
|
if (channel._id === selectedChannelId) return;
|
||||||
|
|
||||||
dispatch({ type: 'channels/selectchannel', channelId: channel._id });
|
dispatch({ type: 'channels/selectchannel', channelId: channel._id });
|
||||||
}, [channel, dispatch]);
|
}, [channels, id, dispatch, channel, selectedChannelId]);
|
||||||
|
|
||||||
if (channel) {
|
if (channel) {
|
||||||
let messagesView = messages.map(m => <Message key={ m._id } message={ m } />);
|
let messagesView = messages.map(m => <Message key={ m._id } message={ m } />);
|
||||||
|
@ -50,49 +46,57 @@ function ChannelView({ channels, messages }) {
|
||||||
if (messagesView === undefined || messagesView.length <= 0) {
|
if (messagesView === undefined || messagesView.length <= 0) {
|
||||||
messagesView = (
|
messagesView = (
|
||||||
<div className='no-messages-warning'>
|
<div className='no-messages-warning'>
|
||||||
A bit empty in here...
|
Wow, such empty!
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card main-card main-content-card">
|
<div className="col-flex-card">
|
||||||
<div className="card bar-card">
|
<div className="bar-card">
|
||||||
<ChannelProfile channel={ channel } />
|
<ChannelProfile channel={ channel } size="24" />
|
||||||
</div>
|
</div>
|
||||||
<div className="card message-list-card">
|
|
||||||
{ messagesView }
|
<div className="main-card row-flex-card">
|
||||||
<div ref={ invisibleBottomMessageRef }></div>
|
<div className="col-flex-card">
|
||||||
</div>
|
<div className="message-list-card">
|
||||||
<div className="card bar-card-bottom">
|
{ messagesView }
|
||||||
<input className="text-input" type="text" placeholder="Go on, type something interesting!" ref={ textInputRef } onKeyDown={ handleTextboxKeydown } onChange={ ({ target }) => setTextInput(target.value) }></input>
|
<div ref={ invisibleBottomMessageRef }></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="invis-bar">
|
||||||
|
<input className="text-input message-input" type="text" placeholder="Go on, type something interesting!" ref={ textInputRef } onKeyDown={ handleTextboxKeydown } onChange={ ({ target }) => setTextInput(target.value) }></input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ChannelUserList />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div className="card main-card main-content-card">
|
<div className="main-card col-flex-card">
|
||||||
<div className="card bar-card">
|
<div className="bar-card">
|
||||||
<ChannelViewLoader />
|
<ChannelViewLoader />
|
||||||
</div>
|
</div>
|
||||||
<div className="card message-list-card">
|
<div className="message-list-card">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="card bar-card-bottom">
|
<div className="bar-card-bottom">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const stateToProps = (state, ownProps) => {
|
const stateToProps = (state, ownProps) => {
|
||||||
const channelId = ownProps.match.params.id; // NOTE(hippoz): kind of a hack, but it works and idk if theres any other solution
|
const channelId = ownProps.match.params.id; // NOTE(hippoz): kind of a hack, but it works and idk if theres any other solution
|
||||||
|
|
||||||
return {
|
return {
|
||||||
channels: state?.channels,
|
channels: state?.channels,
|
||||||
|
channel: state?.channels?.find(x => x._id === channelId),
|
||||||
messages: state?.messages[channelId] || [],
|
messages: state?.messages[channelId] || [],
|
||||||
|
selectedChannelId: state?.selectedChannelId,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -33,12 +33,21 @@ function App({ user }) {
|
||||||
<div id="main-container">
|
<div id="main-container">
|
||||||
<div id="root-container" className="main-display">
|
<div id="root-container" className="main-display">
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
{ user && <Sidebar /> }
|
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/login" component={ Login } />
|
<Route path="/login" component={ Login } />
|
||||||
<Route path="/channels/:id" component={ ChannelView } />
|
<Route path="/channels/:id"
|
||||||
|
render={(props) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Sidebar />
|
||||||
|
<ChannelView match={ props.match } />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<Route path="/">
|
<Route path="/">
|
||||||
|
{ user && <Sidebar /> }
|
||||||
<Root user={user} />
|
<Root user={user} />
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|
|
@ -3,8 +3,8 @@ import UserProfileLink from '../Users/UserProfileLink';
|
||||||
export default function Message({ message }) {
|
export default function Message({ message }) {
|
||||||
return (
|
return (
|
||||||
<div className="message">
|
<div className="message">
|
||||||
<UserProfileLink size="40" user={ message.author } offset="true"><p>a</p></UserProfileLink>
|
<UserProfileLink size="0" user={ message.author }></UserProfileLink>
|
||||||
<span>{ message.content }</span>
|
<span style={ {"padding-left": "5px"} }>{ message.content }</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
import defaultProfile from '../../Content/Images/defaultprofile_256px-256px.png'
|
import defaultProfile from '../../Content/Images/defaultprofile_256px-256px.png'
|
||||||
|
|
||||||
export default function ProfileLink({ object, size=32, type, offset=true, children=null }) {
|
export default function ProfileLink({ object, size, type, offset=true, children=null }) {
|
||||||
let picture;
|
let picture;
|
||||||
|
|
||||||
if (size !== 0) {
|
if (size !== "0") {
|
||||||
// TODO: Make a debug error message for then the size does not exist
|
// TODO: Make a debug error message for then the size does not exist
|
||||||
const pictureClass = `profile-picture profile-picture-${size}`;
|
const pictureClass = `profile-picture profile-picture-${size}`;
|
||||||
|
|
||||||
|
@ -28,4 +28,4 @@ export default function ProfileLink({ object, size=32, type, offset=true, childr
|
||||||
{ bottomInfo }
|
{ bottomInfo }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
|
@ -7,8 +7,8 @@ export default function ChannelViewLoader(props) {
|
||||||
width={100}
|
width={100}
|
||||||
height={46}
|
height={46}
|
||||||
viewBox="0 0 100 46"
|
viewBox="0 0 100 46"
|
||||||
backgroundColor="#434c5e"
|
backgroundColor="#423f3f"
|
||||||
foregroundColor="#4c566a"
|
foregroundColor="#4d4a4a"
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<rect x="50" y="14" rx="0" ry="0" width="50" height="15" />
|
<rect x="50" y="14" rx="0" ry="0" width="50" height="15" />
|
|
@ -1,13 +1,15 @@
|
||||||
import ChannelList from '../Channels/ChannelList';
|
import ChannelList from '../Channels/ChannelList';
|
||||||
import UserProfileLink from '../Users/UserProfileLink';
|
import UserProfileLink from '../Users/UserProfileLink';
|
||||||
|
import ProfileLinkLoader from "../UI/ProfileLinkLoader";
|
||||||
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
function Sidebar({ user }) {
|
function Sidebar({ user }) {
|
||||||
return (
|
return (
|
||||||
<div className="card main-card channel-list-container">
|
<div className="main-card sidebar">
|
||||||
<div className="card bar-card">
|
<div className="bar-card">
|
||||||
<UserProfileLink user={ user } />
|
{ user && <UserProfileLink user={ user } /> }
|
||||||
|
{ !user && <ProfileLinkLoader></ProfileLinkLoader> }
|
||||||
</div>
|
</div>
|
||||||
<ChannelList />
|
<ChannelList />
|
||||||
</div>
|
</div>
|
||||||
|
|
19
bfrontend/src/Components/Users/UserButton.js
Normal file
19
bfrontend/src/Components/Users/UserButton.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import UserProfile from './UserProfileLink';
|
||||||
|
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
|
export default function ChannelUserButton({ user }) {
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
let buttonClasses = 'button button-channel';
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
history.push(`/user/${user._id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button className={ buttonClasses } onClick={ handleClick }>
|
||||||
|
<UserProfile user={ user } size="32" />
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 645 B After Width: | Height: | Size: 1.9 KiB |
|
@ -1,57 +1,13 @@
|
||||||
$nord0darker: #22262e;
|
@import "./colors.scss";
|
||||||
$nord1darker: #282b36;
|
@import "./root.scss";
|
||||||
$nord2darker: #333947;
|
@import "./mixins.scss";
|
||||||
$nord3darker: #40495a;
|
|
||||||
$nord4darker: #9da2ad;
|
|
||||||
|
|
||||||
$nord0: #2E3440;
|
@import "./Components/Card.scss";
|
||||||
$nord1: #3B4252;
|
@import "./Components/Button.scss";
|
||||||
$nord2: #434C5E;
|
@import "./Components/Containers.scss";
|
||||||
$nord3: #4C566A;
|
@import "./Components/ProfileLink.scss";
|
||||||
$nord4: #D8DEE9;
|
@import "./Components/Message.scss";
|
||||||
$nord5: #E5E9F0;
|
@import "./Components/Textbox.scss";
|
||||||
$nord6: #ECEFF4;
|
|
||||||
$nord7: #8FBCBB;
|
|
||||||
$nord8: #88C0D0;
|
|
||||||
$nord9: #81A1C1;
|
|
||||||
$nord10: #5E81AC;
|
|
||||||
$nord11: #BF616A;
|
|
||||||
$nord12: #D08770;
|
|
||||||
$nord13: #EBCB8B;
|
|
||||||
$nord14: #A3BE8C;
|
|
||||||
$nord15: #B48EAD;
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--background-color: #{$nord0darker};
|
|
||||||
|
|
||||||
--default-main-card-color: var(--background-color);
|
|
||||||
--card-box-shadow-color:rgba(0, 0, 0, 0.27);
|
|
||||||
|
|
||||||
--default-text-color: #{$nord5};
|
|
||||||
--darker-text-color: #{$nord4darker};
|
|
||||||
|
|
||||||
--accent-color-dark: #{$nord1darker};
|
|
||||||
--accent-color-light: #{$nord2darker};
|
|
||||||
--accent-color-very-light: #{$nord3darker};
|
|
||||||
|
|
||||||
--channel-top-bar-color: var(--accent-color-light);
|
|
||||||
--channel-bottom-text-bar-color: var(--accent-color-light);
|
|
||||||
|
|
||||||
--channel-list-background-color: var(--background-color);
|
|
||||||
--channel-message-list-background-color: var(--background-color);
|
|
||||||
--channel-message-color: var(--accent-color-dark);
|
|
||||||
|
|
||||||
--button-color: var(--accent-color-dark);
|
|
||||||
--button-hover-color: var(--accent-color-light);
|
|
||||||
|
|
||||||
--default-transition-duration: 50ms;
|
|
||||||
|
|
||||||
--default-border-radius: 0px;
|
|
||||||
--default-button-border-radius: 0px;
|
|
||||||
--channel-message-border-radius: 0px;
|
|
||||||
--bar-cards-border-radius: 0px;
|
|
||||||
--channel-button-border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 0px;
|
width: 0px;
|
||||||
|
@ -59,230 +15,15 @@ $nord15: #B48EAD;
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
background: var(--accent-color-light);
|
background: var(--accent-color-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background: var(--default-main-card-color);
|
background: var(--default-main-card-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin card {
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
background-color: var(--default-main-card-color);
|
|
||||||
border-radius: var(--default-border-radius);
|
|
||||||
box-shadow: 0px 3px 5px var(--card-box-shadow-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin fancy-scrollbar-firefox {
|
|
||||||
scrollbar-width: none;
|
|
||||||
scrollbar-color: var(--default-main-card-color) var(--accent-color-light);
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
|
|
||||||
color: var(--default-text-color);
|
color: var(--default-text-color);
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
font-family: Noto Sans,-apple-system,BlinkMacSystemFont,sans-serif;
|
font-family: Noto Sans,-apple-system,BlinkMacSystemFont,sans-serif;
|
||||||
}
|
|
||||||
|
|
||||||
.main-display {
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
display: flex;
|
padding: 0px;
|
||||||
background-color: var(--background-color);
|
|
||||||
min-height: 100vh;
|
|
||||||
max-height: 100vh;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
@include card;
|
|
||||||
|
|
||||||
&.bar-card {
|
|
||||||
background-color: var(--channel-top-bar-color);
|
|
||||||
min-height: 50px;
|
|
||||||
padding: 5px;
|
|
||||||
|
|
||||||
border-radius: var(--bar-cards-border-radius);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: left;
|
|
||||||
|
|
||||||
font-size: large;
|
|
||||||
|
|
||||||
z-index: 99;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.bar-card-bottom {
|
|
||||||
background-color: var(--channel-bottom-text-bar-color);
|
|
||||||
box-shadow: 0px -3px 5px var(--card-box-shadow-color);
|
|
||||||
|
|
||||||
min-height: 40px;
|
|
||||||
|
|
||||||
border-radius: var(--bar-cards-border-radius);
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.message-list-card {
|
|
||||||
@include fancy-scrollbar-firefox;
|
|
||||||
border-radius: 0px;
|
|
||||||
flex-grow: 1;
|
|
||||||
box-shadow: none;
|
|
||||||
overflow: auto;
|
|
||||||
background-color: var(--channel-message-list-background-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-card {
|
|
||||||
@include card;
|
|
||||||
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
&.main-content-card {
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
@include card;
|
|
||||||
|
|
||||||
padding: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
border: 0px;
|
|
||||||
background-color: var(--button-color);
|
|
||||||
color: var(--default-text-color);
|
|
||||||
cursor: pointer;
|
|
||||||
// transition: background-color, var(--default-transition-duration);
|
|
||||||
border-radius: var(--default-button-border-radius);
|
|
||||||
min-height: 25px;
|
|
||||||
|
|
||||||
&.channel-button {
|
|
||||||
min-width: 200px;
|
|
||||||
max-width: 200px;
|
|
||||||
|
|
||||||
min-height: 40px;
|
|
||||||
max-height: 100px;
|
|
||||||
|
|
||||||
margin: 4px;
|
|
||||||
border-radius: var(--channel-button-border-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.pressed {
|
|
||||||
background-color: var(--accent-color-very-light);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:hover:not(.pressed) {
|
|
||||||
background-color: var(--accent-color-light);
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-list {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-list-container {
|
|
||||||
@include fancy-scrollbar-firefox;
|
|
||||||
|
|
||||||
overflow: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
|
|
||||||
background-color: var(--channel-list-background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-picture {
|
|
||||||
border-radius: 50%;
|
|
||||||
margin: 5px;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
|
|
||||||
&.profile-picture-8 {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.profile-picture-16 {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.profile-picture-32 {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.profile-picture-40 {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.profile-picture-64 {
|
|
||||||
width: 64px;
|
|
||||||
height: 64px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-link {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: left;
|
|
||||||
|
|
||||||
&.profile-link-offset-text {
|
|
||||||
align-items: unset;
|
|
||||||
text-align: start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-username {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message {
|
|
||||||
@include card;
|
|
||||||
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
margin-left: 5px;
|
|
||||||
margin-right: 5px;
|
|
||||||
padding: 5px;
|
|
||||||
border-radius: var(--channel-message-border-radius);
|
|
||||||
background-color: var(--background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-input {
|
|
||||||
@include card;
|
|
||||||
|
|
||||||
margin: 5px;
|
|
||||||
padding: 5px;
|
|
||||||
border: none;
|
|
||||||
color: var(--default-text-color);
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-messages-warning {
|
|
||||||
text-align: center;
|
|
||||||
padding: 50px;
|
|
||||||
color: var(--darker-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.unread-indicator {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 600px) {
|
|
||||||
.button.channel-button {
|
|
||||||
min-width: 100px;
|
|
||||||
max-width: 100px;
|
|
||||||
}
|
|
||||||
}
|
}
|
43
bfrontend/src/Styles/Components/Button.scss
Normal file
43
bfrontend/src/Styles/Components/Button.scss
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
.button {
|
||||||
|
@include card;
|
||||||
|
|
||||||
|
background-color: var(--button-color);
|
||||||
|
color: var(--default-text-color);
|
||||||
|
|
||||||
|
border-radius: var(--default-button-border-radius);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 5px;
|
||||||
|
border: 0px;
|
||||||
|
min-height: 25px;
|
||||||
|
|
||||||
|
&-channel {
|
||||||
|
@extend .button;
|
||||||
|
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
border-radius: var(--channel-button-border-radius);
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 250px;
|
||||||
|
min-height: 40px;
|
||||||
|
margin: 4px;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-pressed {
|
||||||
|
@extend .button;
|
||||||
|
|
||||||
|
background-color: var(--accent-color-very-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover:not(.button-pressed) {
|
||||||
|
background-color: var(--accent-color-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
.button.channel-button {
|
||||||
|
min-width: 100px;
|
||||||
|
max-width: 100px;
|
||||||
|
}
|
||||||
|
}
|
67
bfrontend/src/Styles/Components/Card.scss
Normal file
67
bfrontend/src/Styles/Components/Card.scss
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
@mixin card {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
background-color: var(--default-main-card-color);
|
||||||
|
border-radius: var(--default-border-radius);
|
||||||
|
box-shadow: 0px 1px 1px var(--card-box-shadow-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.card {
|
||||||
|
@include card;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar-card {
|
||||||
|
@include card;
|
||||||
|
|
||||||
|
background-color: var(--channel-top-bar-color);
|
||||||
|
box-shadow: 0 1px 1px var(--card-box-shadow-color);
|
||||||
|
|
||||||
|
height: 32px;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: var(--bar-cards-border-radius);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: left;
|
||||||
|
font-size: medium;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-list-card {
|
||||||
|
@include card;
|
||||||
|
@include fancy-scrollbar-firefox;
|
||||||
|
|
||||||
|
background-color: var(--channel-message-list-background-color);
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
border-radius: 0px;
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-card {
|
||||||
|
@include card;
|
||||||
|
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-flex-card {
|
||||||
|
@include card;
|
||||||
|
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-flex-card {
|
||||||
|
@include card;
|
||||||
|
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
flex-grow: 10;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
38
bfrontend/src/Styles/Components/Containers.scss
Normal file
38
bfrontend/src/Styles/Components/Containers.scss
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
.main-display {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
display: flex;
|
||||||
|
background-color: var(--background-color);
|
||||||
|
min-height: 100vh;
|
||||||
|
max-height: 100vh;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
@include fancy-scrollbar-firefox;
|
||||||
|
|
||||||
|
background-color: var(--channel-list-background-color);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channel-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: hidden;
|
||||||
|
flex-grow: 10;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invis-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
z-index: 100;
|
||||||
|
}
|
23
bfrontend/src/Styles/Components/Message.scss
Normal file
23
bfrontend/src/Styles/Components/Message.scss
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
.message {
|
||||||
|
@include card;
|
||||||
|
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin: 3px;
|
||||||
|
margin-left: 10px;
|
||||||
|
padding: 1px;
|
||||||
|
border-radius: var(--channel-message-border-radius);
|
||||||
|
background-color: var(--background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-messages-warning {
|
||||||
|
text-align: center;
|
||||||
|
padding: 50px;
|
||||||
|
color: var(--darker-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.unread-indicator {
|
||||||
|
float: right;
|
||||||
|
}
|
48
bfrontend/src/Styles/Components/ProfileLink.scss
Normal file
48
bfrontend/src/Styles/Components/ProfileLink.scss
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
.profile-picture {
|
||||||
|
border-radius: 50%;
|
||||||
|
margin: 5px;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
|
||||||
|
&.profile-picture-8 {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.profile-picture-16 {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.profile-picture-32 {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.profile-picture-40 {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.profile-picture-64 {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: hidden;
|
||||||
|
|
||||||
|
&.profile-link-offset-text {
|
||||||
|
align-items: unset;
|
||||||
|
text-align: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-username {
|
||||||
|
font-weight: 550;
|
||||||
|
}
|
15
bfrontend/src/Styles/Components/Textbox.scss
Normal file
15
bfrontend/src/Styles/Components/Textbox.scss
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
.text-input {
|
||||||
|
@include card;
|
||||||
|
|
||||||
|
margin: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
border: none;
|
||||||
|
color: var(--default-text-color);
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
&.message-input {
|
||||||
|
border-radius: var(--message-box-border-radius);
|
||||||
|
background-color: var(--accent-color-dark);
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
}
|
34
bfrontend/src/Styles/colors.scss
Normal file
34
bfrontend/src/Styles/colors.scss
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
$nord0darker: #22262e;
|
||||||
|
$nord1darker: #282b36;
|
||||||
|
$nord2darker: #333947;
|
||||||
|
$nord3darker: #40495a;
|
||||||
|
$nord4darker: #9da2ad;
|
||||||
|
|
||||||
|
$nord0: #2E3440;
|
||||||
|
$nord1: #3B4252;
|
||||||
|
$nord2: #434C5E;
|
||||||
|
$nord3: #4C566A;
|
||||||
|
$nord4: #D8DEE9;
|
||||||
|
$nord5: #E5E9F0;
|
||||||
|
$nord6: #ECEFF4;
|
||||||
|
$nord7: #8FBCBB;
|
||||||
|
$nord8: #88C0D0;
|
||||||
|
$nord9: #81A1C1;
|
||||||
|
$nord10: #5E81AC;
|
||||||
|
$nord11: #BF616A;
|
||||||
|
$nord12: #D08770;
|
||||||
|
$nord13: #EBCB8B;
|
||||||
|
$nord14: #A3BE8C;
|
||||||
|
$nord15: #B48EAD;
|
||||||
|
|
||||||
|
$dark1: #2d2929;
|
||||||
|
$dark2: #332f2f;
|
||||||
|
$dark3: #393636;
|
||||||
|
$dark4: #423f3f;
|
||||||
|
$dark5: #4d4a4a;
|
||||||
|
|
||||||
|
$light1: #999999;
|
||||||
|
$light2: #b0b0b0;
|
||||||
|
$light3: #c2c2c2;
|
||||||
|
$light4: #cfcfcf;
|
||||||
|
$light5: #d9d9d9;
|
4
bfrontend/src/Styles/mixins.scss
Normal file
4
bfrontend/src/Styles/mixins.scss
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
@mixin fancy-scrollbar-firefox {
|
||||||
|
scrollbar-width: none;
|
||||||
|
scrollbar-color: var(--default-main-card-color) var(--accent-color-light);
|
||||||
|
}
|
32
bfrontend/src/Styles/root.scss
Normal file
32
bfrontend/src/Styles/root.scss
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
:root {
|
||||||
|
--background-color: #{$dark1};
|
||||||
|
|
||||||
|
--default-main-card-color: var(--background-color);
|
||||||
|
--card-box-shadow-color:#1f1c1c;
|
||||||
|
|
||||||
|
--default-text-color: #{$light3};
|
||||||
|
--darker-text-color: #{$light1};
|
||||||
|
|
||||||
|
--accent-color-dark: #{$dark2};
|
||||||
|
--accent-color-light: #{$dark3};
|
||||||
|
--accent-color-very-light: #{$dark4};
|
||||||
|
|
||||||
|
--channel-top-bar-color: var(--accent-color-light);
|
||||||
|
--channel-bottom-text-bar-color: var(--accent-color-light);
|
||||||
|
|
||||||
|
--channel-list-background-color: var(--accent-color-dark);
|
||||||
|
--channel-message-list-background-color: var(--background-color);
|
||||||
|
--channel-message-color: var(--accent-color-dark);
|
||||||
|
|
||||||
|
--button-color: var(--accent-color-dark);
|
||||||
|
--button-hover-color: var(--accent-color-light);
|
||||||
|
|
||||||
|
--default-transition-duration: 50ms;
|
||||||
|
|
||||||
|
--default-border-radius: 0px;
|
||||||
|
--default-button-border-radius: 0px;
|
||||||
|
--channel-message-border-radius: 0px;
|
||||||
|
--bar-cards-border-radius: 0px;
|
||||||
|
--channel-button-border-radius: 4px;
|
||||||
|
--message-box-border-radius: 4px;
|
||||||
|
}
|
Loading…
Reference in a new issue