@delkon/apple-letters is a Vue 3 library for generating Apple-style "hello" boot text animations, built around a small engine-first core.
It gives you two layers:
- a thin
LettersVue component for direct rendering - a lower-level engine API for custom SVG or animation workflows
pnpm add @delkon/apple-lettersvue is a peer dependency.
<script setup lang="ts">
import { Letters } from '@delkon/apple-letters'
</script>
<template>
<Letters text="hello" color="#1f2937" />
</template><script setup lang="ts">
import { computed, ref } from 'vue'
import { Letters } from '@delkon/apple-letters'
const progress = ref(0.4)
const percentage = computed(() => `${Math.round(progress.value * 100)}%`)
</script>
<template>
<Letters text="hello" :progress="progress" color="currentColor" />
<input v-model.number="progress" type="range" min="0" max="1" step="0.01" />
<span>{{ percentage }}</span>
</template><script setup lang="ts">
import { Letters } from '@delkon/apple-letters'
</script>
<template>
<Letters
text="bonjour"
color="#b45309"
:stroke-width="2.4"
variant="simple"
:overlap="0.04"
/>
</template><script setup lang="ts">
import { computed, ref } from 'vue'
import { useLettersRender } from '@delkon/apple-letters'
const progress = ref(0.65)
const model = useLettersRender(
computed(() => ({
text: 'engine',
progress: progress.value,
color: '#111827',
strokeWidth: 1,
})),
)
const visiblePaths = computed(() =>
model.value.paths.filter(item => Math.abs(item.strokeDashoffset) < 0.98),
)
</script>
<template>
<svg :viewBox="model.svg.viewBox" fill="none">
<path v-for="item in visiblePaths" :key="item.key" :d="item.d" :stroke="item.stroke"
:stroke-width="item.strokeWidth" :stroke-dasharray="item.strokeDasharray"
:stroke-dashoffset="item.strokeDashoffset" :stroke-linecap="item.linecap" :stroke-linejoin="item.linejoin"
pathLength="1" fill="none" />
</svg>
<circle v-for="item in model.dots" :key="item.key"
:cx="item.translateX != null ? item.cx + item.translateX : item.cx" :cy="item.cy" :r="item.r" :fill="item.fill"
:opacity="item.opacity" />
</template>import { createLettersRenderModel } from '@delkon/apple-letters'
const model = createLettersRenderModel({
text: 'hello',
progress: 0.5,
color: '#2563eb',
strokeWidth: 2,
})
console.log(model.svg.viewBox)
console.log(model.paths)
console.log(model.dots)import {
Letters,
createLettersRenderModel,
layoutText,
useLettersRender,
} from '@delkon/apple-letters'The default Vue component for rendering handwritten SVG paths.
Supported props:
text: stringprogress?: numberstrokeWidth?: numbercolor?: stringvariant?: 'simple' | 'complex'overlap?: numberopts?: SmoothingOptions
Turns reactive input into a computed render model. Useful when you want full control over SVG rendering while staying inside Vue reactivity.
Framework-agnostic engine entry. Returns:
svgpathsdots
This is the best choice when you want to build your own renderer or feed the geometry into another animation system.
Lower-level layout helper for advanced use cases. Most consumers will not need it directly.
progressis expected to be between0and1variant="simple"is the defaultcolordefaults tocurrentColorstrokeWidthdefaults to2overlapdefaults to0.02
pnpm install
pnpm dev
pnpm buildpnpm devruns the local demopnpm buildemits the publishable library bundles and type declarations intodist/
Inspired by @kumailnanji/letters:
https://github.com/kumailnanji/letters