├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt └── src ├── App.js ├── data.js ├── index.css └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-projects-7-slider 2 | 3 | #### IN ACTION 4 | 5 | [Gatsby-Airtable Project](https://gatsby-airtable-design-project.netlify.app/) 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reminder", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.5.0", 8 | "@testing-library/user-event": "^7.2.1", 9 | "react": "^16.13.1", 10 | "react-dom": "^16.13.1", 11 | "react-icons": "^3.11.0", 12 | "react-scripts": "3.4.3" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "CI= react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": "react-app" 22 | }, 23 | "browserslist": { 24 | "production": [ 25 | ">0.2%", 26 | "not dead", 27 | "not op_mini all" 28 | ], 29 | "development": [ 30 | "last 1 chrome version", 31 | "last 1 firefox version", 32 | "last 1 safari version" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/john-smilga/react-projects-7-slider/abc8e9041b9e9fc701bd342a75789cfd185931bc/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Slider Complete 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/john-smilga/react-projects-7-slider/abc8e9041b9e9fc701bd342a75789cfd185931bc/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/john-smilga/react-projects-7-slider/abc8e9041b9e9fc701bd342a75789cfd185931bc/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { FiChevronRight, FiChevronLeft } from 'react-icons/fi'; 3 | import { FaQuoteRight } from 'react-icons/fa'; 4 | import data from './data'; 5 | function App() { 6 | const [people, setPeople] = useState(data); 7 | const [index, setIndex] = React.useState(0); 8 | 9 | useEffect(() => { 10 | const lastIndex = people.length - 1; 11 | if (index < 0) { 12 | setIndex(lastIndex); 13 | } 14 | if (index > lastIndex) { 15 | setIndex(0); 16 | } 17 | }, [index, people]); 18 | 19 | useEffect(() => { 20 | let slider = setInterval(() => { 21 | setIndex(index + 1); 22 | }, 5000); 23 | return () => { 24 | clearInterval(slider); 25 | }; 26 | }, [index]); 27 | 28 | return ( 29 |
30 |
31 |

32 | /reviews 33 |

34 |
35 |
36 | {people.map((person, personIndex) => { 37 | const { id, image, name, title, quote } = person; 38 | 39 | let position = 'nextSlide'; 40 | if (personIndex === index) { 41 | position = 'activeSlide'; 42 | } 43 | if ( 44 | personIndex === index - 1 || 45 | (index === 0 && personIndex === people.length - 1) 46 | ) { 47 | position = 'lastSlide'; 48 | } 49 | 50 | return ( 51 |
52 | {name} 53 |

{name}

54 |

{title}

55 |

{quote}

56 | 57 |
58 | ); 59 | })} 60 | 63 | 66 |
67 |
68 | ); 69 | } 70 | 71 | export default App; 72 | -------------------------------------------------------------------------------- /src/data.js: -------------------------------------------------------------------------------- 1 | const people = [ 2 | { 3 | id: 1, 4 | image: 'https://www.course-api.com/images/people/person-1.jpeg', 5 | name: 'maria ferguson', 6 | title: 'office manager', 7 | quote: 8 | 'Fingerstache umami squid, kinfolk subway tile selvage tumblr man braid viral kombucha gentrify fanny pack raclette pok pok mustache.', 9 | }, 10 | { 11 | id: 2, 12 | image: 'https://www.course-api.com/images/people/person-4.jpeg', 13 | name: 'john doe', 14 | title: 'regular guy', 15 | quote: 16 | 'Gastropub sustainable tousled prism occupy. Viral XOXO roof party brunch actually, chambray listicle microdosing put a bird on it paleo subway tile squid umami.', 17 | }, 18 | { 19 | id: 3, 20 | image: 'https://www.course-api.com/images/people/person-3.jpeg', 21 | name: 'peter smith', 22 | title: 'product designer', 23 | quote: 24 | 'Drinking vinegar polaroid street art echo park, actually semiotics next level butcher master cleanse hammock flexitarian ethical paleo.', 25 | }, 26 | { 27 | id: 4, 28 | image: 'https://www.course-api.com/images/people/person-2.jpeg', 29 | name: 'susan andersen', 30 | title: 'the boss', 31 | quote: 32 | 'Marfa af yr 3 wolf moon kogi, readymade distillery asymmetrical seitan kale chips fingerstache cloud bread mustache twee messenger bag. ', 33 | }, 34 | ]; 35 | 36 | export default people; 37 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | /* 2 | =============== 3 | Variables 4 | =============== 5 | */ 6 | 7 | :root { 8 | /* dark shades of primary color*/ 9 | --clr-primary-1: hsl(21, 91%, 17%); 10 | --clr-primary-2: hsl(21, 84%, 25%); 11 | --clr-primary-3: hsl(21, 81%, 29%); 12 | --clr-primary-4: hsl(21, 77%, 34%); 13 | --clr-primary-5: hsl(21, 62%, 45%); 14 | --clr-primary-6: hsl(21, 57%, 50%); 15 | --clr-primary-7: hsl(21, 65%, 59%); 16 | --clr-primary-8: hsl(21, 80%, 74%); 17 | --clr-primary-9: hsl(21, 94%, 87%); 18 | --clr-primary-10: hsl(21, 100%, 94%); 19 | /* darkest grey - used for headings */ 20 | --clr-grey-1: hsl(209, 61%, 16%); 21 | --clr-grey-2: hsl(211, 39%, 23%); 22 | --clr-grey-3: hsl(209, 34%, 30%); 23 | --clr-grey-4: hsl(209, 28%, 39%); 24 | /* grey used for paragraphs */ 25 | --clr-grey-5: hsl(210, 22%, 49%); 26 | --clr-grey-6: hsl(209, 23%, 60%); 27 | --clr-grey-7: hsl(211, 27%, 70%); 28 | --clr-grey-8: hsl(210, 31%, 80%); 29 | --clr-grey-9: hsl(212, 33%, 89%); 30 | --clr-grey-10: hsl(210, 36%, 96%); 31 | --clr-white: #fff; 32 | --clr-red-dark: hsl(360, 67%, 44%); 33 | --clr-red-light: hsl(360, 71%, 66%); 34 | --clr-green-dark: hsl(125, 67%, 44%); 35 | --clr-green-light: hsl(125, 71%, 66%); 36 | --clr-black: #222; 37 | --transition: all 0.3s linear; 38 | --spacing: 0.1rem; 39 | --radius: 0.25rem; 40 | --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); 41 | --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); 42 | --max-width: 1170px; 43 | --fixed-width: 620px; 44 | } 45 | /* 46 | =============== 47 | Global Styles 48 | =============== 49 | */ 50 | 51 | *, 52 | ::after, 53 | ::before { 54 | margin: 0; 55 | padding: 0; 56 | box-sizing: border-box; 57 | } 58 | body { 59 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, 60 | Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 61 | background: var(--clr-grey-10); 62 | color: var(--clr-grey-1); 63 | line-height: 1.5; 64 | font-size: 0.875rem; 65 | } 66 | ul { 67 | list-style-type: none; 68 | } 69 | a { 70 | text-decoration: none; 71 | } 72 | h1, 73 | h2, 74 | h3, 75 | h4 { 76 | letter-spacing: var(--spacing); 77 | text-transform: capitalize; 78 | line-height: 1.25; 79 | margin-bottom: 0.75rem; 80 | } 81 | h1 { 82 | font-size: 3rem; 83 | } 84 | h2 { 85 | font-size: 2rem; 86 | } 87 | h3 { 88 | font-size: 1.25rem; 89 | } 90 | h4 { 91 | font-size: 0.875rem; 92 | } 93 | p { 94 | margin-bottom: 1.25rem; 95 | color: var(--clr-grey-5); 96 | } 97 | @media screen and (min-width: 800px) { 98 | h1 { 99 | font-size: 4rem; 100 | } 101 | h2 { 102 | font-size: 2.5rem; 103 | } 104 | h3 { 105 | font-size: 1.75rem; 106 | } 107 | h4 { 108 | font-size: 1rem; 109 | } 110 | body { 111 | font-size: 1rem; 112 | } 113 | h1, 114 | h2, 115 | h3, 116 | h4 { 117 | line-height: 1; 118 | } 119 | } 120 | /* global classes */ 121 | 122 | /* section */ 123 | .section { 124 | width: 90vw; 125 | margin: 5rem auto; 126 | max-width: var(--max-width); 127 | } 128 | 129 | @media screen and (min-width: 992px) { 130 | .section { 131 | width: 95vw; 132 | } 133 | } 134 | /* 135 | =============== 136 | Slider 137 | =============== 138 | */ 139 | .title { 140 | text-align: center; 141 | margin-bottom: 2rem; 142 | } 143 | .title h2 { 144 | display: flex; 145 | align-items: center; 146 | justify-content: center; 147 | font-weight: 500; 148 | } 149 | .title span { 150 | font-size: 0.85em; 151 | color: var(--clr-primary-5); 152 | margin-right: 1rem; 153 | font-weight: 700; 154 | } 155 | .section-center { 156 | margin: 0 auto; 157 | margin-top: 4rem; 158 | width: 80vw; 159 | height: 450px; 160 | max-width: 800px; 161 | text-align: center; 162 | position: relative; 163 | display: flex; 164 | overflow: hidden; 165 | } 166 | .person-img { 167 | border-radius: 50%; 168 | margin-bottom: 1rem; 169 | width: 150px; 170 | height: 150px; 171 | object-fit: cover; 172 | border: 4px solid var(--clr-grey-8); 173 | box-shadow: var(--dark-shadow); 174 | } 175 | article h4 { 176 | text-transform: uppercase; 177 | color: var(--clr-primary-5); 178 | margin-bottom: 0.25rem; 179 | } 180 | .title { 181 | text-transform: capitalize; 182 | margin-bottom: 0.75rem; 183 | color: var(--clr-grey-3); 184 | } 185 | .text { 186 | max-width: 35em; 187 | margin: 0 auto; 188 | margin-top: 2rem; 189 | line-height: 2; 190 | color: var(--clr-grey-5); 191 | } 192 | .icon { 193 | font-size: 3rem; 194 | margin-top: 1rem; 195 | color: var(--clr-primary-5); 196 | } 197 | .prev, 198 | .next { 199 | position: absolute; 200 | top: 200px; 201 | transform: translateY(-50%); 202 | background: var(--clr-grey-5); 203 | color: var(--clr-white); 204 | width: 1.25rem; 205 | height: 1.25rem; 206 | display: grid; 207 | place-items: center; 208 | border-color: transparent; 209 | font-size: 1rem; 210 | border-radius: var(--radius); 211 | cursor: pointer; 212 | transition: var(--transition); 213 | } 214 | .prev:hover, 215 | .next:hover { 216 | background: var(--clr-primary-5); 217 | } 218 | .prev { 219 | left: 0; 220 | } 221 | .next { 222 | right: 0; 223 | } 224 | @media (min-width: 800px) { 225 | .text { 226 | max-width: 45em; 227 | } 228 | .prev, 229 | .next { 230 | width: 2rem; 231 | height: 2rem; 232 | font-size: 1.5rem; 233 | } 234 | } 235 | article { 236 | position: absolute; 237 | top: 0; 238 | left: 0; 239 | width: 100%; 240 | height: 100%; 241 | opacity: 0; 242 | transition: var(--transition); 243 | } 244 | article.activeSlide { 245 | opacity: 1; 246 | transform: translateX(0); 247 | } 248 | article.lastSlide { 249 | transform: translateX(-100%); 250 | } 251 | article.nextSlide { 252 | transform: translateX(100%); 253 | } 254 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ); 12 | --------------------------------------------------------------------------------