{"id":42215101,"url":"https://github.com/abcnews/svelte-scrollyteller","last_synced_at":"2026-01-27T01:11:50.101Z","repository":{"id":199848351,"uuid":"481406763","full_name":"abcnews/svelte-scrollyteller","owner":"abcnews","description":"Scrollytelling, but in Svelte","archived":false,"fork":false,"pushed_at":"2025-11-20T06:03:26.000Z","size":819,"stargazers_count":4,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-11-20T08:16:36.424Z","etag":null,"topics":["library","scrollytelling"],"latest_commit_sha":null,"homepage":"","language":"Svelte","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abcnews.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-04-13T23:46:26.000Z","updated_at":"2024-08-15T06:32:45.000Z","dependencies_parsed_at":"2024-03-05T05:27:57.578Z","dependency_job_id":"b42e54e4-540e-4ea8-ab54-43ad4ca6e56d","html_url":"https://github.com/abcnews/svelte-scrollyteller","commit_stats":null,"previous_names":["abcnews/svelte-scrollyteller"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/abcnews/svelte-scrollyteller","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abcnews%2Fsvelte-scrollyteller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abcnews%2Fsvelte-scrollyteller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abcnews%2Fsvelte-scrollyteller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abcnews%2Fsvelte-scrollyteller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abcnews","download_url":"https://codeload.github.com/abcnews/svelte-scrollyteller/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abcnews%2Fsvelte-scrollyteller/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28794945,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T01:07:07.743Z","status":"ssl_error","status_checked_at":"2026-01-27T01:07:06.974Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["library","scrollytelling"],"created_at":"2026-01-27T01:11:49.565Z","updated_at":"2026-01-27T01:11:50.085Z","avatar_url":"https://github.com/abcnews.png","language":"Svelte","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Svelte Scrollyteller\n\nA scrollyteller component for Svelte.\nSvelte port of the ABC News [React Scrollyteller](https://github.com/abcnews/scrollyteller).\n\n## Installation\n\n`npm install @abcnews/svelte-scrollyteller`\n\nAdd aunty config to `package.json`:\n\n```json\n\"aunty\": {\n  \"type\": \"svelte\",\n  \"build\": {\n    \"entry\": [\n      \"index\"\n    ],\n    \"includedDependencies\": [\n      \"@abcnews/svelte-scrollyteller\"\n    ]\n  }\n}\n```\n\n## Usage\n\nThe scrollyteller takes an array of **panels** of content nodes and turns them into a series of elements which scroll over the `\u003cScrollyteller\u003e` component's children.\n\nThe `panels` prop is in the format of:\n\n    [\n      {\n        data: {\n          info: 'Any arbitrary data, returned to you when this marker is active'\n        },\n        align: 'left', // optional: align the panels to the left or right\n        panelClass: 'my-custom-target', // optional: in case you want to style it manually\n        nodes: [\u003cDOM elements for this panel\u003e]\n      },\n      {\n        data: {\n          thing: 'Config when this second marker is hit'\n        },\n        nodes: [\u003cDOM elements for this panel\u003e]\n      }\n    ]\n\nWhen a new box comes into view the `onMarker` callback will fire with the `data` of the incoming panel.\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Scrollyteller from '@abcnews/svelte-scrollyteller';\n\timport MyGraphic from 'MyGraphic.svelte';\n\n  let {panels} = $props();\n  let marker = $state(0);\n  let progress = $state();\n\n\u003c/script\u003e\n\n\u003cScrollyteller\n\t{panels}\n\tonMarker={({ detail }) =\u003e {\n\t\tmarker = detail;\n\t}}\n\tonProgress={({ detail }) =\u003e {\n\t\tprogress = detail;\n\t}}\n  layout={{\n    align: 'left',\n    // resizeInteractive: true\n    // transparentFloat: true\n  }}\n\u003e\n\t\u003cMyGraphic marker=\"{marker}\" /\u003e\n\u003c/Scrollyteller\u003e\n\n\u003cstyle lang=\"scss\"\u003e\n// Optionally create a ratio box for your graphic. It will self-centre itself\n// into the appropriate space when resizeInteractive=true\n.myGraphic{\n  aspect-ratio: 16/9;\n  height: 100%;\n  width: unset;\n  @container (max-aspect-ratio:16/9) {\n    width: 100%;\n    height: auto;\n  }\n}\n \u003c/style\u003e\n```\n\nFor a more complete example using Typescript see the [examples](examples).\n\n## Props\n\n| Property        | Type                     | Description                                                                                                                            | Default            |\n| --------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |\n| panels          | Refer to **Usage**       | **required** Array of nodes and data which dictate the markers                                                                         |\n| onMarker        | callback function        | **required** Called when a marker intersects and returns that markers `data`                                                           |                    |\n| onProgress      | callback function        | Fires on scroll and returns the scrollyteller progress                                                                                 |                    |\n| customPanel     | Svelte Component         | Component to replace the default panel component                                                                                       | Panel.svelte       |\n| observerOptions | IntersectionObserverInit | Options for the intersection observer. Refer to the [docs](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) | `{threshold: 0.5}` |\n\n## Using layouts/styling your own\n\nThe `layout={}` prop controls how the scrollyteller is laid out, and has the following options:\n\n| Property          | Type    | Description                                                                                                                                                          |\n| ----------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| align             | string  | Alignment for blocks. One of left/right/centre/none. \"none\" applies no breakpoint styling so you can do your own custom styles.                                      |\n| resizeInteractive | boolean | Defaults to `true` if not set. This handles the scrollyteller graphic position according to the current breakpoint.                                                  |\n| 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.                         |\n| mobileVariant     | string  | Toggle mobile betwen:\u003cbr/\u003e\u003cul\u003e\u003cli\u003eblocks: traditional block layout scrolling over the viz\u003c/li\u003e\u003cli\u003erows: split screen layout with viz on top and text below\u003c/li\u003e\u003c/ul\u003e |\n\nThe 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.\n\nThe 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.\n\nYou 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.\n\n## Changing block styles\n\nThe scrollyteller inherits the [light/dark colour scheme from Odyssey](https://master-news-web.news-web-developer.presentation-layer.abc-prod.net.au/news/2024-08-16/odyssey-producers-documentation--everything-else/8676886).\n\nThe Svelte Scrollyteller also uses the following CSS variables that you can set anywhere in the DOM above the scrollyteller:\n\n| Attribute               | Variable to use            | Fallback value          |\n| ----------------------- | -------------------------- | ----------------------- |\n| `background-color`      | `--color-panel-background` | dark/light mode variant |\n| Text `colour`           | `--color-panel-text`       | dark/light mode variant |\n| Background `opacity`    | `--color-panel-opacity`    | `1`                     |\n| Background CSS `filter` | `--color-panel-filter`     | `blur(2.5px)`           |\n| Background `border`     | `--color-panel-border`     | `none`                  |\n\nYou can also specify a panelClass class and style the panels manually (see Usage above).\n\n## Usage with Odyssey\n\nWhen developing [ABC News](https://www.abc.net.au) stories with [Odyssey](https://github.com/abcnews/odyssey) you can use the `loadScrollyteller` function to gather `panels` within a CoreMedia article.\n\nSee a more complete [usage example with Odyssey](examples/aunty).\n\nCoreMedia text:\n\n```\n#scrollytellerVARIABLEvalue\nThis is the opening paragraph panel\n#markVARIABLEvalue\nThis is a second panel\n#markVARval\nThis is another paragraph\n#endscrollyteller\n```\n\nJS Code:\n\n```ts\nimport { loadScrollyteller } from \"@abcnews/svelte-scrollyteller\";\nimport App from \"App.svelte\";\n\n/** Optionally, specify generics to type your markers */\ntype MyPanelData = {\n  electorate: string;\n  viz: \"map\" | \"hex\" | \"chart\";\n};\n\nconst scrollyData = loadScrollyteller\u003cMyPanelData\u003e(\n  \"\", // If set to eg. \"one\" use #scrollytellerNAMEone in CoreMedia\n  \"u-full\", // Class to apply to mount point u-full makes it full width in Odyssey\n  \"mark\", // Name of marker in CoreMedia eg. for \"point\" use #point default: #mark\n);\n\nnew App({\n  target: scrollyData.mountNode,\n  props: { panels: scrollyData.panels },\n});\n```\n\n## Usage with other non-Svelte frameworks\n\nThe scrollyteller is available as a Web Component for use in other frameworks. See [README.WebComponent.md](README.WebComponent.md) for more info.\n\n## Development\n\nThe Svelte components are [packaged using SvelteKit svelte-package](https://kit.svelte.dev/docs/packaging).\n\nThe Web Component is built separately using Vite with the `vite-webcomponents.config.js` config.\n\nAdd `#debug=true` to your story to enable debug mode and clearly outline each section, block, breakpoint, and observer trigger point.\n\n### Get started\n\n```sh\ngit clone git@github.com:abcnews/svelte-scrollyteller.git\ncd svelte-scrollyteller\nnpm i\nnpm run dev\n```\n\nThis will get a SvelteKit app to use for development and testing up and running.\n\n### Releasing new versions\n\n```sh\nnpm run release\n```\n\nThis will:\n\n- install dependences\n- build\n- test\n- lint\n- bump version\n- commit\n- publish to npm\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabcnews%2Fsvelte-scrollyteller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabcnews%2Fsvelte-scrollyteller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabcnews%2Fsvelte-scrollyteller/lists"}