├── src ├── assets │ ├── img │ │ ├── .picasa.ini │ │ ├── cyhi.jpg │ │ ├── avatar.jpg │ │ ├── banner.png │ │ ├── favicon.png │ │ ├── user1.jpg │ │ ├── user2.jpg │ │ ├── user3.jpg │ │ ├── user4.jpg │ │ ├── user5.jpg │ │ ├── socialBanner.png │ │ └── transparentBanner.png │ └── svg │ │ ├── TypeScript.svg │ │ ├── NodeJS.svg │ │ ├── ReactJS.svg │ │ ├── Ronne.svg │ │ ├── Pride.svg │ │ ├── CSS.svg │ │ ├── DC.svg │ │ ├── RocketSeat.svg │ │ ├── Mario.svg │ │ ├── Code.svg │ │ └── Pokémon.svg ├── react-app-env.d.ts ├── App.tsx ├── styles │ ├── MaterialUI │ │ └── index.ts │ └── GlobalStyles.ts ├── components │ ├── LoaderSpinner │ │ ├── styles.ts │ │ └── index.tsx │ ├── ServerName │ │ ├── index.tsx │ │ └── styles.ts │ ├── ChannelInfo │ │ ├── index.tsx │ │ └── styles.ts │ ├── index.ts │ ├── ServerList │ │ ├── styles.ts │ │ └── index.tsx │ ├── ChannelList │ │ ├── styles.ts │ │ └── index.tsx │ ├── ServerButton │ │ ├── index.tsx │ │ └── styles.ts │ ├── ChannelMessage │ │ ├── index.tsx │ │ └── styles.ts │ ├── ChannelButton │ │ ├── index.tsx │ │ └── styles.ts │ ├── ChannelData │ │ ├── styles.ts │ │ └── index.tsx │ ├── UserInfo │ │ ├── index.tsx │ │ └── styles.ts │ └── UserList │ │ ├── styles.ts │ │ └── index.tsx ├── index.tsx └── Layout │ ├── index.tsx │ └── styles.ts ├── .prettierrc ├── public ├── favicon.ico ├── logo192.png ├── logo256.png ├── logo512.png ├── robots.txt ├── logo1024.png ├── .htaccess ├── manifest.json └── index.html ├── config-overrides.js ├── .gitignore ├── tsconfig.json ├── .eslintrc.js ├── LICENSE ├── package.json ├── README.md └── CONTRIBUTING.md /src/assets/img/.picasa.ini: -------------------------------------------------------------------------------- 1 | [user4.jpg] 2 | backuphash=13523 3 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "printWidth": 200 4 | } 5 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/public/logo256.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/logo1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/public/logo1024.png -------------------------------------------------------------------------------- /src/assets/img/cyhi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/src/assets/img/cyhi.jpg -------------------------------------------------------------------------------- /src/assets/img/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/src/assets/img/avatar.jpg -------------------------------------------------------------------------------- /src/assets/img/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/src/assets/img/banner.png -------------------------------------------------------------------------------- /src/assets/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/src/assets/img/favicon.png -------------------------------------------------------------------------------- /src/assets/img/user1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/src/assets/img/user1.jpg -------------------------------------------------------------------------------- /src/assets/img/user2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/src/assets/img/user2.jpg -------------------------------------------------------------------------------- /src/assets/img/user3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/src/assets/img/user3.jpg -------------------------------------------------------------------------------- /src/assets/img/user4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/src/assets/img/user4.jpg -------------------------------------------------------------------------------- /src/assets/img/user5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/src/assets/img/user5.jpg -------------------------------------------------------------------------------- /src/assets/img/socialBanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/src/assets/img/socialBanner.png -------------------------------------------------------------------------------- /src/assets/img/transparentBanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leoronne/discord-ui-clone/HEAD/src/assets/img/transparentBanner.png -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | Options -MultiViews 2 | RewriteEngine On 3 | RewriteCond %{REQUEST_FILENAME} !-f 4 | RewriteRule ^ index.html [QSA,L] -------------------------------------------------------------------------------- /config-overrides.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line 2 | const { addBabelPlugin, override } = require('customize-cra'); 3 | 4 | module.exports = override( 5 | addBabelPlugin([ 6 | 'babel-plugin-root-import', 7 | { 8 | rootPathSuffix: 'src', 9 | }, 10 | ]), 11 | ); 12 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Layout from './Layout'; 4 | import GlobalStyles from './styles/GlobalStyles'; 5 | 6 | const App: React.FC = () => { 7 | return ( 8 | <> 9 | 10 | 11 | 12 | ); 13 | } 14 | 15 | export default App; 16 | -------------------------------------------------------------------------------- /src/styles/MaterialUI/index.ts: -------------------------------------------------------------------------------- 1 | import { makeStyles } from '@material-ui/core/styles'; 2 | 3 | export const useStyles = makeStyles({ 4 | tooltip: { 5 | fontSize: '13px', 6 | fontFamily: 'var(--font-family)', 7 | padding: '10px', 8 | fontWeight: 400, 9 | opacity: 1, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /src/components/LoaderSpinner/styles.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export */ 2 | import styled from 'styled-components'; 3 | 4 | export const Container = styled.div` 5 | display: flex; 6 | justify-content: center; 7 | align-items: center; 8 | height: calc(100vh - 18px); 9 | overflow: hidden; 10 | `; 11 | -------------------------------------------------------------------------------- /src/components/ServerName/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Container, Title, ExpandIcon } from './styles'; 4 | 5 | const ServerName: React.FC = () => { 6 | return ( 7 | 8 | Ronne Dev Server 9 | 10 | 11 | 12 | ); 13 | }; 14 | 15 | export default ServerName; -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import { LoaderSpinner } from './components'; 5 | 6 | import App from './App'; 7 | 8 | ReactDOM.render( 9 | }> 10 | 11 | 12 | 13 | , 14 | document.getElementById('root') 15 | ); 16 | -------------------------------------------------------------------------------- /src/components/LoaderSpinner/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { CircularProgress } from '@material-ui/core'; 3 | 4 | import { Container } from './styles'; 5 | 6 | const Loader: React.FC<{ color: string }> = ({ color = '#6e86d6' }) => { 7 | return ( 8 | 9 | 10 | 11 | ); 12 | }; 13 | export default Loader; 14 | -------------------------------------------------------------------------------- /src/components/ChannelInfo/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Container, HashtagIcon, Title, Separator, Description } from './styles'; 4 | 5 | const ChannelInfo: React.FC = () => { 6 | return ( 7 | 8 | 9 | 10 | open-chat 11 | 12 | 13 | 14 | Open channel for chat 15 | 16 | ); 17 | }; 18 | 19 | export default ChannelInfo; 20 | -------------------------------------------------------------------------------- /src/components/index.ts: -------------------------------------------------------------------------------- 1 | export { default as LoaderSpinner } from './LoaderSpinner'; 2 | export { default as ServerList } from './ServerList'; 3 | export { default as ServerName } from './ServerName'; 4 | export { default as ChannelInfo } from './ChannelInfo'; 5 | export { default as ChannelList } from './ChannelList'; 6 | export { default as UserInfo } from './UserInfo'; 7 | export { default as UserList } from './UserList'; 8 | export { default as ChannelData } from './ChannelData'; 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | .firebase 26 | firebase.json 27 | .firebaserc 28 | 29 | .vscode 30 | 31 | *.psd 32 | .eslintcache -------------------------------------------------------------------------------- /src/Layout/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Grid } from './styles'; 4 | 5 | import { ServerList, ChannelData, ChannelInfo, ChannelList, ServerName, UserInfo, UserList } from '../components'; 6 | 7 | const Layout: React.FC = () => { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | }; 20 | 21 | export default Layout; 22 | -------------------------------------------------------------------------------- /src/components/ServerList/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Container = styled.div` 4 | grid-area: SL; 5 | display: flex; 6 | flex-direction: column; 7 | align-items: center; 8 | background-color: var(--tertiary); 9 | padding: 11px 0; 10 | max-height: 100vh; 11 | overflow-y: scroll; 12 | ::-webkit-scrollbar { 13 | display: none; 14 | } 15 | `; 16 | 17 | export const Separator = styled.div` 18 | width: 32px; 19 | border-bottom: 2px solid var(--quaternary); 20 | margin-bottom: 8px; 21 | `; 22 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "noEmit": true, 20 | "jsx": "react-jsx", 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/components/ServerName/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { ExpandMore } from 'styled-icons/material'; 3 | 4 | export const Container = styled.div` 5 | display: flex; 6 | align-items: center; 7 | justify-content: space-between; 8 | padding: 0 11px 0 16px; 9 | background-color: var(--secondary); 10 | box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 0px 0px; 11 | z-index: 2; 12 | 13 | @media (max-width: 598px) { 14 | display: none; 15 | } 16 | `; 17 | 18 | export const Title = styled.h1` 19 | font-size: 16px; 20 | font-weight: bold; 21 | color: var(--white); 22 | `; 23 | 24 | export const ExpandIcon = styled(ExpandMore)` 25 | width: 28px; 26 | height: 28px; 27 | color: var(--white); 28 | cursor: pointer; 29 | `; 30 | -------------------------------------------------------------------------------- /src/Layout/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | // SL - Server List 4 | // SN - Server Name 5 | // CI - Channel Info 6 | // CL - Channel List 7 | // CD - Channel Data 8 | // UI - User Info 9 | 10 | export const Grid = styled.div` 11 | display: grid; 12 | height: 100vh; 13 | 14 | grid-template-columns: 65px auto; 15 | grid-template-rows: 46px auto; 16 | grid-template-areas: 17 | 'SL CI' 18 | 'SL CD'; 19 | 20 | @media (min-width: 598px) { 21 | grid-template-columns: 71px 240px auto 240px; 22 | grid-template-rows: 46px auto 52px; 23 | grid-template-areas: 24 | 'SL SN CI CI' 25 | 'SL CL CD CD' 26 | 'SL UI CD CD'; 27 | } 28 | 29 | @media (min-width: 868px) { 30 | grid-template-areas: 31 | 'SL SN CI CI' 32 | 'SL CL CD UL' 33 | 'SL UI CD UL'; 34 | } 35 | `; 36 | -------------------------------------------------------------------------------- /src/components/ChannelList/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Add } from 'styled-icons/material'; 3 | 4 | export const Container = styled.div` 5 | grid-area: CL; 6 | display: flex; 7 | flex-direction: column; 8 | padding: 24px 9.5px 0 16px; 9 | background-color: var(--secondary); 10 | 11 | @media (max-width: 598px) { 12 | display: none; 13 | } 14 | `; 15 | 16 | export const Category = styled.div` 17 | display: flex; 18 | align-items: center; 19 | justify-content: space-between; 20 | margin-bottom: 6px; 21 | > span { 22 | text-transform: uppercase; 23 | font-size: 12px; 24 | font-weight: 500; 25 | color: var(--gray); 26 | } 27 | `; 28 | 29 | export const AddCategoryIcon = styled(Add)` 30 | width: 21px; 31 | height: 21px; 32 | color: var(--symbol); 33 | cursor: pointer; 34 | `; 35 | -------------------------------------------------------------------------------- /src/components/ChannelInfo/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Hashtag } from 'styled-icons/heroicons-outline'; 3 | 4 | export const Container = styled.div` 5 | grid-area: CI; 6 | display: flex; 7 | align-items: center; 8 | padding: 0 17px; 9 | background-color: var(--primary); 10 | box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 0px 0px; 11 | z-index: 2; 12 | `; 13 | 14 | export const HashtagIcon = styled(Hashtag)` 15 | width: 24px; 16 | height: 24px; 17 | color: var(--symbol); 18 | `; 19 | 20 | export const Title = styled.h1` 21 | margin-left: 9px; 22 | font-size: 16px; 23 | font-weight: bold; 24 | color: var(--white); 25 | `; 26 | 27 | export const Separator = styled.div` 28 | height: 24px; 29 | width: 1px; 30 | background-color: var(--white); 31 | opacity: 0.2; 32 | margin: 0 13px; 33 | `; 34 | 35 | export const Description = styled.span` 36 | font-size: 15px; 37 | color: var(--gray); 38 | `; 39 | -------------------------------------------------------------------------------- /src/components/ChannelList/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Tooltip } from '@material-ui/core'; 3 | 4 | import ChannelButton from '../ChannelButton'; 5 | 6 | import { useStyles } from '../../styles/MaterialUI'; 7 | import { Container, Category, AddCategoryIcon } from './styles'; 8 | 9 | const ChannelList: React.FC = () => { 10 | const classes = useStyles(); 11 | return ( 12 | 13 | 14 | Text channels 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ); 27 | }; 28 | 29 | export default ChannelList; 30 | -------------------------------------------------------------------------------- /src/assets/svg/TypeScript.svg: -------------------------------------------------------------------------------- 1 | file_type_typescript -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es6: true, 5 | }, 6 | extends: ['plugin:react/recommended', 'airbnb', 'plugin:@typescript-eslint/recommended', 'prettier/@typescript-eslint', 'plugin:prettier/recommended'], 7 | globals: { 8 | Atomics: 'readonly', 9 | SharedArrayBuffer: 'readonly', 10 | }, 11 | parserOptions: { 12 | ecmaFeatures: { 13 | jsx: true, 14 | }, 15 | ecmaVersion: 2018, 16 | sourceType: 'module', 17 | }, 18 | plugins: ['react', 'react-hooks', '@typescript-eslint', 'prettier'], 19 | rules: { 20 | 'linebreak-style': 0, 21 | 'react/prop-types': 0, 22 | 'react/jsx-filename-extension': 0, 23 | 'import/extensions': 0, 24 | 'import/no-unresolved': 0, 25 | camelcase: 0, 26 | 'prettier/prettier': 0, 27 | 'no-use-before-define': 0, 28 | 'import/prefer-default-export': 0, 29 | 'jsx-a11y/click-events-have-key-events': 0, 30 | 'jsx-a11y/no-static-element-interactions': 0, 31 | }, 32 | }; 33 | -------------------------------------------------------------------------------- /src/components/ServerButton/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Tooltip } from '@material-ui/core'; 3 | 4 | import { useStyles } from '../../styles/MaterialUI'; 5 | import { Button } from './styles'; 6 | 7 | export interface Props { 8 | selected?: boolean; 9 | isHome?: boolean; 10 | hasNotifications?: boolean; 11 | mentions?: number; 12 | color?: string; 13 | logo?: string; 14 | name?: string; 15 | } 16 | 17 | const ServerButton: React.FC = ({ selected, isHome, hasNotifications, mentions, color, logo, name }) => { 18 | const classes = useStyles(); 19 | return ( 20 | <> 21 | 22 | 25 | 26 | 27 | ); 28 | }; 29 | 30 | export default ServerButton; 31 | -------------------------------------------------------------------------------- /src/components/ChannelMessage/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Container, Avatar, Message, Header, Content } from './styles'; 4 | 5 | export { Mention } from './styles'; 6 | 7 | export interface Props { 8 | author: string; 9 | date: string; 10 | content: string | React.ReactElement | React.ReactNode; 11 | hasMention?: boolean; 12 | isBot?: boolean; 13 | avatar?: string; 14 | } 15 | 16 | const ChannelMessage: React.FC = ({ author, date, content, hasMention, isBot, avatar }) => { 17 | return ( 18 | 19 | {avatar ? {author} : ''} 20 | 21 | 22 |
23 | {author} 24 | 25 | {isBot && Bot} 26 | 27 | 28 |
29 | {content} 30 |
31 |
32 | ); 33 | }; 34 | 35 | export default ChannelMessage; 36 | -------------------------------------------------------------------------------- /src/styles/GlobalStyles.ts: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from 'styled-components'; 2 | 3 | export default createGlobalStyle` 4 | *{ 5 | margin: 0; 6 | padding: 0; 7 | box-sizing: border-box; 8 | scroll-behavior: smooth; 9 | } 10 | 11 | html, body, #root { 12 | height: 100%; 13 | scroll-behavior: smooth; 14 | } 15 | 16 | *, button, input { 17 | border: 0; 18 | outline: 0; 19 | font-family: var(--font-family); 20 | } 21 | 22 | :root { 23 | --primary: #36393f; 24 | --secondary: #2f3136; 25 | --tertiary: rgb(32,34,37); 26 | --quaternary: #292b2f; 27 | --quinary: #393d42; 28 | --senary: #828386; 29 | 30 | --white: #fff; 31 | --gray: #8a8c90; 32 | --chat-input: rgb(64,68,75); 33 | --symbol: #74777a; 34 | --notification: #f84a4b; 35 | --discord: #6e86d6; 36 | --mention-detail: #f9a839; 37 | --mention-message: #413f3f; 38 | --link: #5d80d6; 39 | --rocketseat: #6633cc; 40 | --ifm-scrollbar-hover: #555; 41 | 42 | --font-family: 'Roboto', sans-serif; 43 | } 44 | 45 | `; 46 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "discord-ui-clone", 3 | "name": "Discord UI Clone", 4 | "author": "Leonardo Ronne", 5 | "description": "This application contains an UI clone from Discord (partial) website.", 6 | "developer": { 7 | "name": "Leonardo Ronne", 8 | "url": "https://discord.com/leoronne" 9 | }, 10 | "homepage_url": "https://discord.ui-clone.ronne.dev", 11 | "icons": [ 12 | { 13 | "src": "favicon.ico", 14 | "sizes": "256x256", 15 | "type": "image/x-icon" 16 | }, 17 | { 18 | "src": "logo192.png", 19 | "type": "image/png", 20 | "sizes": "192x192" 21 | }, 22 | { 23 | "src": "logo256.png", 24 | "type": "image/png", 25 | "sizes": "256x256" 26 | }, 27 | { 28 | "src": "logo512.png", 29 | "type": "image/png", 30 | "sizes": "512x512" 31 | }, 32 | { 33 | "src": "logo1024.png", 34 | "type": "image/png", 35 | "sizes": "1024x1024" 36 | } 37 | ], 38 | "start_url": "/", 39 | "display": "standalone", 40 | "theme_color": "#6e86d6", 41 | "background_color": "#6e86d6" 42 | } 43 | -------------------------------------------------------------------------------- /src/components/ChannelButton/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Tooltip } from '@material-ui/core'; 3 | 4 | import { useStyles } from '../../styles/MaterialUI'; 5 | import { Container, HashtagIcon, InviteIcon, SettingsIcon } from './styles'; 6 | 7 | export interface Props { 8 | channelName: string; 9 | selected?: boolean; 10 | } 11 | 12 | const ChannelButton: React.FC = ({ channelName, selected }) => { 13 | const classes = useStyles(); 14 | return ( 15 | 16 |
17 | 18 | {channelName} 19 |
20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | ); 31 | }; 32 | 33 | export default ChannelButton; 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Leonardo Ronne 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/assets/svg/NodeJS.svg: -------------------------------------------------------------------------------- 1 | file_type_node -------------------------------------------------------------------------------- /src/components/ChannelData/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { AlternateEmail } from 'styled-icons/material'; 3 | 4 | export const Container = styled.div` 5 | grid-area: CD; 6 | display: flex; 7 | flex-direction: column; 8 | justify-content: space-between; 9 | background-color: var(--primary); 10 | `; 11 | 12 | export const Messages = styled.div` 13 | padding: 20px 0; 14 | display: flex; 15 | flex-direction: column; 16 | max-height: calc(100vh - 48px - 68px - 61px); 17 | overflow-y: scroll; 18 | ::-webkit-scrollbar { 19 | width: 8px; 20 | } 21 | ::-webkit-scrollbar-thumb { 22 | background-color: var(--tertiary); 23 | border-radius: 4px; 24 | } 25 | ::-webkit-scrollbar-track { 26 | background-color: var(--secondary); 27 | } 28 | `; 29 | 30 | export const InputWrapper = styled.div` 31 | width: 100%; 32 | padding: 0 16px; 33 | `; 34 | 35 | export const Input = styled.input` 36 | width: 100%; 37 | height: 44px; 38 | padding: 0 10px 0 57px; 39 | border-radius: 7px; 40 | color: var(--white); 41 | background-color: var(--chat-input); 42 | position: relative; 43 | &::placeholder { 44 | color: var(--gray); 45 | } 46 | ~ svg { 47 | position: relative; 48 | top: -50%; 49 | left: 14px; 50 | transition: 180ms ease-in-out; 51 | } 52 | `; 53 | 54 | export const InputIcon = styled(AlternateEmail)` 55 | width: 24px; 56 | height: 24px; 57 | color: var(--gray); 58 | `; 59 | -------------------------------------------------------------------------------- /src/components/ChannelButton/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Hashtag } from 'styled-icons/heroicons-outline'; 3 | import { PersonAdd, Settings } from 'styled-icons/material'; 4 | 5 | export const Container = styled.div` 6 | display: flex; 7 | align-items: center; 8 | justify-content: space-between; 9 | cursor: pointer; 10 | padding: 8px 3px; 11 | border-radius: 5px; 12 | background-color: transparent; 13 | transition: background-color 0.2s; 14 | 15 | margin-top: 2px; 16 | > div { 17 | display: flex; 18 | align-items: center; 19 | } 20 | > div span { 21 | margin-left: 5px; 22 | color: var(--senary); 23 | } 24 | &:hover, 25 | &.active { 26 | background-color: var(--quinary); 27 | > div span { 28 | color: var(--white); 29 | } 30 | } 31 | 32 | &:hover > .channel-config { 33 | transition: 0.7ms; 34 | visibility: visible !important; 35 | } 36 | 37 | .channel-config { 38 | transition: 0.7ms; 39 | visibility: hidden; 40 | } 41 | 42 | .channel-active { 43 | transition: 0.7ms; 44 | visibility: visible !important; 45 | } 46 | `; 47 | 48 | export const HashtagIcon = styled(Hashtag)` 49 | width: 20px; 50 | height: 20px; 51 | color: var(--symbol); 52 | `; 53 | 54 | export const InviteIcon = styled(PersonAdd)` 55 | width: 16px; 56 | height: 16px; 57 | color: var(--symbol); 58 | cursor: pointer; 59 | transition: color 0.2s; 60 | &:hover { 61 | color: var(--white); 62 | } 63 | `; 64 | 65 | export const SettingsIcon = styled(Settings)` 66 | width: 16px; 67 | height: 16px; 68 | margin-left: 4px; 69 | color: var(--symbol); 70 | cursor: pointer; 71 | transition: color 0.2s; 72 | &:hover { 73 | color: var(--white); 74 | } 75 | `; 76 | -------------------------------------------------------------------------------- /src/components/ChannelMessage/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Container = styled.div` 4 | display: flex; 5 | align-items: center; 6 | padding: 4px 16px; 7 | margin-right: 4px; 8 | background-color: transparent; 9 | &.mention { 10 | background-color: var(--mention-message); 11 | border-left: 2px solid var(--mention-detail); 12 | padding-left: 14px; 13 | } 14 | & + div { 15 | margin-top: 13px; 16 | } 17 | `; 18 | 19 | export const Avatar = styled.div` 20 | width: 40px; 21 | height: 40px; 22 | background-color: var(--secondary); 23 | border-radius: 50%; 24 | &.bot { 25 | background-color: var(--mention-detail); 26 | } 27 | 28 | .user-avatar { 29 | width: 40px; 30 | border-radius: 50%; 31 | } 32 | `; 33 | 34 | export const Message = styled.div` 35 | min-height: 40px; 36 | display: flex; 37 | flex-direction: column; 38 | justify-content: space-between; 39 | margin-left: 17px; 40 | `; 41 | 42 | export const Header = styled.div` 43 | display: flex; 44 | align-items: center; 45 | > strong { 46 | color: var(--white); 47 | font-size: 16px; 48 | } 49 | > span { 50 | margin-left: 6px; 51 | background-color: var(--discord); 52 | color: var(--white); 53 | border-radius: 4px; 54 | padding: 4px 5px; 55 | text-transform: uppercase; 56 | font-weight: bold; 57 | font-size: 11px; 58 | } 59 | > time { 60 | margin-left: 6px; 61 | color: var(--gray); 62 | font-size: 13px; 63 | } 64 | `; 65 | 66 | export const Content = styled.div` 67 | text-align: left; 68 | font-size: 16px; 69 | color: var(--white); 70 | `; 71 | 72 | export const Mention = styled.span` 73 | color: var(--link); 74 | cursor: pointer; 75 | &:hover { 76 | text-decoration: underline; 77 | } 78 | `; 79 | -------------------------------------------------------------------------------- /src/components/UserInfo/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Tooltip } from '@material-ui/core'; 3 | 4 | import avatar from '~/assets/img/avatar.jpg'; 5 | 6 | import { useStyles } from '../../styles/MaterialUI'; 7 | import { Container, Profile, Avatar, UserData, Icons, Icon, MicIcon, MicOffIcon, VolumeIcon, VolumeOffIcon, SettingsIcon } from './styles'; 8 | 9 | const UserInfo: React.FC = () => { 10 | const classes = useStyles(); 11 | 12 | const [muteMic, setMuteMic] = useState(false); 13 | const [muteAudio, setMuteAudio] = useState(false); 14 | 15 | const handleMuteMic = () => setMuteMic(!muteMic); 16 | const handleMuteAudio = () => setMuteAudio(!muteAudio); 17 | 18 | return ( 19 | 20 | 21 | 22 | leoronne 23 | 24 | 25 | leoronne 26 | #9480 27 | 28 | 29 | 30 | 31 | 32 | {muteMic ? : } 33 | 34 | 35 | {muteAudio ? : } 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ); 45 | }; 46 | 47 | export default UserInfo; 48 | -------------------------------------------------------------------------------- /src/components/ServerList/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import ServerButton from '../ServerButton'; 4 | 5 | import { Container, Separator } from './styles'; 6 | 7 | import RocketSeat from '~/assets/svg/RocketSeat.svg'; 8 | import Pokemon from '~/assets/svg/Pokémon.svg'; 9 | import Code from '~/assets/svg/Code.svg'; 10 | import TypeScript from '~/assets/svg/TypeScript.svg'; 11 | import ReactJS from '~/assets/svg/ReactJS.svg'; 12 | import NodeJS from '~/assets/svg/NodeJS.svg'; 13 | import Mario from '~/assets/svg/Mario.svg'; 14 | import Pride from '~/assets/svg/Pride.svg'; 15 | import DC from '~/assets/svg/DC.svg'; 16 | import CSS from '~/assets/svg/CSS.svg'; 17 | import Ronne from '~/assets/svg/Ronne.svg'; 18 | 19 | const ServerList: React.FC = () => { 20 | return ( 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | ); 38 | }; 39 | 40 | export default ServerList; 41 | -------------------------------------------------------------------------------- /src/components/UserList/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Container = styled.div` 4 | grid-area: UL; 5 | display: flex; 6 | flex-direction: column; 7 | padding: 3px 6px 0 16px; 8 | background-color: var(--secondary); 9 | max-height: calc(100vh - 46px); 10 | overflow-y: scroll; 11 | ::-webkit-scrollbar { 12 | width: 4px; 13 | } 14 | ::-webkit-scrollbar-thumb { 15 | background-color: var(--tertiary); 16 | border-radius: 4px; 17 | } 18 | ::-webkit-scrollbar-track { 19 | background-color: var(--secondary); 20 | } 21 | @media (max-width: 868px) { 22 | display: none; 23 | } 24 | `; 25 | 26 | export const Role = styled.span` 27 | margin-top: 20px; 28 | text-transform: uppercase; 29 | font-size: 12px; 30 | font-weight: 500; 31 | color: var(--gray); 32 | `; 33 | 34 | export const User = styled.div` 35 | margin-top: 5px; 36 | padding: 5px; 37 | display: flex; 38 | align-items: center; 39 | cursor: pointer; 40 | border-radius: 4px; 41 | background: transparent; 42 | transition: background 0.2s; 43 | &:hover { 44 | background: rgba(255, 255, 255, 0.1); 45 | } 46 | > strong { 47 | margin-left: 13px; 48 | font-weight: 500; 49 | color: var(--white); 50 | opacity: 0.7; 51 | white-space: nowrap; 52 | text-overflow: ellipsis; 53 | overflow: hidden; 54 | } 55 | > span { 56 | margin-left: 9px; 57 | background-color: var(--discord); 58 | color: var(--white); 59 | border-radius: 4px; 60 | padding: 4px 5px; 61 | text-transform: uppercase; 62 | font-weight: bold; 63 | font-size: 11px; 64 | } 65 | `; 66 | 67 | export const Avatar = styled.div` 68 | flex-shrink: 0; 69 | width: 32px; 70 | height: 32px; 71 | border-radius: 50%; 72 | background-color: var(--primary); 73 | &.bot { 74 | background-color: var(--mention-detail); 75 | } 76 | .user-avatar { 77 | width: 32px; 78 | border-radius: 50%; 79 | } 80 | `; 81 | -------------------------------------------------------------------------------- /src/assets/svg/ReactJS.svg: -------------------------------------------------------------------------------- 1 | file_type_reactjs -------------------------------------------------------------------------------- /src/assets/svg/Ronne.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 10 | 15 | 20 | 26 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Discord UI Clone 41 | 42 | 43 |
44 | 45 | 46 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "discord-ui-clone", 3 | "version": "1.0.0", 4 | "description": "discord-ui-clone", 5 | "repository": "https://github.com/leoronne/discord-ui-clone", 6 | "author": "Leonardo Ronne", 7 | "license": "MIT", 8 | "dependencies": { 9 | "@material-ui/core": "^4.11.2", 10 | "@testing-library/jest-dom": "^5.11.6", 11 | "@testing-library/react": "^11.2.2", 12 | "@testing-library/user-event": "^12.6.0", 13 | "@types/jest": "^26.0.19", 14 | "@types/node": "^14.14.14", 15 | "@types/react": "^17.0.0", 16 | "@types/react-dom": "^17.0.0", 17 | "react": "^17.0.1", 18 | "react-dom": "^17.0.1", 19 | "react-scripts": "^4.0.1", 20 | "styled-components": "^5.1.1", 21 | "styled-icons": "^10.5.0", 22 | "typescript": "^4.1.3" 23 | }, 24 | "scripts": { 25 | "start": "react-app-rewired start", 26 | "build": "react-app-rewired build", 27 | "test": "react-app-rewired test", 28 | "eject": "react-app-rewired eject" 29 | }, 30 | "eslintConfig": { 31 | "extends": "react-app" 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | }, 45 | "devDependencies": { 46 | "@types/styled-components": "^5.1.0", 47 | "@typescript-eslint/eslint-plugin": "^4.11.0", 48 | "@typescript-eslint/parser": "^4.11.0", 49 | "babel-eslint": "^10.0.3", 50 | "babel-plugin-root-import": "^6.4.1", 51 | "customize-cra": "^1.0.0", 52 | "eslint": "^7.16.0", 53 | "eslint-config-airbnb": "^18.1.0", 54 | "eslint-config-prettier": "^7.1.0", 55 | "eslint-import-resolver-babel-plugin-root-import": "^1.1.1", 56 | "eslint-plugin-import": "^2.20.2", 57 | "eslint-plugin-import-helpers": "^1.0.2", 58 | "eslint-plugin-jsx-a11y": "^6.2.3", 59 | "eslint-plugin-prettier": "^3.3.0", 60 | "eslint-plugin-react": "^7.21.5", 61 | "eslint-plugin-react-hooks": "^4.2.0", 62 | "prettier": "^2.2.1", 63 | "react-app-rewired": "^2.1.6" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/components/UserList/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import leoronne from '~/assets/img/avatar.jpg'; 4 | import cyhi from '~/assets/img/cyhi.jpg'; 5 | import user1 from '~/assets/img/user1.jpg'; 6 | import user2 from '~/assets/img/user2.jpg'; 7 | import user3 from '~/assets/img/user3.jpg'; 8 | import user4 from '~/assets/img/user4.jpg'; 9 | import user5 from '~/assets/img/user5.jpg'; 10 | 11 | import { Container, Role, User, Avatar } from './styles'; 12 | 13 | interface UserProps { 14 | nickname: string; 15 | isBot?: boolean; 16 | avatar?: string; 17 | } 18 | 19 | const UserRow: React.FC = ({ nickname, isBot, avatar }) => { 20 | return ( 21 | 22 | {avatar ? {nickname} : ''} 23 | 24 | {nickname} 25 | 26 | {isBot && Bot} 27 | 28 | ); 29 | }; 30 | 31 | const UserList: React.FC = () => { 32 | return ( 33 | 34 | Online - 4 35 | 36 | 37 | 38 | 39 | 40 | Offline - 17 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | ); 60 | }; 61 | 62 | export default UserList; 63 | -------------------------------------------------------------------------------- /src/assets/svg/Pride.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/svg/CSS.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |
6 | 7 |
8 | 9 | [![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](http://badges.mit-license.org) 10 | ![GitHub last commit](https://img.shields.io/github/last-commit/leoronne/discord-ui-clone?color=green&style=flat-square) 11 | ![GitHub top language](https://img.shields.io/github/languages/top/leoronne/discord-ui-clone?style=flat-square) 12 | 13 |
14 | 15 | ## 16 | 17 |

18 | Project   |    19 | Techs   |    20 | Installation   |    21 | Start   |    22 | Contributing   |    23 | License 24 |

25 | 26 | 27 | ## 28 | 29 |

30 | 31 |

32 | 33 |
34 | 35 | ## Project :star2: 36 | 37 | This project was part of an UI Clone challenge, the idea was to replicate (partially) the Discord's channels page using ReactJS, MUI and styled-components. 38 | 39 | The intent of this project was to work with more complex grid attributes of CSS. 40 | 41 | Deployed [here](https://discord.ui-clone.ronne.dev). 42 | 43 |
44 | 45 | ## Techs :rocket: 46 | 47 | - [x] [ReactJS](https://reactjs.org); 48 | - [x] [TypeScript](https://www.typescriptlang.org/); 49 | - [x] [Styled Components](https://styled-components.com/). 50 | 51 |
52 | 53 | ## Installation :wrench: 54 | 55 | First you need to clone the project using `git clone https://github.com/leoronne/discord-ui-clone.git`. 56 | 57 | You can install the application using `npm install` or `yarn install` on the root dir. 58 | 59 |
60 | 61 | ## Start :on: 62 | 63 | To start the application interface just run `npm start` or `yarn start` on the root dir. 64 | 65 | 66 |
67 | 68 | ## Contributing 🤔 69 | 70 | Please read [CONTRIBUTING](https://github.com/leoronne/discord-ui-clone/blob/master/CONTRIBUTING.md) for details on code of conduct, and the process for submitting pull requests to the project. 71 | 72 |
73 | 74 | ## License :memo: 75 | 76 | [![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](http://badges.mit-license.org) 77 | 78 | - **[MIT license](https://github.com/leoronne/discord-ui-clone/blob/master/LICENSE)**; 79 | - Copyright 2020 © Leonardo Ronne. 80 | 81 | ## 82 | -------------------------------------------------------------------------------- /src/components/UserInfo/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Mic, MicOff, Settings } from 'styled-icons/material'; 3 | import { VolumeFull, VolumeMute } from 'styled-icons/boxicons-regular'; 4 | 5 | export const Container = styled.div` 6 | grid-area: UI; 7 | display: flex; 8 | align-items: center; 9 | justify-content: space-between; 10 | padding: 10px; 11 | background-color: var(--quaternary); 12 | box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 0px 0px; 13 | 14 | @media (max-width: 598px) { 15 | display: none; 16 | } 17 | `; 18 | 19 | export const Profile = styled.div` 20 | display: flex; 21 | align-items: center; 22 | `; 23 | 24 | export const Avatar = styled.div` 25 | width: 32px; 26 | height: 32px; 27 | border-radius: 50%; 28 | background-color: var(--gray); 29 | 30 | .user-avatar { 31 | width: 32px; 32 | border-radius: 50%; 33 | } 34 | `; 35 | 36 | export const UserData = styled.div` 37 | margin-left: 8px; 38 | display: flex; 39 | flex-direction: column; 40 | > strong { 41 | color: var(--white); 42 | font-size: 13px; 43 | display: block; 44 | } 45 | > span { 46 | color: var(--gray); 47 | font-size: 13px; 48 | } 49 | `; 50 | 51 | export const Icons = styled.div` 52 | display: flex; 53 | align-items: center; 54 | margin-top: -5px; 55 | > div:not(:first-child) { 56 | margin-left: 7px; 57 | } 58 | `; 59 | 60 | export const Icon = styled.div` 61 | width: 20px; 62 | height: 20px; 63 | cursor: pointer; 64 | `; 65 | 66 | export const MicOffIcon = styled(MicOff)` 67 | width: 20px; 68 | height: 20px; 69 | color: var(--white); 70 | opacity: 0.7; 71 | cursor: pointer; 72 | transition: opacity 0.2s; 73 | &:hover { 74 | opacity: 1; 75 | } 76 | `; 77 | 78 | export const MicIcon = styled(Mic)` 79 | width: 20px; 80 | height: 20px; 81 | color: var(--white); 82 | opacity: 0.7; 83 | cursor: pointer; 84 | transition: opacity 0.2s; 85 | &:hover { 86 | opacity: 1; 87 | } 88 | `; 89 | 90 | export const VolumeIcon = styled(VolumeFull)` 91 | width: 20px; 92 | height: 20px; 93 | color: var(--white); 94 | opacity: 0.7; 95 | cursor: pointer; 96 | transition: opacity 0.2s; 97 | &:hover { 98 | opacity: 1; 99 | } 100 | `; 101 | 102 | export const VolumeOffIcon = styled(VolumeMute)` 103 | width: 20px; 104 | height: 20px; 105 | color: var(--white); 106 | opacity: 0.7; 107 | cursor: pointer; 108 | transition: opacity 0.2s; 109 | &:hover { 110 | opacity: 1; 111 | } 112 | `; 113 | 114 | export const SettingsIcon = styled(Settings)` 115 | width: 20px; 116 | height: 20px; 117 | color: var(--white); 118 | opacity: 0.7; 119 | cursor: pointer; 120 | transition: opacity 0.2s; 121 | &:hover { 122 | opacity: 1; 123 | } 124 | `; 125 | -------------------------------------------------------------------------------- /src/assets/svg/DC.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 53 | 59 | 60 | -------------------------------------------------------------------------------- /src/components/ChannelData/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useEffect } from 'react'; 2 | 3 | import leoronne from '~/assets/img/avatar.jpg'; 4 | import cyhi from '~/assets/img/cyhi.jpg'; 5 | import user2 from '~/assets/img/user2.jpg'; 6 | import user4 from '~/assets/img/user4.jpg'; 7 | import user5 from '~/assets/img/user5.jpg'; 8 | 9 | import ChannelMessage, { Mention } from '../ChannelMessage'; 10 | 11 | import { Container, Messages, InputWrapper, Input, InputIcon } from './styles'; 12 | 13 | const ChannelData: React.FC = () => { 14 | const messagesRef = useRef() as React.MutableRefObject; 15 | const users = ['Prynce', 'Nyarth', 'John Doe', 'Maria Ciclano', 'H. Montanha', 'James', 'Enzo João', 'Valentina de Jesus', 'Enzo José', 'Valentina Maria', 'Brunno Enzo', 'Lara', 'Lohaine', 'Lika']; 16 | const messages = ['fine, tnx n u?', 'heyy, whats up?', 'hey, what r u up 2?', 'whats gooooooood?!', "good, just coding some rocketseat's challenges"]; 17 | 18 | useEffect(() => { 19 | const div = messagesRef.current; 20 | 21 | if (div) { 22 | div.scrollTop = div.scrollHeight; 23 | } 24 | }, [messagesRef]); 25 | 26 | return ( 27 | 28 | Welcome to the Open Chat channel!} hasMention isBot avatar={cyhi} /> 29 | 30 | 31 | 32 | 37 | @leoronne 38 | {' '} 39 | heyyyy 40 | 41 | )} 42 | hasMention 43 | avatar={user2} 44 | /> 45 | {Array.from(Array(5).keys()).map((n) => ( 46 | 47 | ))} 48 | 49 | 55 | @leoronne 56 | {' '} 57 | {messages[Math.floor(Math.random() * messages.length)]} 58 | 59 | )} 60 | /> 61 | {Array.from(Array(5).keys()).map((n) => ( 62 | 63 | ))} 64 | 70 | @leoronne 71 | {' '} 72 | {messages[Math.floor(Math.random() * messages.length)]} 73 | 74 | )} 75 | /> 76 | There are currently 4 online users and 17 offline!} isBot avatar={user5} /> 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | ); 85 | }; 86 | 87 | export default ChannelData; 88 | -------------------------------------------------------------------------------- /src/components/ServerButton/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | import { Props } from '.'; 4 | 5 | export const Container = styled.div` 6 | width: 48px; 7 | height: 48px; 8 | position: relative; 9 | margin-bottom: 10px; 10 | 11 | @media (max-width: 598px) { 12 | width: 35px; 13 | height: 35px; 14 | } 15 | `; 16 | 17 | export const Button = styled.button` 18 | display: flex; 19 | align-items: center; 20 | justify-content: center; 21 | flex-shrink: 0; 22 | width: 48px; 23 | height: 48px; 24 | border-radius: 50%; 25 | margin-bottom: 15px; 26 | background-color: ${(props) => (props.color ? props.color : 'var(--primary)')}; 27 | /* ${(props) => (props.isHome ? 'var(--rocketseat)' : 'var(--primary)')}; */ 28 | position: relative; 29 | cursor: pointer; 30 | > img { 31 | width: 30px; 32 | height: 30px; 33 | } 34 | &::before { 35 | width: 9px; 36 | height: 9px; 37 | position: absolute; 38 | left: -17px; 39 | top: calc(50% - 4.5px); 40 | background-color: var(--white); 41 | border-radius: 50%; 42 | content: ''; 43 | display: ${(props) => (props.hasNotifications ? 'inline' : 'none')}; 44 | } 45 | &::after { 46 | background-color: var(--notification); 47 | width: auto; 48 | height: 16px; 49 | padding: 0 4px; 50 | position: absolute; 51 | bottom: -4px; 52 | right: -4px; 53 | border-radius: 12px; 54 | border: 4px solid var(--quaternary); 55 | text-align: right; 56 | font-size: 13px; 57 | font-weight: bold; 58 | color: var(--white); 59 | content: '${(props) => props.mentions && props.mentions}'; 60 | display: ${(props) => (props.mentions && props.mentions > 0 ? 'inline' : 'none')}; 61 | } 62 | transition: border-radius 0.2s, background-color 0.2s; 63 | &.active, 64 | &:hover { 65 | border-radius: 16px; 66 | background-color: ${(props) => (props.color ? props.color : 'var(--discord)')}; 67 | } 68 | &:hover ~ .tooltiptext { 69 | visibility: visible; 70 | opacity: 1; 71 | } 72 | 73 | @media (max-width: 598px) { 74 | width: 30px; 75 | height: 30px; 76 | margin-bottom: 10px; 77 | &::before { 78 | width: 5px; 79 | height: 5px; 80 | left: -13px; 81 | } 82 | > img { 83 | width: 25px; 84 | height: 25px; 85 | } 86 | &::after { 87 | height: 10px; 88 | font-size: 7px; 89 | } 90 | } 91 | `; 92 | 93 | export const Tooltip = styled.div` 94 | position: relative; 95 | display: flex; 96 | align-items: center; 97 | justify-content: center; 98 | width: 20px; 99 | 100 | .tooltiptext { 101 | /* visibility: hidden; */ 102 | text-align: center !important; 103 | font-size: 16px; 104 | padding: 5px; 105 | width: 120px; 106 | background-color: var(--ifm-scrollbar-hover); 107 | color: var(--white); 108 | text-align: center; 109 | border-radius: 6px; 110 | position: absolute; 111 | z-index: 1; 112 | bottom: 125%; 113 | left: 50%; 114 | margin-left: -60px; 115 | /* opacity: 0; */ 116 | transition: opacity 0.3s; 117 | display: initial; 118 | } 119 | 120 | .tooltiptext::after { 121 | content: ''; 122 | position: absolute; 123 | top: 100%; 124 | left: 50%; 125 | margin-left: -5px; 126 | border-width: 5px; 127 | border-style: solid; 128 | border-color: var(--ifm-scrollbar-hover) transparent transparent transparent; 129 | } 130 | 131 | .tooltip:hover .tooltiptext { 132 | visibility: visible; 133 | opacity: 1; 134 | } 135 | 136 | @media (max-width: 598px) { 137 | width: 15px; 138 | } 139 | `; 140 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 17 | do not have permission to do that, you may request the second reviewer to merge it for you. 18 | 19 | ## Code of Conduct 20 | 21 | ### Our Pledge 22 | 23 | In the interest of fostering an open and welcoming environment, we as 24 | contributors and maintainers pledge to making participation in our project and 25 | our community a harassment-free experience for everyone, regardless of age, body 26 | size, disability, ethnicity, gender identity and expression, level of experience, 27 | nationality, personal appearance, race, religion, or sexual identity and 28 | orientation. 29 | 30 | ### Our Standards 31 | 32 | Examples of behavior that contributes to creating a positive environment 33 | include: 34 | 35 | * Using welcoming and inclusive language 36 | * Being respectful of differing viewpoints and experiences 37 | * Gracefully accepting constructive criticism 38 | * Focusing on what is best for the community 39 | * Showing empathy towards other community members 40 | 41 | Examples of unacceptable behavior by participants include: 42 | 43 | * The use of sexualized language or imagery and unwelcome sexual attention or 44 | advances 45 | * Trolling, insulting/derogatory comments, and personal or political attacks 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic 48 | address, without explicit permission 49 | * Other conduct which could reasonably be considered inappropriate in a 50 | professional setting 51 | 52 | ### Our Responsibilities 53 | 54 | Project maintainers are responsible for clarifying the standards of acceptable 55 | behavior and are expected to take appropriate and fair corrective action in 56 | response to any instances of unacceptable behavior. 57 | 58 | Project maintainers have the right and responsibility to remove, edit, or 59 | reject comments, commits, code, wiki edits, issues, and other contributions 60 | that are not aligned to this Code of Conduct, or to ban temporarily or 61 | permanently any contributor for other behaviors that they deem inappropriate, 62 | threatening, offensive, or harmful. 63 | 64 | ### Scope 65 | 66 | This Code of Conduct applies both within project spaces and in public spaces 67 | when an individual is representing the project or its community. Examples of 68 | representing a project or community include using an official project e-mail 69 | address, posting via an official social media account, or acting as an appointed 70 | representative at an online or offline event. Representation of a project may be 71 | further defined and clarified by project maintainers. 72 | 73 | ### Enforcement 74 | 75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 76 | reported by contacting the project team at . All 77 | complaints will be reviewed and investigated and will result in a response that 78 | is deemed necessary and appropriate to the circumstances. The project team is 79 | obligated to maintain confidentiality with regard to the reporter of an incident. 80 | Further details of specific enforcement policies may be posted separately. 81 | 82 | Project maintainers who do not follow or enforce the Code of Conduct in good 83 | faith may face temporary or permanent repercussions as determined by other 84 | members of the project's leadership. 85 | -------------------------------------------------------------------------------- /src/assets/svg/RocketSeat.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/assets/svg/Mario.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 10 | 11 | 12 | 14 | 15 | 17 | 24 | 25 | 28 | 29 | 30 | 37 | 38 | 39 | 40 | 41 | 42 | 45 | 46 | 48 | 50 | 51 | 52 | 53 | 54 | 55 | 58 | 60 | 62 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /src/assets/svg/Code.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 20 | 22 | 24 | 25 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 41 | 43 | 44 | 47 | 49 | 52 | 53 | 54 | 55 | 56 | 58 | 62 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/assets/svg/Pokémon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 9 | 10 | 11 | 13 | 14 | 15 | 21 | 22 | 23 | 25 | 26 | 27 | 29 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 43 | 44 | 45 | 46 | 47 | 50 | 51 | 52 | 53 | 54 | 55 | 57 | 58 | 59 | 62 | 63 | 64 | 67 | 68 | 69 | 70 | 71 | 73 | 74 | 75 | 78 | 79 | 80 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 95 | 100 | 101 | 102 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | --------------------------------------------------------------------------------