├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── index.html └── src ├── components ├── app.js ├── dashboard │ ├── charts.js │ └── feed │ │ ├── comment-actions.js │ │ ├── comment.js │ │ ├── feed.js │ │ ├── item-actions.js │ │ └── item.js ├── navigation │ ├── alerts-dropdown.js │ ├── header.js │ ├── messages-dropdown.js │ ├── navigation.js │ ├── sidebar-item.js │ └── sidebar.js ├── pages │ ├── admin.js │ ├── dashboard.js │ ├── forgot-password.js │ ├── login.js │ └── register.js └── ui │ ├── card-box.js │ └── icon-card.js ├── containers ├── alerts-dropdown-container.js ├── messages-dropdown-container.js └── navigation-container.js ├── css ├── index.css └── sb-admin.css ├── data ├── charts.js └── feed-items.js └── index.js /.gitattributes: -------------------------------------------------------------------------------- 1 | *.rb linguist-language=JavaScript -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules/* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Cosmin Seceleanu 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-sb-admin-bootstrap4 2 | SB Admin with React and Bootstrap 4 beta 3 | 4 | Original SB Admin: https://startbootstrap.com/template-overviews/sb-admin/ 5 | 6 | ## Installation 7 | 1. Clone this project or Download that ZIP file 8 | 9 | ```sh 10 | $ git clone https://github.com/cosminseceleanu/react-sb-admin-bootstrap4.git 11 | ``` 12 | 13 | 2. On the command prompt run the following commands 14 | 15 | ```sh 16 | $ cd `project-directory` 17 | ``` 18 | ```sh 19 | $ npm install 20 | ``` 21 | ```sh 22 | $ npm start 23 | ``` 24 | 25 | 3. To build 26 | ```sh 27 | $ npm run build 28 | ``` 29 | ## Pages implemented 30 | 1. http://localhost:3000/ 31 | 2. http://localhost:3000/login 32 | 3. http://localhost:3000/register 33 | 4. http://localhost:3000/forgot-password 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-sb-admin", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "bootstrap": "^4.0.0-beta", 7 | "chart.js": "^1.1.1", 8 | "datatables.net-bs4": "^1.10.16", 9 | "font-awesome": "^4.7.0", 10 | "node-sass-chokidar": "0.0.3", 11 | "npm-run-all": "^4.1.1", 12 | "react": "^15.6.1", 13 | "react-addons-css-transition-group": "^15.6.0", 14 | "react-addons-transition-group": "^15.6.0", 15 | "react-chartjs": "^0.8.0", 16 | "react-dom": "^15.6.1", 17 | "react-router-dom": "^4.2.2", 18 | "react-scripts": "1.0.12", 19 | "react-transition-group": "^1.2.0", 20 | "reactstrap": "^5.0.0-alpha.4" 21 | }, 22 | "scripts": { 23 | "build-css": "node-sass-chokidar src/ -o src/", 24 | "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive", 25 | "start-js": "react-scripts start", 26 | "start": "npm-run-all -p watch-css start-js", 27 | "build": "npm run build-css && react-scripts build", 28 | "test": "react-scripts test --env=jsdom", 29 | "eject": "react-scripts eject" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosminseceleanu/react-sb-admin-bootstrap4/8dd9e44ebb8db261b6b21b4ae3a78531a595e18f/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Sb Admin React App 9 | 10 | 11 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /src/components/app.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { 3 | BrowserRouter as Router, 4 | Route, 5 | Switch, 6 | } from 'react-router-dom' 7 | 8 | import Admin from './pages/admin'; 9 | import Login from './pages/login'; 10 | import Register from './pages/register'; 11 | import ForgotPassword from './pages/forgot-password'; 12 | 13 | class App extends Component { 14 | render() { 15 | return ( 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | } 26 | } 27 | 28 | export default App; -------------------------------------------------------------------------------- /src/components/dashboard/charts.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Line, Bar} from 'react-chartjs'; 3 | 4 | import CardBox from '../ui/card-box'; 5 | import {LineChart, BarChart} from '../../data/charts'; 6 | 7 | const Charts = () => { 8 | return ( 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | ) 18 | }; 19 | 20 | export default Charts; -------------------------------------------------------------------------------- /src/components/dashboard/feed/comment-actions.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const CommentActions = () => { 4 | return ( 5 | 16 | ) 17 | }; 18 | 19 | export default CommentActions; -------------------------------------------------------------------------------- /src/components/dashboard/feed/comment.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Media 4 | } from 'reactstrap'; 5 | 6 | import CommentActions from './comment-actions'; 7 | 8 | const Comment = ({isReply, user, src, text, children}) => { 9 | return ( 10 | 11 | 12 | 13 |
{user}
14 | {text} 15 | 16 | {children} 17 |
18 |
19 | ) 20 | }; 21 | 22 | export default Comment; -------------------------------------------------------------------------------- /src/components/dashboard/feed/feed.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Col 4 | } from 'reactstrap'; 5 | 6 | import Item from './item'; 7 | import {feedItems} from "../../../data/feed-items"; 8 | 9 | const Feed = () => { 10 | const items = feedItems.map((item, index) => ); 11 | return ( 12 | 13 |
14 | News Feed 15 |
16 |
17 |
18 | {items} 19 |
20 | 21 | ) 22 | }; 23 | 24 | export default Feed; -------------------------------------------------------------------------------- /src/components/dashboard/feed/item-actions.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {CardBody} from 'reactstrap'; 4 | 5 | const ItemActions = () => { 6 | return ( 7 | 8 | 9 | Like 10 | 11 | 12 | Comment 13 | 14 | 15 | Share 16 | 17 | 18 | ) 19 | }; 20 | 21 | export default ItemActions; -------------------------------------------------------------------------------- /src/components/dashboard/feed/item.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Comment from "./comment"; 3 | import ItemActions from "./item-actions"; 4 | 5 | import { 6 | Card, 7 | CardImg, 8 | CardBody, 9 | CardFooter, 10 | CardTitle, 11 | CardText 12 | } from 'reactstrap'; 13 | 14 | const Item = ({item}) => { 15 | return ( 16 | 17 | 18 | 19 | {item.user} 20 | 21 | {item.description} 22 | {renderHashTags(item.tags)} 23 | 24 | 25 |
26 | 27 |
28 | 29 | {renderComments(item.comments)} 30 | 31 | {item.date} 32 |
33 | ) 34 | }; 35 | 36 | const renderHashTags = tags => { 37 | return tags.map((tag, index) => { 38 | return ( 39 | {tag} 40 | ) 41 | }) 42 | }; 43 | 44 | const renderComments = comments => { 45 | return comments.map((comment, index) => { 46 | const reply = comment.reply ? renderComment(comment.reply, null) : null; 47 | 48 | return renderComment(comment, reply, index); 49 | }) 50 | }; 51 | 52 | const renderComment = (comment, reply = null, index) => { 53 | 54 | return ( 55 | {reply} 56 | ) 57 | }; 58 | 59 | export default Item; -------------------------------------------------------------------------------- /src/components/navigation/alerts-dropdown.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { 4 | NavDropdown, 5 | DropdownMenu, 6 | DropdownToggle, 7 | DropdownItem, 8 | Badge 9 | } from 'reactstrap'; 10 | 11 | const AlertsDropdown = ({isDropdownOpen, toogleDropdown}) => { 12 | return ( 13 | 14 | 15 | 16 | 17 | Alerts 18 | 6 New 19 | 20 | 21 | 22 | 6 23 | 24 | 25 | 26 | New Alerts: 27 | 28 | 29 | 30 | Status Update 31 | 32 | 11:21 AM 33 |
This is an automated server response message. All systems are online.
34 |
35 | 36 | 37 | 38 | Status Update 39 | 40 | 11:21 AM 41 |
This is an automated server response message. All systems are online.
42 |
43 |
44 |
45 | ) 46 | }; 47 | 48 | export default AlertsDropdown; -------------------------------------------------------------------------------- /src/components/navigation/header.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Nav, 4 | NavItem, 5 | NavLink, 6 | Form, 7 | InputGroup, 8 | Input, 9 | Button, 10 | } from 'reactstrap'; 11 | 12 | import AlertsDropdownContainer from '../../containers/alerts-dropdown-container'; 13 | import MessagesDropdownContainer from '../../containers/messages-dropdown-container'; 14 | 15 | const Header = () => { 16 | return ( 17 | 32 | ) 33 | }; 34 | 35 | export default Header; -------------------------------------------------------------------------------- /src/components/navigation/messages-dropdown.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { 4 | NavDropdown, 5 | DropdownMenu, 6 | DropdownToggle, 7 | DropdownItem, 8 | Badge 9 | } from 'reactstrap'; 10 | 11 | const MessagesDropdown = ({isDropdownOpen, toogleDropdown, messages}) => { 12 | return ( 13 | 14 | 15 | 16 | 17 | Messages 18 | 12 New 19 | 20 | 21 | 22 | 12 23 | 24 | 25 | 26 | 27 | New Messages: 28 | 29 | {renderMessages(messages)} 30 | 31 | 32 | ) 33 | }; 34 | 35 | const renderMessages = messages => { 36 | return messages.map((message, index) => 37 | 38 | {message.sender} 39 | {message.date} 40 |
{message.text}
41 |
42 | ) 43 | }; 44 | 45 | export default MessagesDropdown; -------------------------------------------------------------------------------- /src/components/navigation/navigation.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { 4 | Navbar, 5 | NavbarToggler, 6 | NavbarBrand, 7 | Collapse 8 | } from 'reactstrap'; 9 | 10 | import Sidebar from './sidebar'; 11 | import Header from './header'; 12 | 13 | const Navigation = ({isOpen, toogleNavbar}) => { 14 | return ( 15 | 16 | SB Admin React 17 | 18 | 19 | 20 |
21 | 22 | 23 | ) 24 | }; 25 | 26 | export default Navigation; -------------------------------------------------------------------------------- /src/components/navigation/sidebar-item.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { 4 | NavItem, 5 | NavLink 6 | } from 'reactstrap'; 7 | 8 | const SidebarItem = ({title, icon, href = '/'}) => { 9 | return ( 10 | 11 | 12 | 13 | {title} 14 | 15 | 16 | ) 17 | }; 18 | 19 | export default SidebarItem; -------------------------------------------------------------------------------- /src/components/navigation/sidebar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {Nav} from 'reactstrap'; 4 | 5 | import SidebarItem from './sidebar-item'; 6 | 7 | const Sidebar = () => { 8 | return ( 9 | 14 | ); 15 | }; 16 | 17 | export default Sidebar; -------------------------------------------------------------------------------- /src/components/pages/admin.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Container} from 'reactstrap'; 3 | 4 | import Dashboard from './dashboard'; 5 | import NavigationContainer from '../../containers/navigation-container'; 6 | 7 | const Admin = () => { 8 | return ( 9 |
10 | 11 |
12 | 13 | 14 | 15 |
16 |
17 | ) 18 | }; 19 | 20 | export default Admin; -------------------------------------------------------------------------------- /src/components/pages/dashboard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Row, Col} from 'reactstrap' 3 | 4 | import Feed from "../dashboard/feed/feed"; 5 | import Charts from "../dashboard/charts"; 6 | import IconCard from "../ui/icon-card"; 7 | 8 | const Dashboard = () => { 9 | return ( 10 |
11 | 12 | {renderIconCards()} 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | ) 24 | }; 25 | 26 | const renderIconCards = () => { 27 | return iconCardsMessages.map((message, index) => { 28 | return 29 | }); 30 | }; 31 | 32 | const iconCardsMessages = [ 33 | { 34 | bgColorClass: 'bg-primary', 35 | icon: 'fa fa-fw fa-comments', 36 | text: '26 New Messages!', 37 | buttonText: 'View Details' 38 | }, 39 | { 40 | bgColorClass: 'bg-warning', 41 | icon: 'fa fa-fw fa-list', 42 | text: '11 New Tasks!', 43 | buttonText: 'View Details' 44 | }, 45 | { 46 | bgColorClass: 'bg-success', 47 | icon: 'fa fa-fw fa-shopping-cart', 48 | text: '123 New Orders!', 49 | buttonText: 'View Details' 50 | }, 51 | { 52 | bgColorClass: 'bg-danger', 53 | icon: 'fa fa-fw fa-support', 54 | text: '13 New Tickets!', 55 | buttonText: 'View Details' 56 | } 57 | ]; 58 | 59 | export default Dashboard; -------------------------------------------------------------------------------- /src/components/pages/forgot-password.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Link} from 'react-router-dom'; 3 | 4 | import { 5 | Card, 6 | CardBody, 7 | CardHeader, 8 | Form, 9 | Input, 10 | Label, 11 | FormGroup, 12 | Button 13 | } from 'reactstrap'; 14 | 15 | const ForgotPassword = () => { 16 | return ( 17 | 18 | Reset Password 19 | 20 |
21 |

Forgot your password?

22 |

Enter your email address and we will send you instructions on how to reset your password.

23 |
24 |
25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 | Register an Account 33 | Login 34 |
35 |
36 |
37 | ) 38 | }; 39 | 40 | export default ForgotPassword; -------------------------------------------------------------------------------- /src/components/pages/login.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Link} from 'react-router-dom'; 3 | import { 4 | Card, 5 | CardBody, 6 | CardHeader, 7 | Form, 8 | Input, 9 | Label, 10 | FormGroup, 11 | Button 12 | } from 'reactstrap'; 13 | 14 | const Login = () => { 15 | return ( 16 | 17 | Login 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
31 | Register an Account 32 | Forgot Password? 33 |
34 |
35 |
36 | ) 37 | }; 38 | 39 | export default Login; -------------------------------------------------------------------------------- /src/components/pages/register.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Link} from 'react-router-dom'; 3 | import { 4 | Card, 5 | CardBody, 6 | CardHeader, 7 | Form, 8 | Input, 9 | Label, 10 | FormGroup, 11 | Button, 12 | Col 13 | } from 'reactstrap'; 14 | 15 | const Register = () => { 16 | return ( 17 | 18 | Register an Account 19 | 20 |
21 | 22 |
23 | 24 | 25 | 26 | 27 |
28 |
29 | 30 |
31 | 32 | 33 | 34 | 35 |
36 |
37 | 38 |
39 | 40 | 41 | 42 | 43 |
44 |
45 | 46 |
47 | 48 | 49 | 50 | 51 |
52 |
53 | 54 |
55 | 56 | 57 | 58 | 59 |
60 |
61 | 62 |
63 |
64 | Login 65 | Forgot Password? 66 |
67 |
68 |
69 | ) 70 | }; 71 | 72 | export default Register; -------------------------------------------------------------------------------- /src/components/ui/card-box.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Card, CardFooter, CardHeader, CardBody} from 'reactstrap'; 3 | 4 | const CardBox = ({icon, title, children, footer}) => { 5 | return ( 6 | 7 | 8 | 9 | {" " + title} 10 | 11 | {children} 12 | {footer} 13 | 14 | ) 15 | }; 16 | 17 | export default CardBox; -------------------------------------------------------------------------------- /src/components/ui/icon-card.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Card, CardBody, CardFooter} from 'reactstrap' 3 | 4 | const IconCard = ({bgColorClass, icon, text, buttonText}) => { 5 | return ( 6 | 7 | 8 |
9 | 10 |
11 |
12 | {text} 13 |
14 |
15 | 16 | {buttonText} 17 | 18 | 19 | 20 | 21 |
22 | ) 23 | }; 24 | 25 | export default IconCard; 26 | -------------------------------------------------------------------------------- /src/containers/alerts-dropdown-container.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import AlertsDropdown from '../components/navigation/alerts-dropdown'; 3 | 4 | class AlertsDropdownContainer extends Component { 5 | 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | isDropdownOpen: false 10 | }; 11 | } 12 | 13 | toggleDropdown() { 14 | this.setState({ 15 | isDropdownOpen: !this.state.isDropdownOpen 16 | }); 17 | } 18 | 19 | render() { 20 | return ( 21 | 25 | ) 26 | } 27 | } 28 | 29 | export default AlertsDropdownContainer; -------------------------------------------------------------------------------- /src/containers/messages-dropdown-container.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import MessagesDropdown from '../components/navigation/messages-dropdown'; 3 | 4 | class MessagesDropdownContainer extends Component { 5 | 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | isDropdownOpen: false 10 | }; 11 | } 12 | 13 | toggleMessagesDropdown() { 14 | this.setState({ 15 | isDropdownOpen: !this.state.isDropdownOpen 16 | }); 17 | } 18 | 19 | render() { 20 | const messages = [ 21 | { 22 | sender: 'David Miller', 23 | date: '11: 21 AM', 24 | text: 'Hey there! This new version of SB Admin is pretty awesome!' 25 | } 26 | ]; 27 | return ( 28 | 33 | ) 34 | } 35 | } 36 | 37 | export default MessagesDropdownContainer; -------------------------------------------------------------------------------- /src/containers/navigation-container.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | 3 | 4 | import Navigation from '../components/navigation/navigation'; 5 | 6 | 7 | export default class NavigationContainer extends Component { 8 | constructor(props) { 9 | super(props); 10 | this.state = { 11 | isOpen: false 12 | }; 13 | } 14 | 15 | toggleNavbar() { 16 | this.setState({ 17 | isOpen: !this.state.isOpen 18 | }); 19 | } 20 | 21 | render() { 22 | return ( 23 | 24 | ) 25 | } 26 | } -------------------------------------------------------------------------------- /src/css/index.css: -------------------------------------------------------------------------------- 1 | @import "../../node_modules/bootstrap/dist/css/bootstrap.css"; 2 | @import "../../node_modules/font-awesome/css/font-awesome.min.css"; 3 | @import "sb-admin.css"; 4 | 5 | .navbar-brand-title { 6 | color: #fff !important; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /src/css/sb-admin.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - SB Admin v4.0.0-beta (https://startbootstrap.com/template-overviews/sb-admin) 3 | * Copyright 2013-2017 Start Bootstrap 4 | * Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap-sb-admin/blob/master/LICENSE) 5 | */ 6 | html { 7 | position: relative; 8 | min-height: 100%; } 9 | 10 | body.sticky-footer { 11 | margin-bottom: 56px; } 12 | body.sticky-footer .content-wrapper { 13 | min-height: calc(100vh - 56px - 56px); } 14 | 15 | body.fixed-nav { 16 | padding-top: 56px; } 17 | 18 | .content-wrapper { 19 | min-height: calc(100vh - 56px); 20 | padding-top: 1rem; } 21 | 22 | .scroll-to-top { 23 | position: fixed; 24 | right: 15px; 25 | bottom: 3px; 26 | display: none; 27 | width: 50px; 28 | height: 50px; 29 | text-align: center; 30 | color: white; 31 | background: rgba(52, 58, 64, 0.5); 32 | line-height: 45px; } 33 | .scroll-to-top:focus, .scroll-to-top:hover { 34 | color: white; } 35 | .scroll-to-top:hover { 36 | background: #343a40; } 37 | .scroll-to-top i { 38 | font-weight: 800; } 39 | 40 | .smaller { 41 | font-size: 0.7rem; } 42 | 43 | .o-hidden { 44 | overflow: hidden !important; } 45 | 46 | .z-0 { 47 | z-index: 0; } 48 | 49 | .z-1 { 50 | z-index: 1; } 51 | 52 | .card-body-icon { 53 | position: absolute; 54 | z-index: 0; 55 | top: -25px; 56 | right: -25px; 57 | font-size: 5rem; 58 | -webkit-transform: rotate(15deg); 59 | -ms-transform: rotate(15deg); 60 | transform: rotate(15deg); } 61 | 62 | @media (min-width: 576px) { 63 | .card-columns { 64 | column-count: 1; } } 65 | 66 | @media (min-width: 768px) { 67 | .card-columns { 68 | column-count: 2; } } 69 | 70 | @media (min-width: 1200px) { 71 | .card-columns { 72 | column-count: 2; } } 73 | 74 | #mainNav .navbar-collapse { 75 | overflow: auto; 76 | max-height: 75vh; } 77 | #mainNav .navbar-collapse .navbar-nav .nav-item .nav-link { 78 | cursor: pointer; } 79 | #mainNav .navbar-collapse .navbar-sidenav .nav-link-collapse:after { 80 | float: right; 81 | content: '\f107'; 82 | font-family: 'FontAwesome'; } 83 | #mainNav .navbar-collapse .navbar-sidenav .nav-link-collapse.collapsed:after { 84 | content: '\f105'; } 85 | #mainNav .navbar-collapse .navbar-sidenav .sidenav-second-level, 86 | #mainNav .navbar-collapse .navbar-sidenav .sidenav-third-level { 87 | padding-left: 0; } 88 | #mainNav .navbar-collapse .navbar-sidenav .sidenav-second-level > li > a, 89 | #mainNav .navbar-collapse .navbar-sidenav .sidenav-third-level > li > a { 90 | display: block; 91 | padding: 0.5em 0; } 92 | #mainNav .navbar-collapse .navbar-sidenav .sidenav-second-level > li > a:focus, #mainNav .navbar-collapse .navbar-sidenav .sidenav-second-level > li > a:hover, 93 | #mainNav .navbar-collapse .navbar-sidenav .sidenav-third-level > li > a:focus, 94 | #mainNav .navbar-collapse .navbar-sidenav .sidenav-third-level > li > a:hover { 95 | text-decoration: none; } 96 | #mainNav .navbar-collapse .navbar-sidenav .sidenav-second-level > li > a { 97 | padding-left: 1em; } 98 | #mainNav .navbar-collapse .navbar-sidenav .sidenav-third-level > li > a { 99 | padding-left: 2em; } 100 | #mainNav .navbar-collapse .sidenav-toggler { 101 | display: none; } 102 | #mainNav .navbar-collapse .navbar-nav > .nav-item.dropdown > .nav-link { 103 | position: relative; 104 | min-width: 45px; } 105 | #mainNav .navbar-collapse .navbar-nav > .nav-item.dropdown > .nav-link:after { 106 | float: right; 107 | width: auto; 108 | content: '\f105'; 109 | border: none; 110 | font-family: 'FontAwesome'; } 111 | #mainNav .navbar-collapse .navbar-nav > .nav-item.dropdown > .nav-link .new-indicator { 112 | position: absolute; 113 | top: 0; 114 | right: 25px; 115 | font-size: 1.1rem; } 116 | #mainNav .navbar-collapse .navbar-nav > .nav-item.dropdown > .nav-link .new-indicator .number { 117 | position: absolute; 118 | top: 6px; 119 | left: 0; 120 | width: 22.625px; 121 | text-align: center; 122 | color: white; 123 | font-size: 0.5rem; } 124 | #mainNav .navbar-collapse .navbar-nav > .nav-item.dropdown.show > .nav-link:after { 125 | content: '\f107'; } 126 | #mainNav .navbar-collapse .navbar-nav > .nav-item.dropdown .dropdown-menu > .dropdown-item > .dropdown-message { 127 | overflow: hidden; 128 | max-width: none; 129 | text-overflow: ellipsis; } 130 | 131 | @media (min-width: 992px) { 132 | #mainNav .navbar-brand { 133 | width: 250px; } 134 | #mainNav .navbar-collapse { 135 | overflow: visible; 136 | max-height: none; } 137 | #mainNav .navbar-collapse .navbar-sidenav { 138 | position: absolute; 139 | top: 0; 140 | left: 0; 141 | overflow-x: hidden; 142 | overflow-y: auto; 143 | -webkit-flex-direction: column; 144 | -ms-flex-direction: column; 145 | flex-direction: column; 146 | margin-top: 56px; } 147 | #mainNav .navbar-collapse .navbar-sidenav > .nav-item { 148 | width: 250px; 149 | padding: 0; } 150 | #mainNav .navbar-collapse .navbar-sidenav > .nav-item > .nav-link { 151 | padding: 1em; } 152 | #mainNav .navbar-collapse .navbar-sidenav > .nav-item .sidenav-second-level, 153 | #mainNav .navbar-collapse .navbar-sidenav > .nav-item .sidenav-third-level { 154 | padding-left: 0; 155 | list-style: none; } 156 | #mainNav .navbar-collapse .navbar-sidenav > .nav-item .sidenav-second-level > li, 157 | #mainNav .navbar-collapse .navbar-sidenav > .nav-item .sidenav-third-level > li { 158 | width: 250px; } 159 | #mainNav .navbar-collapse .navbar-sidenav > .nav-item .sidenav-second-level > li > a, 160 | #mainNav .navbar-collapse .navbar-sidenav > .nav-item .sidenav-third-level > li > a { 161 | padding: 1em; } 162 | #mainNav .navbar-collapse .navbar-sidenav > .nav-item .sidenav-second-level > li > a { 163 | padding-left: 2em; } 164 | #mainNav .navbar-collapse .navbar-sidenav > .nav-item .sidenav-third-level > li > a { 165 | padding-left: 3em; } 166 | #mainNav .navbar-collapse .navbar-nav > .nav-item.dropdown > .nav-link { 167 | min-width: 0; } 168 | #mainNav .navbar-collapse .navbar-nav > .nav-item.dropdown > .nav-link:after { 169 | width: 24px; 170 | text-align: center; } 171 | #mainNav .navbar-collapse .navbar-nav > .nav-item.dropdown .dropdown-menu > .dropdown-item > .dropdown-message { 172 | max-width: 300px; } } 173 | 174 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav .nav-link-collapse:after { 175 | color: #868e96; } 176 | 177 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav > .nav-item > .nav-link { 178 | color: #868e96; } 179 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav > .nav-item > .nav-link:hover { 180 | color: #adb5bd; } 181 | 182 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav > .nav-item .sidenav-second-level > li > a, 183 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav > .nav-item .sidenav-third-level > li > a { 184 | color: #868e96; } 185 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav > .nav-item .sidenav-second-level > li > a:focus, #mainNav.navbar-dark .navbar-collapse .navbar-sidenav > .nav-item .sidenav-second-level > li > a:hover, 186 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav > .nav-item .sidenav-third-level > li > a:focus, 187 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav > .nav-item .sidenav-third-level > li > a:hover { 188 | color: #adb5bd; } 189 | 190 | #mainNav.navbar-dark .navbar-collapse .navbar-nav > .nav-item.dropdown > .nav-link:after { 191 | color: #adb5bd; } 192 | 193 | @media (min-width: 992px) { 194 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav { 195 | background: #343a40; } 196 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav li.active a { 197 | color: white !important; 198 | background-color: #495057; } 199 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav li.active a:focus, #mainNav.navbar-dark .navbar-collapse .navbar-sidenav li.active a:hover { 200 | color: white; } 201 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav > .nav-item .sidenav-second-level, 202 | #mainNav.navbar-dark .navbar-collapse .navbar-sidenav > .nav-item .sidenav-third-level { 203 | background: #343a40; } } 204 | 205 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav .nav-link-collapse:after { 206 | color: rgba(0, 0, 0, 0.5); } 207 | 208 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav > .nav-item > .nav-link { 209 | color: rgba(0, 0, 0, 0.5); } 210 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav > .nav-item > .nav-link:hover { 211 | color: rgba(0, 0, 0, 0.7); } 212 | 213 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav > .nav-item .sidenav-second-level > li > a, 214 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav > .nav-item .sidenav-third-level > li > a { 215 | color: rgba(0, 0, 0, 0.5); } 216 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav > .nav-item .sidenav-second-level > li > a:focus, #mainNav.navbar-light .navbar-collapse .navbar-sidenav > .nav-item .sidenav-second-level > li > a:hover, 217 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav > .nav-item .sidenav-third-level > li > a:focus, 218 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav > .nav-item .sidenav-third-level > li > a:hover { 219 | color: rgba(0, 0, 0, 0.7); } 220 | 221 | #mainNav.navbar-light .navbar-collapse .navbar-nav > .nav-item.dropdown > .nav-link:after { 222 | color: rgba(0, 0, 0, 0.5); } 223 | 224 | @media (min-width: 992px) { 225 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav { 226 | background: #f8f9fa; } 227 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav li.active a { 228 | color: #000 !important; 229 | background-color: #e9ecef; } 230 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav li.active a:focus, #mainNav.navbar-light .navbar-collapse .navbar-sidenav li.active a:hover { 231 | color: #000; } 232 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav > .nav-item .sidenav-second-level, 233 | #mainNav.navbar-light .navbar-collapse .navbar-sidenav > .nav-item .sidenav-third-level { 234 | background: #f8f9fa; } } 235 | 236 | #mainNav.fixed-top .sidenav-toggler { 237 | display: none; } 238 | 239 | @media (min-width: 992px) { 240 | #mainNav.fixed-top .navbar-sidenav { 241 | height: calc(100vh - 112px); } 242 | #mainNav.fixed-top .sidenav-toggler { 243 | position: absolute; 244 | top: 0; 245 | left: 0; 246 | display: flex; 247 | overflow-x: hidden; 248 | overflow-y: auto; 249 | -webkit-flex-direction: column; 250 | -ms-flex-direction: column; 251 | flex-direction: column; 252 | margin-top: calc(100vh - 56px); } 253 | #mainNav.fixed-top .sidenav-toggler > .nav-item { 254 | width: 250px; 255 | padding: 0; } 256 | #mainNav.fixed-top .sidenav-toggler > .nav-item > .nav-link { 257 | padding: 1em; } } 258 | 259 | #mainNav.fixed-top.navbar-dark .sidenav-toggler { 260 | background-color: #212529; } 261 | #mainNav.fixed-top.navbar-dark .sidenav-toggler a i { 262 | color: #adb5bd; } 263 | 264 | #mainNav.fixed-top.navbar-light .sidenav-toggler { 265 | background-color: #dee2e6; } 266 | #mainNav.fixed-top.navbar-light .sidenav-toggler a i { 267 | color: rgba(0, 0, 0, 0.5); } 268 | 269 | body.sidenav-toggled #mainNav.fixed-top .sidenav-toggler { 270 | overflow-x: hidden; 271 | width: 55px; } 272 | body.sidenav-toggled #mainNav.fixed-top .sidenav-toggler .nav-item, 273 | body.sidenav-toggled #mainNav.fixed-top .sidenav-toggler .nav-link { 274 | width: 55px !important; } 275 | 276 | body.sidenav-toggled #mainNav.fixed-top #sidenavToggler i { 277 | -webkit-transform: scaleX(-1); 278 | -moz-transform: scaleX(-1); 279 | -o-transform: scaleX(-1); 280 | transform: scaleX(-1); 281 | filter: FlipH; 282 | -ms-filter: 'FlipH'; } 283 | 284 | #mainNav.static-top .sidenav-toggler { 285 | display: none; } 286 | 287 | @media (min-width: 992px) { 288 | #mainNav.static-top .sidenav-toggler { 289 | display: flex; } } 290 | 291 | body.sidenav-toggled #mainNav.static-top #sidenavToggler i { 292 | -webkit-transform: scaleX(-1); 293 | -moz-transform: scaleX(-1); 294 | -o-transform: scaleX(-1); 295 | transform: scaleX(-1); 296 | filter: FlipH; 297 | -ms-filter: 'FlipH'; } 298 | 299 | .content-wrapper { 300 | overflow-x: hidden; 301 | background: white; } 302 | @media (min-width: 992px) { 303 | .content-wrapper { 304 | margin-left: 250px; } } 305 | 306 | #sidenavToggler i { 307 | font-weight: 800; } 308 | 309 | .navbar-sidenav-tooltip.show { 310 | display: none; } 311 | 312 | @media (min-width: 992px) { 313 | body.sidenav-toggled .content-wrapper { 314 | margin-left: 55px; } } 315 | 316 | body.sidenav-toggled .navbar-sidenav { 317 | overflow-x: hidden; 318 | width: 55px; } 319 | body.sidenav-toggled .navbar-sidenav .nav-link-text { 320 | display: none; } 321 | body.sidenav-toggled .navbar-sidenav .nav-item, 322 | body.sidenav-toggled .navbar-sidenav .nav-link { 323 | width: 55px !important; } 324 | body.sidenav-toggled .navbar-sidenav .nav-item:after, 325 | body.sidenav-toggled .navbar-sidenav .nav-link:after { 326 | display: none; } 327 | 328 | body.sidenav-toggled .navbar-sidenav-tooltip.show { 329 | display: flex; } 330 | 331 | .card-login { 332 | max-width: 25rem; } 333 | 334 | .card-register { 335 | max-width: 40rem; } 336 | 337 | footer.sticky-footer { 338 | position: absolute; 339 | right: 0; 340 | bottom: 0; 341 | width: 100%; 342 | height: 56px; 343 | background-color: #e9ecef; 344 | line-height: 55px; } 345 | @media (min-width: 992px) { 346 | footer.sticky-footer { 347 | width: calc(100% - 250px); } } 348 | 349 | @media (min-width: 992px) { 350 | body.sidenav-toggled footer.sticky-footer { 351 | width: calc(100% - 55px); } } 352 | -------------------------------------------------------------------------------- /src/data/charts.js: -------------------------------------------------------------------------------- 1 | export const LineChart = { 2 | data: { 3 | labels: ["Mar 1", "Mar 2", "Mar 3", "Mar 4", "Mar 5", "Mar 6", "Mar 7", "Mar 8", "Mar 9", "Mar 10", "Mar 11", "Mar 12", "Mar 13"], 4 | datasets: [{ 5 | label: "Sessions", 6 | lineTension: 0.3, 7 | pointRadius: 5, 8 | pointHoverRadius: 5, 9 | pointHitRadius: 20, 10 | pointBorderWidth: 2, 11 | data: [10000, 30162, 26263, 18394, 18287, 28682, 31274, 33259, 25849, 24159, 32651, 31984, 38451], 12 | }], 13 | }, 14 | options: { 15 | scales: { 16 | xAxes: [{ 17 | time: { 18 | unit: 'date' 19 | }, 20 | gridLines: { 21 | display: false 22 | }, 23 | ticks: { 24 | maxTicksLimit: 7 25 | } 26 | }], 27 | yAxes: [{ 28 | ticks: { 29 | min: 0, 30 | max: 40000, 31 | maxTicksLimit: 5 32 | }, 33 | }], 34 | }, 35 | legend: { 36 | display: false 37 | } 38 | } 39 | }; 40 | 41 | export const BarChart = { 42 | data: { 43 | labels: ["January", "February", "March", "April", "May", "June"], 44 | datasets: [{ 45 | label: "Revenue", 46 | data: [4215, 5312, 6251, 7841, 9821, 14984], 47 | }], 48 | }, 49 | options: { 50 | scales: { 51 | xAxes: [{ 52 | time: { 53 | unit: 'month' 54 | }, 55 | gridLines: { 56 | display: false 57 | }, 58 | ticks: { 59 | maxTicksLimit: 6 60 | } 61 | }], 62 | yAxes: [{ 63 | ticks: { 64 | min: 0, 65 | max: 15000, 66 | maxTicksLimit: 5 67 | }, 68 | gridLines: { 69 | display: true 70 | } 71 | }], 72 | }, 73 | legend: { 74 | display: true 75 | } 76 | } 77 | }; -------------------------------------------------------------------------------- /src/data/feed-items.js: -------------------------------------------------------------------------------- 1 | export const feedItems = [ 2 | { 3 | photo: 'https://unsplash.it/700/450?image=610', 4 | user: 'David Miller', 5 | description: 'These waves are looking pretty good today!', 6 | tags: ['#surfsup', '#react'], 7 | date: 'Posted 32 mins ago', 8 | comments: [ 9 | { 10 | user: "John Smith", 11 | text: "Very nice! I wish I was there! That looks amazing!", 12 | src: "http://placehold.it/45x45", 13 | reply: { 14 | user: "David Miller", 15 | text: "Next time for sure!", 16 | src: "http://placehold.it/45x45", 17 | } 18 | } 19 | ] 20 | }, 21 | { 22 | photo: 'https://unsplash.it/700/450?image=180', 23 | user: 'John Smith', 24 | description: 'Another day at the office...', 25 | tags: ['#workinghardorhardlyworking'], 26 | date: 'Posted 46 mins ago', 27 | comments: [ 28 | { 29 | user: "Jessy Lucas", 30 | text: " Where did you get that camera?! I want one!", 31 | src: "http://placehold.it/45x45" 32 | } 33 | ] 34 | }, 35 | { 36 | photo: 'https://unsplash.it/700/450?image=281', 37 | user: 'Jeffery Wellings', 38 | description: 'Nice shot from the skate park!', 39 | tags: ['#kickflip', "#holdmybeer", "#igotthis"], 40 | date: 'Posted 1 hr ago', 41 | comments: [] 42 | }, 43 | { 44 | photo: 'https://unsplash.it/700/450?image=185', 45 | user: 'David Miller', 46 | description: 'It\'s hot, and I might be lost...', 47 | tags: ['#desert', '#water', '#anyonehavesomewater', '#noreally', '#thirsty', '#dehydration'], 48 | date: 'Posted 1 hr ago', 49 | comments: [ 50 | { 51 | user: "John Smith", 52 | photo: "http://placehold.it/45x45", 53 | text: "The oasis is a mile that way, or is that just a mirage?" 54 | } 55 | ] 56 | }, 57 | ]; -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './components/app'; 4 | 5 | import './css/index.css'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | --------------------------------------------------------------------------------