├── .eslintignore
├── .eslintrc.cjs
├── .gitignore
├── .npmrc
├── .prettierignore
├── .prettierrc
├── FUNDING.json
├── README.md
├── docs
└── demo.gif
├── package-lock.json
├── package.json
├── playwright.config.ts
├── src
├── app.d.ts
├── app.html
├── index.test.ts
├── lib
│ ├── index.ts
│ ├── step-controller.ts
│ ├── stepper.svelte
│ └── types.ts
└── routes
│ ├── +page.svelte
│ ├── components
│ ├── button.svelte
│ ├── demo-steps
│ │ ├── animations.svelte
│ │ ├── code-examples
│ │ │ └── animations.ts
│ │ ├── components
│ │ │ ├── action-row.svelte
│ │ │ ├── code.svelte
│ │ │ └── step-layout.svelte
│ │ ├── features.svelte
│ │ ├── intro.svelte
│ │ ├── outro.svelte
│ │ ├── sidestep-steps
│ │ │ ├── 1.svelte
│ │ │ └── 2.svelte
│ │ └── sidestep.svelte
│ ├── progress-bar.svelte
│ └── spinner.svelte
│ ├── icons
│ ├── cross-circle.svelte
│ └── icon-wrapper.svelte
│ └── styles.css
├── static
└── favicon.ico
├── svelte.config.js
├── tests
└── test.ts
├── tsconfig.json
└── vite.config.ts
/.eslintignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: '@typescript-eslint/parser',
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:@typescript-eslint/recommended',
7 | 'prettier',
8 | 'plugin:svelte/recommended'
9 | ],
10 | plugins: ['@typescript-eslint'],
11 | ignorePatterns: ['*.cjs'],
12 | overrides: [
13 | {
14 | files: ['*.svelte'],
15 | parser: 'svelte-eslint-parser',
16 | parserOptions: {
17 | parser: '@typescript-eslint/parser'
18 | },
19 | rules: {
20 | 'no-undef': 'off'
21 | }
22 | }
23 | ],
24 | parserOptions: {
25 | sourceType: 'module',
26 | ecmaVersion: 2020,
27 | extraFileExtensions: ['.svelte']
28 | },
29 | env: {
30 | browser: true,
31 | es2017: true,
32 | node: true
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 | vite.config.js.timestamp-*
10 | vite.config.ts.timestamp-*
11 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "useTabs": false,
3 | "singleQuote": true,
4 | "trailingComma": "none",
5 | "printWidth": 100,
6 | "plugins": ["prettier-plugin-svelte"],
7 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
8 | }
9 |
--------------------------------------------------------------------------------
/FUNDING.json:
--------------------------------------------------------------------------------
1 | {
2 | "drips": {
3 | "ethereum": {
4 | "ownedBy": "0x266e9b3Dcf10E393db54838394f49172dC19d3f7"
5 | }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🚶 Svelte Stepper
2 |
3 | 
4 |
5 | A simple library for building delightfully animated stepped flows with Svelte. Svelte Stepper is completely "headless", meaning it steps through whatever components you give it, putting you in full control of container- and step layout, styles and transitions.
6 |
7 | ## 🌍 Interactive demo & docs
8 |
9 | Check out an simple demo implementation at [svelte-stepper.jason-e.dev](https://svelte-stepper.jason-e.dev/).
10 |
11 | You can find the code for the above at `/src/routes` in this repo as a usage example.
12 |
13 | ## ✨ Features
14 |
15 | Svelte Stepper comes with a lot of built-in functionality, while still remaining easy-to-use at its core.
16 |
17 | ### Simple & type-safe
18 |
19 | Svelte Stepper is written entirely in TypeScript, and all its interfaces are fully type-safe out of the box. To get started, all you need to do is provide a sequence of Svelte components as steps. Every step can receive custom props.
20 |
21 | ### Delightful animations
22 |
23 | Svelte Stepper automatically transitions steps in a delightful way, and even smoothly adjusts its height to match each new step component. Of course, you can fully customize all animations.
24 |
25 | ### Context & multi-step forms
26 |
27 | Svelte Stepper includes a full context API, which allows you to share data between steps. This enables advanced usecases like building up form data over several steps, and submitting it at the end.
28 |
29 | ## 💾 Installation
30 |
31 | Install with NPM or yarn:
32 |
33 | ```bash
34 | npm install @efstajas/svelte-stepper
35 | ```
36 |
37 | ```bash
38 | yarn add @efstajas/svelte-stepper
39 | ```
40 |
41 | ## 👋 Getting started
42 |
43 | Getting a simple flow going is easy. First, let's create a few Step components.
44 |
45 | ### Creating Steps
46 |
47 | A step is simply a normal Svelte component, which can dispatch a number of special events in order to communicate with the stepper. Here's a very simple step with some text and a button that advances the flow to the next step:
48 |
49 | ```ts
50 |
55 |
56 |
My first step
57 |
58 |
59 | ```
60 |
61 | As you can see, Svelte Stepper exposes a `createStepController` function, which you can use to create a `stepController`. This object contains a number of functions for communicating with the stepper, such as `nextStep` and `previousStep`.
62 |
63 | Go ahead and create two simple step components so that we can move on to creating our first flow.
64 |
65 | ### Initializing the Stepper
66 |
67 | Getting a simple flow going is easy. The core of Svelte Stepper is the `Stepper` component. Simply import it into your page, and provide an array of your steps using the `makeStep` utility.
68 |
69 | ```ts
70 |
92 |
93 |
94 | ```
95 |
96 | As you can see, you can pass props to your step components using the `props` property. The type of this property is automatically inferred from the provided step component.
97 |
98 | Congratulations! This is everything you need to build a simple flow. Let's have a look at some more advanced features.
99 |
100 | ### A note on padding
101 |
102 | The stepper component automatically hides step overflow during transitions in order to prevent steps from overflowing the container during transition, which doesn't look very nice. If you want to add padding around your steps, please pass a `padding` prop to the Stepper component, instead of wrapping the container in a padded element. This ensures that transitions aren't visually cut off by the step container.
103 |
104 | ## 🎥 Animations
105 |
106 | Svelte Stepper automatically transitions between your steps with a sleek animation by default. Of course, you can fully customize the entry- and exit transitions for steps.
107 |
108 | ### Customizing the transition duration
109 |
110 | If all you want to do is change the duration of the default transition, you can pass a `defaultTransitionDuration` prop to the stepper. Out of the box, it's set to 300 milliseconds. This prop controls the speed of the stepper container height transition, as well as the step's entry- and exit transitions.
111 |
112 | ```ts
113 |
117 | ```
118 |
119 | ### Using custom transition functions and -parameters
120 |
121 | If you want to set fully custom transitions, you can set the `stepIntroTransition` and `stepOutroTransition` props on the stepper.
122 |
123 | ```ts
124 | ({
130 | duration: 600,
131 | delay: 0,
132 | scale: 1,
133 | }),
134 | }}
135 | stepIntroTransition={{
136 | transitionFn: fly,
137 | params: (direction) => ({
138 | duration: 600,
139 | delay: 0,
140 | x: direction === 'forward' ? 100 : -100,
141 | }),
142 | }}
143 | />
144 | ```
145 |
146 | These props accept an object with `transitionFn` and `params` properties. Pass any standard Svelte transition function, and set any custom parameters for it. The `params` property accepts a function with an optional `direction` parameter, allowing you to alter the transition parameters based on whether the user is currently navigating forward or backward within the flow.
147 |
148 | ## 💽 Context API
149 |
150 | Stepped flows frequently collect a bunch of data from the user over multiple steps, and submit it at the end. For exactly this use-case, Svelte Stepper comes with a context system. It allows you to conveniently share a single Svelte `writable` store between all steps.
151 |
152 | To define context, simply write a function that returns a Svelte `writable` store, and pass it to the Stepper component:
153 |
154 | ```ts
155 |
161 |
162 |
179 |
180 |
181 | ```
182 |
183 | In this particular example, we're exporting the type of our context writable from a module, so that we can properly type the context writable in our step components later.
184 |
185 | Passing `context` to the Stepper will make it automatically available to all steps as a `context` prop:
186 |
187 | ```ts
188 |
197 |
198 |
My first step
199 |
200 |
201 | Foo is {$context.foo} and bar is {$context.bar}.
202 |
203 |
204 |
205 |
206 |
207 | ```
208 |
209 | Using this method, you can incrementally populate a store of data throughout multiple steps.
210 |
211 | ## 📬 Stepper Events
212 |
213 | The Stepper component emits events allowing you to react to a step change or conclusion of the flow.
214 |
215 | ```ts
216 |
217 | {
220 | alert('The last step in the flow has called stepController.nextStep()!');
221 | }}
222 | on:stepChange={(e) => {
223 | const { newIndex, of, direction } = e.detail;
224 |
225 | console.log(\`Changed to step \${newIndex + 1} of \${of} going \${direction}\`);
226 | }}
227 | />
228 | ```
229 |
230 | The `stepChange` event is emitted when the stepper moves to a new step. It includes metadata on the current step index, the total amount of steps, as well as the direction of the change.
231 |
232 | The `conclusion` event is emitted when the stepper has reached the last step and `nextStep` is called.
233 |
234 | ## 🕺 Side-Steps
235 |
236 | Sometimes, you may need to temporarily switch to a different set of steps within a flow. Svelte Stepper includes `sidestep` functionality for this purpose. Using a side-step, you can easily temporarily launch a different flow, and come back to the original flow at the end.
237 |
238 | To trigger a side-step, simply call `stepController.sidestep(steps)` within a step component, where `steps` is an array of new steps:
239 |
240 | ```ts
241 |
248 |
249 |
20 | As you probably already noticed, Svelte Stepper automatically transitions between your steps
21 | with a sleek animation by default. Of course, you can fully customize the entry- and exit
22 | transitions for steps.
23 |
24 |
25 |
26 | You can customize the default transition duration, or even set fully custom transition
27 | functions. Check out the full documentation on GitHub to learn how. As a quick example, you can edit the transition duration of this stepper by moving
30 | the slider below. Try it out!
31 |
12 | Svelte Stepper comes with a lot of built-in functionality, while still remaining easy-to-use at
13 | its core.
14 |
15 |
16 |
Simple & safe
17 |
18 | Svelte Stepper is written entirely in TypeScript, and all its interfaces are fully type-safe out
19 | of the box. To get started, all you need to do is provide a sequence of Svelte components as
20 | steps. Every step can receive custom props.
21 |
22 |
23 |
Animations
24 |
25 | Did you see that step transition when you clicked "Next" just now? Svelte Stepper automatically
26 | transitions steps in a delightful way, and even smoothly adjusts its height to match each new
27 | step component. Of course, you can fully customize all animation parameters.
28 |
29 |
30 |
Context & multi-step forms
31 |
32 | Svelte Stepper includes a full context API, which allows you to share data between steps. This
33 | enables advanced usecases like building up form data over several steps, and submitting it at
34 | the end.
35 |
12 | Svelte Stepper is a versatile Svelte component for creating beautifully-animated stepped flows
13 | in modals or wherever your heart desires.
14 |
15 |
16 | The library itself is completely "headless", meaning it steps through whatever components you
17 | give it, while putting you in full control of container- and step layout, styles and
18 | transitions.
19 |
20 |
21 | Check out the full documentation on GitHub.
25 |
26 |
27 | Without further ado — you're looking at a simple demo implementation right now, using default
28 | animations. Click "Next step" to step forward!
29 |
15 | Sometimes, you may need to temporarily switch to a different set of steps within a flow. Svelte
16 | Stepper includes sidestep functionality for this purpose. Using
17 | a side-step, you can easily temporarily launch a different flow, and come back to the original flow
18 | at the end.
19 |
20 |
21 | Try it out! The following button is going to launch a short side-step flow, at the end of which
22 | you'll land back here.
23 |