Primitive React components and hooks for implementing caption functionality in Plate rich-text editors.
—
React components provide the UI layer for caption functionality with primitive, unstyled components that can be fully customized and themed.
React-compatible version of BaseCaptionPlugin for use in React Plate editors.
/**
* React plugin wrapper for caption functionality
*/
const CaptionPlugin = toPlatePlugin(BaseCaptionPlugin);Usage Examples:
import { createPlateEditor } from "@udecode/plate/react";
import { CaptionPlugin } from "@udecode/plate-caption/react";
const editor = createPlateEditor({
plugins: [
CaptionPlugin.configure({
options: {
query: { allow: ['img', 'media'] }
}
})
]
});Main caption container component that renders as a figcaption element with visibility and state management.
/**
* Caption container component
* @param props - Standard figcaption props plus caption options
* @returns JSX.Element or null if hidden
*/
function Caption(props: CaptionProps): JSX.Element;
interface CaptionProps extends React.ComponentPropsWithoutRef<'figcaption'> {
options?: CaptionOptions;
}
interface CaptionOptions {
readOnly?: boolean;
}
/**
* State hook for Caption component
* @param options - Caption configuration options
* @returns State object with caption data and visibility flags
*/
function useCaptionState(options?: CaptionOptions): {
captionString: string;
hidden: boolean;
readOnly: boolean;
selected: boolean;
};
/**
* Props hook for Caption component
* @param state - State from useCaptionState
* @returns Props object for caption element
*/
function useCaption(state: ReturnType<typeof useCaptionState>): {
hidden: boolean;
};Usage Examples:
import { Caption } from "@udecode/plate-caption/react";
// Basic usage
function ImageWithCaption() {
return (
<div>
<img src="example.jpg" />
<Caption className="image-caption">
Caption content here
</Caption>
</div>
);
}
// With read-only option
function ReadOnlyCaption() {
return (
<Caption options={{ readOnly: true }}>
This caption cannot be edited
</Caption>
);
}
// Custom styling
function StyledCaption() {
return (
<Caption
style={{ fontStyle: 'italic', color: '#666' }}
className="custom-caption"
>
Styled caption content
</Caption>
);
}Editable textarea component for caption text with auto-resizing, focus management, and keyboard navigation.
/**
* Auto-resizing textarea for caption editing
* @param props - TextareaAutosize props
* @returns JSX.Element
*/
function CaptionTextarea(
props: React.ComponentProps<typeof TextareaAutosize>
): JSX.Element;
/**
* State hook for CaptionTextarea component
* @returns State object with handlers and refs
*/
function useCaptionTextareaState(): {
captionValue: string;
element: TCaptionElement;
readOnly: boolean;
textareaRef: React.RefObject<HTMLTextAreaElement>;
handleChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
handleCompositionEnd: (e: React.CompositionEvent<HTMLTextAreaElement>) => void;
handleCompositionStart: () => void;
};
/**
* Props hook for CaptionTextarea component
* @param state - State from useCaptionTextareaState
* @returns Props and ref for textarea element
*/
function useCaptionTextarea(
state: ReturnType<typeof useCaptionTextareaState>
): {
props: {
readOnly: boolean;
value: string;
onBlur: (e: React.FocusEvent<HTMLTextAreaElement>) => void;
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
onCompositionEnd: (e: React.CompositionEvent<HTMLTextAreaElement>) => void;
onCompositionStart: () => void;
onKeyDown: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
};
ref: React.RefObject<HTMLTextAreaElement>;
};
/**
* Focus management hook for caption textarea
* @param textareaRef - Ref to textarea element
*/
function useCaptionTextareaFocus(
textareaRef: React.RefObject<HTMLTextAreaElement | null>
): void;Key Features:
Usage Examples:
import { CaptionTextarea } from "@udecode/plate-caption/react";
// Basic usage
function EditableCaption() {
return (
<CaptionTextarea
placeholder="Enter image caption..."
className="caption-input"
/>
);
}
// With custom props
function CustomCaption() {
return (
<CaptionTextarea
placeholder="Describe this image..."
maxRows={3}
style={{
border: '1px solid #ccc',
borderRadius: '4px',
padding: '8px'
}}
/>
);
}
// In combination with Caption container
function CompleteCaption() {
return (
<Caption>
<CaptionTextarea placeholder="Add caption..." />
</Caption>
);
}Auto-resizing textarea primitive with SSR compatibility.
/**
* Auto-resizing textarea component
* @param props - Standard textarea props plus autosize options
* @param ref - Ref to textarea element
* @returns JSX.Element or null during SSR
*/
const TextareaAutosize = React.forwardRef<
HTMLTextAreaElement,
TextareaAutosizeProps
>((props, ref) => JSX.Element);
interface TextareaAutosizeProps {
maxRows?: number;
minRows?: number;
onHeightChange?: (height: number, meta: { rowHeight: number }) => void;
cacheMeasurements?: boolean;
[key: string]: any; // Standard textarea props
}Usage Examples:
import { TextareaAutosize } from "@udecode/plate-caption/react";
// Basic auto-resize textarea
function AutoTextarea() {
return (
<TextareaAutosize
placeholder="Type here..."
minRows={2}
maxRows={8}
/>
);
}
// With height change callback
function MonitoredTextarea() {
const handleHeightChange = (height: number) => {
console.log('Textarea height changed to:', height);
};
return (
<TextareaAutosize
onHeightChange={handleHeightChange}
placeholder="Resizing textarea..."
/>
);
}Utility components for caption interaction buttons.
/**
* State hook for caption button functionality
* @returns State with editor and element references
*/
function useCaptionButtonState(): {
editor: SlateEditor;
element: TElement;
};
/**
* Props hook for caption button
* @param state - State from useCaptionButtonState
* @returns Props with click handler
*/
function useCaptionButton(
state: ReturnType<typeof useCaptionButtonState>
): {
props: {
onClick: () => void;
};
};Usage Examples:
import { useCaptionButton, useCaptionButtonState } from "@udecode/plate-caption/react";
function CaptionToggleButton() {
const state = useCaptionButtonState();
const { props } = useCaptionButton(state);
return (
<button {...props} className="caption-toggle">
Add Caption
</button>
);
}Components are designed to be composed together for complete caption functionality:
import {
Caption,
CaptionTextarea,
useCaptionButton,
useCaptionButtonState
} from "@udecode/plate-caption/react";
function MediaWithCaption({ src, alt }: { src: string; alt: string }) {
const buttonState = useCaptionButtonState();
const { props: buttonProps } = useCaptionButton(buttonState);
return (
<figure>
<img src={src} alt={alt} />
<Caption>
<CaptionTextarea placeholder="Add a caption..." />
</Caption>
<button {...buttonProps} className="add-caption-btn">
📝 Add Caption
</button>
</figure>
);
}All components are unstyled primitives that accept standard HTML props and can be fully customized:
// CSS-in-JS styling
const StyledCaption = styled(Caption)`
font-style: italic;
color: #666;
text-align: center;
margin-top: 8px;
`;
// Tailwind classes
<Caption className="text-sm text-gray-600 italic text-center">
<CaptionTextarea className="w-full border rounded p-2" />
</Caption>
// Inline styles
<Caption style={{ fontFamily: 'Georgia, serif' }}>
<CaptionTextarea style={{ backgroundColor: '#f9f9f9' }} />
</Caption>Install with Tessl CLI
npx tessl i tessl/npm-udecode--plate-caption