Code
Animating code
The <Code>
component uses Shiki for beautiful syntax highlighting:
<script lang="ts">
import { Presentation, Slide, Code, Action } from '@animotion/core'
let code: ReturnType<typeof Code>
</script>
<Presentation>
<Slide class="h-full place-content-center place-items-center">
<Code
bind:this={code}
lang="svelte"
theme="poimandres"
code={`
<script>
let count = 0
$: double = count * 2
<\/script>
<button on:click={() => count++}>
{double}
</button>
`}
options={{ duration: 1000, stagger: 0.3, containerStyle: false }}
/>
<Action
do={() =>
code.update`
<script>
let count = $state(0)
let double = $derived(count * 2)
<\/script>
<button onclick={() => count++}>
{double}
</button>
`}
/>
<Action do={() => code.selectLines`2,3`} />
<Action do={() => code.selectLines`2-3,7`} />
<Action do={() => code.selectToken`double {double}`} />
<Action do={() => code.selectLines`*`} />
</Slide>
</Presentation>
You can pick one of many themes that come with Shiki, choose a language, and provide options to the <Code />
component.
Animating Code Changes
You can animate changes in your code by using the update
method:
code.update`
<script>
let count = $state(0)
let double = $derived(count * 2)
<\/script>
<button onclick={() => count++}>
{double}
</button>
`}
Animotion uses Shiki Magic Move to animate the code changes which does the diffing to know what changed, and then animates the changes.
Code Highlighting
You can highlight lines:
// select line
code.selectLines`2`
// select multiple lines
code.selectLines`2,3`
// select lines range
code.selectLines`2-3`
// select lines range and lines
code.selectLines`2-3,7`
// select all lines
code.selectLines`*`
You can highlight tokens (inspect the code to see what token you can select):
// select token
code.selectToken`double`
// select token on line
code.selectToken`3 double`
// select multiple tokens
code.selectToken`double {double}`
The methods return a promise that is resolved when the transition is done:
<Action do={async () => {
await code.selectLines`2,3`
await code.selectLines`2-3,7`
await code.selectToken`double {double}`
await code.selectLines`*`
}} />
Using Expressions
You can use expressions inside the template function:
<script lang="ts">
let expression = 'false'
</script>
<!-- ... -->
<Action
do={() => {
expression = 'true'
code.update`let bool = ${expression}`
}}
>
Code Indentation
Indenting code creates extra whitespace:
<Code
code={`
->-><script>
->->->let count = 0
->->->$: double = count * 2
->-><\/script>
->-><button on:click={() => count++}>
->->->{double}
->-></button>
`}
/>
If you use tabs Animotion auto-indents your code for you:
<Code
code={`
<script>
->let count = 0
->$: double = count * 2
<\/script>
<button on:click={() => count++}>
->{double}
</button>
`}
/>
If you want to opt-out of this feature, you can set autoIndent
to false:
<Code autoIndent={false} />
Chaining code animations
Instead of creating actions for the code animations yourself, you can use the codes
prop to create them for you:
<script lang="ts">
import { Code } from '@animotion/core'
// get a reference to the instance
let code: ReturnType<typeof Code>
</script>
<Code
ref={(ref) => code = ref}
lang="svelte"
theme="poimandres"
codes={[
`
<script>
let count = 0
$: double = count * 2
<\/script>
<button on:click={() => count++}>
{double}
</button>
`,
`
<script>
let count = $state(0)
let double = $derived(count * 2)
<\/script>
<button onclick={() => count++}>
{double}
</button>
`
]}
/>
<Action
undo={() => {
code.selectLines`*`
}}
actions={[
() => code.selectLines`2,3`,
() => code.selectLines`2-3,7`,
() => code.selectToken`double {double}`,
() => code.selectLines`*`
]}
/>
Escape closing tags
Having a closing tag like </script>
in your code block is going to cause problems because Svelte thinks you’re trying to close the <script>
tag in your component. To solve this problem use the backslash character to escape it:
<Code>
code={`
<script>
// ...
<\/script>
`}
<Code>