Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Precompiled components don't animate #39

Open
lilnasy opened this issue Mar 1, 2025 · 2 comments
Open

Precompiled components don't animate #39

lilnasy opened this issue Mar 1, 2025 · 2 comments

Comments

@lilnasy
Copy link

lilnasy commented Mar 1, 2025

I am using the React renderer with precompiled tokens. The tokenization, serialization, and rendering all seem to work fine, but the transitions are all immediate, not animated.

video.mp4

The component looks like this:

const CodePage: React.FC = () => {
    const [step, setStep] = useState(0)

    return <>
        <ShikiMagicMovePrecompiled
            steps={compiledCode}
            step={step}
            animate={true}
            options={{ duration: 750, stagger: 7, lineNumbers: true }}
        />
        <button onClick={() => setStep(step === 1 ? 0 : 1)}>Animate</button>
    </>
}

compiledCode is generated using this code:

const machine = createMagicMoveMachine(
    code => codeToKeyedTokens(highlighter, code, {
        lang: "tsx",
        theme: "vitesse-light",
    })
)

const compiledCode = [
`function greet() {
    console.log('Hello, World!');
}
greet();`,
`const name = 'Alice';
function greet() {
    console.log('Hello, ' + name + '!');
}
greet();`
].map(code => machine.commit(code).current)
@lilnasy
Copy link
Author

lilnasy commented Mar 1, 2025

  • This may appear as a duplicate of React example not working #32, but that issue is fixed by including shiki-magic-move's stylesheet. This issue remains with the stylesheet included.

@lilnasy
Copy link
Author

lilnasy commented Mar 1, 2025

I noticed that the component was being re-rendered unnecessarily. Maybe an extra re-render was cancelling the animation abruptly.

Looking at the code, I noticed that the useMemo was updating a value it depended on. Recognizing that as a "loop-happy" pattern, I updated the memo's dependencies.

  const result = React.useMemo(() => {
    const res = syncTokenKeys(
      previous,
      steps[Math.min(step, steps.length - 1)],
      options,
    )
    setPrevious(res.to)
    return res
- }, [previous, steps, step, options])
+ }, [steps, step, options])

Preview in the PR.
I don't understand the intention behind the hook, but this also allowed the code block to animate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant