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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@joycostudio/marquee

v0.0.13

Published

Just a marquee

Readme

  JOYCO Marquee

pnpm add @joycostudio/marquee

🤔 Why Marquee?

JOYCO Marquee leverages the Web Animations API (WAAPI) to create smooth, performant animations. While CSS animations are great for simple use cases, we chose to build on top of the JavaScript-based Web Animations API for several key advantages:

  • Precise Control: The Web Animations API provides programmatic control over animation playback, allowing features like dynamic speed adjustment and direction changes without recreating the animation.
  • Performance: By using the browser's native animation engine, we achieve smooth performance off the main thread.
  • Runtime Flexibility: Unlike CSS animations, we can modify animation parameters (speed, direction) on the fly.

📖 Documentation

Basic Usage

import { Marquee } from '@joycostudio/marquee/react'

function App() {
  return (
    <Marquee speed={1} speedFactor={1} direction={1} play={true}>
      <div>Your content here</div>
    </Marquee>
  )
}

Props

  • speed (number): Base speed of the marquee animation
  • speedFactor (number): Multiplier for the base speed
  • direction (1 | -1): Direction of movement (1 for right-to-left, -1 for left-to-right)
  • play (boolean, optional): Controls whether the marquee is playing or paused (default: true)
  • rootClassName (string, optional): Class name for the root container
  • marqueeClassName (string, optional): Class name for the marquee element
  • children (ReactNode): The content to be scrolled

Custom Hook

For more control, you can use the useMarquee hook. This is particularly useful when you need to:

  • Share the same marquee instance configuration across multiple elements
  • Have more granular control over the marquee instance, like controlling its speedFactor.

Let's make an example with lenis from darkroom.engineering.

import { useMarquee, Marquee } from '@joycostudio/marquee/react'
import { useLenis } from 'lenis'

const ScrollVelocityBoundMarquee = ({ inverted }: { inverted?: boolean }) => {
  const [ref, marquee] = useMarquee({ speed: 100, speedFactor: 1, direction: inverted ? -1 : 1 })
  const lastSign = useRef<number>(1)

  useLenis(({ velocity }) => {
    if (!marquee) return
    const sign = Math.sign(velocity)
    if (sign === 0) return
    lastSign.current = sign
    marquee.setSpeedFactor((1 * sign + velocity / 5) * (inverted ? -1 : 1))
  })

  return (
    <Marquee instance={[ref, marquee]}>
      <MarqueeContent className="text-[100px]" />
    </Marquee>
  )
}

Notice how we are using the same <Marquee> component, but instead, we are just passing an instance prop that expects to receive the return type of the useMarquee hook. It will just serve as a shell to add the necessary html and styles to make the marquee work.

The useMarquee hook returns a tuple containing:

  • rootRef: A ref to attach to your container element
  • marquee: A marquee instance with the following methods:
    • play(): Start the marquee animation
    • pause(): Pause the marquee animation
    • setSpeed(speed: number): Update the base speed
    • setSpeedFactor(factor: number): Update the speed multiplier
    • setDirection(direction: 1 | -1): Change the scroll direction
    • destroy(): Clean up the marquee (automatically called on unmount)

Notes

  • The marquee component only supports a single child element. Wrap multiple elements in a container if needed.
  • The marquee automatically handles cleanup on unmount.
  • The component provides built-in styles for proper overflow handling and content positioning.
  • You are responsible for making the marquee cover the full width of it's render area. This library DOES NOT auto-fill that space.

Plain HTML Usage

For vanilla JavaScript applications, you can use the core package directly via CDN:

<body>
  <main>
    <div id="marquee-wrapper">
      <div id="marquee-root">
        <div style="white-space: nowrap">
          Hey there! | Hey there! | Hey there! | Hey there! | Hey there! | Hey there! | Hey there! | Hey there! |&nbsp;
        </div>
      </div>
    </div>
  </main>

  <script type="module">
    import { Marquee } from 'https://cdn.jsdelivr.net/npm/@joycostudio/marquee/dist/core.min.mjs'

    const marqueeChildElm = document.getElementById('marquee-root')

    const marqueeInstance = new Marquee(marqueeChildElm, {
      speed: 500,
      direction: 1,
      speedFactor: 1,
    })

    marqueeInstance.initialize(marqueeChildElm.children[0])
    marqueeInstance.play()
  </script>
</body>

Check the live example: https://stackblitz.com/edit/joyco-marquee-static?file=index.html

Can I use it in [place the latest top-notch high-performance new tech framework here]?

This library is not strictly bound to React, it has a core package and a React implementation of that core functionality. So feel free to create you own implementation in your favorite framework. And if your heart is big enough, leave a PR for the community. The rebels will thank your service 🫡.

🤖 Automatic Workflows

This template comes with two GitHub Actions workflows (currently disabled for convenience):

  1. Release Workflow (.github/workflows/release.yml): Automates the release process using Changesets. When enabled, it will automatically create release pull requests and publish to npm when changes are pushed to the main branch.

  2. Publish Any Commit (.github/workflows/publish-any-commit.yml): A utility workflow that can build and publish packages for any commit or pull request.

🦋 Version Management

This library uses Changesets to manage versions and publish releases. Here's how to use it:

Adding a changeset

When you make changes that need to be released:

pnpm changeset

This will prompt you to:

  1. Select which packages you want to include in the changeset
  2. Choose whether it's a major/minor/patch bump
  3. Provide a summary of the changes

Creating a release

To create a new version and update the changelog:

# 1. Create new versions of packages
pnpm version:package

# 2. Release (builds and publishes to npm)
pnpm release

Remember to commit all changes after creating a release.