npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@abcnews/svelte-scrollyteller

v3.0.1

Published

A scrollyteller component for Svelte. Svelte port of the ABC News [React Scrollyteller](https://github.com/abcnews/scrollyteller).

Downloads

57

Readme

Svelte Scrollyteller

A scrollyteller component for Svelte. Svelte port of the ABC News React Scrollyteller.

Installation

npm install @abcnews/svelte-scrollyteller

Add aunty config to package.json:

"aunty": {
  "type": "svelte",
  "build": {
    "entry": [
      "index"
    ],
    "includedDependencies": [
      "@abcnews/svelte-scrollyteller"
    ]
  }
}

Usage

The scrollyteller takes an array of panels of content nodes and turns them into a series of elements which scroll over the <Scrollyteller> component's children.

The panels prop is in the format of:

[
  {
    data: {
      info: 'Any arbitrary data, returned to you when this marker is active'
    },
    align: 'left', // optional: align the panels to the left or right
    panelClass: 'my-custom-target', // optional: in case you want to style it manually
    nodes: [<DOM elements for this panel>]
  },
  {
    data: {
      thing: 'Config when this second marker is hit'
    },
    nodes: [<DOM elements for this panel>]
  }
]

When a new box comes into view the onMarker callback will fire with the data of the incoming panel.

<script lang="ts">
	import Scrollyteller from '@abcnews/svelte-scrollyteller';
	import MyGraphic from 'MyGraphic.svelte';

  let {panels} = $props();
  let marker = $state(0);
  let progress = $state();

</script>

<Scrollyteller
	{panels}
	onMarker={({ detail }) => {
		marker = detail;
	}}
	onProgress={({ detail }) => {
		progress = detail;
	}}
  layout={{
    align: 'left',
    // resizeInteractive: true
    // transparentFloat: true
  }}
>
	<MyGraphic marker="{marker}" />
</Scrollyteller>

<style lang="scss">
// Optionally create a ratio box for your graphic. It will self-centre itself
// into the appropriate space when resizeInteractive=true
.myGraphic{
  aspect-ratio: 16/9;
  height: 100%;
  width: unset;
  @container (max-aspect-ratio:16/9) {
    width: 100%;
    height: auto;
  }
}
 </style>

For a more complete example using Typescript see the examples.

Props

| Property | Type | Description | Default | | --------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | | panels | Refer to Usage | required Array of nodes and data which dictate the markers | | onMarker | callback function | required Called when a marker intersects and returns that markers data | | | onProgress | callback function | Fires on scroll and returns the scrollyteller progress | | | customPanel | Svelte Component | Component to replace the default panel component | Panel.svelte | | observerOptions | IntersectionObserverInit | Options for the intersection observer. Refer to the docs | {threshold: 0.5} |

Using layouts/styling your own

The layout={} prop controls how the scrollyteller is laid out, and has the following options:

| Property | Type | Description | | ----------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | align | string | Alignment for blocks. One of left/right/centre/none. "none" applies no breakpoint styling so you can do your own custom styles. | | resizeInteractive | boolean | Defaults to true if not set. This handles the scrollyteller graphic position according to the current breakpoint. | | transparentFloat | boolean | Defaults to true if align is left or right. Removes the block background for left/right aligned pieces, for a better reading experience. | | mobileVariant | string | Toggle mobile betwen:blocks: traditional block layout scrolling over the vizrows: split screen layout with viz on top and text below |

The resizeInteractive prop lets you opt into predefined graphic sizes and placements. When enabled, the graphic will appear toward the top on mobile, and in the centre when left/right aligned. On mobile this allows the most space for blocks to scroll without hitting the graphic, and looks aesthetically pleasing on desktop/larger portrait tablets like the iPad Pro.

The graphic slot has position:relative set, uses flexbox to put its contents into the correct spot, and allows you to use container queries to size your interactive. This works best when your interactive fits itself to its container and reserves only the space it needs. See the examples above for some example code using aspect-ratio to fit an interactive to the graphic slot, although you could use any number of methods.

You can opt out of the resizeInteractive behaviour if you want to use your own styles, at which point you can take over the entire screen.

Changing block styles

The scrollyteller inherits the light/dark colour scheme from Odyssey.

The Svelte Scrollyteller also uses the following CSS variables that you can set anywhere in the DOM above the scrollyteller:

| Attribute | Variable to use | Fallback value | | ----------------------- | -------------------------- | ----------------------- | | background-color | --color-panel-background | dark/light mode variant | | Text colour | --color-panel-text | dark/light mode variant | | Background opacity | --color-panel-opacity | 1 | | Background CSS filter | --color-panel-filter | blur(2.5px) | | Background border | --color-panel-border | none |

You can also specify a panelClass class and style the panels manually (see Usage above).

Usage with Odyssey

When developing ABC News stories with Odyssey you can use the loadScrollyteller function to gather panels within a CoreMedia article.

See a more complete usage example with Odyssey.

CoreMedia text:

#scrollytellerVARIABLEvalue
This is the opening paragraph panel
#markVARIABLEvalue
This is a second panel
#markVARval
This is another paragraph
#endscrollyteller

JS Code:

import { loadScrollyteller } from "@abcnews/svelte-scrollyteller";
import App from "App.svelte";

/** Optionally, specify generics to type your markers */
type MyPanelData = {
  electorate: string;
  viz: "map" | "hex" | "chart";
};

const scrollyData = loadScrollyteller<MyPanelData>(
  "", // If set to eg. "one" use #scrollytellerNAMEone in CoreMedia
  "u-full", // Class to apply to mount point u-full makes it full width in Odyssey
  "mark", // Name of marker in CoreMedia eg. for "point" use #point default: #mark
);

new App({
  target: scrollyData.mountNode,
  props: { panels: scrollyData.panels },
});

Usage with other non-Svelte frameworks

The scrollyteller is available as a Web Component for use in other frameworks. See README.WebComponent.md for more info.

Development

The Svelte components are packaged using SvelteKit svelte-package.

The Web Component is built separately using Vite with the vite-webcomponents.config.js config.

Add #debug=true to your story to enable debug mode and clearly outline each section, block, breakpoint, and observer trigger point.

Get started

git clone [email protected]:abcnews/svelte-scrollyteller.git
cd svelte-scrollyteller
npm i
npm run dev

This will get a SvelteKit app to use for development and testing up and running.

Releasing new versions

npm run release

This will:

  • install dependences
  • build
  • test
  • lint
  • bump version
  • commit
  • publish to npm