This is the frontend portion of the Hyperfov Link Preview library. It provides a function linkPreview
that allows you to add a link preview web component to any a
tag:
<html>
<body>
<!-- page markup here with some a tags: -->
<a id="myLink" href="https://example.com">A cool link</a>
<!-- Insert the link preview script at the end of the body -->
<script src="https://unpkg.com/@hyperfov/link-previews@latest/dist/index.js"></script>
<script>
// now we can call `linkPreview` to add a preview
linkPreview("#myLink", {
worker: "https://link-to-worker.workers.dev",
});
</script>
</body>
</html>
Make sure you've set up the worker and have it's url.
npm i @hyperfov/link-previews
import { linkPreview } from "@hyperfov/link-previews";
<script src="https://unpkg.com/@hyperfov/link-previews@latest/dist/index.js"></script>
Add the script to the end of your site's body
.
Create link previews by passing through a selector, element, or list of elements and configuration props to the global linkPreview
constructor:
linkPreview("#myLink", {
worker: "https://link-to-worker.workers.dev",
});
You can also customize the previews' styling. For example:
<style>
link-preview {
--lp-border: 1px dashed rebeccapurple;
--lp-title-color: rebeccapurple;
}
</style>
For more on styling and custom templates, see custom previews.
You can configure the preview element by passing through props in the constructor:
linkPreview("#myLink", {
// props get passed through here
});
Valid props:
The URL of the deployed worker. See the worker's docs for deployment information.
The selector of the template element used to render the preview. See custom previews for more on templates. If nothing is passed, a default template is used.
Should the worker be called to get information for this link? Defaults to true
. You may want to set this to false
if you're pregenerating a page and don't want to make calls to the worker at runtime.
Should the link preview content be fetched when the user hovers on the link? Defaults to true
. When set to false
, the preview content is fetched immediately when the preview component is initialized.
The data passed through to the template's slots. This object can include props such as title
, description
, href
, and image
:
linkPreview(elt, {
content: {
href: "https://example.com/",
description: "Some interesting description",
title: "Example link",
},
});
Note that passing through data in content
will override any data that's returned by the worker.
Any of the keys in content
can also be specified on the element with attributes prefixed with lp-
:
<a
href="https://example.com/"
lp-description="Some interesting description"
lp-title="Example link"
>example</a
>
Props that are passed through to tippy.js, the library used for the preview popups. These can allow you to modify the positioning of the preview and provide options such as an offset, delay, and animation:
linkPreview(elt, {
tippy: {
placement: "bottom-start",
animation: "scale",
offset: [0, 10],
delay: 200,
},
});
Find the full list of props on the tippy docs.
All of the props in tippy
can also be specified on the element with attributes prefixed with tippy-data-
:
<a
href="https://example.com/"
data-tippy-placement="bottom-start"
data-tippy-animation="scale"
data-tippy-offset="[0, 10]"
data-tippy-delay="200"
>example</a
>
You can style the basic template with CSS variables set in the link-preview
selector:
link-preview {
--lp-title-color: red;
--lp-link-color: blue;
}
Variables are in the form --lp-[element]-[css property]
. Here's all the variables the template accepts:
Variable | Default value |
---|---|
--lp-border |
none |
--lp-padding |
0 |
--lp-background |
white |
--lp-box-shadow |
0px 5px 15px rgba(101, 101, 110, 0.3) |
--lp-border-radius |
6px |
--lp-max-width |
225px |
--lp-font-family |
inherit |
--lp-font-weight |
normal |
--lp-link-padding |
0 10px |
--lp-link-color |
grey |
--lp-link-border |
none |
--lp-link-font-size |
12px |
--lp-link-font-family |
inherit |
--lp-link-font-weight |
normal |
--lp-title-padding |
0 10px 3px 10px |
--lp-title-color |
inherit |
--lp-title-border |
none |
--lp-title-font-size |
16px |
--lp-title-font-family |
inherit |
--lp-title-font-weight |
bold |
--lp-description-padding |
0 10px 3px 10px |
--lp-description-color |
inherit |
--lp-description-border |
none |
--lp-description-font-size |
16px |
--lp-description-font-family |
inherit |
--lp-description-font-weight |
normal |
--lp-image-border |
none |
--lp-image-border-radius |
3px 3px 0 0 |
--lp-image-object-fit |
cover |
--lp-image-object-position |
center center |
--lp-image-max-height |
150px |
For instances where the css variables aren't enough, the link preview is completely customizable through an html template with slots. The template that's used by default can be found at src/templates/basic.js
.
Add a custom template to your page (the template
element is invisible, so this can be anywhere in the document):
<template id="link-preview-template">
<style>
.wrapper {
padding: 20px;
background-color: lightsalmon;
}
</style>
<div class="wrapper">
<slot name="lp-title">my title</slot>
<div><slot name="lp-description">my description</slot></div>
<div><slot name="lp-href">my url</slot></div>
</div>
</template>
The styling and markup is totally up to you, though you must ensure styles are either inline or included in a style
tag in the template. The link preview component will look for a slots lp-title
, lp-description
, lp-url
, lp-favicon
, and lp-image
to insert content. Data that doesn't have corresponding slot in the template won't be displayed, so for example if you don't specify an lp-image
slot, no image will be inserted.
Once you've created a template, pass its id
as an option when instantiating your link previews:
linkPreview("#myLink", {
worker: "https://link-to-worker.workers.dev",
template: "#link-preview-template",
});