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, lineNumbers: true, 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 Selection
You can select lines of code:
// 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 select parts of the code:
// select every token
code.select`count`
// select first match
code.select`count:0`
// select first match on line 4
code.select`4 count:0`
// add another selection
code.selectAdd`() => count++` 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.select`count`
await code.selectLines`*`
}} /> Code Scrolling
You might have a scrollable code block:
<Code
bind:this={code}
lang="svelte"
theme="poimandres"
code={`...`}
class="h-[400px] overflow-y-auto"
options={{ duration: 600, stagger: 0.3, containerStyle: false }}
/> You can scroll to a line of code using the scrollToLine method:
await code.scrollToLine`2` You can hide the scrollbar using CSS:
pre::-webkit-scrollbar {
display: none;
} You can also create a Tailwind class:
@utility no-scrollbar {
@apply [scrollbar-width:none] [&::-webkit-scrollbar]:hidden;
} Using Expressions
The update, selectLines, selectTokens, and scrollToLine tag functions support expressions:
<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>