logo Component party
github
  • Reactivity
    • Declare state
    • Update state
    • Computed state
  • Templating
    • Minimal template
    • Styling
    • Loop
    • Event click
    • Dom ref
    • Conditional
  • Lifecycle
    • On mount
    • On unmount
  • Component composition
    • Props
    • Emit to parent
    • Slot
    • Slot fallback
  • Form input
    • Input text
    • Checkbox
    • Radio
    • Select
  • Webapp features
    • Fetch data
    • Router link
    • Routing

Reactivity#

Declare state#

svelte Svelte

<script>
	let name = 'John';
</script>

<h1>Hello {name}</h1>

react React

import { useState } from 'react';

export default function Name() {
	const [name] = useState('John');

	return <h1>Hello {name}</h1>;
}

vue3 Vue 3

<script setup>
import { ref } from 'vue';
const name = ref('John');
</script>

<template>
  <h1>Hello {{ name }}</h1>
</template>

angular Angular

import { Component } from '@angular/core';

@Component({
	selector: 'app-name',
	template: '<h1>Hello {{ name }}</h1>',
})
export class NameComponent {
	name: string = 'John';
}

solid SolidJS

import { createSignal } from 'solid-js';

export default function Name() {
	const [name] = createSignal('John');

	return <h1>Hello {name()}</h1>;
}

lit Lit

<!DOCTYPE html>
<head>
	<script type="module" src="./name.js"></script>
</head>
<body>
	<x-name></x-name>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';

@customElement('x-name')
export class XName extends LitElement {
	@state()
	name = 'John';

	render() {
		return html`<h1>Hello ${this.name}!</h1>`;
	}
}

ember Ember

<h1>Hello {{this.name}}</h1>
import Component from '@glimmer/component';

export default class CounterComponent extends Component {
	name = 'John';
}

alpine Alpine

<h1 x-data="{ name: 'John' }" x-text="name"></h1>

qwik Qwik

import { component$, useStore } from '@builder.io/qwik';

export const Name = component$(() => {
	const store = useStore({ name: 'John' });

	return <h1>Hello {store.name}</h1>;
});

Update state#

svelte Svelte

<script>
	let name = 'John';
	name = 'Jane';
</script>

<h1>Hello {name}</h1>

react React

import { useState } from 'react';

export default function Name() {
	const [name, setName] = useState('John');
	setName('Jane');

	return <h1>Hello {name}</h1>;
}

vue3 Vue 3

<script setup>
import { ref } from 'vue';
const name = ref('John');
name.value = 'Jane';
</script>

<template>
  <h1>Hello {{ name }}</h1>
</template>

angular Angular

import { Component } from '@angular/core';

@Component({
	selector: 'app-name',
	template: '<h1>Hello {{ name }}</h1>',
})
export class NameComponent {
	name: string = 'John';

	constructor() {
		this.name = 'Jane';
	}
}

solid SolidJS

import { createSignal } from 'solid-js';

export default function Name() {
	const [name, setName] = createSignal('John');
	setName('Jane');

	return <h1>Hello {name()}</h1>;
}

lit Lit

<!DOCTYPE html>
<head>
	<script type="module" src="./name.js"></script>
</head>
<body>
	<x-name></x-name>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';

@customElement('x-name')
export class XName extends LitElement {
	@state()
	name = 'John';

	constructor() {
		super();
		this.name = 'Jane';
	}

	render() {
		return html`<h1>Hello ${this.name}!</h1>`;
	}
}

ember Ember

<h1>Hello {{this.name}}</h1>
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

export default class CounterComponent extends Component {
	@tracked name = 'John';

	constructor(owner, args) {
		super(owner, args);

		this.name = 'Jane';
	}
}

alpine Alpine

<h1 x-data="{ name: 'John' }" x-init="name = 'Jane'" x-text="name"></h1>

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

Computed state#

svelte Svelte

<script>
	let count = 10;
	$: doubleCount = count * 2;
</script>

<div>{doubleCount}</div>

react React

import { useState, useMemo } from 'react';

export default function DoubleCount() {
	const [count] = useState(10);
	const doubleCount = useMemo(() => count * 2, [count]);

	return <div>{doubleCount}</div>;
}

vue3 Vue 3

<script setup>
import { ref, computed } from 'vue';
const count = ref(10);
const doubleCount = computed(() => count.value * 2);
</script>

<template>
  <div>{{ doubleCount }}</div>
</template>

angular Angular

import { Component, Pipe, PipeTransform } from '@angular/core';

@Pipe({
	name: 'double',
})
export class DoubleCountPipe implements PipeTransform {
	transform(value: number): number {
		return value * 2;
	}
}

@Component({
	selector: 'app-doublecount',
	template: '<div>{{ number | double }}</div>',
})
export class DoublecountComponent {
	count: number = 10;
}

solid SolidJS

import { createSignal } from 'solid-js';

export default function DoubleCount() {
	const [count] = createSignal(10);
	const doubleCount = () => count() * 2;

	return <div>{doubleCount()}</div>;
}

lit Lit

import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';

@customElement('double-count')
export class DoubleCount extends LitElement {
	@state()
	count = 10;

	get doubleCount() {
		return this.count * 2;
	}

	render() {
		return html`<div>${this.doubleCount}</div>`;
	}
}
<!DOCTYPE html>
<head>
	<script type="module" src="./double-count.js"></script>
</head>
<body>
	<double-count></double-count>
</body>

ember Ember

<div>{{this.doubleCount}}</div>
import Component, { tracked } from '@glimmer/component';

export default class DoubleCount extends Component {
	@tracked count = 10;

	get doubleCount() {
		return this.count * 2;
	}
}

alpine Alpine

<h1
	x-data="{
  count : 10,
  get doubleCount() { return this.count * 2 }
}"
	x-text="doubleCount"
></h1>

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

Templating#

Minimal template#

svelte Svelte

<h1>Hello world</h1>

react React

export default function HelloWorld() {
	return <h1>Hello world</h1>;
}

vue3 Vue 3

<template>
  <h1>Hello world</h1>
</template>

angular Angular

import { Component } from '@angular/core';

@Component({
	selector: 'app-helloworld',
	template: '<h1>Hello world</h1>',
})
export class HelloworldComponent {}

solid SolidJS

export default function HelloWorld() {
	return <h1>Hello World!</h1>;
}

lit Lit

import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';

@customElement('hello-world')
export class HelloWorld extends LitElement {
	render() {
		return html`<h1>Hello world</h1>`;
	}
}
<!DOCTYPE html>
<head>
	<script type="module" src="./hello-world.js"></script>
</head>
<body>
	<hello-world></hello-world>
</body>

ember Ember

<h1>Hello world</h1>

alpine Alpine

<h1>Hello world</h1>

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

Styling#

svelte Svelte

<h1 class="title">I am red</h1>
<button style="font-size: 10rem;">I am a button</button>

<style>
	.title {
		color: red;
	}
</style>

react React

import './style.css';

export default function CssStyle() {
	return (
		<>
			<h1 className="title">I am red</h1>
			<button style={{ 'font-size': '10rem' }}>I am a button</button>
		</>
	);
}
.title {
	color: red;
}

vue3 Vue 3

<template>
  <h1 class="title">
    I am red
  </h1>
  <button style="font-size: 10rem">
    I am a button
  </button>
</template>

<style scoped>
.title {
	color: red;
}
</style>

angular Angular

.title {
	color: red;
}
<h1 class="title">I am red</h1>
<button style="font-size: 10rem">I am a button</button>
import { Component } from '@angular/core';

@Component({
	selector: 'app-cssstyle',
	templateUrl: './cssstyle.component.html',
	styleUrls: ['./cssstyle.component.css'],
})
export class HelloworldComponent {}

solid SolidJS

import './style.css';

export default function CssStyle() {
	return (
		<>
			<h1 class="title">I am red</h1>
			<button style={{ 'font-size': '10rem' }}>I am a button</button>
		</>
	);
}
.title {
	color: red;
}

lit Lit

import { LitElement, html, css } from 'lit';
import { customElement } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';

@customElement('css-style')
export class CssStyle extends LitElement {
	static styles = css`
		.title {
			color: red;
		}
	`;

	render() {
		return html`
			<h1 class="title">I am red</h1>
			<button style=${styleMap({ fontSize: '10rem' })}>I am a button</button>
		`;
	}
}
<!DOCTYPE html>
<head>
	<script type="module" src="./css-style.js"></script>
</head>
<body>
	<css-style></css-style>
</body>

ember Ember

/* using: https://github.com/salsify/ember-css-modules */
.title {
	color: red;
}
<h1 class='title'>I am red</h1>
<button style='font-size: 10rem;'>I am a button</button>

alpine Alpine

<h1 class="title">I am red</h1>
<button style="font-size: 10rem">I am a button</button>

<style>
	.title {
		color: red;
	}
</style>

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

Loop#

svelte Svelte

<script>
	const colors = ['red', 'green', 'blue'];
</script>

<ul>
	{#each colors as color}
		<li>{color}</li>
	{/each}
</ul>

react React

export default function Colors() {
	const colors = ['red', 'green', 'blue'];
	return (
		<ul>
			{colors.map((color) => (
				<li key={color}>{color}</li>
			))}
		</ul>
	);
}

vue3 Vue 3

<script setup>
const colors = ['red', 'green', 'blue'];
</script>

<template>
  <ul>
    <li
      v-for="color in colors"
      :key="color"
    >
      {{ color }}
    </li>
  </ul>
</template>

angular Angular

<ul>
	<li *ngFor="let color of colors">{{ color }}</li>
</ul>
import { Component } from '@angular/core';

@Component({
	selector: 'app-colors',
	templateUrl: './colors.component.html',
})
export class ColorsComponent {
	colors: string[] = ['red', 'green', 'blue'];
}

solid SolidJS

import { For } from 'solid-js';

export default function Colors() {
	const colors = ['red', 'green', 'blue'];

	return (
		<ul>
			<For each={colors}>{(color) => <li>{color}</li>}</For>
		</ul>
	);
}

lit Lit

import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';

@customElement('colors-list')
export class ColorsList extends LitElement {
	colors = ['red', 'green', 'blue'];

	render() {
		return html`
			<ul>
				${this.colors.map((color) => html`<li>${color}</li>`)}
			</ul>
		`;
	}
}
<!DOCTYPE html>
<head>
	<script type="module" src="./colors-list.js"></script>
</head>
<body>
	<colors-list></colors-list>
</body>

ember Ember

<ul>
	{{#each (array 'red' 'green' 'blue') as |color|}}
		<li>{{color}}</li>
	{{/each}}
</ul>

alpine Alpine

<ul x-data="{ colors: ['red', 'green', 'blue'] }">
	<template x-for="color in colors">
		<li x-text="color"></li>
	</template>
</ul>

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

Event click#

svelte Svelte

<script>
	let count = 0;

	function incrementCount() {
		count++;
	}
</script>

<p>Counter: {count}</p>
<button on:click={incrementCount}>+1</button>

react React

import { useState } from 'react';

export default function Counter() {
	const [count, setCount] = useState(0);

	function incrementCount() {
		setCount((count) => count + 1);
	}

	return (
		<>
			<p>Counter: {count}</p>
			<button onClick={incrementCount}>+1</button>
		</>
	);
}

vue3 Vue 3

<script setup>
import { ref } from 'vue';
const count = ref(0);

function incrementCount() {
	count.value++;
}
</script>

<template>
  <p>Counter: {{ count }}</p>
  <button @click="incrementCount">
    +1
  </button>
</template>

angular Angular

<p>Counter: {{ count }}</p>
<button (click)="incrementCount()">+1</button>
import { Component } from '@angular/core';

@Component({
	selector: 'app-counter',
	templateUrl: './counter.component.html',
})
export class CounterComponent {
	count: number = 0;

	incrementCount(): void {
		this.count++;
	}
}

solid SolidJS

import { createSignal } from 'solid-js';

export default function Counter() {
	const [count, setCount] = createSignal(0);

	function incrementCount() {
		setCount(count() + 1);
	}

	return (
		<>
			<p>Counter: {count()}</p>
			<button onClick={incrementCount}>+1</button>
		</>
	);
}

lit Lit

<!DOCTYPE html>
<head>
	<script type="module" src="./x-counter.js"></script>
</head>
<body>
	<x-counter></x-counter>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';

@customElement('x-counter')
export class XCounter extends LitElement {
	@state()
	count = 0;

	incrementCount() {
		this.count = this.count + 1;
	}

	render() {
		return html`
			<p>Counter: ${this.count}</p>
			<button @click=${this.incrementCount}>+1</button>
		`;
	}
}

ember Ember

<p>Counter: {{this.count}}</p>
<button {{on 'click' this.incrementCount}}>+1</button>
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

export default class Counter extends Component {
	@tracked count = 0;

	incrementCount = () => this.count++;
}

alpine Alpine

<div x-data="{ count: 0 }">
	<p>Counter: <span x-text="count"></span></p>
	<button x-on:click="count++">+1</button>
</div>

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

Dom ref#

svelte Svelte

<script>
	import { onMount } from 'svelte';

	let inputElement;

	onMount(() => {
		inputElement.focus();
	});
</script>

<input bind:this={inputElement} />

react React

import { useEffect, useRef } from 'react';

export default function InputFocused() {
	const inputElement = useRef(null);

	useEffect(() => inputElement.current.focus(), []);

	return <input type="text" ref={inputElement} />;
}

vue3 Vue 3

<script setup>
import { ref, onMounted } from 'vue';

const inputElement = ref();

onMounted(() => {
	inputElement.value.focus();
});
</script>

<template>
  <input ref="inputElement">
</template>

angular Angular

import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';

@Component({
	selector: 'app-inputfocused',
	template: '<input type="text" #inputelement />',
})
export class InputfocusedComponent implements AfterViewInit {
	@ViewChild('inputelement')
	inputElement: ElementRef<HTMLInputElement> | undefined;

	ngAfterViewInit(): void {
		this.inputElement?.nativeElement.focus();
	}
}

solid SolidJS

import { onMount } from 'solid-js';

export default function InputFocused() {
	let inputElement;

	onMount(() => inputElement.focus());

	return <input ref={inputElement} type="text" />;
}

lit Lit

<!DOCTYPE html>
<head>
	<script type="module" src="./input-focused.js"></script>
</head>
<body>
	<input-focused></input-focused>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { ref, createRef } from 'lit/directives/ref.js';

@customElement('input-focused')
export class InputFocused extends LitElement {
	inputRef = createRef();

	firstUpdated() {
		this.inputRef.value.focus();
	}

	render() {
		return html`<input type="text" ${ref(this.inputRef)} />`;
	}
}

ember Ember

<input {{this.autofocus}} />
import Component from '@glimmer/component';
import { modifier } from 'ember-modifier';

export default class InputFocused extends Component {
	autofocus = modifier((element) => element.focus());
}

/**
 * modifier: https://github.com/ember-modifier/ember-modifier
 *
 * See also:
 *  - https://github.com/emberjs/rfcs/pull/811
 *    - ember-modifier becomes default part of blueprint
 *  - https://github.com/emberjs/rfcs/pull/757
 *    - dependencyless support for using
 *       `autofocus = element => element.focus()`
 *       instead
 */

alpine Alpine

<input x-init="$el.focus();" />

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

Conditional#

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'}
		<span>STOP</span>
	{:else if light === 'orange'}
		<span>SLOW DOWN</span>
	{:else if light === 'green'}
		<span>GO</span>
	{/if}
</p>

react React

import { useState } from 'react';

const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];

export default function TrafficLight() {
	const [lightIndex, setLightIndex] = useState(0);

	const light = TRAFFIC_LIGHTS[lightIndex];

	function nextLight() {
		if (lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
			setLightIndex(0);
		} else {
			setLightIndex(lightIndex + 1);
		}
	}

	return (
		<>
			<button onClick={nextLight}>Next light</button>
			<p>Light is: {light}</p>
			<p>
				You must
				{light === 'red' && <span>STOP</span>}
				{light === 'orange' && <span>SLOW DOWN</span>}
				{light === 'green' && <span>GO</span>}
			</p>
		</>
	);
}

vue3 Vue 3

<script setup>
import { ref, computed } from 'vue';
const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];
const lightIndex = ref(0);

const light = computed(() => TRAFFIC_LIGHTS[lightIndex.value]);

function nextLight() {
	if (lightIndex.value + 1 > TRAFFIC_LIGHTS.length - 1) {
		lightIndex.value = 0;
	} else {
		lightIndex.value++;
	}
}
</script>

<template>
  <button @click="nextLight">
    Next light
  </button>
  <p>Light is: {{ light }}</p>
  <p>
    You must
    <span v-if="light === 'red'">STOP</span>
    <span v-else-if="light === 'orange'">SLOW DOWN</span>
    <span v-else-if="light === 'green'">GO</span>
  </p>
</template>

angular Angular

<button (click)="nextLight()">Next light</button>
<p>Light is: {{ lightIndex | light }}</p>
<p>
	You must
	<span *ngIf="(lightIndex | light) === 'red'">STOP</span>
	<span *ngIf="(lightIndex | light) === 'orange'">SLOW DOWN</span>
	<span *ngIf="(lightIndex | light) === 'green'">GO</span>
</p>
import { Component, Pipe, PipeTransform } from '@angular/core';

const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];

@Pipe({
	name: 'light',
})
export class TrafficLightPipe implements PipeTransform {
	transform(value: number): string {
		return TRAFFIC_LIGHTS[value];
	}
}

@Component({
	selector: 'app-trafficlight',
	templateUrl: './trafficlight.component.html',
})
export class TrafficlightComponent {
	lightIndex: number = 0;

	nextLight(): void {
		if (this.lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
			this.lightIndex = 0;
		} else {
			this.lightIndex++;
		}
	}
}

solid SolidJS

import { Switch, Match } from 'solid-js/web';
import { createSignal } from 'solid-js';

const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];

export default function TrafficLight() {
	const [lightIndex, setLightIndex] = createSignal(0);

	const light = () => TRAFFIC_LIGHTS[lightIndex()];

	function nextLight() {
		if (lightIndex() + 1 > TRAFFIC_LIGHTS.length - 1) {
			setLightIndex(0);
		} else {
			setLightIndex(lightIndex() + 1);
		}
	}

	return (
		<>
			<button onClick={nextLight}>Next light</button>
			<p>Light is: {light()}</p>
			<p>
				You must
				<Switch>
					<Match when={light() === 'red'}>
						<span>STOP</span>
					</Match>
					<Match when={light() === 'orange'}>
						<span>SLOW DOWN</span>
					</Match>
					<Match when={light() === 'green'}>
						<span>GO</span>
					</Match>
				</Switch>
			</p>
		</>
	);
}

lit Lit

<!DOCTYPE html>
<head>
	<script type="module" src="./traffic-light.js"></script>
</head>
<body>
	<traffic-light></traffic-light>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { choose } from 'lit/directives/choose.js';

const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];

@customElement('traffic-light')
export class TrafficLight extends LitElement {
	@state()
	lightIndex = 0;

	get light() {
		return TRAFFIC_LIGHTS[this.lightIndex];
	}

	nextLight() {
		if (this.lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
			this.lightIndex = 0;
		} else {
			this.lightIndex = this.lightIndex + 1;
		}
	}

	render() {
		return html`
			<button @click=${this.nextLight}>Next light</button>
			<p>Light is ${this.light}</p>
			<p>
				You must
				${choose(this.light, [
					['red', () => html`<span>STOP</span>`],
					['orange', () => html`<span>SLOW DOWN</span>`],
					['green', () => html`<span>GO</span>`],
				])}
			</p>
		`;
	}
}

ember Ember

<button {{on 'click' this.nextLight}}>Next light</button>
<p>Light is: {{this.light}}</p>
<p>
	You must
	{{#if (eq this.light 'red')}}
		STOP
	{{else if (eq this.light 'orange')}}
		SLOW DOWN
	{{else if (eq this.light 'green')}}
		GO
	{{/if}}
</p>
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

const TRAFFIC_LIGHTS = ['red', 'orange', 'green'];

export default class TrafficLight extends Component {
	@tracked lightIndex = 0;

	get light() {
		return TRAFFIC_LIGHTS[this.lightIndex];
	}

	nextLight = () => {
		if (this.lightIndex + 1 > TRAFFIC_LIGHTS.length - 1) {
			this.lightIndex = 0;
		} else {
			this.lightIndex++;
		}
	};
}

alpine Alpine

<div
	x-data="{
  TRAFFIC_LIGHTS: ['red', 'orange', 'green'],
  lightIndex: 0,
  get light() { return this.TRAFFIC_LIGHTS[this.lightIndex] },
  nextLight() {
    if (this.lightIndex + 1 > this.TRAFFIC_LIGHTS.length - 1) {
      this.lightIndex = 0
    } else {
      this.lightIndex++
    }
  }
}"
>
	<button x-on:click="nextLight">Next light</button>
	<p>Light is: <span x-text="light"></span></p>
	<p>
		You must
		<span x-show="light === 'red'">STOP</span>
		<span x-show="light === 'orange'">SLOW DOWN</span>
		<span x-show="light === 'green'">GO</span>
	</p>
</div>

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

Lifecycle#

On mount#

svelte Svelte

<script>
	import { onMount } from 'svelte';
	let pageTitle = '';
	onMount(() => {
		pageTitle = document.title;
	});
</script>

<p>Page title is: {pageTitle}</p>

react React

import { useState, useEffect } from 'react';

export default function PageTitle() {
	const [pageTitle, setPageTitle] = useState('');

	useEffect(() => {
		setPageTitle(document.title);
	}, []);

	return <p>Page title: {pageTitle}</p>;
}

vue3 Vue 3

<script setup>
import { ref, onMounted } from 'vue';
const pageTitle = ref('');
onMounted(() => {
	pageTitle.value = document.title;
});
</script>

<template>
  <p>Page title: {{ pageTitle }}</p>
</template>

angular Angular

import { Component, AfterContentInit } from '@angular/core';

@Component({
	selector: 'app-pagetitle',
	template: '<p>Page title: {{ pageTitle }}</p>',
})
export class PagetitleComponent implements AfterContentInit {
	pageTitle: string = '';

	ngAfterContentInit(): void {
		this.pageTitle = document.title;
	}
}

solid SolidJS

import { createSignal, onMount } from 'solid-js';

export default function PageTitle() {
	const [pageTitle, setPageTitle] = createSignal('');

	onMount(() => {
		setPageTitle(document.title);
	});

	return <p>Page title: {pageTitle()}</p>;
}

lit Lit

<!DOCTYPE html>
<head>
	<script type="module" src="./page-title.js"></script>
</head>
<body>
	<page-title></page-title>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';

@customElement('page-title')
export class PageTitle extends LitElement {
	@state()
	pageTitle = '';

	connectedCallback() {
		super.connectedCallback();
		this.pageTitle = document.title;
	}

	render() {
		return html`<p>Page title: ${this.pageTitle}</p>`;
	}
}

ember Ember

<p>Page title is: {{(this.pageTitle)}}</p>
import Component from '@glimmer/component';

export default class PageTitle extends Component {
	pageTitle = () => document.title;
}

alpine Alpine

<p x-data="{ pageTitle: '' }" x-init="$nextTick(() => { pageTitle = document.title })">Page title: <span x-text="pageTitle"></span></p>

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

On unmount#

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>

react React

import { useState, useEffect } from 'react';

export default function Time() {
	const [time, setTime] = useState(new Date().toLocaleTimeString());

	useEffect(() => {
		const timer = setInterval(() => {
			setTime(new Date().toLocaleTimeString());
		}, 1000);

		return () => {
			clearInterval(timer);
		};
	}, []);

	return <p>Current time: {time}</p>;
}

vue3 Vue 3

<script setup>
import { ref, onUnmounted } from 'vue';

const time = ref(new Date().toLocaleTimeString());

const timer = setInterval(() => {
	time.value = new Date().toLocaleTimeString();
}, 1000);

onUnmounted(() => {
	clearInterval(timer);
});
</script>

<template>
  <p>Current time: {{time}}</p>
</template>

angular Angular

import { Component, OnDestroy } from '@angular/core';

@Component({
	selector: 'app-time',
	template: '<p>Current time: {{ time }}</p>',
})
export class TimeComponent implements OnDestroy {
	time: string = new Date().toLocaleTimeString();
	timer: number;

	constructor() {
		this.timer = window.setInterval(() => {
			this.time = new Date().toLocaleTimeString();
		}, 1000);
	}

	ngOnDestroy(): void {
		window.clearInterval(this.timer);
	}
}

solid SolidJS

import { createSignal, onCleanup } from 'solid-js';

export default function Time() {
	const [time, setTime] = createSignal(new Date().toLocaleTimeString());

	const timer = setInterval(() => {
		setTime(new Date().toLocaleTimeString());
	}, 1000);

	onCleanup(() => clearInterval(timer));

	return <p>Current time: {time()}</p>;
}

lit Lit

<!DOCTYPE html>
<head>
	<script type="module" src="./x-time.js"></script>
</head>
<body>
	<x-time></x-time>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';

@customElement('x-time')
export class XTime extends LitElement {
	@state()
	time = '';

	timer;

	connectedCallback() {
		super.connectedCallback();
		this.timer = setInterval(() => {
			this.time = new Date().toLocaleTimeString();
		}, 1000);
	}

	disconnectedCallback() {
		super.disconnectedCallback();
		clearInterval(this.timer);
	}

	render() {
		return html`<p>Current time: ${this.time}</p>`;
	}
}

ember Ember

<p>Current time: {{this.time}}</p>
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { registerDestructor } from '@ember/destroyable';

export default class Time extends Component {
	@tracked time = new Date().toLocaleTimeString();

	constructor(owner, args) {
		super(owner, args);

		let timer = setInterval(() => {
			this.time = new Date().toLocaleTimeString();
		}, 1000);

		registerDestructor(this, () => clearInterval(timer));
	}
}

alpine Alpine

<p
	x-data="{
  time: new Date().toLocaleTimeString(),
  timer: null,
  init() { this.timer = setInterval(() => (this.time = new Date().toLocaleTimeString()), 1000) },
  destroy() { clearInterval(this.timer) }
}"
>
	Current time: <span x-text="time"></span>
</p>

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

Component composition#

Props#

svelte Svelte

<script>
	import UserProfile from './UserProfile.svelte';
</script>

<UserProfile name="John" age={20} favouriteColors={['green', 'blue', 'red']} isAvailable />
<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.join(', ')} !</p>
<p>I am {isAvailable ? 'available' : 'not available'}</p>

react React

import UserProfile from './UserProfile.jsx';

export default function App() {
	return <UserProfile name="John" age={20} favouriteColors={['green', 'blue', 'red']} isAvailable />;
}
import PropTypes from 'prop-types';

export default function UserProfile({ name = '', age = null, favouriteColors = [], isAvailable = false }) {
	return (
		<>
			<p>My name is {name} !</p>
			<p>My age is {age} !</p>
			<p>My favourite colors are {favouriteColors.join(', ')} !</p>
			<p>I am {isAvailable ? 'available' : 'not available'}</p>
		</>
	);
}

UserProfile.propTypes = {
	name: PropTypes.string.isRequired,
	age: PropTypes.number.isRequired,
	favouriteColors: PropTypes.arrayOf(PropTypes.string).isRequired,
	isAvailable: PropTypes.bool.isRequired,
};

vue3 Vue 3

<script setup>
import UserProfile from './UserProfile.vue';
</script>

<template>
  <UserProfile
    name="John"
    :age="20"
    :favourite-colors="['green', 'blue', 'red']"
    is-available
  />
</template>
<script setup>
const props = defineProps({
	name: {
		type: String,
		required: true,
		default: '',
	},
	age: {
		type: Number,
		required: true,
		default: null,
	},
	favouriteColors: {
		type: Array,
		required: true,
		default: () => [],
	},
	isAvailable: {
		type: Boolean,
		required: true,
		default: false,
	},
});
</script>

<template>
  <p>My name is {{ props.name }} !</p>
  <p>My age is {{ props.age }} !</p>
  <p>My favourite colors are {{ props.favouriteColors.join(', ') }} !</p>
  <p>I am {{ props.isAvailable ? 'available' : 'not available' }}</p>
</template>

angular Angular

<app-userprofile name="John" [age]="20" [favouriteColors]="['green', 'blue', 'red']" [isAvailable]="true"> </app-userprofile>
import { Component } from '@angular/core';

@Component({
	selector: 'app-root',
	templateUrl: './app.component.html',
	styleUrls: ['./app.component.css'],
})
export class AppComponent {}
<p>My name is {{ name }} !</p>
<p>My age is {{ age }} !</p>
<p>My favourite colors are {{ favouriteColors.join(', ') }} !</p>
<p>I am {{ isAvailable ? 'available' : 'not available' }}</p>
import { Component, Input } from '@angular/core';

interface UserprofileComponentProps {
	name: string;
	age: number;
	favouriteColors: string[];
	isAvailable: boolean;
}

@Component({
	selector: 'app-userprofile',
	templateUrl: './userprofile.component.html',
	styleUrls: ['./userprofile.component.css'],
})
export class UserprofileComponent implements UserprofileComponentProps {
	@Input() name: string = '';
	@Input() age: number = 0;
	@Input() favouriteColors: string[] = [];
	@Input() isAvailable: boolean = false;
}

solid SolidJS

import UserProfile from './UserProfile.jsx';

export default function App() {
	return <UserProfile name="John" age={20} favouriteColors={['green', 'blue', 'red']} isAvailable />;
}
import { mergeProps } from 'solid-js';

export default function UserProfile(props) {
	const merged = mergeProps({ name: '', age: null, favouriteColors: [], isAvailable: false }, props);

	return (
		<>
			<p>My name is {merged.name} !</p>
			<p>My age is {merged.age} !</p>
			<p>My favourite colors are {merged.favouriteColors.join(', ')} !</p>
			<p>I am {merged.isAvailable ? 'available' : 'not available'}</p>
		</>
	);
}

lit Lit

<!DOCTYPE html>
<head>
	<script type="module" src="./x-app.js"></script>
</head>
<body>
	<x-app></x-app>
</body>
import { LitElement, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';

@customElement('user-profile')
export class UserProfile extends LitElement {
	@property()
	name = '';

	@property({ type: Number })
	age = null;

	@property({ type: Array })
	favouriteColors = [];

	@property({ type: Boolean })
	isAvailable = false;

	render() {
		return html`
			<p>My name is ${this.name}</p>
			<p>My age is ${this.age}</p>
			<p>My favourite coloros are ${this.favouriteColors.join(', ')}</p>
			<p>I am ${this.isAvailable ? 'available' : 'not available'}</p>
		`;
	}
}
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';

import './user-profile';

@customElement('x-app')
export class XApp extends LitElement {
	render() {
		return html`<user-profile name="John" age="20" .favouriteColors=${['green', 'blue', 'red']} isavailable></user-profile>`;
	}
}

ember Ember

<UserProfile @name='John' @age={{20}} @favouriteColors={{array 'green' 'blue' 'red'}} @isAvailable={{true}} />
<p>My name is {{@name}} !</p>
<p>My age is {{@age}} !</p>
<p>My favourite colors are {{this.formattedColors}} !</p>
<p>I am {{if @isAvailable 'available' 'not available'}}</p>
import Component from '@glimmer/component';

export default class UserProfile extends Component {
	get formattedColors() {
		return this.args.favouriteColors.join(', ');
	}
}

alpine Alpine

<!--Alpine JS suggests using a server-side templating engine or another frontend framework in conjunction with Alpine to do this-->

<div
	x-data="{
  name: 'John',
  age: 20,
  favouriteColors: ['green', 'blue', 'red'],
  isAvailable: true
}"
>
	<p>My name is <span x-text="John"></span></p>
	<p>My age is <span x-text="age"></span></p>
	<p>My favourite colors are <span x-text="favouriteColors.join(', ')"></span></p>
	<p>I am <span x-text="isAvailable ? 'available' : 'not available'"></span></p>
</div>

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

Emit to parent#

svelte Svelte

<script>
	import AnswerButton from './AnswerButton.svelte';

	let canCome = true;

	function onAnswerNo() {
		canCome = false;
	}

	function onAnswerYes() {
		canCome = true;
	}
</script>

<p>Can I come ?</p>
<AnswerButton on:yes={onAnswerYes} on:no={onAnswerNo} />
<p style="font-size: 50px;">{canCome ? '😀' : '😥'}</p>
<script>
	import { createEventDispatcher } from 'svelte';

	const dispatch = createEventDispatcher();

	function clickYes() {
		dispatch('yes');
	}

	function clickNo() {
		dispatch('no');
	}
</script>

<button on:click={clickYes}> YES </button>

<button on:click={clickNo}> NO </button>

react React

import { useState } from 'react';
import AnswerButton from './AnswerButton.jsx';

export default function App() {
	const [canCome, setCanCome] = useState(true);

	function onAnswerNo() {
		setCanCome(false);
	}

	function onAnswerYes() {
		setCanCome(true);
	}

	return (
		<>
			<p>Can I come ?</p>
			<AnswerButton onYes={onAnswerYes} onNo={onAnswerNo} />
			<p style={{ fontSize: 50 }}>{canCome ? '😀' : '😥'}</p>
		</>
	);
}
import PropTypes from 'prop-types';

export default function AnswerButton({ onYes, onNo }) {
	return (
		<>
			<button onClick={onYes}>YES</button>

			<button onClick={onNo}>NO</button>
		</>
	);
}

AnswerButton.propTypes = {
	onYes: PropTypes.func,
	onNo: PropTypes.func,
};

vue3 Vue 3

<script setup>
import { ref } from 'vue';
import AnswerButton from './AnswerButton.vue';

let canCome = ref(true);

function onAnswerNo() {
	canCome.value = false;
}

function onAnswerYes() {
	canCome.value = true;
}
</script>

<template>
  <p>Can I come ?</p>
  <AnswerButton
    @yes="onAnswerYes"
    @no="onAnswerNo"
  />
  <p style="font-size: 50px">
    {{ canCome ? '😀' : '😥' }}
  </p>
</template>
<script setup>
const emit = defineEmits(['yes', 'no']);

function clickYes() {
	emit('yes');
}

function clickNo() {
	emit('no');
}
</script>

<template>
  <button @click="clickYes">
    YES
  </button>

  <button @click="clickNo">
    NO
  </button>
</template>

angular Angular

<button (click)="yes.emit()">YES</button>
<button (click)="no.emit()">NO</button>
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
	selector: 'app-answer-button',
	templateUrl: './answer-button.component.html',
})
export class AnswerButtonComponent {
	@Output()
	yes = new EventEmitter<void>();

	@Output()
	no = new EventEmitter<void>();
}
<p>Can I come ?</p>
<app-answer-button (yes)="onAnswerYes()" (no)="onAnswerNo()"> </app-answer-button>
<p style="font-size: 50px">{{ canCome ? '😀' : '😥' }}</p>
import { Component } from '@angular/core';

@Component({
	selector: 'app-root',
	templateUrl: './app.component.html',
})
export class AppComponent {
	canCome = true;

	onAnswerYes() {
		this.canCome = true;
	}

	onAnswerNo() {
		this.canCome = false;
	}
}

solid SolidJS

import { createSignal } from 'solid-js';
import AnswerButton from './AnswerButton.jsx';

export default function App() {
	const [canCome, setCanCome] = createSignal(true);

	function onAnswerNo() {
		setCanCome(false);
	}

	function onAnswerYes() {
		setCanCome(true);
	}

	return (
		<>
			<p>Can I come ?</p>
			<AnswerButton onYes={onAnswerYes} onNo={onAnswerNo} />
			<p style={{ 'font-size': '50px' }}>{canCome() ? '😀' : '😥'}</p>
		</>
	);
}
export default function AnswerButton(props) {
	return (
		<>
			<button onClick={props.onYes}>YES</button>
			<button onClick={props.onNo}>NO</button>
		</>
	);
}

lit Lit

import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';

@customElement('answer-button')
export class AnswerButton extends LitElement {
	clickYes() {
		this.dispatchEvent(new Event('yes'));
	}

	clickNo() {
		this.dispatchEvent(new Event('no'));
	}

	render() {
		return html`
			<button @click=${this.clickYes}>Yes</button>
			<button @click=${this.clickNo}>No</button>
		`;
	}
}
<!DOCTYPE html>
<head>
	<script type="module" src="./x-app.js"></script>
</head>
<body>
	<x-app></x-app>
</body>
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';

import './answer-button';

@customElement('x-app')
export class XApp extends LitElement {
	@state()
	canCome = true;

	onAnswerNo() {
		this.canCome = false;
	}

	onAnswerYes() {
		this.canCome = true;
	}

	render() {
		return html`
			<p>Can I come ?</p>
			<answer-button @yes=${this.onAnswerYes} @no=${this.onAnswerNo}></answer-button>
			<p style="font-size: 50px;">${this.canCome ? '😀' : '😥'}</p>
		`;
	}
}

ember Ember

<button {{on 'click' @onYes}}> YES </button>
<button {{on 'click' @onNo}}> NO </button>
<p>Can I come ?</p>
<AnswerButton @onYes={{this.handleYes}} @onNo={{this.handleNo}} />
<p style='font-size: 50px;'>{{if this.canCome '😀' '😥'}}</p>
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

export default class App extends Component {
	@tracked canCome = true;

	handleYes = () => (this.canCome = true);
	handleNo = () => (this.canCome = false);
}

alpine Alpine

<div x-data="{ canCome: true }" x-on:yes="canCome = true" x-on:no="canCome = false">
	<p>Can I come ?</p>
	<div>
		<button x-on:click="$dispatch('yes')">YES</button>
		<button x-on:click="$dispatch('no')">NO</button>
	</div>
	<p style="font-size: 50px" x-text="canCome ? '😀' : '😥'"></p>
</div>

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

Slot#

svelte Svelte

<script>
	import FunnyButton from './FunnyButton.svelte';
</script>

<FunnyButton>Click me !</FunnyButton>
<button
	style="background: rgba(0, 0, 0, 0.4); color: #fff; padding: 10px 20px; font-size: 30px; border: 2px solid #fff; margin: 8px; transform: scale(0.9); box-shadow: 4px 4px rgba(0, 0, 0, 0.4); transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s; outline: 0;"
>
	<slot />
</button>

react React

import FunnyButton from './FunnyButton.jsx';

export default function App() {
	return <FunnyButton>Click me !</FunnyButton>;
}
import PropTypes from 'prop-types';

export default function FunnyButton({ children }) {
	return (
		<button
			style={{
				background: 'rgba(0, 0, 0, 0.4)',
				color: '#fff',
				padding: '10px 20px',
				fontSize: '30px',
				border: '2px solid #fff',
				margin: '8px',
				transform: 'scale(0.9)',
				boxShadow: '4px 4px rgba(0, 0, 0, 0.4)',
				transition: 'transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s',
				outline: '0',
			}}
		>
			{children}
		</button>
	);
}

FunnyButton.propTypes = {
	children: PropTypes.node,
};

vue3 Vue 3

<script setup>
import FunnyButton from './FunnyButton.vue';
</script>

<template>
  <FunnyButton> Click me ! </FunnyButton>
</template>
<template>
  <button
    style="
			background: rgba(0, 0, 0, 0.4);
			color: #fff;
			padding: 10px 20px;
			font-size: 30px;
			border: 2px solid #fff;
			margin: 8px;
			transform: scale(0.9);
			box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
			transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
			outline: 0;
		"
  >
    <slot />
  </button>
</template>

angular Angular

import { Component } from '@angular/core';

@Component({
	selector: 'app-root',
	template: '<app-funny-button>Click me !</app-funny-button>',
})
export class AppComponent {}
button {
	background: rgba(0, 0, 0, 0.4);
	color: #fff;
	padding: 10px 20px;
	font-size: 30px;
	border: 2px solid #fff;
	margin: 8px;
	transform: scale(0.9);
	box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
	transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
	outline: 0;
}
import { Component } from '@angular/core';

@Component({
	selector: 'app-root',
	styleUrls: ['./funny-button.component.css'],
	template: `
		<button>
			<ng-content></ng-content>
		</button>
	`,
})
export class FunnyButtonComponent {}

solid SolidJS

import FunnyButton from './FunnyButton.jsx';

export default function App() {
	return <FunnyButton>Click me !</FunnyButton>;
}
export default function FunnyButton(props) {
	return (
		<button
			style={{
				background: 'rgba(0, 0, 0, 0.4)',
				color: '#fff',
				padding: '10px 20px',
				'font-size': '30px',
				border: '2px solid #fff',
				margin: '8px',
				transform: 'scale(0.9)',
				'box-shadow': '4px 4px rgba(0, 0, 0, 0.4)',
				transition: 'transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s',
				outline: '0',
			}}
		>
			{props.children}
		</button>
	);
}

lit Lit

import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';

@customElement('funny-button')
export class FunnyButton extends LitElement {
	render() {
		return html`
			<button
				style=${styleMap({
					background: 'rgba(0, 0, 0, 0.4)',
					color: '#fff',
					padding: '10px 20px',
					fontSize: '30px',
					border: '2px solid #fff',
					margin: '8px',
					transform: 'scale(0.9)',
					boxShadow: '4px 4px rgba(0, 0, 0, 0.4)',
					transition: 'transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s',
					outline: '0',
				})}
			>
				<slot></slot>
			</button>
		`;
	}
}
<!DOCTYPE html>
<head>
	<script type="module" src="./x-app.js"></script>
</head>
<body>
	<x-app></x-app>
</body>
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';

import './funny-button';

@customElement('x-app')
export class XApp extends LitElement {
	render() {
		return html`<funny-button>Click me !</funny-button>`;
	}
}

ember Ember

<FunnyButton> Click me ! </FunnyButton>
<button
	style='
    background: rgba(0, 0, 0, 0.4);
    color: #fff;
    padding: 10px 20px;
    font-size: 30px;
    border: 2px solid #fff;
    margin: 8px;
    transform: scale(0.9);
    box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
    transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
    outline: 0;'
>
	{{yield}}
</button>

alpine Alpine

<!--Alpine JS suggests using a server-side templating engine or another frontend framework in conjunction with Alpine to do this-->

<button
	x-data
	x-text="'Click me !'"
	style="
		background: rgba(0, 0, 0, 0.4);
		color: #fff;
		padding: 10px 20px;
		font-size: 30px;
		border: 2px solid #fff;
		margin: 8px;
		transform: scale(0.9);
		box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
		transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
		outline: 0;
	"
>
	<span>No content found</span>
</button>

qwik Qwik

Missing snippet Help us to improve Component Party 🎉
Contribute on Github

Slot fallback#

svelte Svelte

<script>
	import FunnyButton from './FunnyButton.svelte';
</script>

<FunnyButton />
<FunnyButton>I got content !</FunnyButton>
<button
	style="background: rgba(0, 0, 0, 0.4); color: #fff; padding: 10px 20px; font-size: 30px; border: 2px solid #fff; margin: 8px; transform: scale(0.9); box-shadow: 4px 4px rgba(0, 0, 0, 0.4); transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s; outline: 0;"
>
	<slot>
		<span>No content found</span>
	</slot>
</button>

react React

import FunnyButton from './FunnyButton.jsx';

export default function App() {
	return (
		<>
			<FunnyButton />
			<FunnyButton>I got content !</FunnyButton>
		</>
	);
}
import PropTypes from 'prop-types';

export default function FunnyButton({ children }) {
	return (
		<button
			style={{
				background: 'rgba(0, 0, 0, 0.4)',
				color: '#fff',
				padding: '10px 20px',
				fontSize: '30px',
				border: '2px solid #fff',
				margin: '8px',
				transform: 'scale(0.9)',
				boxShadow: '4px 4px rgba(0, 0, 0, 0.4)',
				transition: 'transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s',
				outline: '0',
			}}
		>
			{children || <span>No content found</span>}
		</button>
	);
}

FunnyButton.propTypes = {
	children: PropTypes.node,
};

vue3 Vue 3

<script setup>
import FunnyButton from './FunnyButton.vue';
</script>

<template>
  <FunnyButton />
  <FunnyButton> I got content ! </FunnyButton>
</template>
<template>
  <button
    style="
			background: rgba(0, 0, 0, 0.4);
			color: #fff;
			padding: 10px 20px;
			font-size: 30px;
			border: 2px solid #fff;
			margin: 8px;
			transform: scale(0.9);
			box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
			transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
			outline: 0;
		"
  >
    <slot>
      <span>No content found</span>
    </slot>
  </button>
</template>

angular Angular

<app-funny-button></app-funny-button>

<app-funny-button>
	<ng-template #content>I got content!</ng-template>
</app-funny-button>
import { Component } from '@angular/core';

@Component({
	selector: 'app-root',
	templateUrl: './app.component.html',
})
export class AppComponent {}
button {
	background: rgba(0, 0, 0, 0.4);
	color: #fff;
	padding: 10px 20px;
	font-size: 30px;
	border: 2px solid #fff;
	margin: 8px;
	transform: scale(0.9);
	box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
	transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
	outline: 0;
}
import { Component, ContentChild, TemplateRef } from '@angular/core';

@Component({
	selector: 'app-root',
	styleUrls: ['./funny-button.component.css'],
	template: `
		<button>
			<ng-container *ngIf="content; else fallback" [ngTemplateOutlet]="content"></ng-container>

			<ng-template #fallback>
				<span>No content found</span>
			</ng-template>
		</button>
	`,
})
export class FunnyButtonComponent {
	@ContentChild('content', { read: TemplateRef })
	content?: TemplateRef<unknown>;
}

solid SolidJS

import FunnyButton from './FunnyButton.jsx';

export default function App() {
	return (
		<>
			<FunnyButton />
			<FunnyButton>I got content !</FunnyButton>
		</>
	);
}
export default function FunnyButton(props) {
	return (
		<button
			style={{
				background: 'rgba(0, 0, 0, 0.4)',
				color: '#fff',
				padding: '10px 20px',
				'font-size': '30px',
				border: '2px solid #fff',
				margin: '8px',
				transform: 'scale(0.9)',
				'box-shadow': '4px 4px rgba(0, 0, 0, 0.4)',
				transition: 'transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s',
				outline: '0',
			}}
		>
			{props.children || <span>No content found</span>}
		</button>
	);
}

lit Lit

import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';

@customElement('funny-button')
export class FunnyButton extends LitElement {
	render() {
		return html`
			<button
				style=${styleMap({
					background: 'rgba(0, 0, 0, 0.4)',
					color: '#fff',
					padding: '10px 20px',
					fontSize: '30px',
					border: '2px solid #fff',
					margin: '8px',
					transform: 'scale(0.9)',
					boxShadow: '4px 4px rgba(0, 0, 0, 0.4)',
					transition: 'transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s',
					outline: '0',
				})}
			>
				<slot>
					<span>No content found</span>
				</slot>
			</button>
		`;
	}
}
<!DOCTYPE html>
<head>
	<script type="module" src="./x-app.js"></script>
</head>
<body>
	<x-app></x-app>
</body>
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';

import './funny-button';

@customElement('x-app')
export class XApp extends LitElement {
	render() {
		return html`
			<funny-button></funny-button>
			<funny-button>Click me !</funny-button>
		`;
	}
}

ember Ember

<FunnyButton />
<FunnyButton>I got content !</FunnyButton>
<button
	style='
    background: rgba(0, 0, 0, 0.4);
    color: #fff;
    padding: 10px 20px;
    font-size: 30px;
    border: 2px solid #fff;
    margin: 8px;
    transform: scale(0.9);
    box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
    transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
    outline: 0;'
>
	{{#if (has-block)