reveal.js

# @revealjs/react `@revealjs/react` is a thin React wrapper around the [Reveal.js](https://revealjs.com) presentation framework. Describe your slides as React components and let the wrapper handle the rest. ## Installation Install the package along with its peer dependencies: ```bash npm i @revealjs/react reveal.js react react-dom # or yarn add @revealjs/react reveal.js react react-dom ``` The package ships only the React bindings. You still need to import Reveal CSS, themes, and any plugins your deck uses. ## Set up a deck Render a `Deck` with one or more `Slide` children and import the core Reveal styles: ```tsx import { Deck, Slide } from '@revealjs/react'; import 'reveal.js/reveal.css'; import 'reveal.js/theme/black.css'; export function Presentation() { return (

Hello

My first Reveal deck in React.

Second slide

); } ``` ## Components Alongside `Deck` and `Slide`, the package ships a few components for common slide patterns. `Fragment` reveals content one step at a time, `Code` renders a syntax-highlighted block via the highlight plugin, and `Stack` groups slides into a vertical column: ```tsx import { Deck, Slide, Stack, Fragment, Code } from '@revealjs/react'; import RevealHighlight from 'reveal.js/plugin/highlight'; import 'reveal.js/plugin/highlight/monokai.css'; export function Presentation() { return (

Step by step

First point
Second point
{`console.log('Hello, world!');`}
Vertical 1 Vertical 2
); } ``` ## Configure Reveal Pass any Reveal configuration through the `config` prop on `Deck`. Plugins are registered separately via `plugins` and are applied once at initialization time, matching Reveal's plugin lifecycle. ```tsx import { Deck, Slide } from '@revealjs/react'; import 'reveal.js/reveal.css'; import 'reveal.js/theme/black.css'; import 'reveal.js/plugin/highlight/monokai.css'; import RevealHighlight from 'reveal.js/plugin/highlight'; export function Presentation() { return ( Configured deck ); } ``` `config` maps directly to [Reveal's configuration object](https://revealjs.com/config/). `Slide` supports convenient Reveal slide props such as `background`, `backgroundImage`, `backgroundColor`, `visibility`, `autoAnimate`, `transition`, `transitionSpeed`, `autoSlide`, `notes`, `backgroundInteractive`, and `preload`, while still passing through raw `data-*` attributes to the rendered `
` element. ## Subscribe to events Use event props on `Deck` to respond to Reveal lifecycle and navigation events: ```tsx import { Deck, Slide } from '@revealjs/react'; export function Presentation() { return ( { console.log('Reveal ready', deck); }} onSync={() => { console.log('Deck synced'); }} onSlideChange={(event) => { console.log('Slide changed', event.indexh, event.indexv); }} onFragmentShown={(event) => { console.log('Fragment shown', event.fragment); }} > Intro Next ); } ``` ## Access the Reveal API Use `useReveal()` inside the deck tree to call the Reveal API from your own components: ```tsx import { Deck, Slide, useReveal } from '@revealjs/react'; function NextButton() { const deck = useReveal(); return ; } export function Presentation() { return (

Controlled from React

); } ``` To access the Reveal instance outside of the component tree, pass a `deckRef` to `Deck`: ```tsx import { useRef } from 'react'; import { Deck, Slide } from '@revealjs/react'; import type { RevealApi } from 'reveal.js'; export function Presentation() { const deckRef = useRef(null); return ( Hello ); } ``` ## How it works - `Deck` creates one Reveal instance on mount and destroys it on unmount. Initialization is asynchronous — `onReady` fires once `reveal.initialize()` resolves, after which the instance is also accessible via `useReveal()` and `deckRef`. - `Deck` calls `reveal.sync()` when the rendered slide structure changes, such as slides being added, removed, reordered, or regrouped into stacks. - `Slide` handles slide-level `data-*` attribute updates locally with `reveal.syncSlide()`, so ordinary React content updates inside a slide do not trigger a full deck sync. - `config` is shallow-compared on each render so that `reveal.configure()` is only called when a value actually changes. - `plugins` are initialization-only, matching Reveal's plugin lifecycle. The prop is captured once on first mount and ignored on subsequent renders. - Event props are wired with `deck.on()` after initialization and cleaned up with `deck.off()`. Changing a callback between renders swaps the listener automatically. ---
MIT licensed | Copyright © 2011-2026 Hakim El Hattab, https://hakim.se