├── .eslintignore ├── .eslintrc ├── .gitattributes ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── README.md ├── package.json ├── pnpm-lock.yaml ├── public ├── img │ ├── favicon.ico │ ├── logo192.png │ └── logo512.png ├── index.html ├── manifest.json └── robots.txt └── src ├── App.css ├── App.js ├── components ├── AppItem │ ├── index.css │ └── index.js ├── AppStore │ ├── index.css │ └── index.js └── TabItem │ ├── index.css │ └── index.js ├── index.js └── setupTests.js /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | build 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "parser": "babel-eslint", 7 | "extends": ["react-app", "airbnb", "prettier"], 8 | "parserOptions": { 9 | "ecmaFeatures": { 10 | "jsx": true 11 | }, 12 | "ecmaVersion": 12, 13 | "sourceType": "module" 14 | }, 15 | "plugins": ["prettier"], 16 | "overrides": [ 17 | { 18 | "files": ["styledComponents.js"], 19 | "rules": { 20 | "import/prefer-default-export": "off" 21 | } 22 | } 23 | ], 24 | "rules": { 25 | "prettier/prettier": "error", 26 | "react/jsx-filename-extension": [1, {"extensions": [".js", ".jsx"]}], 27 | "react/state-in-constructor": "off", 28 | "react/react-in-jsx-scope": "off", 29 | "react/jsx-uses-react": "off", 30 | "no-console": "off", 31 | "react/prop-types": "off", 32 | "jsx-a11y/label-has-associated-control": [ 33 | 2, 34 | { 35 | "labelAttributes": ["htmlFor"] 36 | } 37 | ], 38 | "jsx-a11y/click-events-have-key-events": 0, 39 | "jsx-a11y/no-noninteractive-element-interactions": [ 40 | "off", 41 | { 42 | "handlers": ["onClick"] 43 | } 44 | ], 45 | "react/prefer-stateless-function": [ 46 | 0, 47 | { 48 | "ignorePureComponents": true 49 | } 50 | ], 51 | "no-unused-vars": "warn", 52 | "jsx-a11y/alt-text": 1, 53 | "react/no-unused-state": "warn", 54 | "react/button-has-type": "warn", 55 | "react/no-unescaped-entities": "warn", 56 | "react/jsx-props-no-spreading": "off", 57 | "operator-assignment": ["warn", "always"], 58 | "radix": "off" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | /.pnp 4 | .pnp.js 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 | 23 | .idea/ 24 | .eslintcache 25 | .vscode/ 26 | .results -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org/ 2 | package-lock=true 3 | save-exact=true 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | build 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": false, 4 | "endOfLine": "lf", 5 | "htmlWhitespaceSensitivity": "css", 6 | "insertPragma": false, 7 | "jsxBracketSameLine": false, 8 | "jsxSingleQuote": false, 9 | "printWidth": 80, 10 | "overrides": [ 11 | { 12 | "files": "*.md", 13 | "options": { 14 | "printWidth": 1000 15 | } 16 | } 17 | ], 18 | "proseWrap": "always", 19 | "quoteProps": "as-needed", 20 | "requirePragma": false, 21 | "semi": false, 22 | "singleQuote": true, 23 | "tabWidth": 2, 24 | "trailingComma": "all", 25 | "useTabs": false 26 | } 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-store", 3 | "private": true, 4 | "version": "1.0.0", 5 | "engines": { 6 | "node": "^10.13 || 12 || 14 || 15", 7 | "npm": ">=6" 8 | }, 9 | "dependencies": { 10 | "@testing-library/jest-dom": "5.11.9", 11 | "@testing-library/react": "11.2.5", 12 | "@testing-library/user-event": "12.6.2", 13 | "chalk": "4.1.0", 14 | "react": "17.0.1", 15 | "react-dom": "17.0.1" 16 | }, 17 | "devDependencies": { 18 | "eslint-config-airbnb": "18.2.1", 19 | "eslint-config-prettier": "8.1.0", 20 | "eslint-plugin-prettier": "3.3.1", 21 | "husky": "4.3.8", 22 | "lint-staged": "10.5.4", 23 | "npm-run-all": "4.1.5", 24 | "prettier": "2.2.1", 25 | "react-scripts": "4.0.3" 26 | }, 27 | "scripts": { 28 | "start": "react-scripts start", 29 | "build": "react-scripts build", 30 | "test": "react-scripts test", 31 | "lint": "eslint .", 32 | "lint:fix": "eslint --fix src/", 33 | "format": "prettier --write \"./src\"", 34 | "run-all": "npm-run-all --parallel test lint:fix" 35 | }, 36 | "lint-staged": { 37 | "*.js": [ 38 | "npm run lint:fix" 39 | ], 40 | "*.{js, jsx, json, html, css}": [ 41 | "npm run format" 42 | ] 43 | }, 44 | "husky": { 45 | "hooks": { 46 | "pre-commit": "lint-staged" 47 | } 48 | }, 49 | "jest": { 50 | "collectCoverageFrom": [ 51 | "src/**/*.js" 52 | ] 53 | }, 54 | "browserslist": { 55 | "development": [ 56 | "last 2 chrome versions", 57 | "last 2 firefox versions", 58 | "last 2 edge versions" 59 | ], 60 | "production": [ 61 | ">1%", 62 | "last 4 versions", 63 | "Firefox ESR", 64 | "not ie < 11" 65 | ] 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /public/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NikhilReddy04/BasicAppStore/b476392fdcd362c321ca6f79d3b03e2e39469441/public/img/favicon.ico -------------------------------------------------------------------------------- /public/img/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NikhilReddy04/BasicAppStore/b476392fdcd362c321ca6f79d3b03e2e39469441/public/img/logo192.png -------------------------------------------------------------------------------- /public/img/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NikhilReddy04/BasicAppStore/b476392fdcd362c321ca6f79d3b03e2e39469441/public/img/logo512.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 16 | 17 | 21 | 22 | 31 | React App 32 | 40 | 41 | 42 |
43 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "app_short_name", 3 | "name": "App_name", 4 | "icons": [ 5 | { 6 | "src": "img/favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "img/logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "img/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.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | margin: 0; 7 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 8 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 9 | sans-serif; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import AppStore from './components/AppStore' 2 | 3 | import './App.css' 4 | 5 | const App = () => 6 | 7 | export default App 8 | -------------------------------------------------------------------------------- /src/components/AppItem/index.css: -------------------------------------------------------------------------------- 1 | /* Write your CSS here */ 2 | .app-card { 3 | background-color: #ffffff; 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: center; 8 | padding: 10px; 9 | } 10 | 11 | .app-image { 12 | width: 120px; 13 | padding: 10px; 14 | } 15 | .app-card { 16 | margin: 10px; 17 | border-radius: 10px; 18 | width: 170px; 19 | padding-left: 10px; 20 | padding-right: 10px; 21 | } 22 | 23 | .app-name { 24 | color: #1e293b; 25 | font-family: Bree Serif; 26 | } 27 | -------------------------------------------------------------------------------- /src/components/AppItem/index.js: -------------------------------------------------------------------------------- 1 | import './index.css' 2 | 3 | const AppItem = props => { 4 | const {appItem} = props 5 | 6 | return ( 7 |
  • 8 | {appItem.appName} 9 |

    {appItem.appName}

    10 |
  • 11 | ) 12 | } 13 | 14 | export default AppItem 15 | -------------------------------------------------------------------------------- /src/components/AppStore/index.css: -------------------------------------------------------------------------------- 1 | /* Write your CSS here */ 2 | .bg-container { 3 | background-image: linear-gradient(to bottom, #fff1eb, #ace0f9); 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: flex-start; 8 | text-align: center; 9 | min-height: 100vh; 10 | } 11 | 12 | .top-container { 13 | width: 100%; 14 | display: flex; 15 | flex-direction: column; 16 | align-items: center; 17 | justify-content: center; 18 | } 19 | .apps-container { 20 | display: flex; 21 | flex-wrap: wrap; 22 | } 23 | 24 | .tabs-container { 25 | display: flex; 26 | align-items: center; 27 | justify-content: center; 28 | margin-top: 20px; 29 | } 30 | 31 | .main-heading { 32 | font-size: 30px; 33 | color: #1e293b; 34 | font-family: Bree Serif; 35 | } 36 | 37 | .input-element { 38 | color: #7b8794; 39 | background-color: transparent; 40 | border: none; 41 | width: 90%; 42 | height: 90%; 43 | outline: none; 44 | } 45 | 46 | .search-icon { 47 | width: 30px; 48 | } 49 | 50 | .search-bar-holder { 51 | display: flex; 52 | align-items: center; 53 | justify-content: center; 54 | border: solid 1px #7b8794; 55 | padding: 5px 20px 5px; 56 | width: 30%; 57 | } 58 | 59 | .apps-container { 60 | width: 80%; 61 | align-items: center; 62 | } 63 | 64 | .apps-main-container { 65 | width: 100%; 66 | display: flex; 67 | flex-direction: column; 68 | align-items: center; 69 | justify-content: center; 70 | } 71 | -------------------------------------------------------------------------------- /src/components/AppStore/index.js: -------------------------------------------------------------------------------- 1 | import {Component} from 'react' 2 | 3 | import './index.css' 4 | 5 | import TabItem from '../TabItem/index' 6 | 7 | import AppItem from '../AppItem/index' 8 | 9 | const tabsList = [ 10 | {tabId: 'SOCIAL', displayText: 'Social'}, 11 | {tabId: 'GAMES', displayText: 'Games'}, 12 | {tabId: 'NEWS', displayText: 'News'}, 13 | {tabId: 'FOOD', displayText: 'Food'}, 14 | ] 15 | 16 | const appsList = [ 17 | { 18 | appId: 0, 19 | appName: 'Facebook', 20 | imageUrl: 21 | 'https://assets.ccbp.in/frontend/react-js/app-store/social-facebook.png', 22 | category: 'SOCIAL', 23 | }, 24 | { 25 | appId: 1, 26 | appName: 'Messenger', 27 | imageUrl: 28 | 'https://assets.ccbp.in/frontend/react-js/app-store/social-messenger.png', 29 | category: 'SOCIAL', 30 | }, 31 | { 32 | appId: 2, 33 | appName: 'WhatsApp', 34 | imageUrl: 35 | 'https://assets.ccbp.in/frontend/react-js/app-store/social-whatsapp.png', 36 | category: 'SOCIAL', 37 | }, 38 | { 39 | appId: 3, 40 | appName: 'Instagram', 41 | imageUrl: 42 | 'https://assets.ccbp.in/frontend/react-js/app-store/social-instagram.png', 43 | category: 'SOCIAL', 44 | }, 45 | { 46 | appId: 4, 47 | appName: 'Snapchat', 48 | imageUrl: 49 | 'https://assets.ccbp.in/frontend/react-js/app-store/social-snapchat.png', 50 | category: 'SOCIAL', 51 | }, 52 | { 53 | appId: 5, 54 | appName: 'Twitter', 55 | imageUrl: 56 | 'https://assets.ccbp.in/frontend/react-js/app-store/social-twitter.png', 57 | category: 'SOCIAL', 58 | }, 59 | { 60 | appId: 6, 61 | appName: 'Pinterest', 62 | imageUrl: 63 | 'https://assets.ccbp.in/frontend/react-js/app-store/social-pinterest.png', 64 | category: 'SOCIAL', 65 | }, 66 | { 67 | appId: 7, 68 | appName: 'WeChat', 69 | imageUrl: 70 | 'https://assets.ccbp.in/frontend/react-js/app-store/social-wechat.png', 71 | category: 'SOCIAL', 72 | }, 73 | { 74 | appId: 8, 75 | appName: 'LinkedIn', 76 | imageUrl: 77 | 'https://assets.ccbp.in/frontend/react-js/app-store/social-linkedin.png', 78 | category: 'SOCIAL', 79 | }, 80 | { 81 | appId: 9, 82 | appName: 'Telegram', 83 | imageUrl: 84 | 'https://assets.ccbp.in/frontend/react-js/app-store/social-telegram.png', 85 | category: 'SOCIAL', 86 | }, 87 | { 88 | appId: 10, 89 | appName: 'Subway Surfers', 90 | imageUrl: 91 | 'https://assets.ccbp.in/frontend/react-js/app-store/games-subway-surfers.png', 92 | category: 'GAMES', 93 | }, 94 | { 95 | appId: 11, 96 | appName: 'Crossy Road', 97 | imageUrl: 98 | 'https://assets.ccbp.in/frontend/react-js/app-store/games-crossy-road.png', 99 | category: 'GAMES', 100 | }, 101 | { 102 | appId: 12, 103 | appName: 'Super Chef', 104 | imageUrl: 105 | 'https://assets.ccbp.in/frontend/react-js/app-store/games-super-chef.png', 106 | category: 'GAMES', 107 | }, 108 | { 109 | appId: 13, 110 | appName: 'Angry Birds', 111 | imageUrl: 112 | 'https://assets.ccbp.in/frontend/react-js/app-store/games-angry-birds.png', 113 | category: 'GAMES', 114 | }, 115 | { 116 | appId: 14, 117 | appName: 'Hill Climb 2', 118 | imageUrl: 119 | 'https://assets.ccbp.in/frontend/react-js/app-store/games-hill-climb-2.png', 120 | category: 'GAMES', 121 | }, 122 | { 123 | appId: 15, 124 | appName: 'Temple Run', 125 | imageUrl: 126 | 'https://assets.ccbp.in/frontend/react-js/app-store/games-temple-run.png', 127 | category: 'GAMES', 128 | }, 129 | { 130 | appId: 16, 131 | appName: 'Dr. Driving', 132 | imageUrl: 133 | 'https://assets.ccbp.in/frontend/react-js/app-store/games-dr-driving.png', 134 | category: 'GAMES', 135 | }, 136 | { 137 | appId: 17, 138 | appName: 'Smurfs Bubble', 139 | imageUrl: 140 | 'https://assets.ccbp.in/frontend/react-js/app-store/games-smurfs-bubble.png', 141 | category: 'GAMES', 142 | }, 143 | { 144 | appId: 18, 145 | appName: 'Grade Learning', 146 | imageUrl: 147 | 'https://assets.ccbp.in/frontend/react-js/app-store/games-grade-learning.png', 148 | category: 'GAMES', 149 | }, 150 | { 151 | appId: 19, 152 | appName: 'My Talking Tom', 153 | imageUrl: 154 | 'https://assets.ccbp.in/frontend/react-js/app-store/games-my-talking-tom.png', 155 | category: 'GAMES', 156 | }, 157 | { 158 | appId: 20, 159 | appName: 'Inshorts', 160 | imageUrl: 161 | 'https://assets.ccbp.in/frontend/react-js/app-store/news-inshorts.png', 162 | category: 'NEWS', 163 | }, 164 | { 165 | appId: 21, 166 | appName: 'Way2News', 167 | imageUrl: 168 | 'https://assets.ccbp.in/frontend/react-js/app-store/news-way2news.png', 169 | category: 'NEWS', 170 | }, 171 | { 172 | appId: 22, 173 | appName: 'Google News', 174 | imageUrl: 175 | 'https://assets.ccbp.in/frontend/react-js/app-store/news-google-news.png', 176 | category: 'NEWS', 177 | }, 178 | { 179 | appId: 23, 180 | appName: 'Flipboard', 181 | imageUrl: 182 | 'https://assets.ccbp.in/frontend/react-js/app-store/news-flipboard.png', 183 | category: 'NEWS', 184 | }, 185 | { 186 | appId: 24, 187 | appName: 'SmartNews', 188 | imageUrl: 189 | 'https://assets.ccbp.in/frontend/react-js/app-store/news-smart-news.png', 190 | category: 'NEWS', 191 | }, 192 | { 193 | appId: 25, 194 | appName: 'BBC News', 195 | imageUrl: 196 | 'https://assets.ccbp.in/frontend/react-js/app-store/news-bbc-news.png', 197 | category: 'NEWS', 198 | }, 199 | { 200 | appId: 26, 201 | appName: 'CNN News', 202 | imageUrl: 203 | 'https://assets.ccbp.in/frontend/react-js/app-store/news-cnn-news.png', 204 | category: 'NEWS', 205 | }, 206 | { 207 | appId: 27, 208 | appName: 'Daily Wire', 209 | imageUrl: 210 | 'https://assets.ccbp.in/frontend/react-js/app-store/news-daily-wire.png', 211 | category: 'NEWS', 212 | }, 213 | { 214 | appId: 28, 215 | appName: 'AP News', 216 | imageUrl: 217 | 'https://assets.ccbp.in/frontend/react-js/app-store/news-ap-news.png', 218 | category: 'NEWS', 219 | }, 220 | { 221 | appId: 29, 222 | appName: 'News Break', 223 | imageUrl: 224 | 'https://assets.ccbp.in/frontend/react-js/app-store/news-news-break.png', 225 | category: 'NEWS', 226 | }, 227 | { 228 | appId: 30, 229 | appName: 'Zomato', 230 | imageUrl: 231 | 'https://assets.ccbp.in/frontend/react-js/app-store/food-zomato.png', 232 | category: 'FOOD', 233 | }, 234 | { 235 | appId: 31, 236 | appName: 'Swiggy', 237 | imageUrl: 238 | 'https://assets.ccbp.in/frontend/react-js/app-store/food-swiggy.png', 239 | category: 'FOOD', 240 | }, 241 | { 242 | appId: 32, 243 | appName: "Domino's Pizza", 244 | imageUrl: 245 | 'https://assets.ccbp.in/frontend/react-js/app-store/food-dominos.png', 246 | category: 'FOOD', 247 | }, 248 | { 249 | appId: 33, 250 | appName: 'All in One', 251 | imageUrl: 252 | 'https://assets.ccbp.in/frontend/react-js/app-store/food-all-in-one.png', 253 | category: 'FOOD', 254 | }, 255 | { 256 | appId: 34, 257 | appName: 'Instacart', 258 | imageUrl: 259 | 'https://assets.ccbp.in/frontend/react-js/app-store/food-insta-cart.png', 260 | category: 'FOOD', 261 | }, 262 | { 263 | appId: 35, 264 | appName: 'Saucey', 265 | imageUrl: 266 | 'https://assets.ccbp.in/frontend/react-js/app-store/food-saucey.png', 267 | category: 'FOOD', 268 | }, 269 | { 270 | appId: 36, 271 | appName: 'Waitr', 272 | imageUrl: 273 | 'https://assets.ccbp.in/frontend/react-js/app-store/food-waitr.png', 274 | category: 'FOOD', 275 | }, 276 | { 277 | appId: 37, 278 | appName: 'Grubhub', 279 | imageUrl: 280 | 'https://assets.ccbp.in/frontend/react-js/app-store/food-grubhub.png', 281 | category: 'FOOD', 282 | }, 283 | { 284 | appId: 38, 285 | appName: 'Mercato', 286 | imageUrl: 287 | 'https://assets.ccbp.in/frontend/react-js/app-store/food-mercato.png', 288 | category: 'FOOD', 289 | }, 290 | { 291 | appId: 39, 292 | appName: 'DOT', 293 | imageUrl: 'https://assets.ccbp.in/frontend/react-js/app-store/food-dot.png', 294 | category: 'FOOD', 295 | }, 296 | ] 297 | 298 | class AppStore extends Component { 299 | state = {appCategory: 'SOCIAL', searchIp: ''} 300 | 301 | changeInput = event => { 302 | this.setState({searchIp: event.target.value}) 303 | } 304 | 305 | onChangeTab = Id => { 306 | const tabElement = tabsList.find(eachItem => eachItem.tabId === Id) 307 | this.setState({appCategory: tabElement.tabId}) 308 | } 309 | 310 | render() { 311 | const {appCategory, searchIp} = this.state 312 | 313 | const filteredAppListCategory = appsList.filter( 314 | eachItem => eachItem.category === appCategory, 315 | ) 316 | 317 | const filteredAppList = filteredAppListCategory.filter(eachItem => 318 | eachItem.appName.toLowerCase().includes(searchIp.toLowerCase()), 319 | ) 320 | 321 | return ( 322 |
    323 |
    324 |

    App Store

    325 |
    326 | 332 | search icon 337 |
    338 |
    339 |
    340 |
      341 | {tabsList.map(eachItem => ( 342 | 349 | ))} 350 |
    351 |
      352 | {filteredAppList.map(eachItem => ( 353 | 354 | ))} 355 |
    356 |
    357 |
    358 | ) 359 | } 360 | } 361 | 362 | export default AppStore 363 | -------------------------------------------------------------------------------- /src/components/TabItem/index.css: -------------------------------------------------------------------------------- 1 | /* Write your CSS here */ 2 | .tab-button { 3 | background-color: transparent; 4 | border: none; 5 | border-bottom: solid 2px #7b8794; 6 | color: #7b8794; 7 | font-size: 20px; 8 | padding-right: 10px; 9 | margin-right: 2px; 10 | border-radius: 2px; 11 | } 12 | 13 | .active-class { 14 | color: #2563eb; 15 | border-bottom: solid 2px #2563eb; 16 | } 17 | -------------------------------------------------------------------------------- /src/components/TabItem/index.js: -------------------------------------------------------------------------------- 1 | import './index.css' 2 | 3 | const TabItem = props => { 4 | const {tabItem, onChangeTab, tabId, isActive} = props 5 | const onClickTab = () => { 6 | onChangeTab(tabId) 7 | } 8 | const activeClassName = isActive ? 'active-class' : '' 9 | return ( 10 |
  • 11 | 18 |
  • 19 | ) 20 | } 21 | 22 | export default TabItem 23 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './App' 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root'), 10 | ) 11 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | import '@testing-library/jest-dom' 4 | import {configure} from '@testing-library/react' 5 | 6 | configure({testIdAttribute: 'testid'}) 7 | --------------------------------------------------------------------------------