Demos
INFO
All components of this page are svelte components, wrappend in custom elements (that's what the plugin does). The Page itself is a vue project. To get a better idea, have a look at the source codes provided and inspect the source code of this page.
Counter
No Svelte Demo without the Counter!
Embedded via <x-counter/>
source code
svelte
<!-- @custom-element x-counter -->
<script lang="ts">
let count: number = $state(0)
let props = $props();
const increment = () => {
count += 1
}
</script>
<div class="twp background-color flex flex-col items-center p-6 bg-gray-100 rounded-lg shadow-md max-w-xs mx-auto">
<button
onclick={increment}
class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 shadow-md align-middle m-auto">
count is {count}
</button>
</div>
Pokemon Widget
Embedded via <pokemon-widget/>
source code
svelte
<!-- @custom-element pokemon-widget -->
<script lang="ts">
import {blur} from 'svelte/transition';
type Pokemon = {
name: string;
sprites: { front_default: string };
};
let pokemon = $state<Pokemon | null>(null);
let disableButton = $state(false)
fetchPokemon();
async function fetchPokemon() {
disableButton = true
const id = Math.floor(Math.random() * 1024) + 1; // Random Pokémon ID
pokemon = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`)
.then((res) => {
disableButton = false
return res.json()
});
}
</script>
<div class="twp flex flex-col items-center p-6 rounded-lg shadow-md max-w-xs mx-auto">
<div class="w-20 h-20 object-contain shadow-md rounded-lg">
{#key pokemon?.name}
<img transition:blur
src={pokemon?.sprites.front_default}
alt={pokemon?.name}
class={["w-20 h-20 object-contain absolute"]}/>
{/key}
</div>
<div class="w-60 h-10 ">
{#key pokemon?.name}
<p class={['text-xl font-semibold capitalize w-60 h-10 text-center absolute']}
transition:blur>{pokemon?.name ?? "Loading"}</p>
{/key}
</div>
<button onclick={fetchPokemon} disabled={disableButton}
class="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition w-60"
>
Get Random Pokémon
</button>
</div>
Number Translator
Multiple custom components sharing state.
Embedded via <language-switch/>
and <translator-container number="x"/>
source code
ts
type LanguageType = 'en' | 'es';
class NumberTranslator {
language: LanguageType = $state('en')
labels = [
{'en': 'zero', 'es': 'cero'},
{'en': 'one', 'es': 'uno'},
{'en': 'two', 'es': 'dos'},
{'en': 'three', 'es': 'tres'},
{'en': 'four', 'es': 'cuatro'},
{'en': 'five', 'es': 'cinco'},
{'en': 'six', 'es': 'seis'},
{'en': 'seven', 'es': 'siete'},
{'en': 'eight', 'es': 'ocho'},
{'en': 'nine', 'es': 'nueve'},
{'en': 'ten', 'es': 'diez'}
]
getLanguage() {
return this.language;
}
translate(number: number) {
return this.labels[number][this.language]
}
toggleLanguage() {
this.language = (this.language == 'en') ? 'es' : 'en';
}
}
export const numberTranslator = new NumberTranslator();
svelte
<!-- @custom-element language-switch -->
<script lang="ts">
import {numberTranslator} from "./state.svelte";
let checked: boolean = $derived(numberTranslator.getLanguage() == 'es')
function toggleLanguage() {
numberTranslator.toggleLanguage()
}
</script>
<div class="twp w-48 rounded-lg">
<div class="flex items-center mb-5 mx-5 py-1 ">
<span class="mr-3 text-sm font-medium ">English</span>
<label class="relative flex items-center cursor-pointer">
<input type="checkbox" value="" class="sr-only peer" {checked} onclick={toggleLanguage}>
<div class="w-9 h-5 bg-gray-200 hover:bg-gray-300 peer-focus:outline-0 rounded-full peer transition-all ease-in-out duration-500 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-indigo-600 hover:peer-checked:bg-indigo-700 "></div>
</label>
<span class="ml-3 text-sm font-medium ">Spanish</span>
</div>
</div>
svelte
<!-- @custom-element translator-container -->
<script lang="ts">
import Translator from "./Translator.svelte";
let {number = 0} = $props()
</script>
<div class="twp custom-element background-color flex flex-col items-center p-6 bg-gray-100 rounded-lg shadow-md max-w-xs mx-auto text-sm">
<span>Number is {number}</span>
<span>Translation: <Translator {number}/></span>
</div>
svelte
<!-- @custom-element x-translator -->
<script>
import {numberTranslator} from "./state.svelte";
let {number: number = 0} = $props();
</script>
{numberTranslator.translate(number)}
Using the same Components, you can also let Svelte components output just text. In this case, the listing is part of the Vue-Page, the words are Svelte.
Embedded via <x-translator number="x"/>
and <language-switch/>
Lets count to 5:
Now change the language:
Counter with Shadow-Mode Open
Embedded via <shadow-counter/>
source code
svelte
<!-- @custom-element shadow-counter shadow=open -->
<script lang="ts">
let count: number = $state(0)
let props = $props();
const increment = () => {
count += 1
}
</script>
<div>
<button
onclick={increment}
>
count is {count}
</button>
</div>