0
# React Components
1
2
React components provide the UI layer for caption functionality with primitive, unstyled components that can be fully customized and themed.
3
4
## Capabilities
5
6
### CaptionPlugin
7
8
React-compatible version of BaseCaptionPlugin for use in React Plate editors.
9
10
```typescript { .api }
11
/**
12
* React plugin wrapper for caption functionality
13
*/
14
const CaptionPlugin = toPlatePlugin(BaseCaptionPlugin);
15
```
16
17
**Usage Examples:**
18
19
```typescript
20
import { createPlateEditor } from "@udecode/plate/react";
21
import { CaptionPlugin } from "@udecode/plate-caption/react";
22
23
const editor = createPlateEditor({
24
plugins: [
25
CaptionPlugin.configure({
26
options: {
27
query: { allow: ['img', 'media'] }
28
}
29
})
30
]
31
});
32
```
33
34
### Caption Container
35
36
Main caption container component that renders as a `figcaption` element with visibility and state management.
37
38
```typescript { .api }
39
/**
40
* Caption container component
41
* @param props - Standard figcaption props plus caption options
42
* @returns JSX.Element or null if hidden
43
*/
44
function Caption(props: CaptionProps): JSX.Element;
45
46
interface CaptionProps extends React.ComponentPropsWithoutRef<'figcaption'> {
47
options?: CaptionOptions;
48
}
49
50
interface CaptionOptions {
51
readOnly?: boolean;
52
}
53
54
/**
55
* State hook for Caption component
56
* @param options - Caption configuration options
57
* @returns State object with caption data and visibility flags
58
*/
59
function useCaptionState(options?: CaptionOptions): {
60
captionString: string;
61
hidden: boolean;
62
readOnly: boolean;
63
selected: boolean;
64
};
65
66
/**
67
* Props hook for Caption component
68
* @param state - State from useCaptionState
69
* @returns Props object for caption element
70
*/
71
function useCaption(state: ReturnType<typeof useCaptionState>): {
72
hidden: boolean;
73
};
74
```
75
76
**Usage Examples:**
77
78
```typescript
79
import { Caption } from "@udecode/plate-caption/react";
80
81
// Basic usage
82
function ImageWithCaption() {
83
return (
84
<div>
85
<img src="example.jpg" />
86
<Caption className="image-caption">
87
Caption content here
88
</Caption>
89
</div>
90
);
91
}
92
93
// With read-only option
94
function ReadOnlyCaption() {
95
return (
96
<Caption options={{ readOnly: true }}>
97
This caption cannot be edited
98
</Caption>
99
);
100
}
101
102
// Custom styling
103
function StyledCaption() {
104
return (
105
<Caption
106
style={{ fontStyle: 'italic', color: '#666' }}
107
className="custom-caption"
108
>
109
Styled caption content
110
</Caption>
111
);
112
}
113
```
114
115
### CaptionTextarea
116
117
Editable textarea component for caption text with auto-resizing, focus management, and keyboard navigation.
118
119
```typescript { .api }
120
/**
121
* Auto-resizing textarea for caption editing
122
* @param props - TextareaAutosize props
123
* @returns JSX.Element
124
*/
125
function CaptionTextarea(
126
props: React.ComponentProps<typeof TextareaAutosize>
127
): JSX.Element;
128
129
/**
130
* State hook for CaptionTextarea component
131
* @returns State object with handlers and refs
132
*/
133
function useCaptionTextareaState(): {
134
captionValue: string;
135
element: TCaptionElement;
136
readOnly: boolean;
137
textareaRef: React.RefObject<HTMLTextAreaElement>;
138
handleChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
139
handleCompositionEnd: (e: React.CompositionEvent<HTMLTextAreaElement>) => void;
140
handleCompositionStart: () => void;
141
};
142
143
/**
144
* Props hook for CaptionTextarea component
145
* @param state - State from useCaptionTextareaState
146
* @returns Props and ref for textarea element
147
*/
148
function useCaptionTextarea(
149
state: ReturnType<typeof useCaptionTextareaState>
150
): {
151
props: {
152
readOnly: boolean;
153
value: string;
154
onBlur: (e: React.FocusEvent<HTMLTextAreaElement>) => void;
155
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
156
onCompositionEnd: (e: React.CompositionEvent<HTMLTextAreaElement>) => void;
157
onCompositionStart: () => void;
158
onKeyDown: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
159
};
160
ref: React.RefObject<HTMLTextAreaElement>;
161
};
162
163
/**
164
* Focus management hook for caption textarea
165
* @param textareaRef - Ref to textarea element
166
*/
167
function useCaptionTextareaFocus(
168
textareaRef: React.RefObject<HTMLTextAreaElement | null>
169
): void;
170
```
171
172
**Key Features:**
173
174
- **Auto-resize**: Automatically adjusts height based on content
175
- **Focus Management**: Integrates with plugin focus path system
176
- **Keyboard Navigation**: Up/down arrows move between editor and caption
177
- **Composition Handling**: Proper support for IME input methods
178
- **Auto-save**: Changes are automatically saved to editor state
179
180
**Usage Examples:**
181
182
```typescript
183
import { CaptionTextarea } from "@udecode/plate-caption/react";
184
185
// Basic usage
186
function EditableCaption() {
187
return (
188
<CaptionTextarea
189
placeholder="Enter image caption..."
190
className="caption-input"
191
/>
192
);
193
}
194
195
// With custom props
196
function CustomCaption() {
197
return (
198
<CaptionTextarea
199
placeholder="Describe this image..."
200
maxRows={3}
201
style={{
202
border: '1px solid #ccc',
203
borderRadius: '4px',
204
padding: '8px'
205
}}
206
/>
207
);
208
}
209
210
// In combination with Caption container
211
function CompleteCaption() {
212
return (
213
<Caption>
214
<CaptionTextarea placeholder="Add caption..." />
215
</Caption>
216
);
217
}
218
```
219
220
### TextareaAutosize
221
222
Auto-resizing textarea primitive with SSR compatibility.
223
224
```typescript { .api }
225
/**
226
* Auto-resizing textarea component
227
* @param props - Standard textarea props plus autosize options
228
* @param ref - Ref to textarea element
229
* @returns JSX.Element or null during SSR
230
*/
231
const TextareaAutosize = React.forwardRef<
232
HTMLTextAreaElement,
233
TextareaAutosizeProps
234
>((props, ref) => JSX.Element);
235
236
interface TextareaAutosizeProps {
237
maxRows?: number;
238
minRows?: number;
239
onHeightChange?: (height: number, meta: { rowHeight: number }) => void;
240
cacheMeasurements?: boolean;
241
[key: string]: any; // Standard textarea props
242
}
243
```
244
245
**Usage Examples:**
246
247
```typescript
248
import { TextareaAutosize } from "@udecode/plate-caption/react";
249
250
// Basic auto-resize textarea
251
function AutoTextarea() {
252
return (
253
<TextareaAutosize
254
placeholder="Type here..."
255
minRows={2}
256
maxRows={8}
257
/>
258
);
259
}
260
261
// With height change callback
262
function MonitoredTextarea() {
263
const handleHeightChange = (height: number) => {
264
console.log('Textarea height changed to:', height);
265
};
266
267
return (
268
<TextareaAutosize
269
onHeightChange={handleHeightChange}
270
placeholder="Resizing textarea..."
271
/>
272
);
273
}
274
```
275
276
### Caption Button Components
277
278
Utility components for caption interaction buttons.
279
280
```typescript { .api }
281
/**
282
* State hook for caption button functionality
283
* @returns State with editor and element references
284
*/
285
function useCaptionButtonState(): {
286
editor: SlateEditor;
287
element: TElement;
288
};
289
290
/**
291
* Props hook for caption button
292
* @param state - State from useCaptionButtonState
293
* @returns Props with click handler
294
*/
295
function useCaptionButton(
296
state: ReturnType<typeof useCaptionButtonState>
297
): {
298
props: {
299
onClick: () => void;
300
};
301
};
302
```
303
304
**Usage Examples:**
305
306
```typescript
307
import { useCaptionButton, useCaptionButtonState } from "@udecode/plate-caption/react";
308
309
function CaptionToggleButton() {
310
const state = useCaptionButtonState();
311
const { props } = useCaptionButton(state);
312
313
return (
314
<button {...props} className="caption-toggle">
315
Add Caption
316
</button>
317
);
318
}
319
```
320
321
## Component Composition
322
323
Components are designed to be composed together for complete caption functionality:
324
325
```typescript
326
import {
327
Caption,
328
CaptionTextarea,
329
useCaptionButton,
330
useCaptionButtonState
331
} from "@udecode/plate-caption/react";
332
333
function MediaWithCaption({ src, alt }: { src: string; alt: string }) {
334
const buttonState = useCaptionButtonState();
335
const { props: buttonProps } = useCaptionButton(buttonState);
336
337
return (
338
<figure>
339
<img src={src} alt={alt} />
340
<Caption>
341
<CaptionTextarea placeholder="Add a caption..." />
342
</Caption>
343
<button {...buttonProps} className="add-caption-btn">
344
๐ Add Caption
345
</button>
346
</figure>
347
);
348
}
349
```
350
351
## Styling and Customization
352
353
All components are unstyled primitives that accept standard HTML props and can be fully customized:
354
355
```typescript
356
// CSS-in-JS styling
357
const StyledCaption = styled(Caption)`
358
font-style: italic;
359
color: #666;
360
text-align: center;
361
margin-top: 8px;
362
`;
363
364
// Tailwind classes
365
<Caption className="text-sm text-gray-600 italic text-center">
366
<CaptionTextarea className="w-full border rounded p-2" />
367
</Caption>
368
369
// Inline styles
370
<Caption style={{ fontFamily: 'Georgia, serif' }}>
371
<CaptionTextarea style={{ backgroundColor: '#f9f9f9' }} />
372
</Caption>
373
```