├── src ├── index.css ├── vite-env.d.ts ├── App.tsx ├── main.tsx └── examples │ ├── transition-1 │ ├── styles.css │ ├── Example.tsx │ ├── image1.svg │ ├── image2.svg │ └── image3.svg │ ├── transition-2 │ ├── styles.css │ └── Example.tsx │ └── transition-3 │ ├── styles.css │ └── Example.tsx ├── vite.config.ts ├── tsconfig.node.json ├── .gitignore ├── index.html ├── .eslintrc.cjs ├── tsconfig.json ├── package.json ├── README.md └── public └── vite.svg /src/index.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Example } from "./examples/transition-3/Example"; 2 | 3 | function App() { 4 | return ; 5 | } 6 | 7 | export default App; 8 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.tsx' 4 | import './index.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root')!).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-transitions", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "react": "^18.2.0", 14 | "react-dom": "^18.2.0" 15 | }, 16 | "devDependencies": { 17 | "@types/react": "^18.2.15", 18 | "@types/react-dom": "^18.2.7", 19 | "@typescript-eslint/eslint-plugin": "^6.0.0", 20 | "@typescript-eslint/parser": "^6.0.0", 21 | "@vitejs/plugin-react": "^4.0.3", 22 | "eslint": "^8.45.0", 23 | "eslint-plugin-react-hooks": "^4.6.0", 24 | "eslint-plugin-react-refresh": "^0.4.3", 25 | "react-router-dom": "^6.16.0", 26 | "typescript": "^5.0.2", 27 | "vite": "^4.4.5" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React + TypeScript + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | 10 | ## Expanding the ESLint configuration 11 | 12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: 13 | 14 | - Configure the top-level `parserOptions` property like this: 15 | 16 | ```js 17 | parserOptions: { 18 | ecmaVersion: 'latest', 19 | sourceType: 'module', 20 | project: ['./tsconfig.json', './tsconfig.node.json'], 21 | tsconfigRootDir: __dirname, 22 | }, 23 | ``` 24 | 25 | - Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` 26 | - Optionally add `plugin:@typescript-eslint/stylistic-type-checked` 27 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list 28 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/examples/transition-1/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | height: 100vh; 4 | background: #f6f2f9; 5 | color: #222222; 6 | font-family: "Euclid Circular A", "Poppins"; 7 | } 8 | 9 | h1, 10 | h2 { 11 | font-weight: 500; 12 | } 13 | 14 | h1 { 15 | font-size: 20px; 16 | } 17 | 18 | h2 { 19 | font-size: 20px; 20 | } 21 | 22 | p { 23 | position: relative; 24 | z-index: 0; 25 | opacity: 0.6; 26 | line-height: 1.6; 27 | } 28 | 29 | nav { 30 | position: fixed; 31 | top: 0; 32 | left: 0; 33 | right: 0; 34 | height: 72px; 35 | padding: 0 40px; 36 | display: flex; 37 | align-items: center; 38 | justify-content: space-between; 39 | background: #ffffff; 40 | } 41 | 42 | nav a { 43 | color: inherit; 44 | cursor: pointer; 45 | } 46 | 47 | nav a.active { 48 | color: #8f44fd; 49 | } 50 | 51 | nav ul { 52 | display: flex; 53 | gap: 20px; 54 | list-style-type: none; 55 | } 56 | 57 | main { 58 | padding: 92px 40px 20px; 59 | } 60 | 61 | main article { 62 | display: flex; 63 | align-items: center; 64 | gap: 50px; 65 | padding: 80px 60px; 66 | } 67 | 68 | main article img { 69 | width: 200px; 70 | height: 200px; 71 | object-fit: contain; 72 | } 73 | 74 | .bars { 75 | position: fixed; 76 | z-index: 1; 77 | top: 0; 78 | left: 0; 79 | right: 0; 80 | bottom: 0; 81 | display: grid; 82 | pointer-events: none; 83 | } 84 | 85 | @keyframes show { 86 | 0% { 87 | transform: translateX(-100%); 88 | } 89 | 100% { 90 | transform: translateX(0); 91 | } 92 | } 93 | 94 | @keyframes hide { 95 | 0% { 96 | transform: translateX(0); 97 | } 98 | 100% { 99 | transform: translateX(100%); 100 | } 101 | } 102 | 103 | .bars > div { 104 | background: #8f44fd; 105 | transform: translateX(-100%); 106 | } 107 | 108 | .bars.show > div { 109 | animation: show 0.2s both ease-in-out; 110 | } 111 | 112 | .bars.hide > div { 113 | animation: hide 0.2s both ease-in-out; 114 | } 115 | -------------------------------------------------------------------------------- /src/examples/transition-2/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | height: 100vh; 4 | color: #222222; 5 | font-family: "Euclid Circular A", "Poppins"; 6 | } 7 | 8 | h1, 9 | h2 { 10 | font-weight: 500; 11 | } 12 | 13 | h1 { 14 | font-size: 20px; 15 | } 16 | 17 | h2 { 18 | font-size: 20px; 19 | } 20 | 21 | p { 22 | position: relative; 23 | z-index: 0; 24 | opacity: 0.6; 25 | line-height: 1.6; 26 | } 27 | 28 | nav { 29 | position: fixed; 30 | top: 0; 31 | left: 0; 32 | right: 0; 33 | height: 122px; 34 | padding: 0 40px; 35 | display: flex; 36 | align-items: center; 37 | justify-content: space-between; 38 | } 39 | 40 | nav a { 41 | color: inherit; 42 | cursor: pointer; 43 | } 44 | 45 | nav a.active { 46 | color: #8f44fd; 47 | } 48 | 49 | nav ul { 50 | display: flex; 51 | gap: 20px; 52 | list-style-type: none; 53 | } 54 | 55 | #bubbles { 56 | --size: 250vw; 57 | } 58 | 59 | @media only screen and (min-width: 768px) { 60 | #bubbles { 61 | --size: 300vw; 62 | } 63 | } 64 | 65 | .bubbles__first, 66 | .bubbles__second { 67 | position: fixed; 68 | z-index: 9999; 69 | top: 0; 70 | left: 50%; 71 | translate: -50% 100%; 72 | width: var(--size); 73 | height: var(--size); 74 | border-radius: var(--size); 75 | animation-timing-function: ease-in-out; 76 | } 77 | 78 | #bubbles.show .bubbles__first { 79 | animation-name: bubble-move; 80 | } 81 | 82 | #bubbles.show .bubbles__second { 83 | animation-name: bubble-second-move; 84 | } 85 | 86 | @keyframes bubble-move { 87 | 20% { 88 | border-radius: var(--size); 89 | } 90 | 50%, 91 | 100% { 92 | translate: -50% 0; 93 | border-radius: 0; 94 | } 95 | } 96 | 97 | @keyframes bubble-second-move { 98 | 30% { 99 | translate: -50% 100%; 100 | } 101 | 50% { 102 | border-radius: var(--size); 103 | } 104 | 100% { 105 | translate: -50% 0; 106 | border-radius: 0; 107 | } 108 | } 109 | 110 | @keyframes appear { 111 | 0% { 112 | opacity: 0; 113 | translate: 0 100%; 114 | } 115 | 100% { 116 | opacity: 1; 117 | translate: 0; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/examples/transition-3/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | height: 100vh; 4 | color: #222222; 5 | font-family: "Euclid Circular A", "Poppins"; 6 | } 7 | 8 | h1, 9 | h2 { 10 | font-weight: 500; 11 | } 12 | 13 | h1 { 14 | font-size: 20px; 15 | } 16 | 17 | h2 { 18 | font-size: 20px; 19 | } 20 | 21 | p { 22 | position: relative; 23 | z-index: 0; 24 | opacity: 0.6; 25 | line-height: 1.6; 26 | } 27 | 28 | section { 29 | height: 100vh; 30 | } 31 | 32 | nav { 33 | position: fixed; 34 | top: 0; 35 | left: 0; 36 | right: 0; 37 | height: 142px; 38 | padding: 0 60px; 39 | display: flex; 40 | align-items: center; 41 | justify-content: space-between; 42 | } 43 | 44 | nav a { 45 | color: inherit; 46 | cursor: pointer; 47 | font-weight: 400; 48 | } 49 | 50 | nav a.active { 51 | color: #8f44fd; 52 | } 53 | 54 | nav ul { 55 | display: flex; 56 | gap: 20px; 57 | list-style-type: none; 58 | } 59 | 60 | #bubbles { 61 | --size: 250vw; 62 | } 63 | 64 | @media only screen and (min-width: 768px) { 65 | #bubbles { 66 | --size: 300vw; 67 | } 68 | } 69 | 70 | .bubbles__first, 71 | .bubbles__second { 72 | position: fixed; 73 | z-index: 9999; 74 | top: 0; 75 | left: 50%; 76 | translate: -50% 100%; 77 | width: var(--size); 78 | height: var(--size); 79 | border-radius: var(--size); 80 | animation-timing-function: ease-in-out; 81 | } 82 | 83 | .bubbles__first { 84 | background: #8f44fd; 85 | } 86 | 87 | #bubbles.show .bubbles__first { 88 | animation-name: bubble-move; 89 | } 90 | 91 | #bubbles.show .bubbles__second { 92 | animation-name: bubble-second-move; 93 | } 94 | 95 | @keyframes bubble-move { 96 | 20% { 97 | border-radius: var(--size); 98 | } 99 | 50%, 100 | 100% { 101 | translate: -50% 0; 102 | border-radius: 0; 103 | } 104 | } 105 | 106 | @keyframes bubble-second-move { 107 | 30% { 108 | translate: -50% 100%; 109 | } 110 | 50% { 111 | border-radius: var(--size); 112 | } 113 | 100% { 114 | translate: -50% 0; 115 | border-radius: 0; 116 | } 117 | } 118 | 119 | @keyframes appear { 120 | 0% { 121 | opacity: 0; 122 | translate: 0 100%; 123 | } 124 | 100% { 125 | opacity: 1; 126 | translate: 0; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/examples/transition-2/Example.tsx: -------------------------------------------------------------------------------- 1 | import { PropsWithChildren } from "react"; 2 | import { 3 | BrowserRouter, 4 | Routes, 5 | Route, 6 | Outlet, 7 | useNavigate, 8 | useLocation, 9 | } from "react-router-dom"; 10 | import "./styles.css"; 11 | 12 | const Home = () =>