├── .npmrc ├── src ├── routes │ ├── (hooks) │ │ ├── useEffect │ │ │ ├── +page.svelte │ │ │ ├── svelte.svelte │ │ │ ├── +page.ts │ │ │ └── react.jsx │ │ ├── useMemo │ │ │ ├── +page.svelte │ │ │ ├── svelte.svelte │ │ │ ├── +page.ts │ │ │ └── react.jsx │ │ ├── useRef │ │ │ ├── +page.svelte │ │ │ ├── svelte.svelte │ │ │ ├── +page.ts │ │ │ └── react.jsx │ │ ├── useState │ │ │ ├── +page.svelte │ │ │ ├── svelte.svelte │ │ │ ├── +page.ts │ │ │ └── react.jsx │ │ ├── useCallback │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ ├── svelte.svelte │ │ │ └── react.jsx │ │ ├── useContext │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ ├── svelte.svelte │ │ │ └── react.jsx │ │ ├── useReducer │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ ├── svelte.svelte │ │ │ └── react.jsx │ │ ├── Header.svelte │ │ ├── Snippet.svelte │ │ └── +layout.svelte │ ├── +error.svelte │ ├── +page.svelte │ └── +layout.svelte ├── app.postcss ├── lib │ ├── types.ts │ ├── icons │ │ ├── Svelte.svelte │ │ ├── Code.svelte │ │ ├── Home.svelte │ │ ├── React.svelte │ │ └── GitHub.svelte │ ├── store.ts │ └── Icon.svelte ├── app.d.ts └── app.html ├── static └── favicon.png ├── postcss.config.cjs ├── vite.config.ts ├── .gitignore ├── .eslintignore ├── .prettierignore ├── .prettierrc ├── svelte.config.js ├── .eslintrc.cjs ├── tsconfig.json ├── tailwind.config.cjs ├── README.md └── package.json /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useEffect/+page.svelte: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useMemo/+page.svelte: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useRef/+page.svelte: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useState/+page.svelte: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useCallback/+page.svelte: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useContext/+page.svelte: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useReducer/+page.svelte: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /src/app.postcss: -------------------------------------------------------------------------------- 1 | /*place global styles here */ 2 | html, body { @apply h-full overflow-hidden; } -------------------------------------------------------------------------------- /static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/breadthe/react-hooks-in-svelte/HEAD/static/favicon.png -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } -------------------------------------------------------------------------------- /src/routes/(hooks)/Header.svelte: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | -------------------------------------------------------------------------------- /src/lib/types.ts: -------------------------------------------------------------------------------- 1 | export interface Tile { 2 | id: number 3 | url: string 4 | label: string 5 | title: string 6 | icon: string 7 | } 8 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import { defineConfig } from 'vite'; 3 | 4 | export default defineConfig({ 5 | plugins: [sveltekit()] 6 | }); 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | vite.config.js.timestamp-* 10 | vite.config.ts.timestamp-* 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useRef/svelte.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/lib/icons/Svelte.svelte: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useState/svelte.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | Count: {count} 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useMemo/svelte.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 |

fib({value}) = {result}

11 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "semi": false, 4 | "trailingComma": "none", 5 | "printWidth": 120, 6 | "plugins": ["prettier-plugin-svelte"], 7 | "pluginSearchDirs": ["."], 8 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] 9 | } 10 | -------------------------------------------------------------------------------- /src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | // and what to do when importing types 4 | declare namespace App { 5 | // interface Locals {} 6 | // interface PageData {} 7 | // interface Error {} 8 | // interface Platform {} 9 | } 10 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useEffect/svelte.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | Timer: {count} 16 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useMemo/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from "./$types" 2 | 3 | export const load = (async ({ params }) => { 4 | return { 5 | title: "useMemo", 6 | react: (await import("./react.jsx?raw")).default, 7 | svelte: (await import("./svelte.svelte?raw")).default, 8 | } 9 | }) satisfies PageLoad 10 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useRef/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from "./$types" 2 | 3 | export const load = (async ({ params }) => { 4 | return { 5 | title: "useRef", 6 | react: (await import("./react.jsx?raw")).default, 7 | svelte: (await import("./svelte.svelte?raw")).default, 8 | } 9 | }) satisfies PageLoad 10 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useState/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from "./$types" 2 | 3 | export const load = (async ({ params }) => { 4 | return { 5 | title: "useState", 6 | react: (await import("./react.jsx?raw")).default, 7 | svelte: (await import("./svelte.svelte?raw")).default, 8 | } 9 | }) satisfies PageLoad 10 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useContext/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from "./$types" 2 | 3 | export const load = (async ({ params }) => { 4 | return { 5 | title: "useContext", 6 | react: (await import("./react.jsx?raw")).default, 7 | svelte: (await import("./svelte.svelte?raw")).default, 8 | } 9 | }) satisfies PageLoad 10 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useEffect/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from "./$types" 2 | 3 | export const load = (async ({ params }) => { 4 | return { 5 | title: "useEffect", 6 | react: (await import("./react.jsx?raw")).default, 7 | svelte: (await import("./svelte.svelte?raw")).default, 8 | } 9 | }) satisfies PageLoad 10 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useReducer/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from "./$types" 2 | 3 | export const load = (async ({ params }) => { 4 | return { 5 | title: "useReducer", 6 | react: (await import("./react.jsx?raw")).default, 7 | svelte: (await import("./svelte.svelte?raw")).default, 8 | } 9 | }) satisfies PageLoad 10 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useCallback/+page.ts: -------------------------------------------------------------------------------- 1 | import type { PageLoad } from "./$types" 2 | 3 | export const load = (async ({ params }) => { 4 | return { 5 | title: "useCallback", 6 | react: (await import("./react.jsx?raw")).default, 7 | svelte: (await import("./svelte.svelte?raw")).default, 8 | } 9 | }) satisfies PageLoad 10 | -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-auto'; 2 | import { vitePreprocess } from '@sveltejs/kit/vite'; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | kit: { 7 | adapter: adapter() 8 | }, 9 | preprocess: [ 10 | vitePreprocess({ 11 | postcss: true 12 | }) 13 | ], 14 | }; 15 | 16 | export default config; 17 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useCallback/svelte.svelte: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/routes/+error.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |

{$page.status}

7 |

{$page?.error?.message}

8 | 9 | {#if $page.status === 404} 10 | {$page.url.pathname} 11 | {/if} 12 |
13 | -------------------------------------------------------------------------------- /src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useContext/svelte.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useCallback/react.jsx: -------------------------------------------------------------------------------- 1 | // This function (component) is executed on every render 2 | function Component() { 3 | // this event handler is redefined on every render 4 | const handleClick = () => alert("hello") 5 | 6 | // because `handleClick` is redefined on every render, `ChildComponent` will be re-rendered too. Because its `onClick` prop is considered changed. 7 | return 8 | } 9 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useRef/react.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react' 2 | 3 | export default function TextInputWithFocusButton() { 4 | const inputEl = useRef(null) 5 | const handleClick = () => { 6 | inputEl.current.focus() 7 | } 8 | 9 | return ( 10 | <> 11 | 12 | 13 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useReducer/svelte.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | Count: {$count} 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useEffect/react.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react' 2 | 3 | export default function Timer() { 4 | const [count, setCount] = useState(0) 5 | 6 | useEffect(() => { 7 | const interval = setInterval(() => { 8 | setCount(count => count + 1) 9 | }, 1000) 10 | 11 | return () => clearInterval(interval) 12 | }, []) 13 | 14 | return ( 15 | <> 16 | Timer: {count} 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useState/react.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react" 2 | 3 | export default function Counter() { 4 | const [count, setCount] = useState(0) 5 | 6 | return ( 7 | <> 8 | Count: {count} 9 | 10 | 11 | 12 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /src/lib/icons/Code.svelte: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /src/lib/icons/Home.svelte: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /src/lib/icons/React.svelte: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], 5 | plugins: ['svelte3', '@typescript-eslint'], 6 | ignorePatterns: ['*.cjs'], 7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], 8 | settings: { 9 | 'svelte3/typescript': () => require('typescript') 10 | }, 11 | parserOptions: { 12 | sourceType: 'module', 13 | ecmaVersion: 2020 14 | }, 15 | env: { 16 | browser: true, 17 | es2017: true, 18 | node: true 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useContext/react.jsx: -------------------------------------------------------------------------------- 1 | import React, { createContext } from 'react' 2 | import Toolbar from './Toolbar' 3 | 4 | const themes = { 5 | light: { 6 | foreground: "#000000", 7 | background: "#eeeeee" 8 | }, 9 | dark: { 10 | foreground: "#ffffff", 11 | background: "#222222" 12 | } 13 | } 14 | 15 | export const ThemeContext = createContext(themes.light) 16 | 17 | export default function App() { 18 | return ( 19 | 20 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useMemo/react.jsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo, useState } from 'react' 2 | import fibonacci from './fib' 3 | 4 | export default function Fibonacci() { 5 | const [value, setValue] = useState(0) 6 | const result = useMemo(() => { 7 | return fibonacci(value) 8 | }, [value]) 9 | 10 | const handleChange = (e) => { 11 | setValue(e.target.value) 12 | } 13 | 14 | return ( 15 | <> 16 | 17 |

fib({value}) = {result}

18 | 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true 12 | } 13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 14 | // 15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 16 | // from the referenced tsconfig.json - TypeScript does not merge them in 17 | } 18 | -------------------------------------------------------------------------------- /tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | darkMode: 'class', 4 | content: ['./src/**/*.{html,js,svelte,ts}', require('path').join(require.resolve('@skeletonlabs/skeleton'), '../**/*.{html,js,svelte,ts}')], 5 | theme: { 6 | extend: { 7 | colors: { 8 | 'svelte': '#ff3e00', 9 | 'react': '#61dafb', 10 | } 11 | }, 12 | }, 13 | plugins: [require('@tailwindcss/forms'), require('@tailwindcss/typography'), require('@tailwindcss/line-clamp'), ...require('@skeletonlabs/skeleton/tailwind/skeleton.cjs')()], 14 | } 15 | -------------------------------------------------------------------------------- /src/routes/(hooks)/Snippet.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 |

17 | 18 | {framework} 19 |

20 | 21 | 22 |
23 | -------------------------------------------------------------------------------- /src/routes/(hooks)/useReducer/react.jsx: -------------------------------------------------------------------------------- 1 | import React, { useReducer } from 'react' 2 | 3 | const initialState = { count: 0 } 4 | 5 | function reducer(state, action) { 6 | switch (action.type) { 7 | case 'increment': 8 | return { count: state.count + 1 } 9 | case 'decrement': 10 | return { count: state.count - 1 } 11 | default: 12 | throw new Error() 13 | } 14 | } 15 | 16 | export default function Counter() { 17 | const [state, dispatch] = useReducer(reducer, initialState) 18 | return ( 19 | <> 20 | Count: {state.count} 21 | 22 | 23 | 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /src/lib/store.ts: -------------------------------------------------------------------------------- 1 | import { readable, type Readable, writable, type Writable, derived } from "svelte/store" 2 | import type { Tile } from "./types" 3 | 4 | export const selectedTile: Writable = writable(0) 5 | 6 | export const tiles: Readable = readable([ 7 | { id: 0, url: "/", label: "Home", title: "Home", icon: "home" }, 8 | { id: 1, url: "/useState", label: "useState", title: "useState", icon: "code" }, 9 | { id: 2, url: "/useEffect", label: "useEffect", title: "useEffect", icon: "code" }, 10 | { id: 3, url: "/useMemo", label: "useMemo", title: "useMemo", icon: "code" }, 11 | { id: 4, url: "/useRef", label: "useRef", title: "useRef", icon: "code" }, 12 | { id: 5, url: "/useReducer", label: "useReducer", title: "useReducer", icon: "code" }, 13 | { id: 6, url: "/useCallback", label: "useCallback", title: "useCallback", icon: "code" }, 14 | { id: 7, url: "/useContext", label: "useContext", title: "useContext", icon: "code" } 15 | ]) 16 | 17 | export const hooks = derived(tiles, $tiles => $tiles.slice(1)) 18 | -------------------------------------------------------------------------------- /src/lib/Icon.svelte: -------------------------------------------------------------------------------- 1 | 22 | 23 | 34 | i.id === icon).component} /> 35 | 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Hooks in Svelte 2 | 3 | A SvelteKit website showing side-by-side examples of React hooks and the equivalent Svelte code. 4 | 5 | The code examples are 100% made by [Josh Nuss](https://github.com/joshnuss) with [React Hooks in Svelte](https://github.com/joshnuss/react-hooks-in-svelte). All I've done is dress them up visually, so I could play around with [SvelteKit](https://kit.svelte.dev/) and [Skeleton UI](https://www.skeleton.dev/). 6 | 7 | ![React useState hook in Svelte screenshot](https://user-images.githubusercontent.com/17433578/223051593-5c8530fc-4ed9-4ce9-984e-268e57e19012.png) 8 | 9 | ## Developing 10 | 11 | Once you've installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: 12 | 13 | ```bash 14 | npm run dev 15 | 16 | # or start the server and open the app in a new browser tab 17 | npm run dev -- --open 18 | ``` 19 | 20 | ## Building 21 | 22 | To create a production version of your app: 23 | 24 | ```bash 25 | npm run build 26 | ``` 27 | 28 | You can preview the production build with `npm run preview`. 29 | 30 | > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. 31 | -------------------------------------------------------------------------------- /src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |
7 |

8 | React 9 | 12 | hooks in 13 | 14 | Svelte 15 |

16 |

17 | based on React hooks in Svelte 20 | by Josh Nuss 21 |

22 |

23 | Side-by-side code examples of React hooks implemented in Svelte. A reference for developers who need to work 24 | across Svelte and React. 25 |

26 |
27 | 28 |
29 | {#each $hooks as hook (hook.id)} 30 | 31 | {hook.label} 32 | 33 | {/each} 34 |
35 |
36 | 37 | 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-vs-svelte", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite dev", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 10 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 11 | "lint": "prettier --plugin-search-dir . --check . && eslint .", 12 | "format": "prettier --plugin-search-dir . --write ." 13 | }, 14 | "devDependencies": { 15 | "@skeletonlabs/skeleton": "^1.0.0", 16 | "@sveltejs/adapter-auto": "^2.0.0", 17 | "@sveltejs/kit": "^1.5.0", 18 | "@tailwindcss/forms": "^0.5.3", 19 | "@tailwindcss/line-clamp": "^0.4.2", 20 | "@tailwindcss/typography": "^0.5.9", 21 | "@typescript-eslint/eslint-plugin": "^5.45.0", 22 | "@typescript-eslint/parser": "^5.45.0", 23 | "autoprefixer": "^10.4.13", 24 | "eslint": "^8.28.0", 25 | "eslint-config-prettier": "^8.5.0", 26 | "eslint-plugin-svelte3": "^4.0.0", 27 | "highlight.js": "^11.7.0", 28 | "highlightjs-svelte": "^1.0.6", 29 | "postcss": "^8.4.21", 30 | "prettier": "^2.8.0", 31 | "prettier-plugin-svelte": "^2.8.1", 32 | "svelte": "^3.54.0", 33 | "svelte-check": "^3.0.1", 34 | "svelte-preprocess": "^5.0.1", 35 | "tailwindcss": "^3.2.7", 36 | "tslib": "^2.4.1", 37 | "typescript": "^4.9.3", 38 | "vite": "^4.0.0" 39 | }, 40 | "type": "module" 41 | } 42 | -------------------------------------------------------------------------------- /src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | {title} 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | {siteName} 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | {#each $tiles as tile (tile.id)} 38 | 46 | {/each} 47 | 48 | 49 | 50 | 51 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/lib/icons/GitHub.svelte: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /src/routes/(hooks)/+layout.svelte: -------------------------------------------------------------------------------- 1 | 34 | 35 | 36 | 37 | 38 |
39 | 40 | {$page.data.title} 41 | 42 |
43 | 44 |
45 |
46 |

47 | React 48 | {reactSize} characters 49 |

50 | 51 | 52 | 53 |
54 |
55 |

56 | Svelte 57 | {svelteSize} characters ({percentageSmaller}% less) 58 |

59 | 60 | 61 | 62 | 63 |
64 |
65 | --------------------------------------------------------------------------------