返回 reveal.js
README.md
根目录 / react / README.md
1 <p align="center">
2 <a href="https://revealjs.com">
3 <img src="https://hakim-static.s3.amazonaws.com/reveal-js/logo/v1/reveal-black-text-sticker.png" alt="reveal.js" width="500">
4 </a>
5 </p>
6
7 # @revealjs/react
8
9 `@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.
10
11 ## Installation
12
13 Install the package along with its peer dependencies:
14
15 ```bash
16 npm i @revealjs/react reveal.js react react-dom
17 # or
18 yarn add @revealjs/react reveal.js react react-dom
19 ```
20
21 The package ships only the React bindings. You still need to import Reveal CSS, themes, and any plugins your deck uses.
22
23 ## Set up a deck
24
25 Render a `Deck` with one or more `Slide` children and import the core Reveal styles:
26
27 ```tsx
28 import { Deck, Slide } from '@revealjs/react';
29 import 'reveal.js/reveal.css';
30 import 'reveal.js/theme/black.css';
31
32 export function Presentation() {
33 return (
34 <Deck>
35 <Slide>
36 <h1>Hello</h1>
37 <p>My first Reveal deck in React.</p>
38 </Slide>
39
40 <Slide background="#111827">
41 <h2>Second slide</h2>
42 </Slide>
43 </Deck>
44 );
45 }
46 ```
47
48 ## Components
49
50 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, `Stack` groups slides into a vertical column, and `Markdown` renders Reveal-compatible markdown slides without registering the Reveal markdown plugin:
51
52 ```tsx
53 import { Deck, Slide, Stack, Markdown, Fragment, Code } from '@revealjs/react';
54 import RevealHighlight from 'reveal.js/plugin/highlight';
55 import 'reveal.js/plugin/highlight/monokai.css';
56
57 export function Presentation() {
58 return (
59 <Deck plugins={[RevealHighlight]}>
60 <Slide>
61 <h2>Step by step</h2>
62 <Fragment animation="fade-up" as="p">First point</Fragment>
63 <Fragment animation="fade-up" asChild>
64 <div>Second point</div>
65 </Fragment>
66 <Code language="javascript" lineNumbers>
67 {`console.log('Hello, world!');`}
68 </Code>
69 </Slide>
70
71 <Stack>
72 <Slide>Vertical 1</Slide>
73 <Slide>Vertical 2</Slide>
74 </Stack>
75
76 <Markdown
77 separator="^\n---\n$"
78 verticalSeparator="^\n--\n$"
79 options={{ smartypants: true, animateLists: true }}
80 >
81 {`
82 ## Markdown 1.1
83 - First item <!-- .element: class="fragment" -->
84 - Second item <!-- .element: class="fragment" -->
85
86 --
87
88 ## Markdown 1.2
89
90 Notes:
91 These become speaker notes.
92
93 ---
94
95 <!-- .slide: data-background="#111827" -->
96 ## Markdown 2
97 `}
98 </Markdown>
99 </Deck>
100 );
101 }
102 ```
103
104 `Markdown` accepts string children, a `markdown` prop, or `src` for external markdown. Use the first-class `separator`, `verticalSeparator`, `notesSeparator`, `elementAttributesSeparator`, and `slideAttributesSeparator` props to mirror Reveal's markdown options, and pass any other markdown/Marked settings through `options`.
105
106 ## Configure Reveal
107
108 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.
109
110 ```tsx
111 import { Deck, Slide } from '@revealjs/react';
112 import 'reveal.js/reveal.css';
113 import 'reveal.js/theme/black.css';
114 import 'reveal.js/plugin/highlight/monokai.css';
115 import RevealHighlight from 'reveal.js/plugin/highlight';
116
117 export function Presentation() {
118 return (
119 <Deck
120 config={{
121 width: 1280,
122 height: 720,
123 hash: true,
124 controls: true,
125 progress: true,
126 transition: 'slide',
127 }}
128 plugins={[RevealHighlight]}
129 >
130 <Slide>Configured deck</Slide>
131 </Deck>
132 );
133 }
134 ```
135
136 `config` maps directly to [Reveal's configuration object](https://revealjs.com/config/). `Slide` and `Markdown` both support 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 `<section>` element.
137
138 ## Subscribe to events
139
140 Use event props on `Deck` to respond to Reveal lifecycle and navigation events:
141
142 ```tsx
143 import { Deck, Slide } from '@revealjs/react';
144
145 export function Presentation() {
146 return (
147 <Deck
148 onReady={(deck) => {
149 console.log('Reveal ready', deck);
150 }}
151 onSync={() => {
152 console.log('Deck synced');
153 }}
154 onSlideChange={(event) => {
155 console.log('Slide changed', event.indexh, event.indexv);
156 }}
157 onFragmentShown={(event) => {
158 console.log('Fragment shown', event.fragment);
159 }}
160 >
161 <Slide>Intro</Slide>
162 <Slide>Next</Slide>
163 </Deck>
164 );
165 }
166 ```
167
168 ## Access the Reveal API
169
170 Use `useReveal()` inside the deck tree to call the Reveal API from your own components:
171
172 ```tsx
173 import { Deck, Slide, useReveal } from '@revealjs/react';
174
175 function NextButton() {
176 const deck = useReveal();
177
178 return <button onClick={() => deck?.next()}>Next slide</button>;
179 }
180
181 export function Presentation() {
182 return (
183 <Deck>
184 <Slide>
185 <h2>Controlled from React</h2>
186 <NextButton />
187 </Slide>
188 </Deck>
189 );
190 }
191 ```
192
193 To access the Reveal instance outside of the component tree, pass a `deckRef` to `Deck`:
194
195 ```tsx
196 import { useRef } from 'react';
197 import { Deck, Slide } from '@revealjs/react';
198 import type { RevealApi } from 'reveal.js';
199
200 export function Presentation() {
201 const deckRef = useRef<RevealApi | null>(null);
202
203 return (
204 <Deck deckRef={deckRef}>
205 <Slide>Hello</Slide>
206 </Deck>
207 );
208 }
209 ```
210
211 ## How it works
212
213 - `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`.
214 - `Deck` calls `reveal.sync()` when the rendered slide structure changes, such as slides being added, removed, reordered, or regrouped into stacks.
215 - `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.
216 - `Markdown` uses `marked` plus the same separator and comment-attribute conventions as Reveal's core markdown plugin, including `.slide:` and `.element:` comment syntax.
217 - `config` is shallow-compared on each render so that `reveal.configure()` is only called when a value actually changes.
218 - `plugins` are initialization-only, matching Reveal's plugin lifecycle. The prop is captured once on first mount and ignored on subsequent renders.
219 - Event props are wired with `deck.on()` after initialization and cleaned up with `deck.off()`. Changing a callback between renders swaps the listener automatically.
220
221 ---
222
223 <div align="center">
224 MIT licensed | Copyright © 2011-2026 Hakim El Hattab, https://hakim.se
225 </div>
226
226 lines MARKDOWN