tw-slide
v0.1.1
Published
Modern Tailwind-based presentation library for the web
Maintainers
Readme
tw-slide
Modern presentations, powered by Tailwind.
npm install tw-slideWhy tw-slide?
| | reveal.js | tw-slide |
|---|---|---|
| Styling | Custom CSS themes | Tailwind utility classes |
| Bundle | ~30KB+ gzip | ~4.5KB gzip |
| Dependencies | Multiple | Zero |
| Types | Community @types | Built-in TypeScript |
| Learning curve | Theme API + config | Just HTML + Tailwind |
| Dark mode | Theme-dependent | One class toggle |
Features
Core
- Tailwind-native styling
- 6 GPU-accelerated transitions
- 8 fragment animations
- Keyboard, touch & swipe navigation
- URL hash sync
Extras
- Plugin system (progress, slide numbers, overview)
- Dark / light mode
prefers-reduced-motionsupport- Print-ready PDF export
- TypeScript with full autocompletion
Quick Start
HTML
<div class="ts-deck ts-dark">
<section class="ts-slide">
<div class="ts-content text-center">
<h1 class="text-6xl font-bold text-white">Hello, tw-slide</h1>
<p class="text-xl text-gray-400 mt-4">Press → to continue</p>
</div>
</section>
<section class="ts-slide">
<div class="ts-content">
<h2 class="text-4xl font-bold text-white mb-6">Fragments</h2>
<p class="ts-fragment text-gray-300" data-ts-animation="fade-up">I appear first</p>
<p class="ts-fragment text-gray-300" data-ts-animation="fade-up">I appear second</p>
</div>
</section>
</div>JavaScript
import TailSlide, {
ProgressPlugin,
SlideNumberPlugin,
OverviewPlugin,
} from 'tw-slide';
import 'tw-slide/style.css';
const deck = new TailSlide({
transition: 'slide',
dark: true,
});
deck.use(new ProgressPlugin());
deck.use(new SlideNumberPlugin());
deck.use(new OverviewPlugin());That's it. Style your slides with Tailwind and present.
Transitions
All transitions use the Web Animations API for GPU-accelerated, 60fps performance.
| Transition | Description |
|:---:|---|
| none | Instant cut |
| fade | Crossfade dissolve |
| slide | Horizontal slide (default) |
| zoom | Scale in / out |
| flip | 3D card flip |
| cube | 3D cube rotation |
new TailSlide({ transition: 'cube', transitionSpeed: 600 });Per-slide override via data-ts-transition:
<section class="ts-slide" data-ts-transition="zoom">...</section>Fragments
Reveal content step by step within a slide.
<p class="ts-fragment" data-ts-animation="fade-up">Step 1</p>
<p class="ts-fragment" data-ts-animation="grow">Step 2</p>
<p class="ts-fragment" data-ts-animation="highlight">Step 3</p>| Animation | Effect |
|:---:|---|
| fade-in | Opacity fade (default) |
| fade-up | Slide up + fade |
| fade-down | Slide down + fade |
| fade-left | Slide from right + fade |
| fade-right | Slide from left + fade |
| grow | Scale up from small |
| shrink | Scale down from large |
| highlight | Yellow background highlight |
Configuration
new TailSlide({
el: '.ts-deck', // container selector or element
transition: 'slide', // none | fade | slide | zoom | flip | cube
transitionSpeed: 500, // duration in ms
easing: 'ease-in-out', // CSS easing function
keyboard: true, // keyboard navigation
touch: true, // touch / swipe
hash: true, // URL hash sync
dark: true, // dark mode
loop: false, // loop slides
autoSlide: 0, // auto-advance ms (0 = off)
startSlide: 0, // starting index
});Keyboard Shortcuts
| Key | Action | |:---:|---| | → ↓ Space N | Next slide / fragment | | ← ↑ P | Previous slide / fragment | | Home | First slide | | End | Last slide | | O | Toggle overview grid | | Esc | Toggle overview grid |
Plugins
ProgressPlugin
Thin progress bar at the top edge.
deck.use(new ProgressPlugin());SlideNumberPlugin
Current / total counter at bottom-right.
deck.use(new SlideNumberPlugin());OverviewPlugin
Bird's-eye grid of all slides. Press O to toggle, click to navigate.
deck.use(new OverviewPlugin());API
deck.next(); // next fragment or slide
deck.prev(); // previous fragment or slide
deck.goTo(3); // jump to slide index
deck.getState(); // { currentSlide, totalSlides, ... }
deck.getSlides(); // HTMLElement[]
deck.toggleOverview(); // toggle overview mode
deck.on('slide:changed', callback); // listen to events
deck.off('slide:changed', callback); // remove listener
deck.destroy(); // clean up everythingEvents
| Event | Payload |
|---|---|
| slide:changed | { from: number, to: number } |
| fragment:shown | { slide, fragment, element } |
| fragment:hidden | { slide, fragment, element } |
| deck:ready | { totalSlides } |
| deck:destroyed | {} |
| overview:open | {} |
| overview:close | {} |
Custom Plugins
Extend tw-slide with your own plugins:
import type { TailSlidePlugin, TailSlideAPI } from 'tw-slide';
class ConfettiPlugin implements TailSlidePlugin {
name = 'confetti';
init(deck: TailSlideAPI) {
deck.on('slide:changed', ({ to }) => {
if (to === deck.getSlides().length - 1) {
// 🎉 last slide — fire confetti!
}
});
}
destroy() {}
}
deck.use(new ConfettiPlugin());Browser Support
Chrome, Firefox, Safari, Edge — all modern browsers with Web Animations API support.
License
MIT © bysxx
