svelte-typewriter
Version:
A simple and reusable typewriter effect for your Svelte applications
197 lines (151 loc) • 9.16 kB
Markdown
# svelte-typewriter
> A simple and reusable typewriter effect for your Svelte applications
[](http://makeapullrequest.com)
[](https://www.npmjs.com/package/svelte-typewriter)
[](https://www.npmjs.com/package/svelte-typewriter)
[](https://madewithsvelte.com/p/svelte-typewriter/shield-link)
[DEMO](https://henriquehbr.srht.site/svelte-typewriter)
## Summary
- [Installation](#installation)
- [Usage](#usage)
- [Component-based approach](#component-based-approach)
- [Directive-based approach](#directive-based-approach)
- [Props](#props)
- [Settings](#settings)
- [Modes](#modes)
- [Event listeners](#event-listeners)
- [Child attributes](#child-attributes)
- [CSS variables](#css-variables)
- [Used by](#used-by)
- [FAQs](#faqs)
- [UMD and IIFE output formats are not supported for code-splitting builds](#umd-and-iife-output-formats-are-not-supported-for-code-splitting-builds)
- [Test suite failed to run: SyntaxError: Unexpected token '<'](#test-suite-failed-to-run-syntaxerror-unexpected-token-)
- [Contributing](#contributing)
## Installation
```bash
pnpm i -D svelte-typewriter
```
> `pnpm` is used here just as an example, you can use your package manager of choice
## Usage
### Component-based approach
In order to use this method, you need to import the Svelte component, and wrap
your elements with the `<Typewriter>` component
```svelte
<script>
import Typewriter from 'svelte-typewriter'
</script>
<Typewriter>
<h1>Testing the typewriter effect</h1>
</Typewriter>
```
### Directive-based approach
This method relies on [Svelte actions](https://svelte.dev/docs#template-syntax-element-directives-use-action)
(more specifically, the `use:action` directive), in order to animate your
components with this approach, you must import the directive of the animation
mode you want to use and include it as a attribute on your element
```svelte
<script>
import { concurrent } from 'svelte-typewriter'
</script>
<p use:concurrent={{ interval: 30 }}>Testing the typewriter effect</p>
```
Each mode has it's own directive, which accepts a single object parameter that
can be used to set the animation props (just like on the component-based approach)
There are just a few limitations of this approach to keep in mind:
- For now, there's no way to have the cursor caret on the text being animated
- Event listeners (like `on:done`) won't be triggered
- Depending on the animation mode you're using, some essential animation
properties must be explicitly specified, because they don't have default values
when used on a directive, otherwise the animation won't work properly, those
include `interval`, `wordInterval`, `writeInterval` and `scrambleDuration`
## Props
The `<Typewriter>` component can receive props that allows to manipulate the
behavior of the resulting animation, these props are divided into the following
groups
- **Settings:** general animation properties
- **Event listeners:** functions executed based on the condition of a trigger
- **Child attributes:** child elements animation properties
- **CSS variables:** styling-related properties
### Settings
| Prop | Type | Description | Default |
| --- | --- | --- | --- |
| `mode` | `concurrent`, `cascade`, `loop`, `loopOnce`, `loopRandom` or `scramble` | The animation mode to be used | `concurrent` |
| `interval` | `number` or `array` | The interval (in milliseconds) between each letter, you can also pass a array of distinct intervals to mimic human typing | `30` |
| `cursor` | `boolean` | Enables/disables the cursor on the Typewriter animation | `true` |
| `keepCursorOnFinish` | `number` or `boolean` | Keep the cursor visible (indefinitely, or for a given amount of time, in milliseconds) after the animation has finished | `false` |
| `delay` | `number` | The interval (in milliseconds) before the animation starts | `0` |
| `showCursorOnDelay` | `boolean` | (only usable when `delay` is not 0) Shows the cursor during delay period | `false` |
| `disabled` | `boolean` | Enables/disables the typewriter animation | `false` |
| `element` | `string` | Sets the tag that will be used for the container element | `div` |
| `wordInterval` | `number` | **(`loop`, `loopOnce` and `loopRandom` modes only)** Sets the interval (in milliseconds) between each word | `1500` |
| `unwriteInterval` | `number` | **(`loop`, `loopOnce` and `loopRandom` modes only)** The interval (in milliseconds) between each letter unwrite, if not defined it uses `interval` | `30` |
| `scrambleDuration` | `number` | **(`scramble` mode only)** Sets the duration (in milliseconds) of the scramble animation | `3000` |
| `scrambleSlowdown` | `boolean` | **(`scramble` mode only)** Enables/disables the slowdown effect right before the scramble animation ends (only works in scramble mode) | `true` |
#### Modes
You can control the behavior of the typewriter effect by passing specific props to the `<Typewriter>` component, the table below contains information about all modes:
| Mode | Description |
| --- | --- |
| `concurrent` | Apply animation simultaneously on all elements, as opposed to the sequential animation of `cascade` mode |
| `cascade` | Apply animation on all elements sequentially instead of simultaneously |
| `loop` | Cycles the animation between the children elements of the parent `Typewriter` component |
| `loopOnce` | It's very similar to the `loop` mode, but the animation stops once it reaches the last element |
| `loopRandom` | It's very similar to `loop` mode, but instead of cycling the animation in a linear way, it picks a random child element to animate each time |
| `scramble` | Slowly reveals the a word by continuously randomizing all of it's letters for a specific amount of time |
### Event listeners
| Event | Trigger | Detail |
| --- | --- | --- |
| `on:done` | Is executed at the end of the animation, if used with one of the loop modes, this event will be fired after each word gets written and erased | `"write" \| "unwrite" \| null` |
### Child attributes
| Attribute | Description |
| --- | --- |
| `data-static` | Marks an element as static, excluding it from receiving animations from the `<Typewriter>` component |
### CSS variables
| Variable | Description |
| --- | --- |
| `--cursor-color` | Sets the cursor color (accepts any valid color name, hex code and rgb/rgba values) |
| `--cursor-width` | Sets the cursor width |
## Used by
<div align="center">
<a href="https://github.com/GeopJr/SveltePress">
<img src="https://git.sr.ht/~henriquehbr/svelte-typewriter/blob/main/sveltepress-logo.png" width="128" alt="SveltePress logo">
</a>
<a href="https://github.com/ThatConference/that.us">
<img src="https://git.sr.ht/~henriquehbr/svelte-typewriter/blob/main/that-us-logo.png" width="256" alt="That.us logo">
</a>
<a href="https://github.com/Fronvo/site">
<img src="https://git.sr.ht/~henriquehbr/svelte-typewriter/blob/main/fronvo-logo.png" width="256" alt="Fronvo logo">
</a>
<a href="https://github.com/PlebeianTech/plebeian-market">
<img src="https://git.sr.ht/~henriquehbr/svelte-typewriter/blob/main/plebeian-market-logo.jpg" height="128" alt="plebeian.market logo" />
</a>
<a href="https://github.com/kishansripada/pada">
<img src="https://git.sr.ht/~henriquehbr/svelte-typewriter/blob/main/pada-logo.png" height="128" alt="pada logo" />
</a>
</div>
## FAQs
#### UMD and IIFE output formats are not supported for code-splitting builds.
From version 2.1.17 onwards, this library makes use of dynamic imports, if your
Rollup configuration `output.format` is set to `iife` or `umd`, consider
setting `inlineDynamicImports` to `true`, otherwise, change `output.format` to
something else, like `esm` (for more details, consider checking [#21](https://github.com/henriquehbr/svelte-typewriter/issues/21))
#### Test suite failed to run: SyntaxError: Unexpected token '<'
This happens because Jest cannot parse Svelte syntax right away, it needs to be
transformed by `svelte-jester` first, therefore, we must tell Jest to **NOT**
ignore `svelte-typewriter`, as by default, everything inside `node_modules` is
ignored and parsed as-is without any kind of pre-processing, this can be done
by setting the `transformIgnorePatterns` property on your Jest configuration,
example below:
```js
// jest.config.js
module.exports = {
transformIgnorePatterns: ["/node_modules/(?!(svelte-typewriter)/)"]
}
```
> More details on [#73](https://github.com/henriquehbr/svelte-typewriter/issues/73)
## Contributing
1. Fork it
2. Create your feature branch: `git checkout -b fix/my-new-bug-fix`
3. Preview your changes by running the `dev` script on `package.json`
4. Commit your changes: `git commit -am 'fix: solve some issue'`
5. Push to the branch: `git push --set-upstream origin fix/my-new-bug-fix`
6. Submit a pull request