🚀 Svelte Quick Tip: Using “actions” to integrate with JavaScript libraries (Tippy tooltips)

This article was originally posted on my Dev.to page

👋 Hello, World!

One of Svelte’s super powers is how freaking easy it is to integrate with non-Svelte JavaScript libraries using “actions”.

The button

Let’s say we have a button with a title attribute that we want to add a tooltip to:

<button title="hello world">Hover me</button>

The action

To write our action, we’re going to use the awesome JavaScript tooltip library Tippy.js rather than writing our own custom tooltip library (which you likely don’t want to do!).

// tooltip.js
module.exports = function tooltip(node, params = {}) {
// Determine the title to show. We want to prefer
// the custom content passed in first, then the
// HTML title attribute then the aria-label
// in that order.
const custom = params.content;
const title = node.title;
const label = node.getAttribute("aria-label");
const content = custom || title || label;
// Let's make sure the "aria-label" attribute
// is set so our element is accessible:
// https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute
if (!label) node.setAttribute("aria-label", content);
// Clear out the HTML title attribute since
// we don't want the default behavior of it
// showing up on hover.
node.title = "";
// Support any of the Tippy props by forwarding all "params":
// https://atomiks.github.io/tippyjs/v6/all-props/
const tip = tippy(node, { content, ...params });
return {
// If the props change, let's update the Tippy instance:
update: (newParams) => tip.setProps({ content, ...params }),
// Clean up the Tippy instance on unmount:
destroy: () => tip.destroy(),
};
};

Putting it together

Import the action

First, we will need to import the tooltip action in our Svelte component:

<!--
App.svelte or whatever other component you want
to use the tooltip in!
-->
<script>
import tooltip from "./tooltip";
</script>

Include Tippy CSS/JS

Now, we have to import the Tippy JS and CSS code. Since this example was built for the Svelte REPL, we are using a CDN for this, but you will likely want to instead bundle these assets in your build process (which is out of the scope of this article, check the Tippy docs).

<svelte:head>
<script src="https://unpkg.com/@popperjs/core@2"></script>
<script src="https://unpkg.com/tippy.js@6"></script>
<link rel="stylesheet" href="https://unpkg.com/tippy.js@6/themes/light.css" />
<link
rel="stylesheet"
href="https://unpkg.com/tippy.js@6/themes/light-border.css"
/>
</svelte:head>

Use your action!

Using our new tooltip action is quite simple, all we need to do is use the use: directive on any element and we now have a tooltip:

<button use:tooltip title="hello world">Hover Me!</button>
<!-- using aria-label: -->
<button use:tooltip aria-label="Aria label!">
With "aria-label"
</button>
<!-- custom tooltip content: -->
<button use:tooltip={{ content: "Hi there!" }}>
Custom tooltip
</button>
<!-- setting a tooltip theme: -->
<button use:tooltip={{ theme: "light" }} title="Light theme!">
Light theme
</button>

🛰 Going further

Now this is just a basic example, you can take this and extend it to match the needs of your application by, for example, configuring default themes, animations and positions as needed that way you don’t have to repeat this code throughout your app.

🎬 Fin

I think this feature of Svelte is incredibly compelling because it makes it trivial to integrate with the wide world of JavaScript libraries without tying you directly to a framework which, in frameworks like React, just isn’t as easy.

👨🏻‍💻 Software Hacker 👨🏻‍🏭 Maker 🛩 Travel Junkie 🏕. Outdoors Enthusiast