Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: wizard v2 #68

Merged
merged 10 commits into from
Oct 13, 2022
56 changes: 40 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
},
"dependencies": {
"@aw-labs/appwrite-console": "^6.0.0",
"@aw-labs/icons": "0.0.0-58",
"@aw-labs/ui": "0.0.0-58",
"@aw-labs/icons": "0.0.0-61",
"@aw-labs/ui": "0.0.0-61",
"echarts": "^5.4.0",
"prismjs": "^1.29.0",
"tippy.js": "^6.3.7",
Expand Down
46 changes: 26 additions & 20 deletions src/lib/components/step.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,41 @@
export let currentSub = 0;
export let isSub = false;
export let step: { text: string; substeps?: { text: string }[] };

//TODO: remove inline styling
</script>

<li
on:click|preventDefault
class:steps-item={!isSub}
class:steps-sub-item={isSub}
aria-label={` ${completed ? 'done' : current ? 'current' : ''} step`}>
style={`cursor: ${completed ? 'pointer' : 'default'};`}
aria-label={`${completed ? 'done' : current ? 'current' : ''} step`}>
{#if isSub}
<span class="text">{step.text}</span>
{:else}
{#if completed}
<div class="bullet is-done">
<span class="icon-check" aria-hidden="true" />
</div>
{:else}
<div class="bullet" class:is-current={current} />
{/if}
<div class="step-item-content">
<span class="text">{step.text}</span>
{#if step?.substeps}
<ul class="steps-sub">
{#each step.substeps as subStep, index}
<svelte:self
isSub={true}
step={subStep}
current={currentSub === index}
completed={index < currentSub} />
{/each}
</ul>
<div class="steps-item-wrapper">
{#if completed}
<div class="bullet is-done">
<span class="icon-check" aria-hidden="true" />
</div>
{:else}
<div class="bullet" class:is-current={current} />
{/if}
<div class="step-item-content">
<span class="text">{step.text}</span>
{#if step?.substeps}
<ul class="steps-sub">
{#each step.substeps as subStep, index}
<svelte:self
isSub={true}
step={subStep}
current={currentSub === index}
completed={index < currentSub} />
{/each}
</ul>
{/if}
</div>
</div>
{/if}
</li>
12 changes: 12 additions & 0 deletions src/lib/components/steps.svelte
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import Step from './step.svelte';

export let steps: {
text: string;
optional: boolean;
substeps?: {
text: string;
}[];
}[];
export let currentStep = 1;
export let currentSub = 1;

const dispatch = createEventDispatcher();

$: firstOptional = steps.findIndex((step) => step.optional);
</script>

<ol class="steps">
{#if steps}
{#each steps as step, index}
{@const stepNumber = index + 1}
{#if firstOptional === index}
<li class="steps-item">
<h3 class="eyebrow-heading-3">OPTIONAL</h3>
</li>
{/if}
<Step
on:click={() => dispatch('step', stepNumber)}
bind:currentSub
current={currentStep === stepNumber}
completed={stepNumber < currentStep}
Expand Down
39 changes: 35 additions & 4 deletions src/lib/layout/wizard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
{
label: string;
component: typeof SvelteComponent;
optional?: boolean;
}
>;
</script>
Expand All @@ -13,22 +14,40 @@
import { Button, Form } from '$lib/elements/forms';
import { wizard } from '$lib/stores/wizard';
import { createEventDispatcher, type SvelteComponent } from 'svelte';
import WizardExitModal from './wizardExitModal.svelte';

export let title: string;
export let steps: WizardStepsType;
export let confirmExit = false;
export let finalAction = 'Create';

const dispatch = createEventDispatcher();

let currentStep = 1;
let showExitModal = false;

function handleKeydown(event: KeyboardEvent) {
if (event.key === 'Escape') {
if (event.key === 'Escape' && !showExitModal) {
event.preventDefault();
wizard.hide();
}
}

function handleExit() {
if (confirmExit) {
showExitModal = true;
} else {
wizard.hide();
}
}

function handleStepClick(e: CustomEvent<number>) {
const step = e.detail;
if (step < currentStep) {
currentStep = step;
}
}

function submit() {
if (isLastStep) {
dispatch('finish');
Expand All @@ -52,15 +71,17 @@
<div class="body-text-1">{title}</div>

<slot name="header" />
<button class="x-button" aria-label="close wizard" on:click={wizard.hide}>
<button class="x-button" aria-label="close wizard" on:click={handleExit}>
<span class="icon-x" aria-hidden="true" />
</button>
</header>

<aside class="wizard-side">
<Steps
steps={sortedSteps.map(([, { label }]) => ({
text: label
on:step={handleStepClick}
steps={sortedSteps.map(([, { label, optional }]) => ({
text: label,
optional
}))}
{currentStep} />
</aside>
Expand All @@ -76,6 +97,10 @@
{/each}
<div class="form-footer">
<div class="u-flex u-main-end u-gap-12">
{#if sortedSteps[currentStep - 1][1].optional}
<Button text on:click={() => (isLastStep = true)} submit
>Skip optional steps</Button>
{/if}
{#if currentStep === 1}
<Button secondary on:click={wizard.hide}>Cancel</Button>
<Button submit>Next</Button>
Expand All @@ -91,3 +116,9 @@
</Form>
</div>
</section>

{#if showExitModal}
<WizardExitModal bind:show={showExitModal} on:exit={() => wizard.hide()}>
<slot name="exit">this process</slot>
</WizardExitModal>
{/if}
26 changes: 26 additions & 0 deletions src/lib/layout/wizardExitModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script lang="ts">
import { Modal } from '$lib/components';
import { Button, Form } from '$lib/elements/forms';
import { createEventDispatcher } from 'svelte';

export let show = false;
const dispatch = createEventDispatcher();

function handleSubmit() {
dispatch('exit');
}
</script>

<Form noMargin on:submit={handleSubmit}>
<Modal bind:show warning>
<svelte:fragment slot="header">Exit Process</svelte:fragment>
<p>
Are you sure you want to exit from <slot />? All data will be deleted. This action is
irreversible.
</p>
<svelte:fragment slot="footer">
<Button text on:click={() => (show = false)}>Cancel</Button>
<Button secondary submit>Exit</Button>
</svelte:fragment>
</Modal>
</Form>
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@
});
stepsComponents.set(2, {
label: 'Set permissions',
component: Step2
component: Step2,
optional: true
});
</script>

Expand Down