Create a stepper pure css atomic component using tailwind

I already know that when you need to handle some validation on text inputs, then you do it on keyup events.

And that is ok. Or not?

Actually, if the user types fast, you would like to call a function only when he/she stops typing.

So you start to think about setTimeout or setInterval strategies to implement.

Well, you should know that there is a more abstract technique, called debounce.

But if you’re using svelte, you should not implement debounce everytime you need this behaviour: svelte actions let you extend any HTML element with common logic.

And in this post we will see how to add a custom event to the input, to handle the use case above.

But let’s proceed step by step.

When working with inputs, validation is mandatory: it is necessary to perform some checks when the user stops typing, and not every time a key is pressed.

We want to have a tool to attach this behaviour easily to our inputs everytime.

The same behavior is also useful in autocomplete components, where an action must be performed to decide which elements to show: if I execute it at each keypress I could soon block the system, especially if the action involves an asynchronous call to an endpoint.

The solution is to perform the action only when the user stops typing.

In this frontend pill we will see just how to elegantly implement this functionality using Svelte actions.

As always, before implementing the “on stop typing” custom event, let’s imagine the easiest way for the developer to consume it.

In Svelte, the syntax to add event listener to an input tag is as follows:

bind:value={name} />

The stopTyping event does not exist, so we need to implement it. Using an action:

The result will be as follows:

bind:value={name} />

Let’s then see how to implement the stopTyping action.

In Svelte there is the concept of actions, a syntax keyword to extend native HTML elements with new functionality.

To use an action, we add an attribute, use, and the function that will take care of the custom behavior (on stop typing in our case).

Before explaining how this works, just one important note: actions only work on native HTML tags and not on Svelte components. At least for now.

The Svelte use directive is a kind of attribute on a HTML element that specifies a function.

The function, also called action in this context, takes the referring node as input.

export function aCustomAction(node) {
// some logic
return {
destroy() { }// (optional) some logic on destroy

The function returns an object with one method: destroy. It is optional, and it is called when the component is destroyed.

In Svelte an action can also add some behaviour based on some extra parameters that we can pass to the function.

export function aCustomAction(node, param1) {
// some logic
return {
update() { },// (optional) some logic executed when param1 gets updated
destroy() { }

The update method will be executed when the param1 changes. It is optional.

In this pill we will see how to implement the stop typing action.

Two key points:

  1. it has to be used on HTML inputs
  2. it will fire an event only when the user stops typing on that input

The function is simple:

export function stopTyping(node) {
const handleKeyup = debounce((event: KeyboardEvent) => { // (1) the debounce logic
if (node.contains( { // (2) restrict the event to the only referring node
node.dispatchEvent(new CustomEvent('stopTyping')); // (3) fire the event
}, 500);

// (4) add a generic keyup event
document.addEventListener('keyup', handleKeyup, true);

return {
destroy() {
// (5) cleanup on destroy
document.removeEventListener('keyup', handleKeyup, true);

Let’s go step by step.

First of all, we register the keyup event (4) (and cleanup it on destroy to avoid memory leaks at (5) ).

The interesting parts are:

  • fire the custom event at (3)
  • make sure the stopTyping event is fired only once when the user does not write for half a second (at (1))

To make sure that a function is only runned once after the user stops typing, we make use of the debounce function.

function debounce(inputFunction, timeToWaitBeforeFiringInMs = 500) {
let timer;
return (...args) => {
timer = setTimeout(() => {
inputFunction.apply(this, args);
}, timeToWaitBeforeFiringInMs);

Above, you can find the implementation of the dobounce function in javascript.

It is used to execute a function only once if called multiple times within a constrained time interval.

The debounce function takes a function as argument and returns a new function (that will replace the original one we passed as input).

Other use cases of the debounce function:

  • on mouse move, if we want to know when the user stops moving the mouse
  • on multiple mouse click, to react only after the last click
  • when using websockets, to execute an action only after a burst of packets arrive
  • when collecting multiple information packs, to pass to them to the backend only once every X seconds

To use the function above on our inputs, we just need to import it in our Svelte component:

import { stopTyping } from '../shared/on-stop-typing.event';

let name = "thefrontendteam"

async function onStopTyping() {
// do something with name

bind:value={name} />

That’s all. For more pills remember to subscribe to our newsletter :-)




Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

NativeScript CLI to Telerik Platform — There and Back Again

Improving Next.js Performance

What is Laravel Octane

A simple way to use native AR viewer in React Native

Authenticating Users with Passport.js

How to create simple Command Line Program with Node

bsp create command line program with node

Build a Collaborative Real-time Todo App Backend Using Hasura GraphQL

Are you a manager or stakeholder in a company with teams coding and using JavaScript?

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Frontend Team

Frontend Team

More from Medium

Visma InSchool meets Serverless for Timetable Optimisation

Serverless timetable solver architecture diagram

From OpenAPI to a working integration in minutes

DATEV Nine-Nine | Create your own Operator — RxJS Edition

Implement Trie ii