add framework logos

This commit is contained in:
Mathieu Schimmerling
2022-04-11 16:08:23 +02:00
parent 42897a530c
commit 6eadc6217b
7 changed files with 748 additions and 679 deletions

688
README.md
View File

@@ -32,7 +32,37 @@ How do we solve this ? Developers love having framework overview by examples. It
# Reactivity
## Declare state
### Angular
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let name = 'John';
console.log(name); // John
</script>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
export default function Name() {
const [name] = useState('John');
console.log(name); // John
}
```
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
const name = ref('John');
console.log(name.value); // John
</script>
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
```ts
import { Component, Input } from '@angular/core';
@@ -49,38 +79,42 @@ export class NameComponent {
```
### React
## Update state
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let name = 'John';
name = 'Jane';
console.log(name); // Jane
</script>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
export default function Name() {
const [name] = useState('John');
console.log(name); // John
const [name, setName] = useState('John');
setName('Jane');
console.log(name); // Jane
}
```
### Svelte
```svelte
<script>
let name = 'John';
console.log(name); // John
</script>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
const name = ref('John');
console.log(name.value); // John
name.value = 'Jane';
console.log(name.value); // Jane
</script>
```
## Update state
### Angular
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
```ts
import { Component, Input } from '@angular/core';
@@ -98,42 +132,46 @@ export class NameComponent {
```
### React
## Computed state
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let count = 10;
$: doubleCount = count * 2;
console.log(doubleCount); // 20
</script>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
import { useState, useMemo } from 'react';
export default function Name() {
const [name, setName] = useState('John');
setName('Jane');
console.log(name); // Jane
export default function DoubleCount() {
const [count] = useState(10);
const doubleCount = useMemo(() => count * 2, [count]);
console.log(doubleCount); // 20
return <div />;
}
```
### Svelte
```svelte
<script>
let name = 'John';
name = 'Jane';
console.log(name); // Jane
</script>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
const name = ref('John');
name.value = 'Jane';
console.log(name.value); // Jane
import { ref, computed } from 'vue';
const count = ref(10);
const doubleCount = computed(() => count.value * 2);
console.log(doubleCount.value); // 20
</script>
<template>
<div />
</template>
```
## Computed state
### Angular
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
```ts
import { Component, OnInit, Input, Pipe, PipeTransform, ChangeDetectionStrategy } from '@angular/core';
@@ -159,47 +197,15 @@ export class DoublecountComponent implements OnInit {
```
### React
```jsx
import { useState, useMemo } from 'react';
export default function DoubleCount() {
const [count] = useState(10);
const doubleCount = useMemo(() => count * 2, [count]);
console.log(doubleCount); // 20
return <div />;
}
```
### Svelte
```svelte
<script>
let count = 10;
$: doubleCount = count * 2;
console.log(doubleCount); // 20
</script>
```
### Vue 3
```vue
<script setup>
import { ref, computed } from 'vue';
const count = ref(10);
const doubleCount = computed(() => count.value * 2);
console.log(doubleCount.value); // 20
</script>
<template>
<div />
</template>
```
# Templating
## Minimal template
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<h1>Hello world</h1>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
export default function HelloWorld() {
return <h1>Hello world</h1>;
@@ -207,13 +213,7 @@ export default function HelloWorld() {
```
### Svelte
```svelte
<h1>Hello world</h1>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<template>
<h1>Hello world</h1>
@@ -221,8 +221,23 @@ export default function HelloWorld() {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/2-templating/1-minimal-template">here</a> to fill this snippet.</pre>
## Styling
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<h1 class="title">Hello world</h1>
<button style="font-size: 10rem;">I am a button</button>
<style>
.title {
color: red;
}
</style>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
export default function HelloWorld() {
// how do you declare title class ??
@@ -237,20 +252,7 @@ export default function HelloWorld() {
```
### Svelte
```svelte
<h1 class="title">Hello world</h1>
<button style="font-size: 10rem;">I am a button</button>
<style>
.title {
color: red;
}
</style>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<template>
<h1 class="title">
@@ -269,8 +271,24 @@ export default function HelloWorld() {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/2-templating/2-styling">here</a> to fill this snippet.</pre>
## Loop
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
const colors = ['red', 'green', 'blue'];
</script>
<ul>
{#each colors as color}
<li>{color}</li>
{/each}
</ul>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
export default function Colors() {
const colors = ['red', 'green', 'blue'];
@@ -285,21 +303,7 @@ export default function Colors() {
```
### Svelte
```svelte
<script>
const colors = ['red', 'green', 'blue'];
</script>
<ul>
{#each colors as color}
<li>{color}</li>
{/each}
</ul>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
const colors = ['red', 'green', 'blue'];
@@ -318,8 +322,25 @@ const colors = ['red', 'green', 'blue'];
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/2-templating/3-loop">here</a> to fill this snippet.</pre>
## Event click
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let count = 0;
function incrementCount() {
count++;
}
</script>
<p>Counter: {count}</p>
<button on:click={incrementCount}>+1</button>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
@@ -340,22 +361,7 @@ export default function Name() {
```
### Svelte
```svelte
<script>
let count = 0;
function incrementCount() {
count++;
}
</script>
<p>Counter: {count}</p>
<button on:click={incrementCount}>+1</button>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
@@ -375,22 +381,10 @@ function incrementCount() {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/2-templating/4-event-click">here</a> to fill this snippet.</pre>
## Dom ref
### React
```jsx
import { useEffect, useRef } from 'react';
export default function InputFocused() {
const inputElement = useRef(null);
useEffect(() => inputElement.current.focus());
return <input type="text" ref={inputElement} />;
}
```
### Svelte
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
import { onMount } from 'svelte';
@@ -406,7 +400,21 @@ export default function InputFocused() {
```
### Vue 3
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useEffect, useRef } from 'react';
export default function InputFocused() {
const inputElement = useRef(null);
useEffect(() => inputElement.current.focus());
return <input type="text" ref={inputElement} />;
}
```
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref, onMounted } from 'vue';
@@ -424,8 +432,42 @@ onMounted(() => {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/2-templating/5-dom-ref">here</a> to fill this snippet.</pre>
## Conditional
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
let lightIndex = 0;
$: light = TRAFFIC_LIGHTS[lightIndex];
function nextLight() {
if (lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
lightIndex = 0;
} else {
lightIndex++;
}
}
</script>
<button on:click={nextLight}>Next light</button>
<p>Light is: {light}</p>
<p>
You must
{#if light === 'red'}
STOP
{:else if light === 'orange'}
SLOW DOWN
{:else if light === 'green'}
GO
{/if}
</p>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState, useMemo } from 'react';
@@ -460,39 +502,7 @@ export default function TrafficLight() {
```
### Svelte
```svelte
<script>
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
let lightIndex = 0;
$: light = TRAFFIC_LIGHTS[lightIndex];
function nextLight() {
if (lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
lightIndex = 0;
} else {
lightIndex++;
}
}
</script>
<button on:click={nextLight}>Next light</button>
<p>Light is: {light}</p>
<p>
You must
{#if light === 'red'}
STOP
{:else if light === 'orange'}
SLOW DOWN
{:else if light === 'green'}
GO
{/if}
</p>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref, computed } from 'vue';
@@ -525,9 +535,25 @@ function nextLight() {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/2-templating/6-conditional">here</a> to fill this snippet.</pre>
# Lifecycle
## On mount
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
import { onMount } from 'svelte';
let pageTitle = '';
onMount(() => {
pageTitle = document.title;
});
</script>
<p>Page title is: {pageTitle}</p>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState, useEffect } from 'react';
@@ -543,21 +569,7 @@ export default function PageTitle() {
```
### Svelte
```svelte
<script>
import { onMount } from 'svelte';
let pageTitle = '';
onMount(() => {
pageTitle = document.title;
});
</script>
<p>Page title is: {pageTitle}</p>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref, onMounted } from 'vue';
@@ -573,8 +585,30 @@ onMounted(() => {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/3-lifecycle/1-on-mount">here</a> to fill this snippet.</pre>
## On unmount
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
import { onDestroy } from 'svelte';
let time = new Date().toLocaleTimeString();
const timer = setInterval(() => {
time = new Date().toLocaleTimeString();
}, 1000);
onDestroy(() => {
clearInterval(timer);
});
</script>
<p>Current time: {time}</p>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState, useEffect } from 'react';
@@ -596,27 +630,7 @@ export default function Time() {
```
### Svelte
```svelte
<script>
import { onDestroy } from 'svelte';
let time = new Date().toLocaleTimeString();
const timer = setInterval(() => {
time = new Date().toLocaleTimeString();
}, 1000);
onDestroy(() => {
clearInterval(timer);
});
</script>
<p>Current time: {time}</p>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref, onUnmounted } from 'vue';
@@ -636,9 +650,36 @@ onUnmounted(() => {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/3-lifecycle/2-on-unmount">here</a> to fill this snippet.</pre>
# Component composition
## Props
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
import UserProfile from './UserProfile.svelte';
</script>
<UserProfile name="John" age={20} favouriteColors={['green', 'blue', 'red']} isAvailable />
```
```svelte
<script>
export let name = '';
export let age = null;
export let favouriteColors = [];
export let isAvailable = false;
</script>
<p>My name is {name} !</p>
<p>My age is {age} !</p>
<p>My favourite colors are {favouriteColors.split(', ')} !</p>
<p>I am {isAvailable ? 'available' : 'not available'}</p>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import UserProfile from './UserProfile.jsx';
@@ -671,32 +712,7 @@ UserProfile.propTypes = {
```
### Svelte
```svelte
<script>
import UserProfile from './UserProfile.svelte';
</script>
<UserProfile name="John" age={20} favouriteColors={['green', 'blue', 'red']} isAvailable />
```
```svelte
<script>
export let name = '';
export let age = null;
export let favouriteColors = [];
export let isAvailable = false;
</script>
<p>My name is {name} !</p>
<p>My age is {age} !</p>
<p>My favourite colors are {favouriteColors.split(', ')} !</p>
<p>I am {isAvailable ? 'available' : 'not available'}</p>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
@@ -747,9 +763,22 @@ const props = defineProps({
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/4-component-composition/1-props">here</a> to fill this snippet.</pre>
# Form input
## Input text
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let text = 'Hello World';
</script>
<p>{text}</p>
<input bind:value={text} />
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
@@ -770,18 +799,7 @@ export default function InputHello() {
```
### Svelte
```svelte
<script>
let text = 'Hello World';
</script>
<p>{text}</p>
<input bind:value={text} />
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
@@ -795,8 +813,21 @@ const text = ref('Hello World');
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/6-form-input/1-input-text">here</a> to fill this snippet.</pre>
## Checkbox
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let isAvailable = false;
</script>
<input id="is-available" type="checkbox" bind:checked={isAvailable} />
<label for="is-available">Is available</label>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
@@ -817,18 +848,7 @@ export default function IsAvailable() {
```
### Svelte
```svelte
<script>
let isAvailable = false;
</script>
<input id="is-available" type="checkbox" bind:checked={isAvailable} />
<label for="is-available">Is available</label>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
@@ -847,8 +867,26 @@ const isAvailable = ref(true);
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/6-form-input/2-checkbox">here</a> to fill this snippet.</pre>
## Radio
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let picked = 'red';
</script>
<div>Picked: {picked}</div>
<input id="blue-pill" bind:group={picked} type="radio" value="blue" />
<label for="blue-pill">Blue pill</label>
<input id="red-pill" bind:group={picked} type="radio" value="red" />
<label for="red-pill">Red pill</label>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
@@ -872,23 +910,7 @@ export default function PickPill() {
```
### Svelte
```svelte
<script>
let picked = 'red';
</script>
<div>Picked: {picked}</div>
<input id="blue-pill" bind:group={picked} type="radio" value="blue" />
<label for="blue-pill">Blue pill</label>
<input id="red-pill" bind:group={picked} type="radio" value="red" />
<label for="red-pill">Red pill</label>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
@@ -918,8 +940,33 @@ const picked = ref('red');
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/6-form-input/3-radio">here</a> to fill this snippet.</pre>
## Select
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let selectedColorId = 2;
const colors = [
{ id: 1, text: 'red' },
{ id: 2, text: 'blue' },
{ id: 3, text: 'green' },
{ id: 4, text: 'gray', isDisabled: true },
];
</script>
<select bind:value={selectedColorId}>
{#each colors as color}
<option value={color.id} disabled={color.isDisabled}>
{color.text}
</option>
{/each}
</select>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
@@ -950,30 +997,7 @@ export default function ColorSelect() {
```
### Svelte
```svelte
<script>
let selectedColorId = 2;
const colors = [
{ id: 1, text: 'red' },
{ id: 2, text: 'blue' },
{ id: 3, text: 'green' },
{ id: 4, text: 'gray', isDisabled: true },
];
</script>
<select bind:value={selectedColorId}>
{#each colors as color}
<option value={color.id} disabled={color.isDisabled}>
{color.text}
</option>
{/each}
</select>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
@@ -1002,9 +1026,20 @@ const colors = [
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/6-form-input/4-select">here</a> to fill this snippet.</pre>
# Webapp features
## Routing
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```
|-- routes/
|-- index.svelte // index page "/"
|-- about.svelte // about page "/about"
|-- __error.svelte // handle HTTP errors 404, 500,...
|-- __layout.svelte // global app layout
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```
|-- pages/
|-- index.js // index page "/"
@@ -1016,20 +1051,13 @@ const colors = [
https://remix.run/docs/en/v1/guides/routing
### Svelte
```
|-- routes/
|-- index.svelte // index page "/"
|-- about.svelte // about page "/about"
|-- __error.svelte // handle HTTP errors 404, 500,...
|-- __layout.svelte // global app layout
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```
|-- pages/
|-- index.vue // index page "/"
|-- about.vue // about page "/about"
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/7-webapp-features/1-routing">here</a> to fill this snippet.</pre>

View File

@@ -11,7 +11,7 @@ export default defineConfig({
plugins: [
{
handleHotUpdate({ file }) {
if (file.includes('/content')) {
if (file.includes('/content') || file.includes('/scripts/utils')) {
generateIndexPage();
}
},

View File

@@ -3,6 +3,7 @@ const FRAMEWORKS = [
id: 'svelte',
title: 'Svelte',
ext: 'svelte',
img: "https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg",
eslint: {
files: ['*.svelte'],
processor: 'svelte3/svelte3',
@@ -13,6 +14,7 @@ const FRAMEWORKS = [
id: 'react',
title: 'React',
ext: 'jsx',
img: "https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg",
eslint: {
files: ['*.jsx', '*.tsx'],
extends: ['eslint:recommended', 'plugin:react/recommended', 'plugin:react/jsx-runtime'],
@@ -27,6 +29,7 @@ const FRAMEWORKS = [
id: 'vue3',
title: 'Vue 3',
ext: 'vue',
img: "https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67",
eslint: {
files: ['*.vue'],
env: {
@@ -39,9 +42,7 @@ const FRAMEWORKS = [
id: 'angular',
title: 'Angular',
ext: 'ts',
eslint: {
files: ['**/angular/*.ts'],
},
img: "https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png",
eslint: [
{
files: ['**/angular/*.ts'],

View File

@@ -2,6 +2,7 @@ import fs from 'fs';
import getDocContent from './getDocContent.js';
export default function generateIndexPage() {
console.log('generateIndexPage')
const template = fs.readFileSync('scripts/templates/index.base.md', 'utf8');
fs.writeFileSync('src/pages/index.md', template.replace('<slot/>', getDocContent()), 'utf-8');
}

View File

@@ -32,22 +32,25 @@ export default function getDocContent() {
// write subsection title
fileContent += `## ${subSectionDirTitle}\n`;
const frameworkDirs = fs.readdirSync(`${sectionDir}/${subSectionDir}`).filter((path) => !path.includes('.'));
for (const frameworkDir of frameworkDirs) {
const framework = FRAMEWORKS.find((f) => f.id === frameworkDir);
fileContent += `### ${framework.title}\n`;
const files = fs.readdirSync(`${sectionDir}/${subSectionDir}/${frameworkDir}`);
for (const framework of FRAMEWORKS) {
function addSnippetWrap(content) {
return `\`\`\`${framework.ext}\n${content}\n\`\`\`\n\n`;
}
const imgTag = framework.img ? `<img src="${framework.img}" width="20" height="20" class="framework-logo" />` : '';
fileContent += `### ${imgTag} ${framework.title}\n`;
for (const file of files) {
const parsedFile = path.parse(file);
const currentFileContent = fs.readFileSync(`${sectionDir}/${subSectionDir}/${frameworkDir}/${file}`);
const frameworkFileContent = parsedFile.ext === '.md' ? `${currentFileContent}\n` : addSnippetWrap(currentFileContent);
fileContent += frameworkFileContent;
const frameworkDirPath = `${sectionDir}/${subSectionDir}/${framework.id}`;
if (fs.existsSync(frameworkDirPath)) {
const files = fs.readdirSync(frameworkDirPath);
for (const file of files) {
const parsedFile = path.parse(file);
const currentFileContent = fs.readFileSync(`${frameworkDirPath}/${file}`);
const frameworkFileContent = parsedFile.ext === '.md' ? `${currentFileContent}\n` : addSnippetWrap(currentFileContent);
fileContent += frameworkFileContent;
}
} else {
fileContent += `<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/${sectionDir}/${subSectionDir}">here</a> to fill this snippet.</pre>\n`;
}
}
}

View File

@@ -8,6 +8,14 @@
<title>Component Party 🎉</title>
<link rel="icon" href="/favicon.png" />
<meta name="description" content="Web component JS frameworks overview by their syntax and features." />
<style>
#main-content .framework-logo {
display: inline;
margin-right: 5px;
margin-bottom: 0px;
margin-top: 0px;
}
</style>
</head>
<body class="bg-gray-900 text-white">
<header class="border-b border-gray-700 bg-gray-900 fixed top-0 w-full">
@@ -38,13 +46,13 @@
{#each tree as treeNode}
<ul>
<li>
<a href={`#${treeNode.id}`} class="inline-block py-1">
<a href={`#${treeNode.id}`} class="inline-block py-1 text-white opacity-90 hover:opacity-100">
{treeNode.title}
</a>
<ul>
{#each treeNode.sections as section}
<li>
<a href={`#${section.id}`} class="inline-block py-1 text-gray-500 hover:text-gray-300">
<a href={`#${section.id}`} class="inline-block py-1 text-white opacity-50 hover:opacity-90">
{section.title}
</a>
</li>
@@ -55,7 +63,7 @@
{/each}
</nav>
</aside>
<main class="prose prose-invert prose-h1:scroll-mt-20 prose-h2:scroll-mt-20 w-full mx-auto pb-8 mt-10">
<main id="main-content" class="prose prose-invert prose-h1:scroll-mt-20 prose-h2:scroll-mt-20 w-full mx-auto pb-8 mt-10">
<slot />
</main>
</div>

View File

@@ -4,7 +4,37 @@ layout: ../layouts/BaseLayout.svelte
# Reactivity
## Declare state
### Angular
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let name = 'John';
console.log(name); // John
</script>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
export default function Name() {
const [name] = useState('John');
console.log(name); // John
}
```
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
const name = ref('John');
console.log(name.value); // John
</script>
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
```ts
import { Component, Input } from '@angular/core';
@@ -21,38 +51,42 @@ export class NameComponent {
```
### React
## Update state
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let name = 'John';
name = 'Jane';
console.log(name); // Jane
</script>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
export default function Name() {
const [name] = useState('John');
console.log(name); // John
const [name, setName] = useState('John');
setName('Jane');
console.log(name); // Jane
}
```
### Svelte
```svelte
<script>
let name = 'John';
console.log(name); // John
</script>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
const name = ref('John');
console.log(name.value); // John
name.value = 'Jane';
console.log(name.value); // Jane
</script>
```
## Update state
### Angular
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
```ts
import { Component, Input } from '@angular/core';
@@ -70,42 +104,46 @@ export class NameComponent {
```
### React
## Computed state
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let count = 10;
$: doubleCount = count * 2;
console.log(doubleCount); // 20
</script>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
import { useState, useMemo } from 'react';
export default function Name() {
const [name, setName] = useState('John');
setName('Jane');
console.log(name); // Jane
export default function DoubleCount() {
const [count] = useState(10);
const doubleCount = useMemo(() => count * 2, [count]);
console.log(doubleCount); // 20
return <div />;
}
```
### Svelte
```svelte
<script>
let name = 'John';
name = 'Jane';
console.log(name); // Jane
</script>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
const name = ref('John');
name.value = 'Jane';
console.log(name.value); // Jane
import { ref, computed } from 'vue';
const count = ref(10);
const doubleCount = computed(() => count.value * 2);
console.log(doubleCount.value); // 20
</script>
<template>
<div />
</template>
```
## Computed state
### Angular
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
```ts
import { Component, OnInit, Input, Pipe, PipeTransform, ChangeDetectionStrategy } from '@angular/core';
@@ -131,47 +169,15 @@ export class DoublecountComponent implements OnInit {
```
### React
```jsx
import { useState, useMemo } from 'react';
export default function DoubleCount() {
const [count] = useState(10);
const doubleCount = useMemo(() => count * 2, [count]);
console.log(doubleCount); // 20
return <div />;
}
```
### Svelte
```svelte
<script>
let count = 10;
$: doubleCount = count * 2;
console.log(doubleCount); // 20
</script>
```
### Vue 3
```vue
<script setup>
import { ref, computed } from 'vue';
const count = ref(10);
const doubleCount = computed(() => count.value * 2);
console.log(doubleCount.value); // 20
</script>
<template>
<div />
</template>
```
# Templating
## Minimal template
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<h1>Hello world</h1>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
export default function HelloWorld() {
return <h1>Hello world</h1>;
@@ -179,13 +185,7 @@ export default function HelloWorld() {
```
### Svelte
```svelte
<h1>Hello world</h1>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<template>
<h1>Hello world</h1>
@@ -193,8 +193,23 @@ export default function HelloWorld() {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/2-templating/1-minimal-template">here</a> to fill this snippet.</pre>
## Styling
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<h1 class="title">Hello world</h1>
<button style="font-size: 10rem;">I am a button</button>
<style>
.title {
color: red;
}
</style>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
export default function HelloWorld() {
// how do you declare title class ??
@@ -209,20 +224,7 @@ export default function HelloWorld() {
```
### Svelte
```svelte
<h1 class="title">Hello world</h1>
<button style="font-size: 10rem;">I am a button</button>
<style>
.title {
color: red;
}
</style>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<template>
<h1 class="title">
@@ -241,8 +243,24 @@ export default function HelloWorld() {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/2-templating/2-styling">here</a> to fill this snippet.</pre>
## Loop
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
const colors = ['red', 'green', 'blue'];
</script>
<ul>
{#each colors as color}
<li>{color}</li>
{/each}
</ul>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
export default function Colors() {
const colors = ['red', 'green', 'blue'];
@@ -257,21 +275,7 @@ export default function Colors() {
```
### Svelte
```svelte
<script>
const colors = ['red', 'green', 'blue'];
</script>
<ul>
{#each colors as color}
<li>{color}</li>
{/each}
</ul>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
const colors = ['red', 'green', 'blue'];
@@ -290,8 +294,25 @@ const colors = ['red', 'green', 'blue'];
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/2-templating/3-loop">here</a> to fill this snippet.</pre>
## Event click
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let count = 0;
function incrementCount() {
count++;
}
</script>
<p>Counter: {count}</p>
<button on:click={incrementCount}>+1</button>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
@@ -312,22 +333,7 @@ export default function Name() {
```
### Svelte
```svelte
<script>
let count = 0;
function incrementCount() {
count++;
}
</script>
<p>Counter: {count}</p>
<button on:click={incrementCount}>+1</button>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
@@ -347,22 +353,10 @@ function incrementCount() {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/2-templating/4-event-click">here</a> to fill this snippet.</pre>
## Dom ref
### React
```jsx
import { useEffect, useRef } from 'react';
export default function InputFocused() {
const inputElement = useRef(null);
useEffect(() => inputElement.current.focus());
return <input type="text" ref={inputElement} />;
}
```
### Svelte
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
import { onMount } from 'svelte';
@@ -378,7 +372,21 @@ export default function InputFocused() {
```
### Vue 3
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useEffect, useRef } from 'react';
export default function InputFocused() {
const inputElement = useRef(null);
useEffect(() => inputElement.current.focus());
return <input type="text" ref={inputElement} />;
}
```
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref, onMounted } from 'vue';
@@ -396,8 +404,42 @@ onMounted(() => {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/2-templating/5-dom-ref">here</a> to fill this snippet.</pre>
## Conditional
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
let lightIndex = 0;
$: light = TRAFFIC_LIGHTS[lightIndex];
function nextLight() {
if (lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
lightIndex = 0;
} else {
lightIndex++;
}
}
</script>
<button on:click={nextLight}>Next light</button>
<p>Light is: {light}</p>
<p>
You must
{#if light === 'red'}
STOP
{:else if light === 'orange'}
SLOW DOWN
{:else if light === 'green'}
GO
{/if}
</p>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState, useMemo } from 'react';
@@ -432,39 +474,7 @@ export default function TrafficLight() {
```
### Svelte
```svelte
<script>
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
let lightIndex = 0;
$: light = TRAFFIC_LIGHTS[lightIndex];
function nextLight() {
if (lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
lightIndex = 0;
} else {
lightIndex++;
}
}
</script>
<button on:click={nextLight}>Next light</button>
<p>Light is: {light}</p>
<p>
You must
{#if light === 'red'}
STOP
{:else if light === 'orange'}
SLOW DOWN
{:else if light === 'green'}
GO
{/if}
</p>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref, computed } from 'vue';
@@ -497,9 +507,25 @@ function nextLight() {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/2-templating/6-conditional">here</a> to fill this snippet.</pre>
# Lifecycle
## On mount
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
import { onMount } from 'svelte';
let pageTitle = '';
onMount(() => {
pageTitle = document.title;
});
</script>
<p>Page title is: {pageTitle}</p>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState, useEffect } from 'react';
@@ -515,21 +541,7 @@ export default function PageTitle() {
```
### Svelte
```svelte
<script>
import { onMount } from 'svelte';
let pageTitle = '';
onMount(() => {
pageTitle = document.title;
});
</script>
<p>Page title is: {pageTitle}</p>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref, onMounted } from 'vue';
@@ -545,8 +557,30 @@ onMounted(() => {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/3-lifecycle/1-on-mount">here</a> to fill this snippet.</pre>
## On unmount
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
import { onDestroy } from 'svelte';
let time = new Date().toLocaleTimeString();
const timer = setInterval(() => {
time = new Date().toLocaleTimeString();
}, 1000);
onDestroy(() => {
clearInterval(timer);
});
</script>
<p>Current time: {time}</p>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState, useEffect } from 'react';
@@ -568,27 +602,7 @@ export default function Time() {
```
### Svelte
```svelte
<script>
import { onDestroy } from 'svelte';
let time = new Date().toLocaleTimeString();
const timer = setInterval(() => {
time = new Date().toLocaleTimeString();
}, 1000);
onDestroy(() => {
clearInterval(timer);
});
</script>
<p>Current time: {time}</p>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref, onUnmounted } from 'vue';
@@ -608,9 +622,36 @@ onUnmounted(() => {
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/3-lifecycle/2-on-unmount">here</a> to fill this snippet.</pre>
# Component composition
## Props
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
import UserProfile from './UserProfile.svelte';
</script>
<UserProfile name="John" age={20} favouriteColors={['green', 'blue', 'red']} isAvailable />
```
```svelte
<script>
export let name = '';
export let age = null;
export let favouriteColors = [];
export let isAvailable = false;
</script>
<p>My name is {name} !</p>
<p>My age is {age} !</p>
<p>My favourite colors are {favouriteColors.split(', ')} !</p>
<p>I am {isAvailable ? 'available' : 'not available'}</p>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import UserProfile from './UserProfile.jsx';
@@ -643,32 +684,7 @@ UserProfile.propTypes = {
```
### Svelte
```svelte
<script>
import UserProfile from './UserProfile.svelte';
</script>
<UserProfile name="John" age={20} favouriteColors={['green', 'blue', 'red']} isAvailable />
```
```svelte
<script>
export let name = '';
export let age = null;
export let favouriteColors = [];
export let isAvailable = false;
</script>
<p>My name is {name} !</p>
<p>My age is {age} !</p>
<p>My favourite colors are {favouriteColors.split(', ')} !</p>
<p>I am {isAvailable ? 'available' : 'not available'}</p>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
@@ -719,9 +735,22 @@ const props = defineProps({
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/4-component-composition/1-props">here</a> to fill this snippet.</pre>
# Form input
## Input text
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let text = 'Hello World';
</script>
<p>{text}</p>
<input bind:value={text} />
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
@@ -742,18 +771,7 @@ export default function InputHello() {
```
### Svelte
```svelte
<script>
let text = 'Hello World';
</script>
<p>{text}</p>
<input bind:value={text} />
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
@@ -767,8 +785,21 @@ const text = ref('Hello World');
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/6-form-input/1-input-text">here</a> to fill this snippet.</pre>
## Checkbox
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let isAvailable = false;
</script>
<input id="is-available" type="checkbox" bind:checked={isAvailable} />
<label for="is-available">Is available</label>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
@@ -789,18 +820,7 @@ export default function IsAvailable() {
```
### Svelte
```svelte
<script>
let isAvailable = false;
</script>
<input id="is-available" type="checkbox" bind:checked={isAvailable} />
<label for="is-available">Is available</label>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
@@ -819,8 +839,26 @@ const isAvailable = ref(true);
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/6-form-input/2-checkbox">here</a> to fill this snippet.</pre>
## Radio
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let picked = 'red';
</script>
<div>Picked: {picked}</div>
<input id="blue-pill" bind:group={picked} type="radio" value="blue" />
<label for="blue-pill">Blue pill</label>
<input id="red-pill" bind:group={picked} type="radio" value="red" />
<label for="red-pill">Red pill</label>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
@@ -844,23 +882,7 @@ export default function PickPill() {
```
### Svelte
```svelte
<script>
let picked = 'red';
</script>
<div>Picked: {picked}</div>
<input id="blue-pill" bind:group={picked} type="radio" value="blue" />
<label for="blue-pill">Blue pill</label>
<input id="red-pill" bind:group={picked} type="radio" value="red" />
<label for="red-pill">Red pill</label>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
@@ -890,8 +912,33 @@ const picked = ref('red');
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/6-form-input/3-radio">here</a> to fill this snippet.</pre>
## Select
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```svelte
<script>
let selectedColorId = 2;
const colors = [
{ id: 1, text: 'red' },
{ id: 2, text: 'blue' },
{ id: 3, text: 'green' },
{ id: 4, text: 'gray', isDisabled: true },
];
</script>
<select bind:value={selectedColorId}>
{#each colors as color}
<option value={color.id} disabled={color.isDisabled}>
{color.text}
</option>
{/each}
</select>
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```jsx
import { useState } from 'react';
@@ -922,30 +969,7 @@ export default function ColorSelect() {
```
### Svelte
```svelte
<script>
let selectedColorId = 2;
const colors = [
{ id: 1, text: 'red' },
{ id: 2, text: 'blue' },
{ id: 3, text: 'green' },
{ id: 4, text: 'gray', isDisabled: true },
];
</script>
<select bind:value={selectedColorId}>
{#each colors as color}
<option value={color.id} disabled={color.isDisabled}>
{color.text}
</option>
{/each}
</select>
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```vue
<script setup>
import { ref } from 'vue';
@@ -974,9 +998,20 @@ const colors = [
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/6-form-input/4-select">here</a> to fill this snippet.</pre>
# Webapp features
## Routing
### React
### <img src="https://raw.githubusercontent.com/sveltejs/branding/master/svelte-logo.svg" width="20" height="20" class="framework-logo" /> Svelte
```
|-- routes/
|-- index.svelte // index page "/"
|-- about.svelte // about page "/about"
|-- __error.svelte // handle HTTP errors 404, 500,...
|-- __layout.svelte // global app layout
```
### <img src="https://raw.githubusercontent.com/facebook/react/main/fixtures/dom/public/react-logo.svg" width="20" height="20" class="framework-logo" /> React
```
|-- pages/
|-- index.js // index page "/"
@@ -988,20 +1023,13 @@ const colors = [
https://remix.run/docs/en/v1/guides/routing
### Svelte
```
|-- routes/
|-- index.svelte // index page "/"
|-- about.svelte // about page "/about"
|-- __error.svelte // handle HTTP errors 404, 500,...
|-- __layout.svelte // global app layout
```
### Vue 3
### <img src="https://camo.githubusercontent.com/c8f91d18976e27123643a926a2588b8d931a0292fd0b6532c3155379e8591629/68747470733a2f2f7675656a732e6f72672f696d616765732f6c6f676f2e706e67" width="20" height="20" class="framework-logo" /> Vue 3
```
|-- pages/
|-- index.vue // index page "/"
|-- about.vue // about page "/about"
```
### <img src="https://github.com/angular/angular/raw/master/aio/src/assets/images/logos/angular/angular.png" width="20" height="20" class="framework-logo" /> Angular
<pre>Oops, missing snippet ! You can contribute <a href="https://github.com/matschik/component-party/tree/main/content/7-webapp-features/1-routing">here</a> to fill this snippet.</pre>