state machine: add demo & fix

This commit is contained in:
Elijah Duffy
2025-09-05 10:57:05 -07:00
parent 4e6a8c62c5
commit 047044cbbe
2 changed files with 102 additions and 3 deletions

View File

@@ -40,7 +40,7 @@
import { tweened } from 'svelte/motion';
import { fade, fly } from 'svelte/transition';
import { validateForm } from '@svelte-toolkit/validate';
import { ArrowLeft, Check } from 'phosphor-svelte';
import { ArrowLeft, Check, CheckFat } from 'phosphor-svelte';
import type { IconDef } from './util';
interface Props {
@@ -167,6 +167,7 @@
// validate the form
const result = await validateForm(formElement);
console.log('validated form', result);
if (!result) {
buttonComponent.animateBounce();
setTimeout(() => focusFirstInput(true), 50);
@@ -359,7 +360,7 @@
{#if i >= index}
<span class="mb-[0.0625rem]">{i + 1}</span>
{:else}
<Check class="mt-0.5" size="1.5rem" weight="bold" />
<CheckFat size="0.9rem" weight="fill" />
{/if}
</div>
{/each}
@@ -378,7 +379,7 @@
onclick={() => (index -= 1)}
transition:fly={{ x: -200, duration: 200 }}
>
<ArrowLeft />
<ArrowLeft size="1.5em" />
Back
</button>
{/if}
@@ -460,6 +461,7 @@
{#if index < pages.length - 1 && page.button && $height > 0}
<div class="mt-4" out:fade bind:this={buttonContainer}>
<Button
type="submit"
icon={page.button.icon}
onclick={handleContinueClick}
animate={false}

View File

@@ -0,0 +1,97 @@
<script lang="ts">
import PhoneInput from '$lib/PhoneInput.svelte';
import StateMachine, { type StateMachinePage } from '$lib/StateMachine.svelte';
import TextInput from '$lib/TextInput.svelte';
import { ArrowRight, Check } from 'phosphor-svelte';
let stateMachineRef: StateMachine;
let index = $state(1);
const pages: StateMachinePage[] = [
{
hero: {
text: 'Hey there!',
fontSize: 'large',
colour: 'light',
size: 'large'
},
snippet: firstPage,
button: {
text: 'Next',
onclick: () => console.log('next'),
icon: {
component: ArrowRight,
props: { size: '1.2em', weight: 'bold' }
}
}
},
{
hero: {
text: 'How can we reach you?',
fontSize: 'small',
colour: 'dark',
size: 'small'
},
snippet: secondPage,
button: {
text: 'Submit',
onclick: () => console.log('finish'),
icon: {
component: Check,
props: { size: '1.2em', weight: 'bold' }
}
}
}
];
const successPage: StateMachinePage = {
disableBack: true,
hero: {
text: 'All done! 🎉',
fontSize: 'small',
size: 'large',
colour: 'light'
},
snippet: finishedSnippet,
button: false
};
const failurePage: StateMachinePage = {
disableBack: true,
hero: {
text: 'Something went wrong 😔',
fontSize: 'small',
size: 'large',
colour: 'dark'
},
snippet: failureSnippet,
button: false
};
</script>
<StateMachine
bind:this={stateMachineRef}
{pages}
success={successPage}
failure={failurePage}
{index}
></StateMachine>
{#snippet firstPage()}
<TextInput label="What's your name?" validate={{ required: true }} />
{/snippet}
{#snippet secondPage()}
<PhoneInput label="What's your phone number?" required={true} />
{/snippet}
{#snippet finishedSnippet()}
<p>All done! Thanks so much for submitting.</p>
{/snippet}
{#snippet failureSnippet()}
<p class="my-3">
We're sorry for the inconvenience. Something went wrong on our end and we couldn't process your
submission.
</p>
{/snippet}