├── 14-ParcelJs ├── src │ ├── App.css │ ├── index.js │ └── App.js └── index.html ├── 17-React.Children ├── src │ ├── App.css │ ├── index.js │ ├── SlideShow.js │ ├── App.js │ ├── SlideShow.css │ └── SlideShow-Finished.js └── index.html ├── 15-Fetching ├── src │ ├── App.css │ ├── index.js │ ├── SearchBar.js │ ├── App.js │ ├── Users.css │ ├── Users.js │ ├── UserList.js │ └── App-Finished.js └── index.html ├── 16-Higher-Order-Component ├── src │ ├── App.css │ ├── index.js │ ├── Loading.js │ ├── SearchBar.js │ ├── Users.css │ ├── Loading-Finished.js │ ├── Users.js │ ├── UserList.js │ ├── App.js │ └── Loading.css └── index.html ├── .babelrc ├── 12-create-react-app ├── src │ ├── index.css │ ├── index.js │ ├── List.js │ ├── Todo.js │ └── Todo.css ├── public │ ├── favicon.ico │ └── index.html ├── .gitignore └── package.json ├── 13-Firebase-rebase ├── src │ ├── index.css │ ├── index.js │ ├── re-base.js │ ├── List.js │ ├── Todo.js │ ├── Todo-Finished.js │ └── Todo.css ├── public │ ├── favicon.ico │ └── index.html ├── .gitignore └── package.json ├── 24-Lazy ├── src │ ├── index.js │ ├── User.js │ └── App.js └── index.html ├── 18-Toggler ├── src │ ├── index.js │ ├── Toggle.js │ ├── Toggle-Finished.js │ ├── Switch.js │ └── App.css └── index.html ├── 21-Context ├── src │ ├── index.js │ ├── Switch.js │ ├── Toggle.js │ ├── Toggle-Finished.js │ └── App.css └── index.html ├── 22-Render-Props ├── src │ ├── index.js │ ├── Toggle.js │ ├── Toggle-Finished.js │ ├── Switch.js │ └── App.css └── index.html ├── 19-Toggler-Composed ├── src │ ├── index.js │ ├── Toggle.js │ ├── Switch.js │ ├── Toggle-Finished.js │ └── App.css └── index.html ├── 20-Compound-Components ├── src │ ├── index.js │ ├── Switch.js │ ├── Toggle.js │ ├── Toggle-Finished.js │ └── App.css └── index.html ├── HELP.md ├── 23-HOC-Vs-RenderProps ├── src │ ├── index.js │ ├── App.js │ ├── App-HOC.js │ ├── App-RenderProps.js │ └── App-Cool.js └── index.html ├── 01-Hello-World ├── index-start.html └── index-finished.html ├── 06-Rerender ├── index-start.html └── index-finished.html ├── 05-Conditional-Render ├── index-start.html └── index-finished.html ├── 02-JSX ├── index-start.html └── index-finished.html ├── 04-propTypes ├── index-start.html └── index-finished.html ├── 03-Functional-Components ├── index-start.html └── index-finished.html ├── 10-Todo-App ├── index-start.js ├── index.html ├── index-finished.js └── css │ └── styles.css ├── package.json ├── .gitignore ├── Requirements.md ├── 09-Event-Handling ├── index-start.html └── index-finished.html ├── 11-Component-Patterns ├── index.html ├── index-start.js ├── index-finished.js └── css │ └── styles.css ├── 07-Styling └── index.html ├── 08-Component & Lifecycle └── index.html ├── .eslintrc └── README.md /14-ParcelJs/src/App.css: -------------------------------------------------------------------------------- 1 | .Main { 2 | color: rebeccapurple; 3 | } -------------------------------------------------------------------------------- /17-React.Children/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | -------------------------------------------------------------------------------- /15-Fetching/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | width: 400px; 3 | margin: auto; 4 | } 5 | -------------------------------------------------------------------------------- /16-Higher-Order-Component/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | width: 400px; 3 | margin: auto; 4 | } 5 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env", "react", "stage-2"], 3 | "plugins": ["transform-decorators-legacy"] 4 | } 5 | -------------------------------------------------------------------------------- /12-create-react-app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /13-Firebase-rebase/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /13-Firebase-rebase/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vigzmv/Into-the-ReactJs/HEAD/13-Firebase-rebase/public/favicon.ico -------------------------------------------------------------------------------- /12-create-react-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vigzmv/Into-the-ReactJs/HEAD/12-create-react-app/public/favicon.ico -------------------------------------------------------------------------------- /24-Lazy/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render(, document.getElementById('root')); 6 | -------------------------------------------------------------------------------- /14-ParcelJs/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render(, document.getElementById('root')); 6 | -------------------------------------------------------------------------------- /15-Fetching/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render(, document.getElementById('root')); 6 | -------------------------------------------------------------------------------- /17-React.Children/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render(, document.getElementById('root')); 6 | -------------------------------------------------------------------------------- /16-Higher-Order-Component/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render(, document.getElementById('root')); 6 | -------------------------------------------------------------------------------- /18-Toggler/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Toggle from './Toggle'; 4 | import './App.css'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /21-Context/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Toggle from './Toggle'; 4 | import './App.css'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /12-create-react-app/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import Todo from './Todo'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /13-Firebase-rebase/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import Todo from './Todo'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /22-Render-Props/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Toggle from './Toggle'; 4 | import './App.css'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /19-Toggler-Composed/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Toggle from './Toggle'; 4 | import './App.css'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /20-Compound-Components/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Toggle from './Toggle'; 4 | import './App.css'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /HELP.md: -------------------------------------------------------------------------------- 1 | #### Browser-sync server with live reloading 2 | 3 | ```sh 4 | # Install browser-sync 5 | $ sudo npm i -g browser-sync 6 | 7 | # Run browser-sync server 8 | $ browser-sync start --server --files "**/**" --no-notify --directory 9 | ``` 10 | -------------------------------------------------------------------------------- /14-ParcelJs/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import './App.css'; 3 | 4 | class App extends Component { 5 | render() { 6 | return
Hello World!
; 7 | } 8 | } 9 | 10 | export default App; 11 | -------------------------------------------------------------------------------- /18-Toggler/src/Toggle.js: -------------------------------------------------------------------------------- 1 | // state changing, defaultProps 2 | 3 | import React from 'react'; 4 | import Switch from './Switch'; 5 | 6 | class Toggle extends React.Component { 7 | render() { 8 | return ; 9 | } 10 | } 11 | export default Toggle; 12 | -------------------------------------------------------------------------------- /16-Higher-Order-Component/src/Loading.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import './Loading.css'; 3 | 4 | const isEmpty = prop => 5 | prop === null || 6 | prop === undefined || 7 | (prop.hasOwnProperty('length') && prop.length === 0) || 8 | (prop.constructor === Object && Object.keys(prop).length === 0); 9 | -------------------------------------------------------------------------------- /23-HOC-Vs-RenderProps/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | // import App from './App-HOC'; 6 | // import App from './App-RenderProps'; 7 | // import App from './App-Cool'; 8 | 9 | ReactDOM.render(, document.getElementById('root')); 10 | -------------------------------------------------------------------------------- /17-React.Children/src/SlideShow.js: -------------------------------------------------------------------------------- 1 | import React, { Component, Children } from 'react'; 2 | // import ReactCSSTransitionGroup from 'react-addons-css-transition-group'; 3 | import './SlideShow.css'; 4 | 5 | class SlideShow extends Component { 6 | render() { 7 | return
{this.props.children}
; 8 | } 9 | } 10 | 11 | export default SlideShow; 12 | -------------------------------------------------------------------------------- /15-Fetching/src/SearchBar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const getInput = event => event.target.value; 4 | 5 | const SearchBar = ({ filterText, onUserInput }) => ( 6 | onUserInput(getInput(event))} 11 | /> 12 | ); 13 | 14 | export default SearchBar; 15 | -------------------------------------------------------------------------------- /16-Higher-Order-Component/src/SearchBar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const getInput = event => event.target.value; 4 | 5 | const SearchBar = ({ filterText, onUserInput }) => ( 6 | onUserInput(getInput(event))} 11 | /> 12 | ); 13 | 14 | export default SearchBar; 15 | -------------------------------------------------------------------------------- /18-Toggler/src/Toggle-Finished.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Switch from './Switch'; 3 | 4 | class Toggle extends React.Component { 5 | state = { on: false }; 6 | 7 | toggle = () => this.setState({ on: !this.state.on }); 8 | 9 | render() { 10 | const { on } = this.state; 11 | return ; 12 | } 13 | } 14 | 15 | export default Toggle; 16 | -------------------------------------------------------------------------------- /12-create-react-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /13-Firebase-rebase/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /15-Fetching/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | User List 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /17-React.Children/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Slideshow 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /16-Higher-Order-Component/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | User List 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /15-Fetching/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Users from './Users'; 3 | import './App.css'; 4 | 5 | class App extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { users: [] }; 9 | } 10 | 11 | render() { 12 | return ( 13 |
14 | 15 |
16 | ); 17 | } 18 | } 19 | 20 | export default App; 21 | -------------------------------------------------------------------------------- /12-create-react-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "11-create-react-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "react": "^16.5.2", 7 | "react-dom": "^16.5.2", 8 | "react-scripts": "2.0.4" 9 | }, 10 | "scripts": { 11 | "start": "react-scripts start", 12 | "build": "react-scripts build", 13 | "test": "react-scripts test --env=jsdom", 14 | "eject": "react-scripts eject" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /14-ParcelJs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | React App 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /13-Firebase-rebase/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "11-create-react-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "re-base": "^3.2.1", 7 | "react": "^16.5.2", 8 | "react-dom": "^16.5.2", 9 | "react-scripts": "2.0.4" 10 | }, 11 | "scripts": { 12 | "start": "react-scripts start", 13 | "build": "react-scripts build", 14 | "test": "react-scripts test --env=jsdom", 15 | "eject": "react-scripts eject" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /19-Toggler-Composed/src/Toggle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Switch from './Switch'; 3 | 4 | class Toggle extends React.Component { 5 | state = { on: false }; 6 | 7 | toggle = () => this.setState({ on: !this.state.on }); 8 | 9 | render() { 10 | const { on } = this.state; 11 | return ( 12 |
13 | {' '} 14 |
15 | ); 16 | } 17 | } 18 | 19 | export default Toggle; 20 | -------------------------------------------------------------------------------- /13-Firebase-rebase/src/re-base.js: -------------------------------------------------------------------------------- 1 | const Rebase = require('re-base'); 2 | const firebase = require('firebase/app'); 3 | const database = require('firebase/database'); 4 | 5 | const app = firebase.initializeApp({ 6 | apiKey: 'AIzaSyA3qzYSGdBHYJc2O7tDAIhal3f1L14qd-s', 7 | authDomain: 'into-the-react.firebaseio.com', 8 | databaseURL: 'https://into-the-react.firebaseio.com/' 9 | }); 10 | const db = firebase.database(app); 11 | const base = Rebase.createClass(db); 12 | 13 | export default base; 14 | -------------------------------------------------------------------------------- /18-Toggler/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Toggler 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /21-Context/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Toggler 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /22-Render-Props/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Toggler 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /19-Toggler-Composed/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Toggler 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /20-Compound-Components/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Toggler 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /13-Firebase-rebase/src/List.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function List(props) { 4 | return props.list.map((item, i) => ( 5 |
  • 6 | props.onRemove(i)}> 7 | 8 | 9 | props.onComplete(i)}> 10 | 11 | 12 | {item.content} 13 |
  • 14 | )); 15 | } 16 | 17 | export default List; 18 | -------------------------------------------------------------------------------- /12-create-react-app/src/List.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function List(props) { 4 | return props.list.map((item, i) => ( 5 |
  • 6 | props.onRemove(i)}> 7 | 8 | 9 | props.onComplete(i)}> 10 | 11 | 12 | {item.content} 13 |
  • 14 | )); 15 | } 16 | 17 | export default List; 18 | -------------------------------------------------------------------------------- /22-Render-Props/src/Toggle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Switch from './Switch'; 3 | 4 | class Toggle extends React.Component { 5 | state = { on: false }; 6 | 7 | toggle = () => this.setState({ on: !this.state.on }); 8 | 9 | render() { 10 | const { on } = this.state; 11 | return ( 12 |
    13 | 14 |
    15 | ); 16 | } 17 | } 18 | 19 | function ToggleApp() { 20 | return ; 21 | } 22 | 23 | export default ToggleApp; 24 | -------------------------------------------------------------------------------- /17-React.Children/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import SlideShow from './SlideShow'; 3 | import './App.css'; 4 | 5 | class App extends Component { 6 | render() { 7 | return ( 8 |
    9 | 10 | Cat Pic 11 | Cat Pic 12 | Cat Pic 13 | 14 |
    15 | ); 16 | } 17 | } 18 | 19 | export default App; 20 | -------------------------------------------------------------------------------- /15-Fetching/src/Users.css: -------------------------------------------------------------------------------- 1 | .userApp { 2 | width: 400px; 3 | } 4 | 5 | .userApp > *{ 6 | width: 100%; 7 | } 8 | 9 | ul { 10 | padding: 0; 11 | } 12 | 13 | li { 14 | list-style: none; 15 | margin: 5px; 16 | background:rgb(213, 218, 248); 17 | 18 | } 19 | 20 | .userData { 21 | padding: 10px; 22 | height: 95px; 23 | border: solid rgb(177, 227, 247) 1px; 24 | text-transform: capitalize; 25 | } 26 | 27 | li img{ 28 | /* border-radius: 50%; */ 29 | margin-right: 20px; 30 | margin-left: 5px; 31 | margin-bottom: 5px; 32 | margin-top: 5px; 33 | float: left; 34 | } 35 | -------------------------------------------------------------------------------- /16-Higher-Order-Component/src/Users.css: -------------------------------------------------------------------------------- 1 | .userApp { 2 | width: 400px; 3 | } 4 | 5 | .userApp > *{ 6 | width: 100%; 7 | } 8 | 9 | ul { 10 | padding: 0; 11 | } 12 | 13 | li { 14 | list-style: none; 15 | margin: 5px; 16 | background:rgb(213, 218, 248); 17 | 18 | } 19 | 20 | .userData { 21 | padding: 10px; 22 | height: 95px; 23 | border: solid rgb(177, 227, 247) 1px; 24 | text-transform: capitalize; 25 | } 26 | 27 | li img{ 28 | /* border-radius: 50%; */ 29 | margin-right: 20px; 30 | margin-left: 5px; 31 | margin-bottom: 5px; 32 | margin-top: 5px; 33 | float: left; 34 | } 35 | -------------------------------------------------------------------------------- /24-Lazy/src/User.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const User = props => { 4 | const { user } = props; 5 | return ( 6 |
    7 | user 8 |

    {`${user.name.title} ${user.name.first} ${user.name.last}`}

    9 | 15 | Learn about React Lazy 16 | 17 |
    18 | ); 19 | }; 20 | 21 | export default User; 22 | -------------------------------------------------------------------------------- /17-React.Children/src/SlideShow.css: -------------------------------------------------------------------------------- 1 | .example-enter { 2 | opacity: 0.01; 3 | } 4 | 5 | .example-enter.example-enter-active { 6 | opacity: 1; 7 | transition: opacity 800ms ease-in; 8 | } 9 | 10 | .example-leave { 11 | opacity: 1; 12 | } 13 | 14 | .example-leave.example-leave-active { 15 | opacity: 0.01; 16 | transition: opacity 800ms ease-in; 17 | } 18 | 19 | .group { 20 | display: block; 21 | position: relative; 22 | width: 100%; 23 | height: 100%; 24 | } 25 | 26 | .group > * { 27 | position: absolute; 28 | top: 10px; 29 | left:0; 30 | right:0; 31 | margin-left:auto; 32 | margin-right:auto; 33 | } 34 | -------------------------------------------------------------------------------- /23-HOC-Vs-RenderProps/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | class Mouse extends React.Component { 4 | state = { x: 0, y: 0 }; 5 | 6 | handleMouseMove(event) { 7 | this.setState({ 8 | x: event.clientX, 9 | y: event.clientY 10 | }); 11 | } 12 | 13 | render() { 14 | const { x, y } = this.state; 15 | 16 | return ( 17 |
    18 |

    19 | The mouse position is ({x}, {y}) 20 |

    21 |
    22 | ); 23 | } 24 | } 25 | 26 | function App() { 27 | return ; 28 | } 29 | 30 | export default App; 31 | -------------------------------------------------------------------------------- /16-Higher-Order-Component/src/Loading-Finished.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import './Loading.css'; 3 | 4 | const isEmpty = prop => 5 | prop === null || 6 | prop === undefined || 7 | (prop.hasOwnProperty('length') && prop.length === 0) || 8 | (prop.constructor === Object && Object.keys(prop).length === 0); 9 | 10 | const Loading = loadingProp => WrappedComponent => 11 | class Loading extends Component { 12 | render() { 13 | return isEmpty(this.props[loadingProp]) ? ( 14 |
    15 | ) : ( 16 | 17 | ); 18 | } 19 | }; 20 | 21 | export default Loading; 22 | -------------------------------------------------------------------------------- /01-Hello-World/index-start.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 |
    9 | 10 | 20 | 21 | -------------------------------------------------------------------------------- /06-Rerender/index-start.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
    9 | 10 | 24 | -------------------------------------------------------------------------------- /15-Fetching/src/Users.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import SearchBar from './SearchBar'; 3 | import UserList from './UserList'; 4 | import './Users.css'; 5 | 6 | class Users extends Component { 7 | state = { 8 | filterText: '' 9 | }; 10 | 11 | handleUserInput = searchTerm => { 12 | this.setState({ filterText: searchTerm }); 13 | }; 14 | 15 | render() { 16 | return ( 17 |
    18 | 22 | 23 |
    24 | ); 25 | } 26 | } 27 | 28 | export default Users; 29 | -------------------------------------------------------------------------------- /05-Conditional-Render/index-start.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
    9 | 10 | 24 | -------------------------------------------------------------------------------- /02-JSX/index-start.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | 13 | 14 |
    15 | 16 | 24 | -------------------------------------------------------------------------------- /23-HOC-Vs-RenderProps/src/App-HOC.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const withMouse = Component => 4 | class Mouse extends React.Component { 5 | state = { x: 0, y: 0 }; 6 | 7 | handleMouseMove(event) { 8 | this.setState({ 9 | x: event.clientX, 10 | y: event.clientY 11 | }); 12 | } 13 | 14 | render() { 15 | return ( 16 |
    17 | 18 |
    19 | ); 20 | } 21 | }; 22 | 23 | function App(props) { 24 | return ( 25 |
    26 |

    27 | The mouse position is {props.mouse.x}, {props.mouse.y} 28 |

    29 |
    30 | ); 31 | } 32 | 33 | export default withMouse(App); 34 | -------------------------------------------------------------------------------- /23-HOC-Vs-RenderProps/src/App-RenderProps.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | class Mouse extends React.Component { 4 | state = { x: 0, y: 0 }; 5 | 6 | handleMouseMove(event) { 7 | this.setState({ 8 | x: event.clientX, 9 | y: event.clientY 10 | }); 11 | } 12 | 13 | render() { 14 | const { x, y } = this.state; 15 | 16 | return ( 17 |
    18 | {this.props.render(this.state)} 19 |
    20 | ); 21 | } 22 | } 23 | 24 | function App() { 25 | return ( 26 | ( 28 |
    29 |

    30 | The mouse position is {x}, {y} 31 |

    32 |
    33 | )} 34 | /> 35 | ); 36 | } 37 | 38 | export default App; 39 | -------------------------------------------------------------------------------- /04-propTypes/index-start.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
    10 | 11 | 26 | 27 | -------------------------------------------------------------------------------- /16-Higher-Order-Component/src/Users.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import SearchBar from './SearchBar'; 3 | import UserList from './UserList'; 4 | import './Users.css'; 5 | // import Loading from './Loading'; 6 | 7 | class Users extends Component { 8 | state = { 9 | filterText: '' 10 | }; 11 | 12 | handleUserInput = searchTerm => { 13 | this.setState({ filterText: searchTerm }); 14 | }; 15 | 16 | render() { 17 | return ( 18 |
    19 | 23 | 24 |
    25 | ); 26 | } 27 | } 28 | 29 | export default Users; 30 | // export default Loading('users')(Users); 31 | -------------------------------------------------------------------------------- /15-Fetching/src/UserList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const UserList = ({ users, filterText }) => { 4 | const filteredUsers = users.filter( 5 | user => user.name.indexOf(filterText) !== -1 6 | ); 7 | 8 | return ( 9 |
      10 | {filteredUsers.map(user => ( 11 |
    • 12 |
      13 | 14 | {user.name} 15 |
      16 | {user.username} 17 |
      18 | {user.email} 19 |
      20 | {user.phone} 21 |
      22 | 23 | {user.city}, {user.state} 24 | 25 |
      26 |
    • 27 | ))} 28 |
    29 | ); 30 | }; 31 | 32 | export default UserList; 33 | -------------------------------------------------------------------------------- /23-HOC-Vs-RenderProps/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | React App 9 | 10 | 33 | 34 | 35 | 36 |
    37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /22-Render-Props/src/Toggle-Finished.js: -------------------------------------------------------------------------------- 1 | // renderSwitch(), make it pure and move, inline it 2 | 3 | import React from 'react'; 4 | import Switch from './Switch'; 5 | 6 | class Toggle extends React.Component { 7 | state = { on: false }; 8 | 9 | toggle = () => this.setState({ on: !this.state.on }); 10 | 11 | render() { 12 | const { on } = this.state; 13 | return this.props.render({ on, toggle: this.toggle }); 14 | } 15 | } 16 | 17 | // const renderSwitch = ({ on, toggle }) => ; 18 | 19 | function ToggleApp() { 20 | return ( 21 | ( 24 |
    25 | {on ? 'It is Night' : 'It is Day'} 26 | 27 |
    28 | )} 29 | /> 30 | ); 31 | } 32 | 33 | export default ToggleApp; 34 | -------------------------------------------------------------------------------- /16-Higher-Order-Component/src/UserList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const UserList = ({ users, filterText }) => { 4 | const filteredUsers = users.filter( 5 | user => user.name.indexOf(filterText) !== -1 6 | ); 7 | 8 | return ( 9 |
      10 | {filteredUsers.map(user => ( 11 |
    • 12 |
      13 | 14 | {user.name} 15 |
      16 | {user.username} 17 |
      18 | {user.email} 19 |
      20 | {user.phone} 21 |
      22 | 23 | {user.city}, {user.state} 24 | 25 |
      26 |
    • 27 | ))} 28 |
    29 | ); 30 | }; 31 | 32 | export default UserList; 33 | -------------------------------------------------------------------------------- /18-Toggler/src/Switch.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Switch({ on, ...props }) { 4 | return ( 5 |
    6 | 13 | 26 |
    27 | ); 28 | } 29 | 30 | export default Switch; 31 | -------------------------------------------------------------------------------- /21-Context/src/Switch.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Switch({ on, ...props }) { 4 | return ( 5 |
    6 | 13 | 26 |
    27 | ); 28 | } 29 | 30 | export default Switch; 31 | -------------------------------------------------------------------------------- /22-Render-Props/src/Switch.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Switch({ on, ...props }) { 4 | return ( 5 |
    6 | 13 | 26 |
    27 | ); 28 | } 29 | 30 | export default Switch; 31 | -------------------------------------------------------------------------------- /19-Toggler-Composed/src/Switch.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Switch({ on, ...props }) { 4 | return ( 5 |
    6 | 13 | 26 |
    27 | ); 28 | } 29 | 30 | export default Switch; 31 | -------------------------------------------------------------------------------- /20-Compound-Components/src/Switch.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Switch({ on, ...props }) { 4 | return ( 5 |
    6 | 13 | 26 |
    27 | ); 28 | } 29 | 30 | export default Switch; 31 | -------------------------------------------------------------------------------- /20-Compound-Components/src/Toggle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Switch from './Switch'; 3 | 4 | class Toggle extends React.Component { 5 | state = { on: false }; 6 | 7 | toggle = () => this.setState({ on: !this.state.on }); 8 | 9 | render() { 10 | const { on } = this.state; 11 | const { textPosition } = this.props; 12 | 13 | if (textPosition === 'top') 14 | return ( 15 |
    16 | It is {on ? 'Starry' : 'Sunny'} 17 | 18 |
    19 | ); 20 | else if (textPosition === 'bottom') 21 | return ( 22 |
    23 | 24 | It is {on ? 'Starry' : 'Sunny'} 25 |
    26 | ); 27 | } 28 | } 29 | 30 | function ToggleApp() { 31 | return ; 32 | } 33 | 34 | export default ToggleApp; 35 | -------------------------------------------------------------------------------- /19-Toggler-Composed/src/Toggle-Finished.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Switch from './Switch'; 3 | 4 | class Toggle extends React.Component { 5 | state = { on: false }; 6 | 7 | toggle = () => this.setState({ on: !this.state.on }); 8 | 9 | render() { 10 | const { on } = this.state; 11 | const { textPosition } = this.props; 12 | 13 | if (textPosition === 'top') 14 | return ( 15 |
    16 | It is {on ? 'Starry' : 'Sunny'} 17 | 18 |
    19 | ); 20 | else if (textPosition === 'bottom') 21 | return ( 22 |
    23 | 24 | It is {on ? 'Starry' : 'Sunny'} 25 |
    26 | ); 27 | } 28 | } 29 | 30 | function ToggleApp() { 31 | return ; 32 | } 33 | 34 | export default ToggleApp; 35 | -------------------------------------------------------------------------------- /03-Functional-Components/index-start.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
    14 | 15 | 30 | 31 | -------------------------------------------------------------------------------- /10-Todo-App/index-start.js: -------------------------------------------------------------------------------- 1 | const root = document.getElementById('root'); 2 | 3 | class Todo extends React.Component { 4 | render() { 5 | return ( 6 |
    7 |
    8 |
    9 |

    Things To Do

    10 |
    11 |
    12 | 13 | 14 | 15 | 16 |
    17 | 28 |
    29 |
    30 | ); 31 | } 32 | } 33 | 34 | ReactDOM.render(, root); 35 | -------------------------------------------------------------------------------- /16-Higher-Order-Component/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Users from './Users'; 3 | 4 | import './App.css'; 5 | 6 | class App extends Component { 7 | constructor(props) { 8 | super(props); 9 | this.state = { users: [] }; 10 | } 11 | 12 | componentDidMount() { 13 | fetch('https://api.randomuser.me/?nat=us,gb&results=50') 14 | .then(response => response.json()) 15 | .then(parsedResponse => 16 | parsedResponse.results.map(user => ({ 17 | name: `${user.name.first} ${user.name.last}`, 18 | email: user.email, 19 | username: user.login.username, 20 | phone: user.phone, 21 | thumbnail: user.picture.medium, 22 | city: user.location.city, 23 | state: user.location.state 24 | })) 25 | ) 26 | .then(users => this.setState({ users })); 27 | } 28 | 29 | render() { 30 | return ( 31 |
    32 | 33 |
    34 | ); 35 | } 36 | } 37 | 38 | export default App; 39 | -------------------------------------------------------------------------------- /15-Fetching/src/App-Finished.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Users from './Users'; 3 | import './App.css'; 4 | 5 | class App extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { users: [] }; 9 | } 10 | 11 | // Fetching Data from api 12 | componentDidMount() { 13 | fetch('https://api.randomuser.me/?nat=us,gb&results=50') 14 | .then(response => response.json()) 15 | .then(parsedResponse => 16 | parsedResponse.results.map(user => ({ 17 | name: `${user.name.first} ${user.name.last}`, 18 | email: user.email, 19 | username: user.login.username, 20 | phone: user.phone, 21 | thumbnail: user.picture.medium, 22 | city: user.location.city, 23 | state: user.location.state 24 | })) 25 | ) 26 | .then(users => this.setState({ users })); 27 | } 28 | 29 | render() { 30 | return ( 31 |
    32 | 33 |
    34 | ); 35 | } 36 | } 37 | 38 | export default App; 39 | -------------------------------------------------------------------------------- /24-Lazy/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | const User = React.lazy(() => import('./User')); 4 | 5 | const fetchRandomUser = () => 6 | fetch('https://randomuser.me/api/') 7 | .then(res => res.json()) 8 | .then(res => res.results[0]); 9 | 10 | class App extends Component { 11 | state = { 12 | user: null 13 | }; 14 | 15 | loadUser = () => { 16 | this.setState( 17 | { 18 | loading: true 19 | }, 20 | async () => 21 | this.setState({ user: await fetchRandomUser(), loading: false }) 22 | ); 23 | }; 24 | 25 | render() { 26 | const { user, loading } = this.state; 27 | 28 | return ( 29 |
    30 | Loading Component...
    }> 31 | {user && } 32 | {loading ? ( 33 |
    Loading User...
    34 | ) : ( 35 | !user && 36 | )} 37 | 38 |
    39 | ); 40 | } 41 | } 42 | 43 | export default App; 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Into-the-ReactJs", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "repository": "git@github.com:vigzmv/Into-the-ReactJs.git", 6 | "author": "vigzmv ", 7 | "license": "MIT", 8 | "scripts": { 9 | "start": "parcel index.html" 10 | }, 11 | "dependencies": { 12 | "prop-types": "^15.7.2", 13 | "react": "^16.10.2", 14 | "react-addons-css-transition-group": "^15.6.2", 15 | "react-dom": "^16.10.2" 16 | }, 17 | "devDependencies": { 18 | "babel-eslint": "^8.0.3", 19 | "babel-plugin-transform-decorators-legacy": "^1.3.4", 20 | "babel-preset-env": "^1.6.1", 21 | "babel-preset-react": "^6.24.1", 22 | "babel-preset-stage-2": "^6.24.1", 23 | "eslint": "^4.13.1", 24 | "eslint-config-airbnb": "^16.1.0", 25 | "eslint-config-prettier": "^2.9.0", 26 | "eslint-plugin-html": "^4.0.1", 27 | "eslint-plugin-import": "^2.8.0", 28 | "eslint-plugin-jsx-a11y": "^6.0.3", 29 | "eslint-plugin-prettier": "^2.4.0", 30 | "eslint-plugin-react": "^7.5.1", 31 | "parcel-bundler": "^1.10.2", 32 | "prettier-eslint": "^8.3.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | .cache 3 | 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # Bower dependency directory (https://bower.io/) 31 | bower_components 32 | 33 | # node-waf configuration 34 | .lock-wscript 35 | 36 | # Compiled binary addons (http://nodejs.org/api/addons.html) 37 | build/Release 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # Typescript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | 64 | -------------------------------------------------------------------------------- /Requirements.md: -------------------------------------------------------------------------------- 1 | # Please make sure you have the following requirements installed on your systems before the event. 2 | 3 | ## 1. Chrome: Latest or at least > 62 4 | 5 | [Get Chrome](https://www.google.com/chrome/browser/features.html) 6 | 7 | ## 2. Node: Latest or at least > 9.2 and (npm > 5.5 and/or yarn > 1.3) 8 | 9 | [Get Node](https://nodejs.org/en/download/package-manager/) 10 | 11 | [Check your node version](https://stackoverflow.com/questions/14888471/node-js-version-on-the-command-line-not-the-repl) 12 | 13 | ## 3. Git: Latest or at least > 2.1 14 | 15 | [Get git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) 16 | 17 | [Check your git version](https://superuser.com/questions/347728/terminal-command-to-find-what-version-of-git-i-have-installed) 18 | 19 | ## 4. A Nice code editor (VsCode, Sublime, Atom) 20 | 21 | ## 5. Node dependencies 22 | 23 | * http-server 24 | * browser-sync 25 | * create-react-app 26 | * parcel-bundler 27 | 28 | Install these node dependencies by doing 29 | 30 | ```sh 31 | # For Mac/Linux 32 | sudo npm install -g http-server browser-sync create-react-app parcel-bundler 33 | 34 | # For Windows 35 | npm install -g http-server browser-sync create-react-app parcel-bundler 36 | ``` 37 | -------------------------------------------------------------------------------- /09-Event-Handling/index-start.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
    11 | 12 | 43 | -------------------------------------------------------------------------------- /20-Compound-Components/src/Toggle-Finished.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Switch from './Switch'; 3 | 4 | function ToggleDay({ on, children }) { 5 | return on ? children : null; 6 | } 7 | 8 | function ToggleNight({ on, children }) { 9 | return on ? null : children; 10 | } 11 | 12 | function ToggleButton({ on, toggle, ...props }) { 13 | return ; 14 | } 15 | 16 | class Toggle extends React.Component { 17 | static Day = ToggleDay; 18 | static Night = ToggleNight; 19 | static Button = ToggleButton; 20 | 21 | state = { on: false }; 22 | 23 | toggle = () => this.setState({ on: !this.state.on }); 24 | 25 | render() { 26 | const children = React.Children.map(this.props.children, child => 27 | React.cloneElement(child, { 28 | on: this.state.on, 29 | toggle: this.toggle 30 | }) 31 | ); 32 | 33 | return
    {children}
    ; 34 | } 35 | } 36 | 37 | function ToggleApp() { 38 | return ( 39 | 40 | 41 | It is Sunny 42 | 43 | 44 | 45 | It is Night 46 | 47 | 48 | ); 49 | } 50 | 51 | export default ToggleApp; 52 | -------------------------------------------------------------------------------- /21-Context/src/Toggle.js: -------------------------------------------------------------------------------- 1 | // context, proptyles, 2 | 3 | import React from 'react'; 4 | import Switch from './Switch'; 5 | 6 | function ToggleDay({ on, children }) { 7 | return on ? children : null; 8 | } 9 | 10 | function ToggleNight({ on, children }) { 11 | return on ? null : children; 12 | } 13 | 14 | function ToggleButton({ on, toggle, ...props }) { 15 | return ; 16 | } 17 | 18 | class Toggle extends React.Component { 19 | static Day = ToggleDay; 20 | static Night = ToggleNight; 21 | static Button = ToggleButton; 22 | 23 | state = { on: false }; 24 | 25 | toggle = () => this.setState({ on: !this.state.on }); 26 | 27 | render() { 28 | const children = React.Children.map(this.props.children, child => 29 | React.cloneElement(child, { 30 | on: this.state.on, 31 | toggle: this.toggle 32 | }) 33 | ); 34 | 35 | return
    {children}
    ; 36 | } 37 | } 38 | 39 | function ToggleApp() { 40 | return ( 41 | 42 | 43 | It is Sunny 44 | 45 | 46 | 47 | It is Night 48 | 49 | 50 | ); 51 | } 52 | 53 | export default ToggleApp; 54 | -------------------------------------------------------------------------------- /01-Hello-World/index-finished.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | 13 | 14 | 15 |
    16 | 17 | 35 | 36 | -------------------------------------------------------------------------------- /10-Todo-App/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Todo App 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
    22 | 23 | 24 | 25 | 27 | 28 | -------------------------------------------------------------------------------- /11-Component-Patterns/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Todo App 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
    22 | 23 | 24 | 25 | 27 | 28 | -------------------------------------------------------------------------------- /17-React.Children/src/SlideShow-Finished.js: -------------------------------------------------------------------------------- 1 | import React, { Component, Children } from 'react'; 2 | import ReactCSSTransitionGroup from 'react-addons-css-transition-group'; 3 | import './SlideShow.css'; 4 | 5 | class SlideShow extends Component { 6 | state = { 7 | total: 0, 8 | current: 0 9 | }; 10 | 11 | componentDidMount() { 12 | const { children } = this.props; 13 | this.setState({ total: Children.count(children) }); 14 | this.interval = setInterval(this.showNext, 3000); 15 | } 16 | 17 | componentWillUnmount() { 18 | clearInterval(this.interval); 19 | } 20 | 21 | showNext = () => { 22 | const { total, current } = this.state; 23 | this.setState({ 24 | current: current + 1 === total ? 0 : current + 1 25 | }); 26 | }; 27 | 28 | render() { 29 | const { children } = this.props; 30 | const bullets = Array(this.state.total).fill('○'); 31 | bullets[this.state.current] = '●'; 32 | 33 | return ( 34 |
    35 |
    {bullets}
    36 | 42 | {Children.toArray(children)[this.state.current]} 43 | 44 |
    45 | ); 46 | } 47 | } 48 | 49 | export default SlideShow; 50 | -------------------------------------------------------------------------------- /05-Conditional-Render/index-finished.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
    10 | 11 | 54 | -------------------------------------------------------------------------------- /02-JSX/index-finished.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | 13 |
    14 | 15 | 39 | 40 | -------------------------------------------------------------------------------- /16-Higher-Order-Component/src/Loading.css: -------------------------------------------------------------------------------- 1 | .loader { 2 | position: absolute; 3 | top: 50%; 4 | left: 50%; 5 | -webkit-transform: translateX(-50%) translateY(-50%); 6 | -ms-transform: translateX(-50%) translateY(-50%); 7 | transform: translateX(-50%) translateY(-50%); 8 | } 9 | 10 | /* Static Shape */ 11 | 12 | .loader:before { 13 | position: absolute; 14 | content: ''; 15 | top: 0%; 16 | left: 50%; 17 | width: 100%; 18 | height: 100%; 19 | border-radius: 500rem; 20 | border: 0.2em solid rgba(0, 0, 0, 0.1); 21 | } 22 | 23 | /* Active Shape */ 24 | 25 | .loader:after { 26 | position: absolute; 27 | content: ''; 28 | top: 0%; 29 | left: 50%; 30 | width: 100%; 31 | height: 100%; 32 | animation: loader 0.6s linear; 33 | animation-iteration-count: infinite; 34 | border-radius: 500rem; 35 | border-color: #767676 transparent transparent; 36 | border-style: solid; 37 | border-width: 0.2em; 38 | box-shadow: 0px 0px 0px 1px transparent; 39 | } 40 | 41 | /* Active Animation */ 42 | 43 | @-webkit-keyframes loader { 44 | from { 45 | -webkit-transform: rotate(0deg); 46 | transform: rotate(0deg); 47 | } 48 | 49 | to { 50 | -webkit-transform: rotate(360deg); 51 | transform: rotate(360deg); 52 | } 53 | } 54 | 55 | @keyframes loader { 56 | from { 57 | -webkit-transform: rotate(0deg); 58 | transform: rotate(0deg); 59 | } 60 | 61 | to { 62 | -webkit-transform: rotate(360deg); 63 | transform: rotate(360deg); 64 | } 65 | } 66 | 67 | .loader:before, 68 | .loader:after { 69 | width: 2.28571429rem; 70 | height: 2.28571429rem; 71 | margin: 0em; 72 | } 73 | -------------------------------------------------------------------------------- /07-Styling/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
    7 | 8 | 28 | 29 | 68 | -------------------------------------------------------------------------------- /11-Component-Patterns/index-start.js: -------------------------------------------------------------------------------- 1 | const root = document.getElementById('root'); 2 | 3 | class Todo extends React.Component { 4 | constructor(props) { 5 | super(props); 6 | 7 | this.state = { 8 | todoList: [], 9 | inputValue: '' 10 | }; 11 | } 12 | 13 | addTodo = () => { 14 | this.setState({ 15 | todoList: [...this.state.todoList, { content: this.state.inputValue }], 16 | inputValue: '' 17 | }); 18 | }; 19 | 20 | handleInputChange = e => { 21 | this.setState({ 22 | inputValue: e.target.value 23 | }); 24 | }; 25 | 26 | render() { 27 | return ( 28 |
    29 |
    30 |
    31 |

    Things To Do

    32 |
    33 |
    34 | 35 | 36 | 37 | 43 |
    44 |
      45 | {this.state.todoList.map(todo => ( 46 |
    • 47 | 48 | 49 | 50 | 51 | 52 | 53 | {todo.content} 54 |
    • 55 | ))} 56 |
    57 |
    58 |
    59 | ); 60 | } 61 | } 62 | 63 | ReactDOM.render(, root); 64 | -------------------------------------------------------------------------------- /24-Lazy/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React App 8 | 9 | 59 | 60 | 61 |
    62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /08-Component & Lifecycle/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
    9 | 10 | 59 | -------------------------------------------------------------------------------- /23-HOC-Vs-RenderProps/src/App-Cool.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | class Mouse extends React.Component { 4 | state = { x: 0, y: 0 }; 5 | 6 | handleMouseMove(event) { 7 | const hero = document.querySelector('.hero'); 8 | let x = event.nativeEvent.offsetX; 9 | let y = event.nativeEvent.offsetY; 10 | 11 | if (hero !== event.target) { 12 | x += event.target.offsetLeft; 13 | y += event.target.offsetTop; 14 | } 15 | 16 | this.setState({ 17 | x, 18 | y 19 | }); 20 | console.log(event.nativeEvent.offsetX, event.nativeEvent.offsetY); 21 | } 22 | 23 | render() { 24 | const { x, y } = this.state; 25 | 26 | return ( 27 |
    28 | {this.props.render(this.state)} 29 |
    30 | ); 31 | } 32 | } 33 | 34 | function App() { 35 | const walk = 300; // 100px 36 | 37 | return ( 38 | { 40 | const hero = document.querySelector('.hero'); 41 | const { offsetWidth: width, offsetHeight: height } = hero || { 42 | offsetWidth: 0, 43 | offsetHeight: 0 44 | }; 45 | const xWalk = Math.round(x / width * walk - walk / 2); 46 | const yWalk = Math.round(y / height * walk - walk / 2); 47 | return ( 48 |
    49 |

    57 | React!! 58 |

    59 |
    60 | ); 61 | }} 62 | /> 63 | ); 64 | } 65 | 66 | export default App; 67 | -------------------------------------------------------------------------------- /21-Context/src/Toggle-Finished.js: -------------------------------------------------------------------------------- 1 | // context, PropTypes, childContextTypes, getChildContext, render only children, contextTypes to all children components, toggle in variable 2 | 3 | import React from 'react'; 4 | import PropTypes from 'prop-types'; 5 | import Switch from './Switch'; 6 | 7 | function ToggleDay({ children }, context) { 8 | const { on } = context.toggle; 9 | return on ? children : null; 10 | } 11 | ToggleDay.contextTypes = { 12 | toggle: PropTypes.object.isRequired 13 | }; 14 | 15 | function ToggleNight({ children }, context) { 16 | const { on } = context.toggle; 17 | return on ? null : children; 18 | } 19 | ToggleNight.contextTypes = { 20 | toggle: PropTypes.object.isRequired 21 | }; 22 | 23 | function ToggleButton(props, context) { 24 | const { on, toggle } = context.toggle; 25 | return ; 26 | } 27 | ToggleButton.contextTypes = { 28 | toggle: PropTypes.object.isRequired 29 | }; 30 | 31 | class Toggle extends React.Component { 32 | static Day = ToggleDay; 33 | static Night = ToggleNight; 34 | static Button = ToggleButton; 35 | 36 | static childContextTypes = { 37 | toggle: PropTypes.object.isRequired 38 | }; 39 | 40 | state = { on: false }; 41 | 42 | getChildContext() { 43 | return { 44 | toggle: { 45 | on: this.state.on, 46 | toggle: this.toggle 47 | } 48 | }; 49 | } 50 | 51 | toggle = () => this.setState({ on: !this.state.on }); 52 | 53 | render() { 54 | return
    {this.props.children}
    ; 55 | } 56 | } 57 | 58 | function ToggleApp() { 59 | return ( 60 | 61 | 62 | It is Sunny 63 | 64 |
    65 | 66 |
    67 | 68 | It is Night 69 | 70 |
    71 | ); 72 | } 73 | 74 | export default ToggleApp; 75 | -------------------------------------------------------------------------------- /12-create-react-app/src/Todo.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import List from './List'; 3 | import './Todo.css'; 4 | 5 | class Todo extends Component { 6 | constructor(props) { 7 | super(props); 8 | 9 | this.state = { 10 | todoList: [], 11 | inputValue: '' 12 | }; 13 | } 14 | 15 | addTodo = () => { 16 | this.setState({ 17 | todoList: [ 18 | ...this.state.todoList, 19 | { content: this.state.inputValue, completed: false } 20 | ], 21 | inputValue: '' 22 | }); 23 | }; 24 | 25 | handleInputChange = e => { 26 | this.setState({ 27 | inputValue: e.target.value 28 | }); 29 | }; 30 | 31 | removeTodo = index => { 32 | const newTotoList = this.state.todoList.filter((item, i) => i !== index); 33 | this.setState({ todoList: newTotoList }); 34 | }; 35 | 36 | markCompleteTodo = index => { 37 | const newTotoList = this.state.todoList.map((item, i) => { 38 | if (index === i) { 39 | item.completed = !item.completed; 40 | } 41 | return item; 42 | }); 43 | 44 | this.setState({ todoList: newTotoList }); 45 | }; 46 | 47 | render() { 48 | return ( 49 |
    50 |
    51 |
    52 |

    Things To Do

    53 |
    54 |
    55 | 56 | 57 | 58 | 64 |
    65 | 70 |
    71 |
    72 | ); 73 | } 74 | } 75 | 76 | export default Todo; 77 | -------------------------------------------------------------------------------- /04-propTypes/index-finished.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 | 17 | 72 | -------------------------------------------------------------------------------- /10-Todo-App/index-finished.js: -------------------------------------------------------------------------------- 1 | // Notes: styling, state, static state, setState, map, react dev tool 2 | 3 | const root = document.getElementById('root'); 4 | 5 | class Todo extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | 9 | // static state 10 | 11 | // this.state = { 12 | // todoList: [ 13 | // { 14 | // content: 'Complete This', 15 | // }, 16 | // ], 17 | // }; 18 | 19 | this.state = { 20 | todoList: [], 21 | inputValue: '' 22 | }; 23 | } 24 | 25 | addTodo = () => { 26 | this.setState({ 27 | todoList: [...this.state.todoList, { content: this.state.inputValue }], 28 | inputValue: '' 29 | }); 30 | }; 31 | 32 | handleInputChange = e => { 33 | const inputValue = e.target.value; 34 | this.setState({ 35 | inputValue 36 | }); 37 | }; 38 | 39 | render() { 40 | return ( 41 |
    42 |
    43 |
    44 |

    Things To Do

    45 |
    46 |
    47 | 48 | 49 | 50 | 56 |
    57 |
      58 | {this.state.todoList.map(todo => ( 59 |
    • 60 | 61 | 62 | 63 | 64 | 65 | 66 | {todo.content} 67 |
    • 68 | ))} 69 |
    70 |
    71 |
    72 | ); 73 | } 74 | } 75 | 76 | ReactDOM.render(, root); 77 | -------------------------------------------------------------------------------- /13-Firebase-rebase/src/Todo.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import List from './List'; 3 | import './Todo.css'; 4 | import base from './re-base'; 5 | 6 | class Todo extends Component { 7 | constructor(props) { 8 | super(props); 9 | 10 | this.state = { 11 | todoList: [], 12 | inputValue: '' 13 | }; 14 | } 15 | 16 | addTodo = () => { 17 | this.setState({ 18 | todoList: [ 19 | ...this.state.todoList, 20 | { content: this.state.inputValue, completed: false } 21 | ], 22 | inputValue: '' 23 | }); 24 | }; 25 | 26 | handleInputChange = e => { 27 | this.setState({ 28 | inputValue: e.target.value 29 | }); 30 | }; 31 | 32 | removeTodo = index => { 33 | const newTotoList = this.state.todoList.filter((item, i) => i !== index); 34 | this.setState({ todoList: newTotoList }); 35 | }; 36 | 37 | markCompleteTodo = index => { 38 | const newTotoList = this.state.todoList.map((item, i) => { 39 | if (index === i) { 40 | item.completed = !item.completed; 41 | } 42 | return item; 43 | }); 44 | 45 | this.setState({ todoList: newTotoList }); 46 | }; 47 | 48 | render() { 49 | return ( 50 |
    51 |
    52 |
    53 |

    Things To Do

    54 |
    55 |
    56 | 57 | 58 | 59 | 65 |
    66 | 71 |
    72 |
    73 | ); 74 | } 75 | } 76 | 77 | export default Todo; 78 | -------------------------------------------------------------------------------- /09-Event-Handling/index-finished.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
    12 | 13 | 68 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["airbnb", "prettier", "prettier/react"], 3 | "parser": "babel-eslint", 4 | "parserOptions": { 5 | "ecmaVersion": 8, 6 | "ecmaFeatures": { 7 | "experimentalObjectRestSpread": true, 8 | "impliedStrict": true, 9 | "classes": true 10 | } 11 | }, 12 | "env": { 13 | "browser": true, 14 | "node": true, 15 | "jquery": true 16 | }, 17 | "rules": { 18 | "no-unused-vars": [ 19 | 1, 20 | { 21 | "argsIgnorePattern": "res|next|^err" 22 | } 23 | ], 24 | "arrow-body-style": [2, "as-needed"], 25 | "no-param-reassign": [ 26 | 2, 27 | { 28 | "props": false 29 | } 30 | ], 31 | "no-console": "off", 32 | "import": "off", 33 | "func-names": "off", 34 | "space-before-function-paren": "off", 35 | "comma-dangle": "off", 36 | "max-len": "off", 37 | "import/extensions": "off", 38 | "no-underscore-dangle": "off", 39 | "consistent-return": "off", 40 | "react/display-name": 1, 41 | "react/react-in-jsx-scope": "off", 42 | "react/forbid-prop-types": "off", 43 | "react/no-unescaped-entities": "off", 44 | "react/prefer-stateless-function": "off", 45 | "react/prop-types": "off", 46 | "react/jsx-filename-extension": [ 47 | 1, 48 | { 49 | "extensions": [".js", ".jsx"] 50 | } 51 | ], 52 | "radix": "off", 53 | "no-shadow": [ 54 | 2, 55 | { 56 | "hoist": "all", 57 | "allow": ["resolve", "reject", "done", "next", "err", "error"] 58 | } 59 | ], 60 | "quotes": [ 61 | 2, 62 | "single", 63 | { 64 | "avoidEscape": true, 65 | "allowTemplateLiterals": true 66 | } 67 | ], 68 | "prettier/prettier": [ 69 | "error", 70 | { 71 | "singleQuote": true, 72 | "printWidth": 80 73 | } 74 | ], 75 | "jsx-a11y/href-no-hash": "off", 76 | "jsx-a11y/anchor-is-valid": [ 77 | "warn", 78 | { 79 | "aspects": ["invalidHref"] 80 | } 81 | ] 82 | }, 83 | "plugins": ["eslint-plugin-html", "prettier"] 84 | } 85 | -------------------------------------------------------------------------------- /06-Rerender/index-finished.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
    9 | 10 | 79 | -------------------------------------------------------------------------------- /13-Firebase-rebase/src/Todo-Finished.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import List from './List'; 3 | import './Todo.css'; 4 | import base from './re-base'; 5 | 6 | class Todo extends Component { 7 | constructor(props) { 8 | super(props); 9 | 10 | this.state = { 11 | todoList: [], 12 | inputValue: '' 13 | }; 14 | } 15 | 16 | // re-base ing 17 | componentDidMount() { 18 | base.syncState(`todoList`, { 19 | context: this, 20 | state: 'todoList', 21 | asArray: true 22 | }); 23 | } 24 | 25 | addTodo = () => { 26 | this.setState({ 27 | todoList: [ 28 | ...this.state.todoList, 29 | { content: this.state.inputValue, completed: false } 30 | ], 31 | inputValue: '' 32 | }); 33 | }; 34 | 35 | handleInputChange = e => { 36 | this.setState({ 37 | inputValue: e.target.value 38 | }); 39 | }; 40 | 41 | removeTodo = index => { 42 | const newTotoList = this.state.todoList.filter((item, i) => i !== index); 43 | this.setState({ todoList: newTotoList }); 44 | }; 45 | 46 | markCompleteTodo = index => { 47 | const newTotoList = this.state.todoList.map((item, i) => { 48 | if (index === i) { 49 | item.completed = !item.completed; 50 | } 51 | return item; 52 | }); 53 | 54 | this.setState({ todoList: newTotoList }); 55 | }; 56 | 57 | render() { 58 | return ( 59 |
    60 |
    61 |
    62 |

    Things To Do

    63 |
    64 |
    65 | 66 | 67 | 68 | 74 |
    75 | 80 |
    81 |
    82 | ); 83 | } 84 | } 85 | 86 | export default Todo; 87 | -------------------------------------------------------------------------------- /13-Firebase-rebase/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 28 | Todo 29 | 30 | 31 | 32 | 35 |
    36 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /12-create-react-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 28 | Todo App 29 | 30 | 31 | 32 | 35 |
    36 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Into-the-ReactJs 2 | 3 | Code content for my Session/Workshop on React. 4 | 5 | ## Agenda 6 | 7 | A deep dive into the React. Starting from the very basics, exploring what? why? how? the APIs work and levelling up to its advanced patterns. 8 | 9 | 1. **Introduction**: What is and Why should one do React? 10 | 1. **The Basics**: Exploring the basic elements of React with just one single HTML file. Building few core React APIs ourself and learning how they work. 11 | 1. **Thinking in React**: Setup and building simple React Front End. Create react App. Life Cycles. Synthetic Events. Lifting State. Dropping Props. Some Styling. Some Tooling. Different Component Patterns. Data Fetching. Data persistence with Firebase re-base. Deploying builds. 12 | 1. **Advanced Patterns**: Declarative Development, Compound Components, HOCs, Refs, Context, Portals and More! Learning by building real-world usages. 13 | 14 | ## Slides 15 | 16 | [Vignesh M - React](http://slides.com/vigzmv/react/) 17 | 18 | ## Requirements 19 | 20 | See [Requirements](./Requirements.md) 21 | 22 | ## How to run 23 | 24 | Execute `npm install` once in root folder and switch to the respective project folder to run the examples. 25 | 26 | * **01 to 09**
    27 | Use any http-server and to open index\*.html
    28 | The starter code is in index-start.html and finished code is in index-finished.html 29 | 30 | * **10 to 11**
    31 | Use any http-server (http-server/browser-sync) to open index\*.html
    32 | The starter code is in index-start.js and finished code is in index-finished.js
    33 | You will have to swap out the src of js file in index.html 34 | 35 | * **12 to 13**
    36 | These are created with create-react-app.
    37 | Install node dependencies with `npm install` and then start development server using `npm start`.
    38 | 39 | * **14 to 24**
    40 | These are created as parceljs projects.
    41 | Install parceljs globally using `sudo npm install -g parcel-bundler` once and run start the server using `parcel index.html`.
    42 | 43 | ## More Resources 44 | 45 | * [The Beginner's Guide to ReactJS - Kent C. Dodds](https://egghead.io/courses/the-beginner-s-guide-to-reactjs) 46 | * [ReactJs](https://reactjs.org/) 47 | * [Create React App](https://github.com/facebook/create-react-app) 48 | * [ParcelJs](https://parceljs.org/) 49 | * [Rebase](https://github.com/tylermcginnis/re-base) -------------------------------------------------------------------------------- /03-Functional-Components/index-finished.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
    10 | 11 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /11-Component-Patterns/index-finished.js: -------------------------------------------------------------------------------- 1 | // Component Patterns. 2 | // Statefull, Controlling, Smart Component 3 | // Stateless, Presentational, Dumb Component 4 | // Components, Containers 5 | // state lifted to top 6 | // handlers 7 | 8 | const root = document.getElementById('root'); 9 | 10 | // functional presentational component 11 | function List(props) { 12 | return props.list.map((item, i) => ( 13 |
  • 14 | props.onRemove(i)}> 15 | 16 | 17 | props.onComplete(i)}> 18 | 19 | 20 | {item.content} 21 |
  • 22 | )); 23 | } 24 | 25 | // class based stateful component 26 | class Todo extends React.Component { 27 | constructor(props) { 28 | super(props); 29 | 30 | this.state = { 31 | todoList: [], 32 | inputValue: '' 33 | }; 34 | } 35 | 36 | addTodo = () => { 37 | this.setState({ 38 | todoList: [ 39 | ...this.state.todoList, 40 | { content: this.state.inputValue, completed: false } 41 | ], 42 | inputValue: '' 43 | }); 44 | }; 45 | 46 | handleInputChange = e => { 47 | this.setState({ 48 | inputValue: e.target.value 49 | }); 50 | }; 51 | 52 | removeTodo = index => { 53 | const newTotoList = this.state.todoList.filter((item, i) => i !== index); 54 | this.setState({ todoList: newTotoList }); 55 | }; 56 | 57 | markCompleteTodo = index => { 58 | const newTotoList = this.state.todoList; 59 | newTotoList[index].completed = !newTotoList[index].completed; 60 | 61 | // immutable method 62 | // const newTotoList = this.state.todoList.map((item, i) => { 63 | // if (index === i) { 64 | // item.completed = !item.completed; 65 | // } 66 | // return item; 67 | // }); 68 | 69 | this.setState({ todoList: newTotoList }); 70 | }; 71 | 72 | render() { 73 | return ( 74 |
    75 |
    76 |
    77 |

    Things To Do

    78 |
    79 |
    80 | 81 | 82 | 83 | 89 |
    90 | 95 |
    96 |
    97 | ); 98 | } 99 | } 100 | 101 | ReactDOM.render(, root); 102 | -------------------------------------------------------------------------------- /10-Todo-App/css/styles.css: -------------------------------------------------------------------------------- 1 | *, *:before, *:after { 2 | -webkit-box-sizing: border-box; 3 | box-sizing: border-box; 4 | } 5 | 6 | p { 7 | color: #eee; 8 | text-align: center; 9 | margin: 60px 0 30px 0; 10 | } 11 | 12 | li { 13 | list-style: none; 14 | } 15 | 16 | body { 17 | font-family: 'Open Sans', sans-serif; 18 | background: #34495e; 19 | font-size: 14px; 20 | -webkit-font-smoothing: antialiased; 21 | -moz-osx-font-smoothing: grayscale; 22 | text-rendering: optimizeLegibility; 23 | } 24 | 25 | .container { 26 | background: #2c3e50; 27 | overflow: hidden; 28 | width: 360px; 29 | margin: 10% auto; 30 | color: #FFF; 31 | border-radius: 3px 3px 0 0; 32 | -webkit-box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 33 | box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 34 | } 35 | 36 | .container .title { 37 | background: #3498db; 38 | } 39 | 40 | .container h1 { 41 | font-size: 20px; 42 | font-weight: 600; 43 | padding: 10px 15px; 44 | text-transform: uppercase; 45 | } 46 | 47 | .add { 48 | float: right; 49 | border-radius: 3px; 50 | margin-right: 20px; 51 | margin-top: 5px; 52 | padding: 8px 10px; 53 | background: #2980b9; 54 | } 55 | 56 | .add:hover { 57 | background: rgba(0, 0, 0, 0.3); 58 | cursor: pointer; 59 | } 60 | 61 | .row { 62 | color: #333; 63 | background: #FFF; 64 | width: 100%; 65 | height: 40px; 66 | padding-left: 10px; 67 | line-height: 2.8; 68 | } 69 | 70 | .row:hover a { 71 | width: 40px; 72 | opacity: 1; 73 | } 74 | 75 | .row:nth-child(2n) { 76 | background: #f7f7f7; 77 | } 78 | 79 | .row:hover { 80 | background: #eee; 81 | } 82 | 83 | .remove, .completed { 84 | float: right; 85 | text-align: center; 86 | height: 40px; 87 | width: 0; 88 | background: #2ecc71; 89 | color: #FFF; 90 | opacity: 0; 91 | text-decoration: none; 92 | display: inline-block; 93 | -webkit-transition: all .2s ease; 94 | transition: all .2s ease; 95 | } 96 | 97 | .remove:hover, .completed:hover { 98 | background: #27ae60; 99 | } 100 | 101 | .remove { 102 | background: #e74c3c; 103 | } 104 | 105 | .remove:hover { 106 | background: #c0392b; 107 | } 108 | 109 | .done { 110 | text-decoration: line-through; 111 | color: #ccc; 112 | } 113 | 114 | .add-new { 115 | float: right; 116 | height: 40px; 117 | width: 40px; 118 | text-align: center; 119 | background: #2ecc71; 120 | color: #FFF; 121 | line-height: 2.8; 122 | -webkit-transition: all .3s linear; 123 | transition: all .3s linear; 124 | } 125 | 126 | .add-new:hover { 127 | background: #27ae60; 128 | } 129 | 130 | .new-task { 131 | /* display: none; */ 132 | } 133 | 134 | .new-task input { 135 | -webkit-appearance: none; 136 | -moz-appearance: none; 137 | border-radius: 0; 138 | background: #ecf0f1; 139 | font-size: 14px; 140 | font-family: 'Open Sans', sans-serif; 141 | width: 320px; 142 | padding: 5px 10px; 143 | height: 40px; 144 | border: none; 145 | outline: none; 146 | } 147 | 148 | .ui-sortable-helper { 149 | -webkit-box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 150 | box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 151 | } 152 | -------------------------------------------------------------------------------- /13-Firebase-rebase/src/Todo.css: -------------------------------------------------------------------------------- 1 | *, *:before, *:after { 2 | -webkit-box-sizing: border-box; 3 | box-sizing: border-box; 4 | } 5 | 6 | p { 7 | color: #eee; 8 | text-align: center; 9 | margin: 60px 0 30px 0; 10 | } 11 | 12 | li { 13 | list-style: none; 14 | } 15 | 16 | body { 17 | font-family: 'Open Sans', sans-serif; 18 | background: #34495e; 19 | font-size: 14px; 20 | -webkit-font-smoothing: antialiased; 21 | -moz-osx-font-smoothing: grayscale; 22 | text-rendering: optimizeLegibility; 23 | } 24 | 25 | .container { 26 | background: #2c3e50; 27 | overflow: hidden; 28 | width: 360px; 29 | margin: 10% auto; 30 | color: #FFF; 31 | border-radius: 3px 3px 0 0; 32 | -webkit-box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 33 | box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 34 | } 35 | 36 | .container .title { 37 | background: #3498db; 38 | } 39 | 40 | .container h1 { 41 | font-size: 20px; 42 | font-weight: 600; 43 | padding: 10px 15px; 44 | text-transform: uppercase; 45 | } 46 | 47 | .add { 48 | float: right; 49 | border-radius: 3px; 50 | margin-right: 20px; 51 | margin-top: 5px; 52 | padding: 8px 10px; 53 | background: #2980b9; 54 | } 55 | 56 | .add:hover { 57 | background: rgba(0, 0, 0, 0.3); 58 | cursor: pointer; 59 | } 60 | 61 | .row { 62 | color: #333; 63 | background: #FFF; 64 | width: 100%; 65 | height: 40px; 66 | padding-left: 10px; 67 | line-height: 2.8; 68 | } 69 | 70 | .row:hover a { 71 | width: 40px; 72 | opacity: 1; 73 | } 74 | 75 | .row:nth-child(2n) { 76 | background: #f7f7f7; 77 | } 78 | 79 | .row:hover { 80 | background: #eee; 81 | } 82 | 83 | .remove, .completed { 84 | float: right; 85 | text-align: center; 86 | height: 40px; 87 | width: 0; 88 | background: #2ecc71; 89 | color: #FFF; 90 | opacity: 0; 91 | text-decoration: none; 92 | display: inline-block; 93 | -webkit-transition: all .2s ease; 94 | transition: all .2s ease; 95 | } 96 | 97 | .remove:hover, .completed:hover { 98 | background: #27ae60; 99 | } 100 | 101 | .remove { 102 | background: #e74c3c; 103 | } 104 | 105 | .remove:hover { 106 | background: #c0392b; 107 | } 108 | 109 | .done { 110 | text-decoration: line-through; 111 | color: #ccc; 112 | } 113 | 114 | .add-new { 115 | float: right; 116 | height: 40px; 117 | width: 40px; 118 | text-align: center; 119 | background: #2ecc71; 120 | color: #FFF; 121 | line-height: 2.8; 122 | -webkit-transition: all .3s linear; 123 | transition: all .3s linear; 124 | } 125 | 126 | .add-new:hover { 127 | background: #27ae60; 128 | } 129 | 130 | .new-task { 131 | /* display: none; */ 132 | } 133 | 134 | .new-task input { 135 | -webkit-appearance: none; 136 | -moz-appearance: none; 137 | border-radius: 0; 138 | background: #ecf0f1; 139 | font-size: 14px; 140 | font-family: 'Open Sans', sans-serif; 141 | width: 320px; 142 | padding: 5px 10px; 143 | height: 40px; 144 | border: none; 145 | outline: none; 146 | } 147 | 148 | .ui-sortable-helper { 149 | -webkit-box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 150 | box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 151 | } 152 | -------------------------------------------------------------------------------- /11-Component-Patterns/css/styles.css: -------------------------------------------------------------------------------- 1 | *, *:before, *:after { 2 | -webkit-box-sizing: border-box; 3 | box-sizing: border-box; 4 | } 5 | 6 | p { 7 | color: #eee; 8 | text-align: center; 9 | margin: 60px 0 30px 0; 10 | } 11 | 12 | li { 13 | list-style: none; 14 | } 15 | 16 | body { 17 | font-family: 'Open Sans', sans-serif; 18 | background: #34495e; 19 | font-size: 14px; 20 | -webkit-font-smoothing: antialiased; 21 | -moz-osx-font-smoothing: grayscale; 22 | text-rendering: optimizeLegibility; 23 | } 24 | 25 | .container { 26 | background: #2c3e50; 27 | overflow: hidden; 28 | width: 360px; 29 | margin: 10% auto; 30 | color: #FFF; 31 | border-radius: 3px 3px 0 0; 32 | -webkit-box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 33 | box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 34 | } 35 | 36 | .container .title { 37 | background: #3498db; 38 | } 39 | 40 | .container h1 { 41 | font-size: 20px; 42 | font-weight: 600; 43 | padding: 10px 15px; 44 | text-transform: uppercase; 45 | } 46 | 47 | .add { 48 | float: right; 49 | border-radius: 3px; 50 | margin-right: 20px; 51 | margin-top: 5px; 52 | padding: 8px 10px; 53 | background: #2980b9; 54 | } 55 | 56 | .add:hover { 57 | background: rgba(0, 0, 0, 0.3); 58 | cursor: pointer; 59 | } 60 | 61 | .row { 62 | color: #333; 63 | background: #FFF; 64 | width: 100%; 65 | height: 40px; 66 | padding-left: 10px; 67 | line-height: 2.8; 68 | } 69 | 70 | .row:hover a { 71 | width: 40px; 72 | opacity: 1; 73 | } 74 | 75 | .row:nth-child(2n) { 76 | background: #f7f7f7; 77 | } 78 | 79 | .row:hover { 80 | background: #eee; 81 | } 82 | 83 | .remove, .completed { 84 | float: right; 85 | text-align: center; 86 | height: 40px; 87 | width: 0; 88 | background: #2ecc71; 89 | color: #FFF; 90 | opacity: 0; 91 | text-decoration: none; 92 | display: inline-block; 93 | -webkit-transition: all .2s ease; 94 | transition: all .2s ease; 95 | } 96 | 97 | .remove:hover, .completed:hover { 98 | background: #27ae60; 99 | } 100 | 101 | .remove { 102 | background: #e74c3c; 103 | } 104 | 105 | .remove:hover { 106 | background: #c0392b; 107 | } 108 | 109 | .done { 110 | text-decoration: line-through; 111 | color: #ccc; 112 | } 113 | 114 | .add-new { 115 | float: right; 116 | height: 40px; 117 | width: 40px; 118 | text-align: center; 119 | background: #2ecc71; 120 | color: #FFF; 121 | line-height: 2.8; 122 | -webkit-transition: all .3s linear; 123 | transition: all .3s linear; 124 | } 125 | 126 | .add-new:hover { 127 | background: #27ae60; 128 | } 129 | 130 | .new-task { 131 | /* display: none; */ 132 | } 133 | 134 | .new-task input { 135 | -webkit-appearance: none; 136 | -moz-appearance: none; 137 | border-radius: 0; 138 | background: #ecf0f1; 139 | font-size: 14px; 140 | font-family: 'Open Sans', sans-serif; 141 | width: 320px; 142 | padding: 5px 10px; 143 | height: 40px; 144 | border: none; 145 | outline: none; 146 | } 147 | 148 | .ui-sortable-helper { 149 | -webkit-box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 150 | box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 151 | } 152 | -------------------------------------------------------------------------------- /12-create-react-app/src/Todo.css: -------------------------------------------------------------------------------- 1 | *, *:before, *:after { 2 | -webkit-box-sizing: border-box; 3 | box-sizing: border-box; 4 | } 5 | 6 | p { 7 | color: #eee; 8 | text-align: center; 9 | margin: 60px 0 30px 0; 10 | } 11 | 12 | li { 13 | list-style: none; 14 | } 15 | 16 | body { 17 | font-family: 'Open Sans', sans-serif; 18 | background: #34495e; 19 | font-size: 14px; 20 | -webkit-font-smoothing: antialiased; 21 | -moz-osx-font-smoothing: grayscale; 22 | text-rendering: optimizeLegibility; 23 | } 24 | 25 | .container { 26 | background: #2c3e50; 27 | overflow: hidden; 28 | width: 360px; 29 | margin: 10% auto; 30 | color: #FFF; 31 | border-radius: 3px 3px 0 0; 32 | -webkit-box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 33 | box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 34 | } 35 | 36 | .container .title { 37 | background: #3498db; 38 | } 39 | 40 | .container h1 { 41 | font-size: 20px; 42 | font-weight: 600; 43 | padding: 10px 15px; 44 | text-transform: uppercase; 45 | } 46 | 47 | .add { 48 | float: right; 49 | border-radius: 3px; 50 | margin-right: 20px; 51 | margin-top: 5px; 52 | padding: 8px 10px; 53 | background: #2980b9; 54 | } 55 | 56 | .add:hover { 57 | background: rgba(0, 0, 0, 0.3); 58 | cursor: pointer; 59 | } 60 | 61 | .row { 62 | color: #333; 63 | background: #FFF; 64 | width: 100%; 65 | height: 40px; 66 | padding-left: 10px; 67 | line-height: 2.8; 68 | } 69 | 70 | .row:hover a { 71 | width: 40px; 72 | opacity: 1; 73 | } 74 | 75 | .row:nth-child(2n) { 76 | background: #f7f7f7; 77 | } 78 | 79 | .row:hover { 80 | background: #eee; 81 | } 82 | 83 | .remove, .completed { 84 | float: right; 85 | text-align: center; 86 | height: 40px; 87 | width: 0; 88 | background: #2ecc71; 89 | color: #FFF; 90 | opacity: 0; 91 | text-decoration: none; 92 | display: inline-block; 93 | -webkit-transition: all .2s ease; 94 | transition: all .2s ease; 95 | } 96 | 97 | .remove:hover, .completed:hover { 98 | background: #27ae60; 99 | } 100 | 101 | .remove { 102 | background: #e74c3c; 103 | } 104 | 105 | .remove:hover { 106 | background: #c0392b; 107 | } 108 | 109 | .done { 110 | text-decoration: line-through; 111 | color: #ccc; 112 | } 113 | 114 | .add-new { 115 | float: right; 116 | height: 40px; 117 | width: 40px; 118 | text-align: center; 119 | background: #2ecc71; 120 | color: #FFF; 121 | line-height: 2.8; 122 | -webkit-transition: all .3s linear; 123 | transition: all .3s linear; 124 | } 125 | 126 | .add-new:hover { 127 | background: #27ae60; 128 | } 129 | 130 | .new-task { 131 | /* display: none; */ 132 | } 133 | 134 | .new-task input { 135 | -webkit-appearance: none; 136 | -moz-appearance: none; 137 | border-radius: 0; 138 | background: #ecf0f1; 139 | font-size: 14px; 140 | font-family: 'Open Sans', sans-serif; 141 | width: 320px; 142 | padding: 5px 10px; 143 | height: 40px; 144 | border: none; 145 | outline: none; 146 | } 147 | 148 | .ui-sortable-helper { 149 | -webkit-box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 150 | box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.2); 151 | } 152 | -------------------------------------------------------------------------------- /21-Context/src/App.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #1E314F; 3 | font-family: 'Helvetica Rounded', 'Arial Rounded MT Bold', 'Montserrat', sans-serif; 4 | color: #fff; 5 | } 6 | 7 | .toggleWrapper { 8 | position: absolute; 9 | top: 50%; 10 | left: 50%; 11 | transform: translate3d(-50%, -50%, 0); 12 | } 13 | 14 | .toggleWrapper>span { 15 | text-align: center; 16 | display: block; 17 | } 18 | 19 | .toggleWrapper input { 20 | position: absolute; 21 | left: -99em; 22 | } 23 | 24 | .toggle { 25 | cursor: pointer; 26 | display: inline-block; 27 | position: relative; 28 | width: 90px; 29 | height: 50px; 30 | background-color: #83D8FF; 31 | border-radius: 84px; 32 | transition: background-color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 33 | margin: 2px; 34 | } 35 | 36 | .toggle:before { 37 | position: absolute; 38 | left: -50px; 39 | top: 15px; 40 | font-size: 18px; 41 | } 42 | 43 | .toggle:after { 44 | position: absolute; 45 | right: -48px; 46 | top: 15px; 47 | font-size: 18px; 48 | color: #749ED7; 49 | } 50 | 51 | .toggle__handler { 52 | display: inline-block; 53 | position: relative; 54 | z-index: 1; 55 | top: 3px; 56 | left: 3px; 57 | width: 44px; 58 | height: 44px; 59 | background-color: #FFCF96; 60 | border-radius: 50px; 61 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); 62 | transition: all 400ms cubic-bezier(0.68, -0.55, 0.265, 1.55); 63 | transform: rotate(-45deg); 64 | } 65 | 66 | .toggle__handler .crater { 67 | position: absolute; 68 | background-color: #E8CDA5; 69 | opacity: 0; 70 | transition: opacity 200ms ease-in-out; 71 | border-radius: 100%; 72 | } 73 | 74 | .toggle__handler .crater--1 { 75 | top: 18px; 76 | left: 10px; 77 | width: 4px; 78 | height: 4px; 79 | } 80 | 81 | .toggle__handler .crater--2 { 82 | top: 28px; 83 | left: 22px; 84 | width: 6px; 85 | height: 6px; 86 | } 87 | 88 | .toggle__handler .crater--3 { 89 | top: 10px; 90 | left: 25px; 91 | width: 8px; 92 | height: 8px; 93 | } 94 | 95 | .star { 96 | position: absolute; 97 | background-color: #ffffff; 98 | transition: all 300ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 99 | border-radius: 50%; 100 | } 101 | 102 | .star--1 { 103 | top: 10px; 104 | left: 35px; 105 | z-index: 0; 106 | width: 30px; 107 | height: 3px; 108 | } 109 | 110 | .star--2 { 111 | top: 18px; 112 | left: 28px; 113 | z-index: 1; 114 | width: 30px; 115 | height: 3px; 116 | } 117 | 118 | .star--3 { 119 | top: 27px; 120 | left: 40px; 121 | z-index: 0; 122 | width: 30px; 123 | height: 3px; 124 | } 125 | 126 | .star--4, 127 | .star--5, 128 | .star--6 { 129 | opacity: 0; 130 | transition: all 300ms 0 cubic-bezier(0.445, 0.05, 0.55, 0.95); 131 | } 132 | 133 | .star--4 { 134 | top: 16px; 135 | left: 11px; 136 | z-index: 0; 137 | width: 2px; 138 | height: 2px; 139 | transform: translate3d(3px, 0, 0); 140 | } 141 | 142 | .star--5 { 143 | top: 32px; 144 | left: 17px; 145 | z-index: 0; 146 | width: 3px; 147 | height: 3px; 148 | transform: translate3d(3px, 0, 0); 149 | } 150 | 151 | .star--6 { 152 | top: 36px; 153 | left: 28px; 154 | z-index: 0; 155 | width: 2px; 156 | height: 2px; 157 | transform: translate3d(3px, 0, 0); 158 | } 159 | 160 | input:checked+.toggle { 161 | background-color: #749DD6; 162 | } 163 | 164 | input:checked+.toggle:before { 165 | color: #749ED7; 166 | } 167 | 168 | input:checked+.toggle:after { 169 | color: #ffffff; 170 | } 171 | 172 | input:checked+.toggle .toggle__handler { 173 | background-color: #FFE5B5; 174 | transform: translate3d(40px, 0, 0) rotate(0); 175 | } 176 | 177 | input:checked+.toggle .toggle__handler .crater { 178 | opacity: 1; 179 | } 180 | 181 | input:checked+.toggle .star--1 { 182 | width: 2px; 183 | height: 2px; 184 | } 185 | 186 | input:checked+.toggle .star--2 { 187 | width: 4px; 188 | height: 4px; 189 | transform: translate3d(-5px, 0, 0); 190 | } 191 | 192 | input:checked+.toggle .star--3 { 193 | width: 2px; 194 | height: 2px; 195 | transform: translate3d(-7px, 0, 0); 196 | } 197 | 198 | input:checked+.toggle .star--4, 199 | input:checked+.toggle .star--5, 200 | input:checked+.toggle .star--6 { 201 | opacity: 1; 202 | transform: translate3d(0, 0, 0); 203 | } 204 | 205 | input:checked+.toggle .star--4 { 206 | transition: all 300ms 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 207 | } 208 | 209 | input:checked+.toggle .star--5 { 210 | transition: all 300ms 300ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 211 | } 212 | 213 | input:checked+.toggle .star--6 { 214 | transition: all 300ms 400ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 215 | } -------------------------------------------------------------------------------- /22-Render-Props/src/App.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #1E314F; 3 | font-family: 'Helvetica Rounded', 'Arial Rounded MT Bold', 'Montserrat', sans-serif; 4 | color: #fff; 5 | } 6 | 7 | .toggleWrapper { 8 | position: absolute; 9 | top: 50%; 10 | left: 50%; 11 | transform: translate3d(-50%, -50%, 0); 12 | } 13 | 14 | .toggleWrapper>span { 15 | text-align: center; 16 | display: block; 17 | } 18 | 19 | .toggleWrapper input { 20 | position: absolute; 21 | left: -99em; 22 | } 23 | 24 | .toggle { 25 | cursor: pointer; 26 | display: inline-block; 27 | position: relative; 28 | width: 90px; 29 | height: 50px; 30 | background-color: #83D8FF; 31 | border-radius: 84px; 32 | transition: background-color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 33 | margin: 2px; 34 | } 35 | 36 | .toggle:before { 37 | position: absolute; 38 | left: -50px; 39 | top: 15px; 40 | font-size: 18px; 41 | } 42 | 43 | .toggle:after { 44 | position: absolute; 45 | right: -48px; 46 | top: 15px; 47 | font-size: 18px; 48 | color: #749ED7; 49 | } 50 | 51 | .toggle__handler { 52 | display: inline-block; 53 | position: relative; 54 | z-index: 1; 55 | top: 3px; 56 | left: 3px; 57 | width: 44px; 58 | height: 44px; 59 | background-color: #FFCF96; 60 | border-radius: 50px; 61 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); 62 | transition: all 400ms cubic-bezier(0.68, -0.55, 0.265, 1.55); 63 | transform: rotate(-45deg); 64 | } 65 | 66 | .toggle__handler .crater { 67 | position: absolute; 68 | background-color: #E8CDA5; 69 | opacity: 0; 70 | transition: opacity 200ms ease-in-out; 71 | border-radius: 100%; 72 | } 73 | 74 | .toggle__handler .crater--1 { 75 | top: 18px; 76 | left: 10px; 77 | width: 4px; 78 | height: 4px; 79 | } 80 | 81 | .toggle__handler .crater--2 { 82 | top: 28px; 83 | left: 22px; 84 | width: 6px; 85 | height: 6px; 86 | } 87 | 88 | .toggle__handler .crater--3 { 89 | top: 10px; 90 | left: 25px; 91 | width: 8px; 92 | height: 8px; 93 | } 94 | 95 | .star { 96 | position: absolute; 97 | background-color: #ffffff; 98 | transition: all 300ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 99 | border-radius: 50%; 100 | } 101 | 102 | .star--1 { 103 | top: 10px; 104 | left: 35px; 105 | z-index: 0; 106 | width: 30px; 107 | height: 3px; 108 | } 109 | 110 | .star--2 { 111 | top: 18px; 112 | left: 28px; 113 | z-index: 1; 114 | width: 30px; 115 | height: 3px; 116 | } 117 | 118 | .star--3 { 119 | top: 27px; 120 | left: 40px; 121 | z-index: 0; 122 | width: 30px; 123 | height: 3px; 124 | } 125 | 126 | .star--4, 127 | .star--5, 128 | .star--6 { 129 | opacity: 0; 130 | transition: all 300ms 0 cubic-bezier(0.445, 0.05, 0.55, 0.95); 131 | } 132 | 133 | .star--4 { 134 | top: 16px; 135 | left: 11px; 136 | z-index: 0; 137 | width: 2px; 138 | height: 2px; 139 | transform: translate3d(3px, 0, 0); 140 | } 141 | 142 | .star--5 { 143 | top: 32px; 144 | left: 17px; 145 | z-index: 0; 146 | width: 3px; 147 | height: 3px; 148 | transform: translate3d(3px, 0, 0); 149 | } 150 | 151 | .star--6 { 152 | top: 36px; 153 | left: 28px; 154 | z-index: 0; 155 | width: 2px; 156 | height: 2px; 157 | transform: translate3d(3px, 0, 0); 158 | } 159 | 160 | input:checked+.toggle { 161 | background-color: #749DD6; 162 | } 163 | 164 | input:checked+.toggle:before { 165 | color: #749ED7; 166 | } 167 | 168 | input:checked+.toggle:after { 169 | color: #ffffff; 170 | } 171 | 172 | input:checked+.toggle .toggle__handler { 173 | background-color: #FFE5B5; 174 | transform: translate3d(40px, 0, 0) rotate(0); 175 | } 176 | 177 | input:checked+.toggle .toggle__handler .crater { 178 | opacity: 1; 179 | } 180 | 181 | input:checked+.toggle .star--1 { 182 | width: 2px; 183 | height: 2px; 184 | } 185 | 186 | input:checked+.toggle .star--2 { 187 | width: 4px; 188 | height: 4px; 189 | transform: translate3d(-5px, 0, 0); 190 | } 191 | 192 | input:checked+.toggle .star--3 { 193 | width: 2px; 194 | height: 2px; 195 | transform: translate3d(-7px, 0, 0); 196 | } 197 | 198 | input:checked+.toggle .star--4, 199 | input:checked+.toggle .star--5, 200 | input:checked+.toggle .star--6 { 201 | opacity: 1; 202 | transform: translate3d(0, 0, 0); 203 | } 204 | 205 | input:checked+.toggle .star--4 { 206 | transition: all 300ms 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 207 | } 208 | 209 | input:checked+.toggle .star--5 { 210 | transition: all 300ms 300ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 211 | } 212 | 213 | input:checked+.toggle .star--6 { 214 | transition: all 300ms 400ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 215 | } -------------------------------------------------------------------------------- /19-Toggler-Composed/src/App.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #1E314F; 3 | font-family: 'Helvetica Rounded', 'Arial Rounded MT Bold', 'Montserrat', sans-serif; 4 | color: #fff; 5 | } 6 | 7 | .toggleWrapper { 8 | position: absolute; 9 | top: 50%; 10 | left: 50%; 11 | transform: translate3d(-50%, -50%, 0); 12 | } 13 | 14 | .toggleWrapper>span { 15 | text-align: center; 16 | display: block; 17 | } 18 | 19 | .toggleWrapper input { 20 | position: absolute; 21 | left: -99em; 22 | } 23 | 24 | .toggle { 25 | cursor: pointer; 26 | display: inline-block; 27 | position: relative; 28 | width: 90px; 29 | height: 50px; 30 | background-color: #83D8FF; 31 | border-radius: 84px; 32 | transition: background-color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 33 | margin: 2px; 34 | } 35 | 36 | .toggle:before { 37 | position: absolute; 38 | left: -50px; 39 | top: 15px; 40 | font-size: 18px; 41 | } 42 | 43 | .toggle:after { 44 | position: absolute; 45 | right: -48px; 46 | top: 15px; 47 | font-size: 18px; 48 | color: #749ED7; 49 | } 50 | 51 | .toggle__handler { 52 | display: inline-block; 53 | position: relative; 54 | z-index: 1; 55 | top: 3px; 56 | left: 3px; 57 | width: 44px; 58 | height: 44px; 59 | background-color: #FFCF96; 60 | border-radius: 50px; 61 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); 62 | transition: all 400ms cubic-bezier(0.68, -0.55, 0.265, 1.55); 63 | transform: rotate(-45deg); 64 | } 65 | 66 | .toggle__handler .crater { 67 | position: absolute; 68 | background-color: #E8CDA5; 69 | opacity: 0; 70 | transition: opacity 200ms ease-in-out; 71 | border-radius: 100%; 72 | } 73 | 74 | .toggle__handler .crater--1 { 75 | top: 18px; 76 | left: 10px; 77 | width: 4px; 78 | height: 4px; 79 | } 80 | 81 | .toggle__handler .crater--2 { 82 | top: 28px; 83 | left: 22px; 84 | width: 6px; 85 | height: 6px; 86 | } 87 | 88 | .toggle__handler .crater--3 { 89 | top: 10px; 90 | left: 25px; 91 | width: 8px; 92 | height: 8px; 93 | } 94 | 95 | .star { 96 | position: absolute; 97 | background-color: #ffffff; 98 | transition: all 300ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 99 | border-radius: 50%; 100 | } 101 | 102 | .star--1 { 103 | top: 10px; 104 | left: 35px; 105 | z-index: 0; 106 | width: 30px; 107 | height: 3px; 108 | } 109 | 110 | .star--2 { 111 | top: 18px; 112 | left: 28px; 113 | z-index: 1; 114 | width: 30px; 115 | height: 3px; 116 | } 117 | 118 | .star--3 { 119 | top: 27px; 120 | left: 40px; 121 | z-index: 0; 122 | width: 30px; 123 | height: 3px; 124 | } 125 | 126 | .star--4, 127 | .star--5, 128 | .star--6 { 129 | opacity: 0; 130 | transition: all 300ms 0 cubic-bezier(0.445, 0.05, 0.55, 0.95); 131 | } 132 | 133 | .star--4 { 134 | top: 16px; 135 | left: 11px; 136 | z-index: 0; 137 | width: 2px; 138 | height: 2px; 139 | transform: translate3d(3px, 0, 0); 140 | } 141 | 142 | .star--5 { 143 | top: 32px; 144 | left: 17px; 145 | z-index: 0; 146 | width: 3px; 147 | height: 3px; 148 | transform: translate3d(3px, 0, 0); 149 | } 150 | 151 | .star--6 { 152 | top: 36px; 153 | left: 28px; 154 | z-index: 0; 155 | width: 2px; 156 | height: 2px; 157 | transform: translate3d(3px, 0, 0); 158 | } 159 | 160 | input:checked+.toggle { 161 | background-color: #749DD6; 162 | } 163 | 164 | input:checked+.toggle:before { 165 | color: #749ED7; 166 | } 167 | 168 | input:checked+.toggle:after { 169 | color: #ffffff; 170 | } 171 | 172 | input:checked+.toggle .toggle__handler { 173 | background-color: #FFE5B5; 174 | transform: translate3d(40px, 0, 0) rotate(0); 175 | } 176 | 177 | input:checked+.toggle .toggle__handler .crater { 178 | opacity: 1; 179 | } 180 | 181 | input:checked+.toggle .star--1 { 182 | width: 2px; 183 | height: 2px; 184 | } 185 | 186 | input:checked+.toggle .star--2 { 187 | width: 4px; 188 | height: 4px; 189 | transform: translate3d(-5px, 0, 0); 190 | } 191 | 192 | input:checked+.toggle .star--3 { 193 | width: 2px; 194 | height: 2px; 195 | transform: translate3d(-7px, 0, 0); 196 | } 197 | 198 | input:checked+.toggle .star--4, 199 | input:checked+.toggle .star--5, 200 | input:checked+.toggle .star--6 { 201 | opacity: 1; 202 | transform: translate3d(0, 0, 0); 203 | } 204 | 205 | input:checked+.toggle .star--4 { 206 | transition: all 300ms 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 207 | } 208 | 209 | input:checked+.toggle .star--5 { 210 | transition: all 300ms 300ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 211 | } 212 | 213 | input:checked+.toggle .star--6 { 214 | transition: all 300ms 400ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 215 | } 216 | -------------------------------------------------------------------------------- /20-Compound-Components/src/App.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #1E314F; 3 | font-family: 'Helvetica Rounded', 'Arial Rounded MT Bold', 'Montserrat', sans-serif; 4 | color: #fff; 5 | } 6 | 7 | .toggleWrapper { 8 | position: absolute; 9 | top: 50%; 10 | left: 50%; 11 | transform: translate3d(-50%, -50%, 0); 12 | } 13 | 14 | .toggleWrapper>span { 15 | text-align: center; 16 | display: block; 17 | } 18 | 19 | .toggleWrapper input { 20 | position: absolute; 21 | left: -99em; 22 | } 23 | 24 | .toggle { 25 | cursor: pointer; 26 | display: inline-block; 27 | position: relative; 28 | width: 90px; 29 | height: 50px; 30 | background-color: #83D8FF; 31 | border-radius: 84px; 32 | transition: background-color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 33 | margin: 2px; 34 | } 35 | 36 | .toggle:before { 37 | position: absolute; 38 | left: -50px; 39 | top: 15px; 40 | font-size: 18px; 41 | } 42 | 43 | .toggle:after { 44 | position: absolute; 45 | right: -48px; 46 | top: 15px; 47 | font-size: 18px; 48 | color: #749ED7; 49 | } 50 | 51 | .toggle__handler { 52 | display: inline-block; 53 | position: relative; 54 | z-index: 1; 55 | top: 3px; 56 | left: 3px; 57 | width: 44px; 58 | height: 44px; 59 | background-color: #FFCF96; 60 | border-radius: 50px; 61 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); 62 | transition: all 400ms cubic-bezier(0.68, -0.55, 0.265, 1.55); 63 | transform: rotate(-45deg); 64 | } 65 | 66 | .toggle__handler .crater { 67 | position: absolute; 68 | background-color: #E8CDA5; 69 | opacity: 0; 70 | transition: opacity 200ms ease-in-out; 71 | border-radius: 100%; 72 | } 73 | 74 | .toggle__handler .crater--1 { 75 | top: 18px; 76 | left: 10px; 77 | width: 4px; 78 | height: 4px; 79 | } 80 | 81 | .toggle__handler .crater--2 { 82 | top: 28px; 83 | left: 22px; 84 | width: 6px; 85 | height: 6px; 86 | } 87 | 88 | .toggle__handler .crater--3 { 89 | top: 10px; 90 | left: 25px; 91 | width: 8px; 92 | height: 8px; 93 | } 94 | 95 | .star { 96 | position: absolute; 97 | background-color: #ffffff; 98 | transition: all 300ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 99 | border-radius: 50%; 100 | } 101 | 102 | .star--1 { 103 | top: 10px; 104 | left: 35px; 105 | z-index: 0; 106 | width: 30px; 107 | height: 3px; 108 | } 109 | 110 | .star--2 { 111 | top: 18px; 112 | left: 28px; 113 | z-index: 1; 114 | width: 30px; 115 | height: 3px; 116 | } 117 | 118 | .star--3 { 119 | top: 27px; 120 | left: 40px; 121 | z-index: 0; 122 | width: 30px; 123 | height: 3px; 124 | } 125 | 126 | .star--4, 127 | .star--5, 128 | .star--6 { 129 | opacity: 0; 130 | transition: all 300ms 0 cubic-bezier(0.445, 0.05, 0.55, 0.95); 131 | } 132 | 133 | .star--4 { 134 | top: 16px; 135 | left: 11px; 136 | z-index: 0; 137 | width: 2px; 138 | height: 2px; 139 | transform: translate3d(3px, 0, 0); 140 | } 141 | 142 | .star--5 { 143 | top: 32px; 144 | left: 17px; 145 | z-index: 0; 146 | width: 3px; 147 | height: 3px; 148 | transform: translate3d(3px, 0, 0); 149 | } 150 | 151 | .star--6 { 152 | top: 36px; 153 | left: 28px; 154 | z-index: 0; 155 | width: 2px; 156 | height: 2px; 157 | transform: translate3d(3px, 0, 0); 158 | } 159 | 160 | input:checked+.toggle { 161 | background-color: #749DD6; 162 | } 163 | 164 | input:checked+.toggle:before { 165 | color: #749ED7; 166 | } 167 | 168 | input:checked+.toggle:after { 169 | color: #ffffff; 170 | } 171 | 172 | input:checked+.toggle .toggle__handler { 173 | background-color: #FFE5B5; 174 | transform: translate3d(40px, 0, 0) rotate(0); 175 | } 176 | 177 | input:checked+.toggle .toggle__handler .crater { 178 | opacity: 1; 179 | } 180 | 181 | input:checked+.toggle .star--1 { 182 | width: 2px; 183 | height: 2px; 184 | } 185 | 186 | input:checked+.toggle .star--2 { 187 | width: 4px; 188 | height: 4px; 189 | transform: translate3d(-5px, 0, 0); 190 | } 191 | 192 | input:checked+.toggle .star--3 { 193 | width: 2px; 194 | height: 2px; 195 | transform: translate3d(-7px, 0, 0); 196 | } 197 | 198 | input:checked+.toggle .star--4, 199 | input:checked+.toggle .star--5, 200 | input:checked+.toggle .star--6 { 201 | opacity: 1; 202 | transform: translate3d(0, 0, 0); 203 | } 204 | 205 | input:checked+.toggle .star--4 { 206 | transition: all 300ms 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 207 | } 208 | 209 | input:checked+.toggle .star--5 { 210 | transition: all 300ms 300ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 211 | } 212 | 213 | input:checked+.toggle .star--6 { 214 | transition: all 300ms 400ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 215 | } 216 | -------------------------------------------------------------------------------- /18-Toggler/src/App.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #1E314F; 3 | font-family: 'Helvetica Rounded', 'Arial Rounded MT Bold', 'Montserrat', sans-serif; 4 | color: #fff; 5 | } 6 | 7 | .toggleWrapper { 8 | position: absolute; 9 | top: 50%; 10 | left: 50%; 11 | overflow: hidden; 12 | transform: translate3d(-50%, -50%, 0); 13 | } 14 | 15 | .toggleWrapper input { 16 | position: absolute; 17 | left: -99em; 18 | } 19 | 20 | .toggle { 21 | cursor: pointer; 22 | display: inline-block; 23 | position: relative; 24 | width: 90px; 25 | height: 50px; 26 | background-color: #83D8FF; 27 | border-radius: 84px; 28 | transition: background-color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 29 | margin: 2px; 30 | } 31 | 32 | .toggle:before { 33 | position: absolute; 34 | left: -50px; 35 | top: 15px; 36 | font-size: 18px; 37 | } 38 | 39 | .toggle:after { 40 | position: absolute; 41 | right: -48px; 42 | top: 15px; 43 | font-size: 18px; 44 | color: #749ED7; 45 | } 46 | 47 | .toggle__handler { 48 | display: inline-block; 49 | position: relative; 50 | z-index: 1; 51 | top: 3px; 52 | left: 3px; 53 | width: 44px; 54 | height: 44px; 55 | background-color: #FFCF96; 56 | border-radius: 50px; 57 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); 58 | transition: all 400ms cubic-bezier(0.68, -0.55, 0.265, 1.55); 59 | transform: rotate(-45deg); 60 | } 61 | 62 | .toggle__handler .crater { 63 | position: absolute; 64 | background-color: #E8CDA5; 65 | opacity: 0; 66 | transition: opacity 200ms ease-in-out; 67 | border-radius: 100%; 68 | } 69 | 70 | .toggle__handler .crater--1 { 71 | top: 18px; 72 | left: 10px; 73 | width: 4px; 74 | height: 4px; 75 | } 76 | 77 | .toggle__handler .crater--2 { 78 | top: 28px; 79 | left: 22px; 80 | width: 6px; 81 | height: 6px; 82 | } 83 | 84 | .toggle__handler .crater--3 { 85 | top: 10px; 86 | left: 25px; 87 | width: 8px; 88 | height: 8px; 89 | } 90 | 91 | .star { 92 | position: absolute; 93 | background-color: #ffffff; 94 | transition: all 300ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 95 | border-radius: 50%; 96 | } 97 | 98 | .star--1 { 99 | top: 10px; 100 | left: 35px; 101 | z-index: 0; 102 | width: 30px; 103 | height: 3px; 104 | } 105 | 106 | .star--2 { 107 | top: 18px; 108 | left: 28px; 109 | z-index: 1; 110 | width: 30px; 111 | height: 3px; 112 | } 113 | 114 | .star--3 { 115 | top: 27px; 116 | left: 40px; 117 | z-index: 0; 118 | width: 30px; 119 | height: 3px; 120 | } 121 | 122 | .star--4, 123 | .star--5, 124 | .star--6 { 125 | opacity: 0; 126 | transition: all 300ms 0 cubic-bezier(0.445, 0.05, 0.55, 0.95); 127 | } 128 | 129 | .star--4 { 130 | top: 16px; 131 | left: 11px; 132 | z-index: 0; 133 | width: 2px; 134 | height: 2px; 135 | transform: translate3d(3px, 0, 0); 136 | } 137 | 138 | .star--5 { 139 | top: 32px; 140 | left: 17px; 141 | z-index: 0; 142 | width: 3px; 143 | height: 3px; 144 | transform: translate3d(3px, 0, 0); 145 | } 146 | 147 | .star--6 { 148 | top: 36px; 149 | left: 28px; 150 | z-index: 0; 151 | width: 2px; 152 | height: 2px; 153 | transform: translate3d(3px, 0, 0); 154 | } 155 | 156 | input:checked+.toggle { 157 | background-color: #749DD6; 158 | } 159 | 160 | input:checked+.toggle:before { 161 | color: #749ED7; 162 | } 163 | 164 | input:checked+.toggle:after { 165 | color: #ffffff; 166 | } 167 | 168 | input:checked+.toggle .toggle__handler { 169 | background-color: #FFE5B5; 170 | transform: translate3d(40px, 0, 0) rotate(0); 171 | } 172 | 173 | input:checked+.toggle .toggle__handler .crater { 174 | opacity: 1; 175 | } 176 | 177 | input:checked+.toggle .star--1 { 178 | width: 2px; 179 | height: 2px; 180 | } 181 | 182 | input:checked+.toggle .star--2 { 183 | width: 4px; 184 | height: 4px; 185 | transform: translate3d(-5px, 0, 0); 186 | } 187 | 188 | input:checked+.toggle .star--3 { 189 | width: 2px; 190 | height: 2px; 191 | transform: translate3d(-7px, 0, 0); 192 | } 193 | 194 | input:checked+.toggle .star--4, 195 | input:checked+.toggle .star--5, 196 | input:checked+.toggle .star--6 { 197 | opacity: 1; 198 | transform: translate3d(0, 0, 0); 199 | } 200 | 201 | input:checked+.toggle .star--4 { 202 | transition: all 300ms 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 203 | } 204 | 205 | input:checked+.toggle .star--5 { 206 | transition: all 300ms 300ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 207 | } 208 | 209 | input:checked+.toggle .star--6 { 210 | transition: all 300ms 400ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 211 | } 212 | 213 | #root>div>label:active { 214 | animation: shake 0.1s cubic-bezier(.36, .07, .19, .97) both; 215 | transform: translate3d(0, 0, 0); 216 | backface-visibility: hidden; 217 | perspective: 1000px; 218 | } 219 | 220 | @keyframes shake { 221 | 10%, 222 | 90% { 223 | transform: translate3d(-1px, 0, 0); 224 | } 225 | 20%, 226 | 80% { 227 | transform: translate3d(1px, 0, 0); 228 | } 229 | 30%, 230 | 50%, 231 | 70% { 232 | transform: translate3d(-1px, 0, 0); 233 | } 234 | 40%, 235 | 60% { 236 | transform: translate3d(1px, 0, 0); 237 | } 238 | } --------------------------------------------------------------------------------