Skip to content

Instantly share code, notes, and snippets.

@stripedpurple
Created January 15, 2023 18:09
Show Gist options
  • Save stripedpurple/e57f938008e6cf18ed5234543734c0ff to your computer and use it in GitHub Desktop.
Save stripedpurple/e57f938008e6cf18ed5234543734c0ff to your computer and use it in GitHub Desktop.
import type { Directive, DirectiveBinding } from "vue";
let interval: number;
const write = (
el: HTMLElement,
binding: DirectiveBinding<Array<string> | string>
) => {
const { value } = binding;
let direction = "inc";
let sliceTo = 0;
let paused = false;
const queue: string[] = typeof value === "string" ? [value] : [...value];
// This class is used to make a blinking cursor requires the import of typewriter.css
el.classList.add("typewriter");
// Start of loop
interval = setInterval(() => {
// only makes updates if not paused
if (!paused) {
// Sets typing to increment and rotates queue
if (sliceTo === 0) {
direction = "inc";
queue.push(queue.shift() ?? "");
}
// Sets typing to delete
if (sliceTo >= queue[0].length) {
direction = "dec";
paused = true;
setTimeout(() => {
paused = false;
}, 1500);
}
// Updates element to have correct content
el.innerText = queue[0].slice(0, sliceTo);
sliceTo >= 0 && sliceTo < queue[0].length && direction === "inc"
? sliceTo++
: sliceTo--;
}
}, 200);
};
export default {
mounted: write,
beforeUnmount: () => clearInterval(interval),
} as Directive;
.typewriter:after {
content: '|';
animation: 1s blink infinite;
}
@keyframes blink {
0%, 50% {
opacity: 1;
}
51%, 100% {
opacity: 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment