
Syncfusion React Notifications
- 339 installs
- 3 repo stars
- Updated July 28, 2026
- syncfusion/react-ui-components-skills
Use syncfusion-react-notifications for development tasks
About
syncfusion-react-notifications: A skill for development. This provides functionality for development workflows.
- syncfusion-react-notifications
Syncfusion React Notifications by the numbers
- 339 all-time installs (skills.sh)
- +22 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #1,186 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/react-ui-components-skills --skill syncfusion-react-notificationsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 339 |
|---|---|
| repo stars | ★ 3 |
| Last updated | July 28, 2026 |
| Repository | syncfusion/react-ui-components-skills ↗ |
What it does
Use syncfusion-react-notifications for development tasks
Files
Implementing Syncfusion React Notifications
Toast
The Syncfusion React Toast component displays brief, non-intrusive notifications that auto-dismiss after a configurable timeout. Toasts support rich content through templates, action buttons, animated entry/exit, precise positioning, and programmatic control via ToastUtility.
🛑 Agentic use: Do not execute multiple steps autonomously. Confirm with the user before each action (install, run, file creation).
Package and Setup
📄 Read: references/getting-started.md
- Installing
@syncfusion/ej2-react-notifications🛑 STOP — Do not install packages autonomously. Ask the user to run: `npm install @syncfusion/ej2-react-notifications@33.x.x --save`. Verify with `npm audit` - CSS imports for all required themes
- Basic
ToastComponentusage (class and functional patterns) - Rendering toast in a custom target container
- Triggering show in the
createdevent
Documentation and Navigation Guide
Configuration and Layout
📄 Read: references/configuration.md
- Setting
titleandcontent(plain text, HTML, elements) - Custom
targetcontainer for scoped notifications showCloseButtonfor manual dismissalshowProgressBarandprogressDirection(Ltr / Rtl)newestOnTopstacking orderwidthandheightdimensions (px, %, auto)
Positioning
📄 Read: references/position.md
- Nine predefined X/Y positions (Left, Center, Right / Top, Bottom)
- Custom pixel and percentage coordinates
- Targeting a container element for relative positioning
- Multiple Toast instances at different screen positions
Timeout and Dismissal
📄 Read: references/timeout-and-dismissal.md
timeOutproperty (default 5000 ms)extendedTimeouton hover (default 1000 ms)- Static persistent toasts with
timeOut: 0 - Click-to-close via
clickToClosein theclickevent - Preventing mobile swipe dismissal with
beforeClose
Templates and Styling
📄 Read: references/templates-and-styling.md
templateproperty with HTML strings and DOM selectors- Dynamic templates passed at
show()call time - Semantic CSS classes:
e-toast-success,e-toast-info,e-toast-warning,e-toast-danger - CSS selectors for title, content, icon, and background customization
Animation
📄 Read: references/animation.md
animationproperty withshowandhideeffect settings- Available effects: FadeIn, FadeZoomIn, SlideBottomIn, ZoomIn, FlipLeftUpIn, and more
- Default: FadeIn / FadeOut
- Accessibility: reduced-motion considerations
Toast Services and Advanced Patterns
📄 Read: references/toast-services.md
ToastUtility.show()for quick toasts without component instantiation- Four predefined types:
Information,Success,Error,Warning - Passing a full
ToastModeltoToastUtility.show() - Playing audio on
beforeOpen - Restricting maximum simultaneous toasts with
beforeOpen - Preventing duplicate toasts using
beforeOpen+close
Accessibility
📄 Read: references/accessibility.md
- WAI-ARIA:
role="alert",aria-live="assertive",aria-label - WCAG 2.2, Section 508, ADA compliance
- Screen reader support (JAWS, NVDA, VoiceOver)
- RTL support via
enableRtl - Mobile and accessibility checker validation
API Reference
📄 Read: references/api.md
- All properties with types, defaults, and descriptions
show()andhide()method signatures- All events:
beforeOpen,open,click,beforeClose,close,created,destroyed,beforeSanitizeHtml
Quick Start Example
🛑 STOP — Do not start the dev server autonomously. Ask the user to run: `npm run dev` after setup.
import { ToastComponent } from '@syncfusion/ej2-react-notifications';
import '@syncfusion/ej2-base/styles/tailwind3.css';
import '@syncfusion/ej2-react-notifications/styles/tailwind3.css';
import { useRef } from 'react';
function App() {
const toastRef = useRef<ToastComponent>(null);
return (
<>
<button onClick={() => toastRef.current?.show()}>Show Toast</button>
<ToastComponent
ref={toastRef}
title="Success!"
content="Your changes have been saved."
cssClass="e-toast-success"
position={{ X: 'Right', Y: 'Bottom' }}
timeOut={4000}
showProgressBar={true}
showCloseButton={true}
/>
</>
);
}Quick Utility Toast (No Component Needed)
import { ToastUtility } from '@syncfusion/ej2-react-notifications';
// Show a success toast instantly
ToastUtility.show('File saved successfully', 'Success', 3000);
// Show an error toast
ToastUtility.show('Connection failed', 'Error', 5000);Common Patterns
Semantic type toasts
Use cssClass with e-toast-success, e-toast-info, e-toast-warning, e-toast-danger for visual differentiation — see references/templates-and-styling.md.
Static/persistent toasts
Set timeOut: 0 with showCloseButton: true for notifications users must explicitly dismiss — see references/timeout-and-dismissal.md.
Action-required toasts
Use the buttons property to add Ignore/Confirm/Undo buttons — see references/configuration.md.
Prevent duplicates
Use the beforeOpen event to cancel duplicate toasts already on screen — see references/toast-services.md.
Limit max visible toasts
Cap simultaneous toasts at N using beforeOpen and element.childElementCount — see references/toast-services.md.
Message
The Syncfusion MessageComponent displays contextual messages with visual severity indicators—icons and colors—to communicate importance and context to end users. It supports five severity levels, three visual variants, close-icon dismissal, custom templates, and full accessibility compliance.
🛑 Agentic use: Do not execute multiple steps autonomously. Confirm with the user before each action (install, run, file creation).
Navigation Guide
Getting Started
📄 Read: references/message-getting-started.md
- Installation of
@syncfusion/ej2-react-notifications🛑 STOP — Do not install packages autonomously. Ask the user to run: `npm install @syncfusion/ej2-react-notifications@33.x.x --save`. Verify with `npm audit` - CSS imports and theme configuration
- Rendering the first
MessageComponent - Content via
contentprop or JSX children - Running the Vite development server
Severity Levels
📄 Read: references/message-severities.md
- Five severity levels: Normal, Success, Info, Warning, Error
severityprop usage and valid values- Visual distinctions (icons and colors per severity)
- Choosing the right severity for your use case
Display Variants
📄 Read: references/message-variants.md
- Three variants: Text (default), Outlined, Filled
variantprop usage- Combining variant with severity
- Visual trade-offs and when to use each
Icons and Close Icon
📄 Read: references/message-icons-and-close.md
- Severity icon visibility:
showIconprop (defaulttrue) - Disabling severity icons
- Custom severity icons via
cssClassCSS overrides - Close icon:
showCloseIconprop (defaultfalse) closedevent handler for dismiss callbacks- Toggling visibility with the
visibleprop
Customization and Templates
📄 Read: references/message-customization.md
- Content alignment: left (default), center (
e-content-center), right (e-content-right) - Custom appearance with
cssClass - CSS-only message rendering (no JS, pure HTML + CSS)
- Content templates: JSX element or render function via
contentprop - RTL support via
enableRtl - Persistence with
enablePersistence
Accessibility
📄 Read: references/message-accessibility.md
- WCAG 2.2, Section 508, ADA compliance
- WAI-ARIA attributes (
role=alert,aria-label) - Keyboard navigation (Tab, Enter/Space)
- Screen reader support
API Reference
📄 Read: references/message-api.md
- All properties with types, defaults, and descriptions
- Methods:
destroy,getPersistData - Events:
closed,created,destroyed MessageCloseEventArgsinterfaceSeverityandVariantenum values
---
Quick Start
🛑 STOP — Do not start the dev server autonomously. Ask the user to run: `npm run dev` after setup.
npm install @syncfusion/ej2-react-notifications@33.x.x --save
npm audit/* src/App.css */
@import '../node_modules/@syncfusion/ej2-base/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-react-notifications/styles/tailwind3.css';import { MessageComponent } from '@syncfusion/ej2-react-notifications';
import './App.css';
function App() {
return (
<MessageComponent content="Please read the comments carefully" />
);
}
export default App;---
Common Patterns
Severity Messages
<MessageComponent content="Editing is restricted" />
<MessageComponent content="Operation completed" severity="Success" />
<MessageComponent content="Read these notes" severity="Info" />
<MessageComponent content="Check your connection" severity="Warning" />
<MessageComponent content="Submission failed" severity="Error" />Variant + Severity Combo
<MessageComponent content="Editing is restricted" variant="Filled" />
<MessageComponent content="Operation completed" severity="Success" variant="Outlined" />
<MessageComponent content="Submission failed" severity="Error" variant="Filled" />Dismissible Message
import { useState } from 'react';
function App() {
const [visible, setVisible] = useState(true);
return (
<MessageComponent
content="Your session will expire soon"
severity="Warning"
showCloseIcon={true}
visible={visible}
closed={() => setVisible(false)}
/>
);
}Content Template
const contentTemplate = () => (
<div>
<h4>Build succeeded</h4>
<p>All 42 tests passed.</p>
</div>
);
<MessageComponent content={contentTemplate} severity="Success" />---
Skeleton
The Syncfusion React SkeletonComponent renders animated placeholder shapes that mimic the layout of loading content. It reduces perceived load time and communicates progress to users with configurable shapes, shimmer animations, and full accessibility support.
Package: @syncfusion/ej2-react-notifications
🛑 Agentic use: Do not execute multiple steps autonomously. Confirm with the user before each action (install, run, file creation).
---
Navigation Guide
Getting Started
📄 Read: references/skeleton-getting-started.md
- Installing
@syncfusion/ej2-react-notifications🛑 STOP — Do not install packages autonomously. Ask the user to run: `npm install @syncfusion/ej2-react-notifications@33.x.x --save`. Verify with `npm audit` - CSS theme imports (tailwind3)
- Minimal
SkeletonComponentsetup withheightandwidth - Running the Vite/React app
Shapes
📄 Read: references/skeleton-shapes.md
shapeprop:"Circle","Square","Rectangle","Text"(default)- Dimension rules: width required for Circle/Square; width + height for Rectangle/Text
- Building multi-shape card skeleton layouts
- Choosing the right shape for avatar, image, text, and icon placeholders
Shimmer Effects
📄 Read: references/skeleton-shimmer-effect.md
shimmerEffectprop:"Wave"(default),"Pulse","Fade"- Visual behavior of each effect type
- List skeleton example with Pulse effect
- Selecting an effect to match UI context
Styles and Visibility
📄 Read: references/skeleton-styles.md
cssClassprop for custom CSS overrides (wave color, background, animation speed)visibleprop to toggle skeleton on/off based on loading state- Transition pattern: skeleton → actual content
- CSS variable customization
Accessibility
📄 Read: references/skeleton-accessibility.md
- WCAG 2.2, Section 508, ADA compliance
- WAI-ARIA attributes:
role="status",aria-label,aria-live,aria-busy labelprop for accessible skeleton names- RTL support via
enableRtl prefers-reduced-motionrespect
API Reference
📄 Read: references/skeleton-api.md
- All properties:
cssClass,enablePersistence,enableRtl,height,label,locale,shape,shimmerEffect,visible,width - Methods:
destroy() SkeletonTypeandShimmerEffectenum values
---
Quick Start
🛑 STOP — Do not start the dev server autonomously. Ask the user to run: `npm run dev` after setup.
npm install @syncfusion/ej2-react-notifications@33.x.x --save
npm audit/* src/App.css */
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-notifications/styles/tailwind3.css";import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
import './App.css';
function App() {
return (
<SkeletonComponent height="15px" width="100%" />
);
}
export default App;---
Common Patterns
Profile Card Skeleton
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function ProfileCardSkeleton() {
return (
<div style={{ display: 'flex', alignItems: 'center', gap: '12px', padding: '16px' }}>
{/* Avatar placeholder */}
<SkeletonComponent shape="Circle" width="48px" />
{/* Name and subtitle placeholders */}
<div style={{ flex: 1 }}>
<SkeletonComponent width="60%" height="15px" />
<br />
<SkeletonComponent width="40%" height="12px" />
</div>
</div>
);
}
export default ProfileCardSkeleton;Toggle Skeleton on Data Load
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function DataCard() {
const [loading, setLoading] = React.useState(true);
const [content, setContent] = React.useState('');
React.useEffect(() => {
setTimeout(() => {
setContent('Data loaded successfully');
setLoading(false);
}, 2000);
}, []);
return (
<div>
{loading ? (
<SkeletonComponent width="80%" height="20px" />
) : (
<p>{content}</p>
)}
</div>
);
}
export default DataCard;Shimmer List with Pulse Effect
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function ListSkeleton() {
return (
<ul style={{ listStyle: 'none', padding: 0 }}>
{[1, 2, 3].map((i) => (
<li key={i} style={{ display: 'flex', gap: '10px', marginBottom: '12px' }}>
<SkeletonComponent shape="Circle" width="40px" shimmerEffect="Pulse" />
<div style={{ flex: 1 }}>
<SkeletonComponent width="70%" height="14px" shimmerEffect="Pulse" />
<br />
<SkeletonComponent width="45%" height="12px" shimmerEffect="Pulse" />
</div>
</li>
))}
</ul>
);
}
export default ListSkeleton;---
Key Props at a Glance
| Prop | Type | Default | Purpose |
|---|---|---|---|
shape | `'Text' \ | 'Circle' \ | 'Square' \ |
width | `string \ | number` | '' |
height | `string \ | number` | '' |
shimmerEffect | `'Wave' \ | 'Pulse' \ | 'Fade'` |
visible | boolean | true | Show/hide skeleton |
cssClass | string | '' | Custom CSS class(es) |
label | string | 'Loading…' | ARIA label for accessibility |
enableRtl | boolean | false | Right-to-left rendering |
enablePersistence | boolean | false | Persist state across reloads |
---
Spinner
A skill for implementing the Syncfusion React Spinner — a load indicator that blocks user interaction with a target element while an operation is in progress.
🛑 Agentic use: Do not execute multiple steps autonomously. Confirm with the user before each action (install, run, file creation).
Documentation
Getting Started
📄 Read: references/spinner-getting-started.md
- Installation: 🛑 STOP — Do not install packages autonomously. Ask the user to run: `npm install @syncfusion/ej2-react-popups@33.x.x --save`. Verify with `npm audit`
- CSS theme imports (ej2-base + ej2-react-popups)
- Basic functional and class component patterns
createSpinner→showSpinnerworkflow- Show/hide control
- Full-page overlay spinner
- Troubleshooting missing styles and TypeScript errors
Spinner Features
📄 Read: references/spinner-features.md
- Global spinner configuration with
setSpinner - All
SpinnerTypevalues (Material, Bootstrap5, Fluent2, etc.) - Spinner size via
widthproperty - Label text alongside spinner
- Custom HTML template support
- Show/hide toggle patterns
- Multiple spinners on one page
- Async data fetching with
finallycleanup - React state + spinner synchronization
- Spinner inside cards and modals
API Reference
📄 Read: references/spinner-api.md
createSpinner(args: SpinnerArgs)— full signature and paramsshowSpinner(container: HTMLElement)— signaturehideSpinner(container: HTMLElement)— signaturesetSpinner(args: SetSpinnerArgs)— signatureSpinnerArgsinterface (target, width, label, cssClass, template, type)SetSpinnerArgsinterface (template, cssClass, type)- All 11
SpinnerTypevalues - CSS import paths per theme
- Common invalid API gotchas
Customization
📄 Read: references/spinner-customization.md
cssClassfor CSS hook customizationwidthfor spinner icon sizingtemplatefor custom HTML animationssetSpinnerfor global defaults- Overriding spinner colors via CSS
- Label positioning with CSS
- Overlay backdrop customization
- Theme-specific type mapping
- Responsive spinner patterns
Accessibility
📄 Read: references/spinner-accessibility.md
aria-busyon the loading regionaria-liveregion for screen reader announcementstype: 'HighContrast'for high contrast displays- Keyboard accessibility (trigger focus, return focus)
- Focus management patterns
- Complete accessible spinner pattern
- WCAG 2.1 compliance checklist
Quick Start
Minimal Spinner (Functional Component)
🛑 STOP — Do not start the dev server autonomously. Ask the user to run: `npm run dev` after setup.
import { createSpinner, showSpinner } from '@syncfusion/ej2-react-popups';
import * as React from 'react';
import { useEffect } from 'react';
import './App.css';
function App() {
useEffect(() => {
createSpinner({
target: document.getElementById('container') as HTMLElement
});
showSpinner(document.getElementById('container') as HTMLElement);
}, []);
return (
<div id="container" style={{ height: '200px' }} />
);
}
export default App;Spinner with Show/Hide Toggle
import { createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-react-popups';
import { useEffect, useRef, useState } from 'react';
function DataLoader() {
const ref = useRef<HTMLDivElement>(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (ref.current) {
createSpinner({ target: ref.current, label: 'Loading...' });
}
}, []);
const load = async () => {
setLoading(true);
showSpinner(ref.current as HTMLElement);
try {
await fetchData();
} finally {
hideSpinner(ref.current as HTMLElement);
setLoading(false);
}
};
return (
<div>
<button onClick={load} disabled={loading}>Load Data</button>
<div ref={ref} style={{ height: '200px', position: 'relative' }} />
</div>
);
}Global Spinner Type
import { setSpinner } from '@syncfusion/ej2-react-popups';
// Call BEFORE any createSpinner — sets global default type
setSpinner({ type: 'Bootstrap5' });Common Patterns
Pattern 1: Async Fetch with Cleanup
const fetchWithSpinner = async (container: HTMLElement) => {
showSpinner(container);
try {
const data = await fetch('/api/data').then(r => r.json());
return data;
} finally {
hideSpinner(container); // Always hide, even on error
}
};Pattern 2: React State Sync
useEffect(() => {
if (!ref.current) return;
if (isLoading) {
showSpinner(ref.current);
} else {
hideSpinner(ref.current);
}
}, [isLoading]);Pattern 3: Full-Page Loading
useEffect(() => {
createSpinner({ target: document.body, label: 'Initializing...' });
showSpinner(document.body);
initializeApp().finally(() => hideSpinner(document.body));
}, []);Pattern 4: Spinner with Custom Type
createSpinner({
target: el,
type: 'Fluent2',
width: '40px',
label: 'Processing...',
cssClass: 'my-overlay'
});Key API Quick Reference
| Function | Signature | Purpose |
|---|---|---|
createSpinner | (args: SpinnerArgs) => void | Initialize spinner on DOM element |
showSpinner | (el: HTMLElement) => void | Show an existing spinner |
hideSpinner | (el: HTMLElement) => void | Hide a visible spinner |
setSpinner | (args: SetSpinnerArgs) => void | Set global defaults for all spinners |
SpinnerArgs properties: target (required), width, label, cssClass, template, type
SpinnerType values: 'Material' | 'Material3' | 'Fabric' | 'Bootstrap' | 'Bootstrap4' | 'Bootstrap5' | 'HighContrast' | 'Tailwind' | 'Tailwind3' | 'Fluent' | 'Fluent2'
Critical Rules
- ❌ No `SpinnerComponent` class —
import { SpinnerComponent }does NOT exist - ✅ Only use:
createSpinner,showSpinner,hideSpinner,setSpinner - ❌ Do NOT use:
color,size,visible,isLoadingas SpinnerArgs — they don't exist - ✅ Valid SpinnerArgs:
target,width,label,cssClass,template,type - ⚠️ Call `createSpinner` BEFORE `showSpinner` — order matters
- ⚠️ Put spinner logic in `useEffect` — the DOM element must exist before calling createSpinner
- ✅ Always call `hideSpinner` in `finally` — prevents stuck loading states
Troubleshooting
| Issue | Solution |
|---|---|
| Spinner not showing | Ensure createSpinner is called before showSpinner; check DOM element exists |
| Spinner stays visible | Call hideSpinner in finally block; check for unhandled promise rejections |
| No animation | Verify both ej2-base and ej2-react-popups CSS imported; ej2-base must come first |
| TypeScript error | Cast: document.getElementById('id') as HTMLElement or use useRef<HTMLDivElement> |
| Spinner outside bounds | Add position: relative to target element |
| Wrong theme | Set type to match your app's CSS theme (e.g., 'Fluent2' for Fluent 2 CSS) |
Related Components
- Progress Bar — For determinate progress with a percentage
- Skeleton — For content placeholder/shimmer loading patterns
- Toast — For non-blocking loading notifications
- Dialog — For modal loading states that require user acknowledgment
Resources
- Official Docs: https://ej2.syncfusion.com/react/documentation/spinner/
- Getting Started: https://ej2.syncfusion.com/react/documentation/spinner/getting-started
- npm Package: @syncfusion/ej2-react-popups
Badge
The Syncfusion React Badge is a pure CSS component — no React component class to import. Badges are applied by adding CSS modifier classes to a <span> (or <a>) element nested inside the target UI element.
Package: @syncfusion/ej2-react-notifications
🛑 Agentic use: Do not execute multiple steps autonomously. Confirm with the user before each action (install, run, file creation).
Key Features
- 8 color variants — primary, secondary, success, danger, warning, info, light, dark
- Shape types — circle, pill, link, notification, dot, overlap
- Positioning — top (default) and bottom placement on parent elements
- Customization — custom colors, sizes, and arbitrary positions via CSS
- ListView integration — embed badges in list items with dynamic content
Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Package installation: 🛑 STOP — Do not install packages autonomously. Ask the user to run: `npm install @syncfusion/ej2-react-notifications@33.x.x --save`. Verify with `npm audit`
- Adding the first badge to a React component
- Minimal working example
- Running the application
Badge Types and Shapes
📄 Read: references/types-and-shapes.md
- 8 predefined color variants and their semantic purpose
- Circle, pill, link, notification, dot, overlap shape types
- Badge positioning (top vs bottom)
- When to combine modifier classes (e.g., overlap + notification + circle)
Customization
📄 Read: references/customization.md
- Custom color overrides with CSS classes
- Adjusting badge size via
font-size - Custom positioning (left-top, left-bottom) with CSS overrides
- When to use custom CSS vs built-in modifier classes
How-To Guides
📄 Read: references/how-to.md
- Integrate badges into a ListView component
- Update badge content dynamically (increment counts)
- React pattern for badge state management using DOM updates
Quick Start
1. Install the package:
npm install @syncfusion/ej2-react-notifications@33.x.x --save
npm audit2. Add CSS to `src/App.css`:
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-notifications/styles/tailwind3.css";3. Add a badge in your component:
import * as React from 'react';
import './App.css';
function App() {
return (
<h1>Badge Component <span className="e-badge e-badge-primary">New</span></h1>
);
}
export default App;Common Patterns
Notification badge on an icon
// Parent must have position: relative
<div className="badge-block">
<div className="skype svg_icons"></div>
<span className="e-badge e-badge-success e-badge-overlap e-badge-notification">99+</span>
</div>Dot status indicator (bottom position)
<div className="badge-block">
<div className="firefox svg_icons"></div>
<span className="e-badge e-badge-success e-badge-overlap e-badge-dot e-badge-bottom"></span>
</div>Pill-shaped label
<h1>Messages <span className="e-badge e-badge-primary e-badge-pill">New</span></h1>CSS Class Reference
| Class | Purpose |
|---|---|
e-badge | Required base class for all badges |
e-badge-primary / e-badge-{color} | Color variant |
e-badge-pill | Pill (rounded rectangle) shape |
e-badge-circle | Circle shape |
e-badge-notification | Notification counter badge |
e-badge-dot | Minimalist dot badge (no text) |
e-badge-overlap | Overlaps the parent element edge |
e-badge-bottom | Positions badge at bottom instead of top |
Badge Customization
Table of Contents
---
Color Customization
The Badge provides eight built-in color variants. When those don't match your design requirements, apply a custom CSS class to override the badge's background and text colors.
The pattern is to keep a built-in color class for the base styles and add your own class to override color properties:
import * as React from "react";
import * as ReactDOM from "react-dom";
function App() {
return (
<div>
<h1>Color Customization <span className="e-badge e-badge-primary e-badge-pill green">New</span></h1>
<h1>Color Customization <span className="e-badge e-badge-primary e-badge-pill bue">New</span></h1>
<h1>Color Customization <span className="e-badge e-badge-primary e-badge-pill purple">New</span></h1>
<h1>Color Customization <span className="e-badge e-badge-primary e-badge-pill gradient">New</span></h1>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));Define the custom classes in your CSS file:
/* Example custom color overrides */
.e-badge.green {
background-color: #4CAF50;
color: #fff;
}
.e-badge.purple {
background-color: #9C27B0;
color: #fff;
}
.e-badge.gradient {
background: linear-gradient(45deg, #f06, #48f);
color: #fff;
}Use specific selectors (e.g., .e-badge.green) to avoid conflicts with other elements.---
Size Customization
The Badge automatically scales with its text content. To explicitly control the badge size, change the font-size CSS property — the badge dimensions respond proportionally.
import * as React from "react";
import * as ReactDOM from "react-dom";
function App() {
return (
<div>
<h1>Badge Component <span className="e-badge e-badge-primary size_1">New</span></h1>
<h1>Badge Component <span className="e-badge e-badge-primary size_2">New</span></h1>
<h1>Badge Component <span className="e-badge e-badge-primary size_3">New</span></h1>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));Define size classes in your CSS:
.e-badge.size_1 {
font-size: 10px;
}
.e-badge.size_2 {
font-size: 14px;
}
.e-badge.size_3 {
font-size: 18px;
}Changing font-size is the recommended way to resize badges — the padding, border-radius, and line-height all scale relative to the font size.---
Custom Positioning
The built-in .e-badge-bottom class only supports top and bottom placement. For left-side or other arbitrary positions, apply a custom CSS class that overrides the badge's top, right, bottom, and left properties.
import * as React from "react";
import * as ReactDOM from "react-dom";
function App() {
return (
<div>
<div className="block">
{/* Left-top custom position */}
<div className="badge-block">
<div className="firefox svg_icons"></div>
<span className="e-badge e-badge-warning e-badge-notification e-badge-overlap leftTop">99+</span>
</div>
<div className="badge-block">
<div className="facebook svg_icons"></div>
<span className="e-badge e-badge-danger e-badge-notification e-badge-overlap leftTop">99+</span>
</div>
<div className="badge-block">
<div className="skype svg_icons"></div>
<span className="e-badge e-badge-secondary e-badge-notification e-badge-overlap leftTop">18</span>
</div>
</div>
<div className="badge-block">
{/* Left-bottom custom position */}
<div className="badge-block">
<div className="firefox svg_icons"></div>
<span className="e-badge e-badge-warning e-badge-notification e-badge-overlap leftBottom">99+</span>
</div>
<div className="badge-block">
<div className="facebook svg_icons"></div>
<span className="e-badge e-badge-danger e-badge-notification e-badge-overlap leftBottom">99+</span>
</div>
<div className="badge-block">
<div className="skype svg_icons"></div>
<span className="e-badge e-badge-secondary e-badge-notification e-badge-overlap leftBottom">18</span>
</div>
</div>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));Define the custom position classes in CSS:
/* Left-top position */
.e-badge.leftTop {
right: auto;
left: -10px;
top: -10px;
}
/* Left-bottom position */
.e-badge.leftBottom {
right: auto;
left: -10px;
top: auto;
bottom: -10px;
}Always keep.e-badge-overlapwhen using custom positions — it sets theposition: absoluteneeded for CSS coordinate overrides to work.
Getting Started with React Badge
The Syncfusion React Badge is a pure CSS component. There is no React component class — badges are rendered as plain HTML elements styled with CSS modifier classes.
Installation
Install the notifications package which bundles the Badge component:
npm install @syncfusion/ej2-react-notifications --saveThe--saveflag records the package in thedependenciessection ofpackage.json.
Setting Up a React Project
Create a new React + Vite project (recommended):
# TypeScript
npm create vite@latest my-app -- --template react-ts
cd my-app
npm run dev
# JavaScript
npm create vite@latest my-app -- --template react
cd my-app
npm run devAdding CSS References
Add the following imports to src/App.css:
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-notifications/styles/tailwind3.css";Then import App.css in src/App.tsx:
import './App.css';Adding Your First Badge
Badges attach to any inline element — typically a <span> nested inside a heading, button, or container. The only requirement is the base e-badge class plus a color variant class:
import * as React from "react";
import * as ReactDOM from "react-dom";
function App() {
return (
<h1>Badge Component <span className="e-badge e-badge-primary">New</span></h1>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));Running the Application
npm run devThe browser opens with your badge rendered inline inside the heading.
Key Points
- No component import needed — Badge is CSS-only; just add classes to a
<span>or<a>. - Always include `e-badge` as the base class alongside any modifier class.
- Parent positioning — For notification/dot/overlap badges, the parent container should have
position: relativeso the badge positions correctly.
How-To Guides
Table of Contents
---
Integrate Badge into ListView
Badges can be embedded directly in ListViewComponent item templates to display notification counts or status alongside list entries. The badge automatically scales to match the list item height — no manual size configuration is needed.
When to use: Email inboxes, notification panels, sidebar navigation with unread counts.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { ListViewComponent } from '@syncfusion/ej2-react-lists';
function App() {
// Each item carries a `badge` field holding the CSS classes, and a `messages` field for display text
let dataSource: { [key: string]: Object }[] = [
{ id: 'p_01', text: 'Primary', messages: '3 New', badge: 'e-badge e-badge-primary', icons: 'primary', type: 'Primary' },
{ id: 'p_02', text: 'Social', messages: '27 New', badge: 'e-badge e-badge-secondary', icons: 'social', type: 'Primary' },
{ id: 'p_03', text: 'Promotions', messages: '7 New', badge: 'e-badge e-badge-success', icons: 'promotion', type: 'Primary' },
{ id: 'p_04', text: 'Updates', messages: '13 New', badge: 'e-badge e-badge-info', icons: 'updates', type: 'Primary' },
{ id: 'p_05', text: 'Starred', messages: '', badge: '', icons: 'starred', type: 'All Labels' },
{ id: 'p_06', text: 'Important', messages: '2 New', badge: 'e-badge e-badge-danger', icons: 'important', type: 'All Labels' },
{ id: 'p_07', text: 'Sent', messages: '', badge: '', icons: 'sent', type: 'All Labels' },
{ id: 'p_08', text: 'Outbox', messages: '', badge: '', icons: 'outbox', type: 'All Labels' },
{ id: 'p_09', text: 'Drafts', messages: '7 New', badge: 'e-badge e-badge-warning', icons: 'draft', type: 'All Labels' },
];
let fields: object = { groupBy: 'type' };
function template(data: any): JSX.Element {
return (
<div className='listWrapper' style={{ width: 'inherit', height: 'inherit' }}>
<span className={`${data.icons} list_svg`}> </span>
<span className='list_text'>{data.text}</span>
<span className={`${data.badge}`} style={{ float: 'right', marginTop: '16px', fontSize: '12px' }}>
{data.messages}
</span>
</div>
);
}
function onActionComplete() {
let list: HTMLElement = document.getElementById('lists').getElementsByClassName('e-list-group-item')[0] as HTMLElement;
list.style.display = 'none';
}
return (
<div className="sample_container badge-list">
<ListViewComponent
id="lists"
dataSource={dataSource}
fields={fields}
headerTitle='Inbox'
showHeader={true}
template={template as any}
actionComplete={onActionComplete.bind(this)}
/>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));Key points:
- Store badge CSS classes in the data source (
badgefield) so each item controls its own badge color independently. - Items without a badge have an empty string for the
badgefield — the template renders nothing in that case. onActionCompletehides the first group header if not needed.- Install
@syncfusion/ej2-react-listsforListViewComponent:npm install @syncfusion/ej2-react-lists --save
---
Dynamic Badge Content
Many applications need badge counts that update in response to user actions or incoming data. Because Badge is CSS-only, update the badge text content directly via DOM queries rather than through a React state-driven re-render.
When to use: Inbox counters that increment on new messages, notification panels with live updates.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { ListViewComponent } from '@syncfusion/ej2-react-lists';
interface IBadgeValuesProps {
BadgeType: string;
BadgeContent: string;
}
function BadgePortable(props: IBadgeValuesProps) {
return (
<span
className={props.BadgeType}
style={{ float: 'right', marginTop: '16px', fontSize: '12px' }}
>
{props.BadgeContent} New
</span>
);
}
function App() {
let dataSource: { [key: string]: Object }[] = [
{ id: 'p_01', text: 'Primary', badge: 'e-badge e-badge-primary', icons: 'primary', type: 'Primary' },
{ id: 'p_02', text: 'Social', badge: 'e-badge e-badge-secondary', icons: 'social', type: 'Primary' },
{ id: 'p_03', text: 'Promotions', badge: 'e-badge e-badge-success', icons: 'promotion', type: 'Primary' },
{ id: 'p_04', text: 'Updates', badge: 'e-badge e-badge-info', icons: 'updates', type: 'Primary' },
{ id: 'p_05', text: 'Starred', badge: '', icons: 'starred', type: 'All Labels' },
{ id: 'p_06', text: 'Important', badge: 'e-badge e-badge-danger', icons: 'important', type: 'All Labels' },
{ id: 'p_07', text: 'Sent', badge: '', icons: 'sent', type: 'All Labels' },
{ id: 'p_08', text: 'Outbox', badge: '', icons: 'outbox', type: 'All Labels' },
{ id: 'p_09', text: 'Drafts', badge: 'e-badge e-badge-warning', icons: 'draft', type: 'All Labels' },
];
let fields: object = { groupBy: 'type' };
// Initial badge values mapped by list item text
let Values: { [key: string]: number } = {
Primary: 3,
Social: 27,
Promotions: 7,
Updates: 13,
Drafts: 7,
Important: 2
};
function listTemplate(data: any): JSX.Element {
return (
<div className='listWrapper' style={{ width: 'inherit', height: 'inherit' }}>
<span className={`${data.icons} list_svg`}> </span>
<span className='list_text'>{data.text}</span>
{data.badge !== '' ?
<BadgePortable BadgeContent={Values[data.text]} BadgeType={data.badge} /> : ''
}
</div>
);
}
// Increment all badge counts by querying the DOM directly
function onClick(): void {
let badgeElements = Array.prototype.slice.call(
document.getElementById('lists').getElementsByClassName('e-badge')
);
badgeElements.forEach((element) => {
element.textContent = (Number(element.textContent.split(' ')[0])) + 1 + ' New';
});
}
return (
<div className="sample_container badge-list">
<ListViewComponent
id="lists"
dataSource={dataSource}
fields={fields}
headerTitle='Inbox'
showHeader={true}
template={listTemplate.bind(this) as any}
/>
<p className='crossline'></p>
<span className='incr_button'>
<button className='e-btn e-primary' onClick={onClick.bind(this)}>Increment Badge Count</button>
</span>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));Key points:
- Badge text follows the pattern
"{count} New"— the increment splits on the space and parses the number. getElementsByClassName('e-badge')selects all badge elements within the list container by ID (lists).- The
BadgePortablesub-component keeps badge rendering isolated and reusable across list items. - For real-time updates (WebSockets, polling), call the same DOM-update logic inside your data handler instead of the button
onClick.
Badge Types and Shapes
Table of Contents
- Color Variants
- Shape Types
- Circle
- Pill
- Link
- Notification
- Dot
- Overlap
- Badge Positioning
- Combining Modifier Classes
---
Color Variants
The Badge component provides eight predefined color variants. Each carries a semantic meaning to communicate intent to users:
| Class | Purpose |
|---|---|
e-badge-primary | General notifications, default state |
e-badge-secondary | Supplementary or secondary information |
e-badge-success | Positive outcomes, confirmations |
e-badge-danger | Errors, critical issues requiring attention |
e-badge-warning | Caution, items needing review |
e-badge-info | Informational messages or guidance |
e-badge-light | Subtle indicators on dark backgrounds |
e-badge-dark | Prominent indicators on light backgrounds |
import * as React from "react";
import * as ReactDOM from "react-dom";
function App() {
return (
<div className="sample_container">
<div className="block">
<div className="e-card e-badge-showcase">
<div className="e-card-content">
<div><span className="e-badge e-badge-primary">Primary</span></div>
</div>
<div className="e-card-content">
<div><code>.e-badge-primary</code></div>
</div>
</div>
</div>
{/* Repeat pattern for secondary, success, danger, warning, info, light, dark */}
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));---
Shape Types
Circle
Apply .e-badge-circle to render a circular badge. Typically combined with .e-badge-notification and .e-badge-overlap for icon overlays.
import * as React from "react";
import * as ReactDOM from "react-dom";
function App() {
return (
<div>
<div className="badge-block">
<div className="skype svg_icons"></div>
<span className="e-badge e-badge-success e-badge-overlap e-badge-notification e-badge-circle">18</span>
</div>
<div className="badge-block">
<div className="twitter svg_icons"></div>
<span className="e-badge e-badge-info e-badge-overlap e-badge-notification e-badge-circle">9</span>
</div>
<div className="badge-block">
<div className="facebook svg_icons"></div>
<span className="e-badge e-badge-info e-badge-overlap e-badge-notification e-badge-circle">2</span>
</div>
<div className="badge-block">
<div className="firefox svg_icons"></div>
<span className="e-badge e-badge-danger e-badge-overlap e-badge-notification e-badge-circle">35</span>
</div>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));---
Pill
Apply .e-badge-pill for a rounded-rectangle (pill) shape — ideal for text labels and "New" indicators.
import * as React from "react";
import * as ReactDOM from "react-dom";
function App() {
return (
<h1>Badge Component <span className="e-badge e-badge-primary e-badge-pill">New</span></h1>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));---
Link
When badge classes are applied to an <a> tag, the badge gains hover state styling automatically.
import * as React from "react";
import * as ReactDOM from "react-dom";
function App() {
return (
<div className="badge-block">
<a href="#" className="e-badge e-badge-primary">Link Badge</a>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));---
Notification
Apply .e-badge-notification to create a counter badge. Use for alert counts and status changes that need immediate attention.
Note: Ensure the parent element has position: relative for correct placement.import * as React from "react";
import * as ReactDOM from "react-dom";
function App() {
return (
<div>
<div className="badge-block">
<div className="skype svg_icons"></div>
<span className="e-badge e-badge-success e-badge-overlap e-badge-notification">99+</span>
</div>
<div className="badge-block">
<div className="twitter svg_icons"></div>
<span className="e-badge e-badge-info e-badge-overlap e-badge-notification">27</span>
</div>
<div className="badge-block">
<div className="facebook svg_icons"></div>
<span className="e-badge e-badge-info e-badge-overlap e-badge-notification">2</span>
</div>
<div className="badge-block">
<div className="firefox svg_icons"></div>
<span className="e-badge e-badge-danger e-badge-overlap e-badge-notification">35</span>
</div>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));---
Dot
Apply .e-badge-dot to render a small dot with no text content — ideal for presence/availability indicators.
Note: Leave the<span>empty. Set the parent toposition: relative.
import * as React from "react";
import * as ReactDOM from "react-dom";
function App() {
return (
<div>
<div className="badge-block">
<div className="skype svg_icons"></div>
<span className="e-badge e-badge-success e-badge-overlap e-badge-dot"></span>
</div>
<div className="badge-block">
<div className="twitter svg_icons"></div>
<span className="e-badge e-badge-info e-badge-overlap e-badge-dot"></span>
</div>
<div className="badge-block">
<div className="facebook svg_icons"></div>
<span className="e-badge e-badge-info e-badge-overlap e-badge-dot"></span>
</div>
<div className="badge-block">
<div className="firefox svg_icons"></div>
<span className="e-badge e-badge-danger e-badge-overlap e-badge-dot"></span>
</div>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));---
Overlap
Apply .e-badge-overlap to make the badge extend beyond the boundary of the parent element. Combine it with .e-badge-notification or .e-badge-dot for icon overlays.
import * as React from "react";
import * as ReactDOM from "react-dom";
function App() {
return (
<div>
<div className="badge-block">
<div className="skype svg_icons"></div>
<span className="e-badge e-badge-success e-badge-overlap e-badge-notification">99+</span>
</div>
<div className="badge-block">
<div className="twitter svg_icons"></div>
<span className="e-badge e-badge-info e-badge-overlap e-badge-notification">27</span>
</div>
<div className="badge-block">
<div className="facebook svg_icons"></div>
<span className="e-badge e-badge-info e-badge-overlap e-badge-notification">2</span>
</div>
<div className="badge-block">
<div className="firefox svg_icons"></div>
<span className="e-badge e-badge-danger e-badge-overlap e-badge-notification">35</span>
</div>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));---
Badge Positioning
Notification and dot badges default to top placement. Add .e-badge-bottom to move the badge to the bottom of the parent.
This is particularly useful for avatar components where bottom placement communicates status more intuitively.
import * as React from "react";
import * as ReactDOM from "react-dom";
function App() {
return (
<div>
<div className="badge-block">
<div className="firefox svg_icons"></div>
{/* Bottom position */}
<span className="e-badge e-badge-success e-badge-overlap e-badge-dot e-badge-bottom"></span>
</div>
<div className="badge-block">
<div className="skype svg_icons"></div>
<span className="e-badge e-badge-info e-badge-overlap e-badge-dot e-badge-bottom"></span>
</div>
<div className="badge-block">
<div className="facebook svg_icons"></div>
{/* Default top position (no e-badge-bottom) */}
<span className="e-badge e-badge-info e-badge-overlap e-badge-dot"></span>
</div>
<div className="badge-block">
<div className="twitter svg_icons"></div>
<span className="e-badge e-badge-danger e-badge-overlap e-badge-dot e-badge-bottom"></span>
</div>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));---
Combining Modifier Classes
Modifier classes compose freely. The typical pattern for icon notification badges is:
e-badge + [color] + e-badge-overlap + e-badge-notification + [optional: e-badge-circle]| Goal | Classes to combine |
|---|---|
| Notification counter on icon (default) | e-badge e-badge-{color} e-badge-overlap e-badge-notification |
| Circular notification counter | e-badge e-badge-{color} e-badge-overlap e-badge-notification e-badge-circle |
| Dot status indicator (top) | e-badge e-badge-{color} e-badge-overlap e-badge-dot |
| Dot status indicator (bottom) | e-badge e-badge-{color} e-badge-overlap e-badge-dot e-badge-bottom |
| Pill label | e-badge e-badge-{color} e-badge-pill |
Accessibility in React Message
The Syncfusion Message component is built to full accessibility compliance, meeting WCAG 2.2, Section 508, and ADA standards. It is validated using accessibility-checker and axe-core in continuous testing.
Compliance Summary
| Accessibility Criteria | Compliance |
|---|---|
| WCAG 2.2 | Full |
| Section 508 | Full |
| Screen Reader Support | Full |
| Right-To-Left Support | Full |
| Color Contrast | Full |
| Mobile Device Support | Full |
| Keyboard Navigation | Full |
| accessibility-checker Validation | Full |
| axe-core Validation | Full |
WAI-ARIA Attributes
The Message component implements the WAI-ARIA alert pattern:
| Attribute | Applied To | Purpose |
|---|---|---|
role="alert" | Message root element | Announces the message to screen readers immediately on render |
aria-label | Close icon button | Provides an accessible name for the close icon for screen readers |
The role="alert" attribute causes screen readers to announce the message content as soon as it appears in the DOM — making it critical for dynamic notifications.
Keyboard Navigation
Users who rely on keyboard navigation can interact with the close icon:
| Key | Action |
|---|---|
Tab / Shift+Tab | Move focus to the close icon in the message |
Enter / Space | Close the focused message (fires the closed event) |
Note: Keyboard interaction applies only when showCloseIcon={true}. Messages without a close icon are purely informational and require no keyboard interaction.
Implementation Notes
Dismissible Messages
When showCloseIcon={true}, the close icon is a focusable button with an aria-label. Ensure your closed handler updates state to reflect dismissal:
import { useState } from 'react';
import { MessageComponent } from '@syncfusion/ej2-react-notifications';
function AccessibleMessage() {
const [visible, setVisible] = useState(true);
return (
<MessageComponent
content="Your session will expire in 5 minutes"
severity="Warning"
showCloseIcon={true}
visible={visible}
closed={() => setVisible(false)}
/>
);
}Dynamic Messages
Because the Message component uses role="alert", screen readers will automatically announce newly rendered messages. If you're conditionally rendering messages based on user actions (e.g., form submission), the announcement happens without additional ARIA management:
{submitError && (
<MessageComponent
content="A problem occurred while submitting your data"
severity="Error"
/>
)}Color Contrast
All severity color combinations (Normal, Info, Success, Warning, Error) across all variants (Text, Outlined, Filled) meet WCAG 2.2 color contrast requirements for both text and icons.
RTL Support
Enable right-to-left layout for RTL languages to ensure proper visual ordering for screen readers operating in RTL mode:
<MessageComponent content="رسالة تحذير" severity="Warning" enableRtl={true} />API Reference — Syncfusion React MessageComponent
Source: https://ej2.syncfusion.com/react/documentation/api/message/index-default
Table of Contents
---
Import
import { MessageComponent } from '@syncfusion/ej2-react-notifications';---
Properties
content
Type: string | function | JSX.Element Default: null
Specifies the content to be displayed in the Message component. Accepts a plain string, a render function that returns JSX, or a JSX element directly.
{/* String */}
<MessageComponent content="Please read the comments carefully" />
{/* Render function */}
const template = () => <div><strong>Note:</strong> Action cannot be undone.</div>;
<MessageComponent content={template} />---
cssClass
Type: string Default: ''
Specifies one or more CSS classes (space-separated) to append to the root element of the Message component. Use for custom styling, content alignment, or appearance overrides.
<MessageComponent content="Warning" cssClass="e-content-center rounded" severity="Warning" />Built-in alignment classes: e-content-center, e-content-right.
---
enablePersistence
Type: boolean Default: false
When true, the component's state (including visible) is persisted across page reloads using browser storage.
<MessageComponent content="Persistent message" enablePersistence={true} />---
enableRtl
Type: boolean Default: false
Enables right-to-left rendering for RTL language support (Arabic, Hebrew, etc.).
<MessageComponent content="مرحبا" enableRtl={true} />---
locale
Type: string Default: ''
Overrides the global culture and localization value for this component. Defaults to 'en-US' when empty.
<MessageComponent content="Message" locale="fr-FR" />---
severity
Type: string | Severity Default: Severity.Normal
Specifies the severity of the message, which controls the icon and color scheme. Valid values:
| Value | Description |
|---|---|
"Normal" | Default — neutral/general message |
"Success" | Positive outcome or confirmation |
"Info" | Informational content |
"Warning" | Caution or potential issue |
"Error" | Critical failure or error |
<MessageComponent content="Operation failed" severity="Error" />---
showCloseIcon
Type: boolean Default: false
Shows a close icon that allows users to dismiss the message. When clicked (or activated via keyboard), the closed event fires.
<MessageComponent content="Session expiring" showCloseIcon={true} closed={() => setVisible(false)} />---
showIcon
Type: boolean Default: true
Shows or hides the severity icon displayed at the left edge of the message. Set to false for text-only appearance.
<MessageComponent content="No icon" showIcon={false} />---
variant
Type: string | Variant Default: Variant.Text
Specifies the visual presentation variant. Valid values:
| Value | Description |
|---|---|
"Text" | Subtle styling — light background with colored text (default) |
"Outlined" | Colored border with transparent background |
"Filled" | Bold — dark background with contrasting text |
<MessageComponent content="Critical error" severity="Error" variant="Filled" />---
visible
Type: boolean Default: true
Controls the visibility of the Message component. When false, the message is hidden but remains mounted in the DOM.
<MessageComponent content="Done" severity="Success" visible={isComplete} />---
Methods
destroy()
Returns: void
Destroys the Message component instance — removes it from the DOM and detaches all bound events, attributes, and classes.
const msgRef = useRef<MessageComponent>(null);
// Call to clean up
msgRef.current?.destroy();---
getPersistData()
Returns: string
Returns a JSON string of the component's persisted state properties. Useful for debugging or manually saving state.
const data = msgRef.current?.getPersistData();
console.log(data);---
Events
closed
Type: EmitType<MessageCloseEventArgs>
Fires when the Message component is closed (dismissed) by the user via the close icon.
<MessageComponent
content="Dismissible message"
showCloseIcon={true}
closed={(args: MessageCloseEventArgs) => {
console.log('Message closed', args);
setVisible(false);
}}
/>---
created
Type: EmitType<Object>
Fires when the Message component has been successfully created and mounted.
<MessageComponent
content="Hello"
created={() => console.log('Message created')}
/>---
destroyed
Type: EmitType<Event>
Fires when the Message component is destroyed via the destroy() method.
<MessageComponent
content="Hello"
destroyed={() => console.log('Message destroyed')}
/>---
Types and Enums
Severity Enum
enum Severity {
Normal = 'Normal',
Success = 'Success',
Info = 'Info',
Warning = 'Warning',
Error = 'Error'
}Variant Enum
enum Variant {
Text = 'Text',
Outlined = 'Outlined',
Filled = 'Filled'
}MessageCloseEventArgs
The argument object passed to the closed event handler:
| Property | Type | Description |
|---|---|---|
| (event args from closed event) | object | Standard event arguments provided when the message is closed |
Customization and Templates
Table of Contents
- Content Alignment
- Custom Appearance with cssClass
- CSS-Only Message Rendering
- Content Templates
- RTL Support
- Persistence
---
Content Alignment
By default, message content aligns to the left. Use built-in CSS classes via the cssClass prop to change alignment:
| CSS Class | Effect |
|---|---|
| (none) | Left-aligned (default) |
e-content-center | Center-aligned |
e-content-right | Right-aligned |
import { MessageComponent } from '@syncfusion/ej2-react-notifications';
function App() {
return (
<div>
{/* Left (default) */}
<MessageComponent content="Your license has been activated successfully" severity="Success" />
{/* Centered */}
<MessageComponent
content="The license will expire today"
cssClass="e-content-center"
severity="Warning"
/>
{/* Right-aligned */}
<MessageComponent
content="The license key is invalid"
cssClass="e-content-right"
severity="Error"
/>
</div>
);
}---
Custom Appearance with cssClass
The cssClass prop appends one or more CSS classes to the message's root element. Use this to override default styles, set border-radius, change padding, or apply any custom design:
{/* Rounded corners */}
<MessageComponent content="The license will expire today" cssClass="rounded" severity="Warning" />
{/* Square (no border-radius) */}
<MessageComponent content="The license key is invalid" cssClass="square" severity="Error" />/* App.css */
.rounded {
border-radius: 20px;
}
.square {
border-radius: 0;
}Multiple classes are space-separated:
<MessageComponent cssClass="e-content-center rounded" severity="Info" content="Centered + rounded" />---
CSS-Only Message Rendering
The Message component can be rendered using pure HTML and CSS without any JavaScript initialization. This is ideal for static content, server-rendered HTML, or lightweight scenarios.
Structure — Content Only
<div class="e-message" role="alert">
<div class="e-msg-content">Editing is restricted</div>
</div>Structure — Content with Severity Icon
<div class="e-message" role="alert">
<span class="e-msg-icon"></span>
<div class="e-msg-content">Editing is restricted</div>
</div>Available Predefined CSS Classes
| Class | Description |
|---|---|
e-message | Root message wrapper (required) |
e-msg-icon | Severity type icon |
e-msg-content | Message content container |
e-msg-close-icon | Close icon |
e-info | Info severity styling |
e-success | Success severity styling |
e-warning | Warning severity styling |
e-error | Error severity styling |
e-content-center | Center-align message content |
e-content-right | Right-align message content |
Full CSS-Only Example
<div class="e-message" role="alert">
<span class="e-msg-icon"></span>
<div class="e-msg-content">Editing is restricted</div>
</div>
<div class="e-message e-info" role="alert">
<span class="e-msg-icon"></span>
<div class="e-msg-content">Please read the comments carefully</div>
</div>
<div class="e-message e-success" role="alert">
<span class="e-msg-icon"></span>
<div class="e-msg-content">Your message has been sent successfully</div>
</div>
<div class="e-message e-warning" role="alert">
<span class="e-msg-icon"></span>
<div class="e-msg-content">There was a problem with your network connection</div>
</div>
<div class="e-message e-error" role="alert">
<span class="e-msg-icon"></span>
<div class="e-msg-content">A problem occurred while submitting your data</div>
</div>---
Content Templates
The content prop accepts a string, a JSX element, or a render function — enabling rich, interactive message bodies:
String Content
<MessageComponent content="Simple text message" />JSX / Function Template
Pass a function that returns JSX to embed HTML structure or React components inside the message:
import { useState } from 'react';
import { MessageComponent } from '@syncfusion/ej2-react-notifications';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
const [visible, setVisible] = useState(true);
const contentTemplate = () => (
<div>
<h1>Merged pull request</h1>
<p>Pull request #41 merged after a successful build</p>
<ButtonComponent cssClass="e-link" content="View commit" />
<ButtonComponent cssClass="e-link" content="Dismiss" onClick={() => setVisible(false)} />
</div>
);
return (
<MessageComponent
visible={visible}
content={contentTemplate}
severity="Success"
closed={() => setVisible(false)}
/>
);
}Children as Content
JSX children are also supported:
<MessageComponent severity="Info">
<strong>Note:</strong> This action cannot be undone.
</MessageComponent>---
RTL Support
Enable right-to-left text direction for RTL languages (Arabic, Hebrew, etc.) using enableRtl:
<MessageComponent content="مرحبا بالعالم" severity="Info" enableRtl={true} />---
Persistence
The enablePersistence prop saves the component's state (including visible) across page reloads using browser storage:
<MessageComponent content="Persistent message" enablePersistence={true} />Use this when you want dismissed messages to stay dismissed after a page reload.
Getting Started with Syncfusion React Message
This guide walks through installing, configuring, and rendering your first MessageComponent in a React application.
Prerequisites
- React 16.8+ (hooks support required)
- Node.js 14+
- A Vite or Create React App project
Installation
Install the Syncfusion notifications package, which includes the Message component:
npm install @syncfusion/ej2-react-notifications --saveAdding CSS
Import the required stylesheets in src/App.css. The ej2-base styles provide foundational theme tokens; the notifications styles provide component-specific styling:
@import '../node_modules/@syncfusion/ej2-base/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-react-notifications/styles/tailwind3.css';Then import App.css in your entry file:
// src/App.tsx
import './App.css';Basic Usage
Import MessageComponent from the notifications package and render it in JSX:
import { MessageComponent } from '@syncfusion/ej2-react-notifications';
import './App.css';
function App() {
return (
<MessageComponent content="Please read the comments carefully" />
);
}
export default App;Content: Prop vs Children
The content prop and JSX children are both supported for message text:
{/* Using the content prop (string) */}
<MessageComponent content="Your message has been sent successfully" />
{/* Using JSX children (string) */}
<MessageComponent>Your message has been sent successfully</MessageComponent>For rich/templated content, pass a function or JSX element to content — see customization.md for details.
Running the Application
Start the Vite development server:
npm run devThe browser will open with your message displayed immediately. No additional initialization is needed beyond the CSS import and the component tag.
Setup for TypeScript
To scaffold a TypeScript-enabled React app with Vite:
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install @syncfusion/ej2-react-notifications --save
npm run devSetup for JavaScript
To scaffold a JavaScript React app with Vite:
npm create vite@latest my-app -- --template react
cd my-app
npm install @syncfusion/ej2-react-notifications --save
npm run devGotchas
- Missing styles: If the message appears unstyled, ensure both
ej2-baseandej2-react-notificationsCSS files are imported before the component renders. - SSR environments: The component requires a DOM — ensure it only renders client-side in SSR frameworks (Next.js, Remix).
Icons and Close Icon
Table of Contents
- Severity Icons
- Disabling Severity Icons
- Custom Severity Icons
- Close Icon
- Controlling Visibility with `visible`
---
Severity Icons
By default, showIcon is true, meaning each message displays a severity-specific icon on its left edge. The icon changes automatically based on the severity prop:
import { MessageComponent } from '@syncfusion/ej2-react-notifications';
function App() {
return (
<div>
<MessageComponent content="Editing is restricted" />
<MessageComponent content="Please read the comments carefully" severity="Info" />
<MessageComponent content="Your message has been sent successfully" severity="Success" />
<MessageComponent content="There was a problem with your network connection" severity="Warning" />
<MessageComponent content="A problem occurred while submitting your data" severity="Error" />
</div>
);
}---
Disabling Severity Icons
Set showIcon={false} to hide the severity icon for a cleaner, text-only appearance:
function App() {
return (
<div>
<MessageComponent content="Editing is restricted" showIcon={false} />
<MessageComponent content="Please read the comments carefully" severity="Info" showIcon={false} />
<MessageComponent content="Your message has been sent successfully" severity="Success" showIcon={false} />
<MessageComponent content="There was a problem with your network connection" severity="Warning" showIcon={false} />
<MessageComponent content="A problem occurred while submitting your data" severity="Error" showIcon={false} />
</div>
);
}---
Custom Severity Icons
Override the default severity icon by using the cssClass prop to apply a custom CSS class, then target the .e-msg-icon selector in your stylesheet:
<MessageComponent
id="msg_icon"
cssClass="custom"
content="Essential JS 2 is a modern JavaScript UI Controls library."
/>/* App.css — override the icon for messages with cssClass="custom" */
.custom .e-msg-icon::before {
content: '\e704'; /* your custom icon font character */
font-family: 'e-icons';
}This allows you to replace default icons with custom icon fonts or images that match your design system.
---
Close Icon
The close icon lets users dismiss messages interactively. It is hidden by default. Enable it with showCloseIcon={true}:
import { useState } from 'react';
import { MessageComponent } from '@syncfusion/ej2-react-notifications';
function App() {
const [visible, setVisible] = useState(true);
return (
<MessageComponent
content="Your session will expire in 5 minutes"
severity="Warning"
showCloseIcon={true}
visible={visible}
closed={() => setVisible(false)}
/>
);
}The closed event fires when the user clicks the close icon (or presses Enter/Space while focused on it). Use it to update state so the message doesn't reappear on re-render.
Restore a Dismissed Message
import { useState } from 'react';
import { MessageComponent } from '@syncfusion/ej2-react-notifications';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
const [visible, setVisible] = useState(true);
return (
<div>
{!visible && (
<ButtonComponent cssClass="e-outline e-primary" onClick={() => setVisible(true)}>
Show Message
</ButtonComponent>
)}
<MessageComponent
content="Editing is restricted"
showCloseIcon={true}
visible={visible}
closed={() => setVisible(false)}
/>
</div>
);
}---
Controlling Visibility with visible
The visible prop shows or hides the entire message without unmounting it. This is useful for toggling messages in response to application state:
<MessageComponent
content="Operation complete"
severity="Success"
visible={isOperationDone}
/>visible={true}(default) — message is displayedvisible={false}— message is hidden (but still mounted in the DOM)
Full Example: Multiple Dismissible Messages
import { useState } from 'react';
import { MessageComponent } from '@syncfusion/ej2-react-notifications';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
function App() {
const [infoVisible, setInfoVisible] = useState(true);
const [errorVisible, setErrorVisible] = useState(true);
return (
<div>
<MessageComponent
content="Please read the comments carefully"
severity="Info"
showCloseIcon={true}
visible={infoVisible}
closed={() => setInfoVisible(false)}
/>
<MessageComponent
content="A problem occurred while submitting your data"
severity="Error"
showCloseIcon={true}
visible={errorVisible}
closed={() => setErrorVisible(false)}
/>
<ButtonComponent
cssClass="e-outline e-primary"
onClick={() => { setInfoVisible(true); setErrorVisible(true); }}
>
Reset Messages
</ButtonComponent>
</div>
);
}Message Severity Levels
Severity communicates the importance and type of information in a message. The Message component uses the severity prop to apply distinct icons and color schemes that help users quickly understand the message context.
Available Severity Levels
| Severity | Value | Use Case |
|---|---|---|
| Normal | "Normal" (default) | General information, neutral messages |
| Info | "Info" | Informational content, tips, guidance |
| Success | "Success" | Confirmation, completed operations, positive outcomes |
| Warning | "Warning" | Caution, potential issues, non-critical problems |
| Error | "Error" | Critical failures, invalid input, system errors |
Basic Usage
Set the severity prop to one of the five values. When omitted, Normal is used:
import { MessageComponent } from '@syncfusion/ej2-react-notifications';
function App() {
return (
<div>
<MessageComponent content="Editing is restricted" />
<MessageComponent content="Please read the comments carefully" severity="Info" />
<MessageComponent content="Your message has been sent successfully" severity="Success" />
<MessageComponent content="There was a problem with your network connection" severity="Warning" />
<MessageComponent content="A problem occurred while submitting your data" severity="Error" />
</div>
);
}Choosing the Right Severity
- Normal — Neutral context that doesn't require action (e.g., a read-only notice).
- Info — Background information the user should know, but no action required (e.g., a tooltip-style note).
- Success — Confirm an action completed correctly (e.g., form submitted, file uploaded).
- Warning — Alert the user to something that may become a problem (e.g., session expiring soon, low disk space).
- Error — Signal a failure that needs immediate attention (e.g., validation failed, network unreachable).
Combining Severity with Variant
Severity works independently of the variant prop. You can combine any severity with any variant:
{/* Filled error — maximum visual emphasis */}
<MessageComponent content="A problem occurred" severity="Error" variant="Filled" />
{/* Outlined success — clear but not overwhelming */}
<MessageComponent content="Changes saved" severity="Success" variant="Outlined" />See variants.md for full variant documentation.
Dynamic Severity
Severity can be controlled dynamically via state:
import { useState } from 'react';
import { MessageComponent } from '@syncfusion/ej2-react-notifications';
function StatusMessage({ status }: { status: 'success' | 'error' | 'info' }) {
const severityMap = { success: 'Success', error: 'Error', info: 'Info' } as const;
return (
<MessageComponent
content={`Status: ${status}`}
severity={severityMap[status]}
/>
);
}Message Display Variants
Variants define the visual presentation style of the Message component. Three predefined variants are available, each offering a different design aesthetic. Configure the variant using the variant prop.
Available Variants
| Variant | Value | Description |
|---|---|---|
| Text | "Text" (default) | Subtle styling — light background with colored text. Non-intrusive. |
| Outlined | "Outlined" | Colored border with matching text on a transparent background. Balanced emphasis. |
| Filled | "Filled" | Bold styling — dark background with contrasting text. High-priority or critical content. |
Basic Usage
Set the variant prop to control the visual style:
import { MessageComponent } from '@syncfusion/ej2-react-notifications';
function App() {
return (
<div>
{/* Text (default) — subtle */}
<MessageComponent content="Editing is restricted" />
{/* Outlined — clear without a filled background */}
<MessageComponent content="Editing is restricted" variant="Outlined" />
{/* Filled — bold, commands attention */}
<MessageComponent content="Editing is restricted" variant="Filled" />
</div>
);
}Combining Variant with Severity
Every variant works with every severity level. The severity drives the color palette; the variant drives the fill/border style:
function App() {
return (
<div>
{/* Filled variants */}
<MessageComponent content="Editing is restricted" variant="Filled" />
<MessageComponent content="Please read the comments carefully" severity="Info" variant="Filled" />
<MessageComponent content="Your message has been sent successfully" severity="Success" variant="Filled" />
<MessageComponent content="There was a problem with your network connection" severity="Warning" variant="Filled" />
<MessageComponent content="A problem occurred while submitting your data" severity="Error" variant="Filled" />
{/* Outlined variants */}
<MessageComponent content="Editing is restricted" variant="Outlined" />
<MessageComponent content="Please read the comments carefully" severity="Info" variant="Outlined" />
<MessageComponent content="Your message has been sent successfully" severity="Success" variant="Outlined" />
<MessageComponent content="There was a problem with your network connection" severity="Warning" variant="Outlined" />
<MessageComponent content="A problem occurred while submitting your data" severity="Error" variant="Outlined" />
</div>
);
}When to Use Each Variant
- Text — Inline notices, help text, or contextual notes where you don't want the message to dominate the layout.
- Outlined — Form validation messages, status cards, or secondary alerts where you want clear visual separation without a heavy background.
- Filled — Critical system alerts, banners, or high-priority notifications where the message must stand out immediately.
Gotcha
The variant prop is independent of severity. Omitting variant defaults to "Text" regardless of severity, so a severity="Error" message will still use the subtle text style unless variant="Filled" is explicitly set.
Skeleton Accessibility
Table of Contents
- Compliance Overview
- WAI-ARIA Attributes
- Using the label Prop
- RTL Support
- Motion and Animation Accessibility
- Screen Reader Behavior
---
Compliance Overview
The Syncfusion React Skeleton component meets the following accessibility standards:
| Accessibility Criteria | Support |
|---|---|
| WCAG 2.2 | Full |
| Section 508 | Full |
| ADA | Full |
| Screen Reader | Full |
| Right-To-Left (RTL) | Full |
| Color Contrast | Full |
| Mobile Device | Full |
| Keyboard Navigation | Full |
| Accessibility Checker Validation | Full |
| Axe-core Validation | Full |
The component is validated using accessibility-checker and axe-core during automated testing.
---
WAI-ARIA Attributes
The Skeleton component implements the WAI-ARIA status pattern to communicate loading state to assistive technologies:
| Attribute | Value | Purpose |
|---|---|---|
role | "status" | Identifies the element as a live status region announcing loading state |
aria-label | Configurable via label prop | Describes the skeleton's purpose or the content loading |
aria-live | "polite" | Announces updates to screen readers when content replaces the skeleton |
aria-busy | "true" while loading, "false" when done | Signals pending content to assistive technologies |
These attributes are applied automatically — no manual configuration needed.
---
Using the label Prop
The label prop sets the aria-label value for the skeleton element. By default, it reads "Loading…".
Customize label to describe the specific content being loaded, giving screen reader users meaningful context:
{/* Default: announces "Loading…" */}
<SkeletonComponent height="15px" width="60%" />
{/* Custom: announces "Loading user profile" */}
<SkeletonComponent shape="Circle" width="48px" label="Loading user profile" />
{/* Custom: announces "Loading article image" */}
<SkeletonComponent shape="Rectangle" width="100%" height="200px" label="Loading article image" />Providing descriptive labels is especially important in multi-skeleton layouts where each skeleton represents a different content element:
<div>
<SkeletonComponent shape="Circle" width="48px" label="Loading avatar" />
<SkeletonComponent height="15px" width="60%" label="Loading user name" />
<SkeletonComponent height="12px" width="40%" label="Loading user role" />
</div>---
RTL Support
Enable right-to-left rendering using the enableRtl prop. This mirrors the shimmer animation direction and flips the layout for RTL languages (Arabic, Hebrew, etc.):
<SkeletonComponent height="15px" width="80%" enableRtl={true} />For a full RTL card skeleton:
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function RTLCardSkeleton() {
return (
<div dir="rtl" style={{ padding: '16px' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<SkeletonComponent shape="Circle" width="48px" enableRtl={true} label="تحميل الصورة الرمزية" />
<div style={{ flex: 1 }}>
<SkeletonComponent height="15px" width="50%" enableRtl={true} label="تحميل الاسم" />
<br />
<SkeletonComponent height="12px" width="35%" enableRtl={true} label="تحميل الدور" />
</div>
</div>
</div>
);
}
export default RTLCardSkeleton;---
Motion and Animation Accessibility
The Skeleton component's shimmer effects (Wave, Pulse, Fade) respect the prefers-reduced-motion CSS media query. Users who have configured their OS or browser to reduce motion will see minimal or no animation, maintaining accessibility without requiring any code changes.
This behavior is automatic — no extra configuration needed.
---
Screen Reader Behavior
- Screen readers announce the skeleton's
aria-labelwhen the skeleton becomes visible (aria-busy="true") - When the skeleton is replaced with actual content,
aria-live="polite"ensures the transition is announced without interrupting the user - The
role="status"landmark keeps skeleton announcements non-intrusive
For the best screen reader experience: 1. Set meaningful label values on each skeleton 2. Use conditional rendering to swap skeletons for real content once loaded 3. Avoid rapidly toggling visible on/off, which can produce excessive announcements
Skeleton API Reference
Table of Contents
---
Import
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';---
Properties
cssClass
string — Default: ""
Defines one or more CSS classes (space-separated) for customizing the Skeleton's appearance. Use to override shimmer color, background, border-radius, and animation speed.
<SkeletonComponent shape="Circle" width="60px" cssClass="my-custom-skeleton" />---
enablePersistence
boolean — Default: false
Enable or disable persisting the component's state between page reloads. When true, state is stored in browser local storage.
<SkeletonComponent height="15px" enablePersistence={true} />---
enableRtl
boolean — Default: false
Enable or disable rendering the component in right-to-left direction. Mirrors shimmer animation and layout for RTL languages.
<SkeletonComponent height="15px" width="80%" enableRtl={true} />---
height
string | number — Default: ""
Defines the height of the Skeleton. Height is required for "Text" and "Rectangle" shapes. It is not required when shape is "Circle" or "Square" (width is used as the dimension for those).
<SkeletonComponent height="20px" width="60%" />
<SkeletonComponent shape="Rectangle" width="100%" height="150px" />---
label
string — Default: "Loading…"
Defines the aria-label attribute value for accessibility. Customize to describe the specific content being loaded, improving screen reader context.
<SkeletonComponent shape="Circle" width="48px" label="Loading user avatar" />---
locale
string — Default: ''
Overrides the global culture and localization value for this component. The default global culture is 'en-US'.
<SkeletonComponent height="15px" locale="fr-FR" />---
shape
string | SkeletonType — Default: SkeletonType.Text ("Text")
Defines the visual shape of the Skeleton. Accepted values: "Text", "Circle", "Square", "Rectangle".
<SkeletonComponent shape="Circle" width="48px" />
<SkeletonComponent shape="Square" width="32px" />
<SkeletonComponent shape="Rectangle" width="100%" height="150px" />
<SkeletonComponent height="15px" /> {/* Text (default) */}---
shimmerEffect
string | ShimmerEffect — Default: ShimmerEffect.Wave ("Wave")
Defines the animation effect of the Skeleton. Accepted values: "Wave", "Pulse", "Fade".
<SkeletonComponent shape="Circle" width="48px" shimmerEffect="Pulse" />
<SkeletonComponent height="15px" shimmerEffect="Fade" />
<SkeletonComponent height="15px" shimmerEffect="Wave" /> {/* default */}---
visible
boolean — Default: true
Defines the visibility state of the Skeleton. Set to false to hide the skeleton when content has loaded.
<SkeletonComponent height="15px" width="60%" visible={true} />
<SkeletonComponent height="15px" width="60%" visible={false} />---
width
string | number — Default: ""
Defines the width of the Skeleton. Width is required for "Circle" and "Square" shapes (used as the sole dimension). Width is also required for "Rectangle". Optional for "Text".
<SkeletonComponent shape="Circle" width="60px" />
<SkeletonComponent shape="Rectangle" width="100%" height="200px" />
<SkeletonComponent height="15px" width="75%" />---
Methods
destroy()
void
Destroys the Skeleton component instance, removing event listeners and cleaning up internal state. Call when programmatically removing the component outside of React's lifecycle.
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function App() {
const skeletonRef = React.useRef<SkeletonComponent>(null);
const handleDestroy = () => {
skeletonRef.current?.destroy();
};
return (
<div>
<SkeletonComponent ref={skeletonRef} height="15px" width="80%" />
<button onClick={handleDestroy}>Destroy</button>
</div>
);
}
export default App;---
Enums
SkeletonType
Defines the shape prop values:
| Value | Description |
|---|---|
Text | Horizontal line (default) |
Circle | Circle/round shape |
Square | Equal-sided square |
Rectangle | Rectangular block |
ShimmerEffect
Defines the shimmerEffect prop values:
| Value | Description |
|---|---|
Wave | Left-to-right sweeping wave (default) |
Pulse | Uniform fade in/out pulsing |
Fade | Gradual fade animation |
---
Usage Examples
All properties combined
<SkeletonComponent
shape="Rectangle"
width="100%"
height="200px"
shimmerEffect="Pulse"
cssClass="my-card-skeleton"
label="Loading featured image"
visible={true}
enableRtl={false}
enablePersistence={false}
/>Minimal text skeleton
<SkeletonComponent height="15px" />Circle with custom label
<SkeletonComponent shape="Circle" width="48px" label="Loading profile photo" />Hidden skeleton (content loaded)
<SkeletonComponent height="20px" width="50%" visible={false} />Getting Started with Syncfusion React Skeleton
Table of Contents
- Prerequisites
- Installation
- Adding CSS References
- Basic Skeleton Setup
- Running the Application
- Minimal Examples
---
Prerequisites
- React project created with Vite (recommended) or Create React App
- Node.js installed
Create a new Vite-based React app:
# TypeScript
npm create vite@latest my-app -- --template react-ts
cd my-app
npm run dev
# JavaScript
npm create vite@latest my-app -- --template react
cd my-app
npm run dev---
Installation
Install the Syncfusion notifications package, which includes SkeletonComponent:
npm install @syncfusion/ej2-react-notifications --saveThe--saveflag adds the package to thedependenciessection ofpackage.json.
---
Adding CSS References
Add the required CSS imports in src/App.css:
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-notifications/styles/tailwind3.css";Then import App.css in src/App.tsx:
import './App.css';---
Basic Skeleton Setup
Add SkeletonComponent to your component. At minimum, provide a height for text-style skeletons:
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
import './App.css';
function App() {
return (
<SkeletonComponent height="15px" />
);
}
export default App;For circle or square shapes, provide width (used as the dimension):
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function App() {
return (
<SkeletonComponent shape="Circle" width="48px" />
);
}
export default App;---
Running the Application
Start the development server:
npm run devThe app opens in the browser. Skeleton placeholders render immediately with the default Wave shimmer animation.
---
Minimal Examples
Text line placeholder (default)
<SkeletonComponent height="15px" width="80%" />Avatar placeholder
<SkeletonComponent shape="Circle" width="48px" />Image placeholder
<SkeletonComponent shape="Rectangle" width="100%" height="200px" />Small icon placeholder
<SkeletonComponent shape="Square" width="32px" />---
Dimension Rules
| Shape | Width | Height |
|---|---|---|
Text (default) | Optional | Required |
Rectangle | Required | Required |
Circle | Required (used as diameter) | Not needed |
Square | Required (used as side length) | Not needed |
ForCircleandSquare,widthis used as the single dimension. Height is ignored.
Skeleton Shapes
Table of Contents
- Overview
- Available Shapes
- Dimension Rules by Shape
- Shape Examples
- Multi-Shape Card Layout
- Choosing the Right Shape
---
Overview
Use the shape prop on SkeletonComponent to select the visual form of the loading placeholder. Each shape is designed to mirror a specific type of real content, helping users understand what is loading.
<SkeletonComponent shape="Circle" width="60px" />Default shape is "Text" when shape is omitted.
---
Available Shapes
Text (default)
Horizontal line representing a text row or headline. Use for paragraphs, titles, labels.
<SkeletonComponent height="15px" width="70%" />Circle
Round placeholder for avatars, profile photos, or circular icons.
<SkeletonComponent shape="Circle" width="60px" />Square
Equal-sided placeholder for compact icons, thumbnails, or grid tiles.
<SkeletonComponent shape="Square" width="40px" />Rectangle
Rectangular placeholder for images, cards, banners, or large content blocks.
<SkeletonComponent shape="Rectangle" width="100%" height="150px" />---
Dimension Rules by Shape
| Shape | Width | Height | Notes |
|---|---|---|---|
Text | Optional | Required | Height controls line thickness |
Rectangle | Required | Required | Both dimensions define the block |
Circle | Required | Not needed | width is used as diameter |
Square | Required | Not needed | width is used as side length |
Height is ignored forCircleandSquare;widthalone determines their size.
---
Shape Examples
Circle — Avatar
<SkeletonComponent shape="Circle" width="60px" />Square — Icon tile
<SkeletonComponent shape="Square" width="40px" />Rectangle — Banner image
<SkeletonComponent shape="Rectangle" width="100%" height="200px" />Text — Headline
<SkeletonComponent height="20px" width="50%" />Text — Body paragraph lines
<>
<SkeletonComponent height="14px" width="100%" />
<br />
<SkeletonComponent height="14px" width="95%" />
<br />
<SkeletonComponent height="14px" width="80%" />
</>---
Multi-Shape Card Layout
Combine shapes to build a full card skeleton that mirrors real card content:
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function CardSkeleton() {
return (
<div style={{ padding: '16px', maxWidth: '320px' }}>
{/* Profile row */}
<div style={{ display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '12px' }}>
<SkeletonComponent shape="Circle" width="60px" />
<div style={{ flex: 1 }}>
<SkeletonComponent width="30%" height="15px" />
<br />
<SkeletonComponent width="15%" height="15px" />
</div>
</div>
{/* Image placeholder */}
<SkeletonComponent shape="Rectangle" width="100%" height="150px" />
{/* Action buttons row */}
<div style={{ display: 'flex', gap: '8px', marginTop: '12px' }}>
<SkeletonComponent shape="Rectangle" width="20%" height="32px" />
<SkeletonComponent shape="Rectangle" width="20%" height="32px" />
</div>
</div>
);
}
export default CardSkeleton;---
Choosing the Right Shape
| Content type | Recommended shape |
|---|---|
| Avatar / profile photo | Circle |
| Icon / badge | Square |
| Image / banner / card | Rectangle |
| Text line / heading | Text (default) |
| Button | Rectangle with small height |
| Paragraph block | Multiple Text lines stacked |
Skeleton Shimmer Effects
Table of Contents
---
Overview
Shimmer effects provide animated visual feedback that signals to users the application is actively loading content. Configure the animation style with the shimmerEffect prop.
<SkeletonComponent shape="Circle" width="48px" shimmerEffect="Pulse" />Default effect is "Wave" when shimmerEffect is omitted.
---
Effect Types
Wave (default)
A flowing highlight sweeps across the skeleton from left to right, mimicking a scan or reflection. Best for most general-purpose loading states.
<SkeletonComponent height="15px" width="100%" shimmerEffect="Wave" />Pulse
The entire skeleton fades in and out uniformly, creating a breathing or pulsing rhythm. Works well for lists and items where you want a subtler, less directional animation.
<SkeletonComponent height="15px" width="100%" shimmerEffect="Pulse" />Fade
A gradual fade in/out animation. Provides the most subtle visual feedback; appropriate when you want a calm, non-distracting loading state.
<SkeletonComponent height="15px" width="100%" shimmerEffect="Fade" />---
Usage
Apply shimmerEffect directly on any SkeletonComponent. All skeletons in a layout can share the same effect or use different ones:
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function EffectDemo() {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
<SkeletonComponent height="15px" width="100%" shimmerEffect="Wave" />
<SkeletonComponent height="15px" width="80%" shimmerEffect="Pulse" />
<SkeletonComponent height="15px" width="60%" shimmerEffect="Fade" />
</div>
);
}
export default EffectDemo;---
Examples
List Skeleton with Pulse
Pulse is ideal for list items where the whole row fades together:
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function ListSkeleton() {
return (
<ul style={{ listStyle: 'none', padding: 0 }}>
{[1, 2, 3].map((i) => (
<li key={i} style={{ display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '14px' }}>
<SkeletonComponent shape="Circle" width="40px" shimmerEffect="Pulse" />
<div style={{ flex: 1 }}>
<SkeletonComponent width="60%" height="15px" shimmerEffect="Pulse" />
<br />
<SkeletonComponent width="40%" height="15px" shimmerEffect="Pulse" />
</div>
</li>
))}
</ul>
);
}
export default ListSkeleton;Card Skeleton with Wave (default)
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function CardSkeleton() {
return (
<div style={{ padding: '16px' }}>
<SkeletonComponent shape="Rectangle" width="100%" height="180px" />
<br />
<SkeletonComponent height="18px" width="60%" />
<br />
<SkeletonComponent height="14px" width="90%" />
<br />
<SkeletonComponent height="14px" width="75%" />
</div>
);
}
export default CardSkeleton;Fade Effect for Subtle Transitions
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function SubtleSkeleton() {
return (
<div>
<SkeletonComponent shape="Circle" width="56px" shimmerEffect="Fade" />
<br />
<SkeletonComponent height="16px" width="50%" shimmerEffect="Fade" />
</div>
);
}
export default SubtleSkeleton;---
Choosing an Effect
| Effect | Best for | Visual style |
|---|---|---|
Wave | General use, cards, images | Directional left-to-right sweep |
Pulse | Lists, repeated items | Uniform in/out breathing |
Fade | Subtle or low-distraction UI | Soft, non-directional fade |
All three effects respect the prefers-reduced-motion media query for users who prefer reduced animation.Skeleton Styles and Visibility
Table of Contents
---
Custom CSS with cssClass
Use the cssClass prop to apply one or more CSS classes to a SkeletonComponent. This lets you override the default skeleton appearance — changing shimmer wave color, background color, dimensions, border radius, or animation speed.
<SkeletonComponent shape="Circle" width="60px" cssClass="e-customize" />Define the class in your CSS file:
/* Example: custom purple shimmer wave */
.e-customize.e-skeleton {
background-color: #e8d5f5;
}
.e-customize.e-skeleton::after {
background: linear-gradient(
90deg,
transparent,
rgba(150, 80, 200, 0.4),
transparent
);
}Multiple classes are supported (space-separated):
<SkeletonComponent height="15px" width="80%" cssClass="e-custom-bg e-custom-wave" />---
Visibility Control
Use the visible prop to show or hide the skeleton placeholder based on your application's loading state.
visible={true}— Skeleton is displayed (default)visible={false}— Skeleton is hidden
<SkeletonComponent height="15px" width="60%" visible={true} />The visible prop enables dynamic toggling without mounting/unmounting the component. Set it to false when content has finished loading, then render your actual content.
---
Loading to Content Transition
A common pattern is to conditionally render either the skeleton or the real content based on loading state:
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function UserProfile() {
const [loading, setLoading] = React.useState(true);
const [user, setUser] = React.useState<{ name: string; role: string } | null>(null);
React.useEffect(() => {
// Simulate data fetch
setTimeout(() => {
setUser({ name: 'Jane Smith', role: 'Developer' });
setLoading(false);
}, 2000);
}, []);
return (
<div style={{ display: 'flex', alignItems: 'center', gap: '12px', padding: '16px' }}>
{loading ? (
<>
<SkeletonComponent shape="Circle" width="48px" />
<div>
<SkeletonComponent width="120px" height="15px" />
<br />
<SkeletonComponent width="80px" height="12px" />
</div>
</>
) : (
<>
<div style={{ width: '48px', height: '48px', borderRadius: '50%', background: '#6366f1' }} />
<div>
<strong>{user?.name}</strong>
<p style={{ margin: 0, fontSize: '12px' }}>{user?.role}</p>
</div>
</>
)}
</div>
);
}
export default UserProfile;Alternatively, use the visible prop to hide the skeleton while keeping it in the DOM:
import { SkeletonComponent } from '@syncfusion/ej2-react-notifications';
import * as React from 'react';
function FadingContent() {
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
setTimeout(() => setLoading(false), 1500);
}, []);
return (
<div>
<SkeletonComponent height="20px" width="200px" visible={loading} />
{!loading && <h2>Content Loaded!</h2>}
</div>
);
}
export default FadingContent;---
CSS Customization Examples
Change background color
.my-skeleton.e-skeleton {
background-color: #dbeafe; /* light blue */
}Change wave/shimmer color
.my-skeleton.e-skeleton::after {
background: linear-gradient(
90deg,
transparent,
rgba(59, 130, 246, 0.5),
transparent
);
}Slow down animation
.my-skeleton.e-skeleton::after {
animation-duration: 2.5s;
}Rounded rectangle
.rounded-skeleton.e-skeleton {
border-radius: 8px;
}Apply the class:
<SkeletonComponent shape="Rectangle" width="100%" height="120px" cssClass="rounded-skeleton" />Accessibility — React Spinner
Table of Contents
- Overview
- ARIA Attributes
- Screen Reader Announcements
- High Contrast Mode
- Keyboard Accessibility
- Focus Management
- Accessible Spinner Pattern
- WCAG 2.1 Compliance Notes
---
Overview
The Syncfusion Spinner is a visual loading indicator. Because it blocks user interaction during loading, accessibility considerations focus on:
- Communicating loading state to screen readers via ARIA live regions
- Providing meaningful labels
- Supporting high contrast mode via the
'HighContrast'spinner type - Managing focus appropriately when spinner appears/disappears
---
ARIA Attributes
The Spinner renders with the following ARIA roles and attributes by default:
| Attribute | Value | Purpose |
|---|---|---|
role | "progressbar" or not set (varies by version) | Indicates it is an indeterminate progress indicator |
aria-label | Derived from the label property | Announces the loading message |
aria-busy | Set on parent container | Signals that the region is loading |
Best practice: manage `aria-busy` yourself:
import { createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-react-popups';
import * as React from 'react';
import { useEffect, useRef, useState } from 'react';
function AccessibleSpinner() {
const ref = useRef<HTMLDivElement>(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (ref.current) {
createSpinner({
target: ref.current,
label: 'Loading content, please wait'
});
}
}, []);
const startLoad = async () => {
setLoading(true);
showSpinner(ref.current as HTMLElement);
try {
await new Promise(resolve => setTimeout(resolve, 2000));
} finally {
hideSpinner(ref.current as HTMLElement);
setLoading(false);
}
};
return (
<div>
<button onClick={startLoad} disabled={loading}>Load Data</button>
<div
ref={ref}
aria-busy={loading} // ✅ Tell screen readers region is loading
aria-label="Content area"
style={{ minHeight: '120px', position: 'relative' }}
/>
</div>
);
}---
Screen Reader Announcements
Use an ARIA live region to announce loading state changes to screen reader users:
import { createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-react-popups';
import * as React from 'react';
import { useEffect, useRef, useState } from 'react';
function ScreenReaderFriendlySpinner() {
const spinnerRef = useRef<HTMLDivElement>(null);
const [announcement, setAnnouncement] = useState('');
useEffect(() => {
if (spinnerRef.current) {
createSpinner({
target: spinnerRef.current,
label: 'Loading...'
});
}
}, []);
const fetchData = async () => {
// Announce start
setAnnouncement('Loading data, please wait.');
showSpinner(spinnerRef.current as HTMLElement);
try {
await new Promise(resolve => setTimeout(resolve, 2500));
setAnnouncement('Data loaded successfully.');
} catch {
setAnnouncement('Failed to load data. Please try again.');
} finally {
hideSpinner(spinnerRef.current as HTMLElement);
}
};
return (
<div>
{/* Visually hidden live region for screen readers */}
<div
role="status"
aria-live="polite"
aria-atomic="true"
style={{
position: 'absolute',
width: '1px',
height: '1px',
overflow: 'hidden',
clip: 'rect(0,0,0,0)',
whiteSpace: 'nowrap'
}}
>
{announcement}
</div>
<button onClick={fetchData}>Fetch Data</button>
<div
ref={spinnerRef}
style={{ height: '200px', position: 'relative' }}
/>
</div>
);
}
export default ScreenReaderFriendlySpinner;Key patterns:
role="status"+aria-live="polite"— announces changes without interrupting current speecharia-live="assertive"— use for urgent messages that should interrupt (e.g., errors)aria-atomic="true"— reads the entire region content, not just changed parts
---
High Contrast Mode
Use type: 'HighContrast' for users with high contrast display settings:
import { createSpinner, showSpinner, setSpinner } from '@syncfusion/ej2-react-popups';
import { useEffect, useRef } from 'react';
function HighContrastSpinner() {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
if (ref.current) {
createSpinner({
target: ref.current,
type: 'HighContrast',
label: 'Loading...'
});
showSpinner(ref.current);
}
}, []);
return <div ref={ref} style={{ height: '200px', background: '#000' }} />;
}Detect and apply high contrast automatically:
import { setSpinner } from '@syncfusion/ej2-react-popups';
// Detect Windows high contrast mode (forced-colors media query)
const prefersHighContrast = window.matchMedia('(forced-colors: active)').matches;
setSpinner({
type: prefersHighContrast ? 'HighContrast' : 'Fluent2'
});Import high contrast CSS:
@import "../node_modules/@syncfusion/ej2-base/styles/highcontrast.css";
@import "../node_modules/@syncfusion/ej2-react-popups/styles/highcontrast.css";---
Keyboard Accessibility
The Spinner itself is not keyboard-operable (it's a visual overlay). However, ensure that:
1. Focus is not trapped inside the spinner overlay 2. Controls that trigger the spinner are keyboard-accessible (use <button>, not <div onClick>) 3. Focus returns to the triggering element after the spinner hides
import { createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-react-popups';
import * as React from 'react';
import { useEffect, useRef, useState } from 'react';
function KeyboardFriendlySpinner() {
const spinnerRef = useRef<HTMLDivElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (spinnerRef.current) {
createSpinner({ target: spinnerRef.current });
}
}, []);
const handleAction = async () => {
setLoading(true);
showSpinner(spinnerRef.current as HTMLElement);
try {
await new Promise(resolve => setTimeout(resolve, 2000));
} finally {
hideSpinner(spinnerRef.current as HTMLElement);
setLoading(false);
// Return focus to the trigger button after loading
buttonRef.current?.focus();
}
};
return (
<div>
{/* ✅ Use native <button> for keyboard accessibility */}
<button
ref={buttonRef}
onClick={handleAction}
disabled={loading}
aria-busy={loading}
aria-label={loading ? 'Loading, please wait' : 'Load content'}
>
{loading ? 'Loading...' : 'Load Content'}
</button>
<div
ref={spinnerRef}
aria-hidden={!loading}
style={{ height: '150px', position: 'relative' }}
/>
</div>
);
}
export default KeyboardFriendlySpinner;---
Focus Management
When the spinner blocks a region, prevent focus from entering it:
import { createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-react-popups';
import * as React from 'react';
import { useEffect, useRef, useState } from 'react';
function FocusManagedSpinner() {
const spinnerRef = useRef<HTMLDivElement>(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (spinnerRef.current) {
createSpinner({ target: spinnerRef.current });
}
}, []);
const load = async () => {
setLoading(true);
showSpinner(spinnerRef.current as HTMLElement);
await new Promise(resolve => setTimeout(resolve, 2000));
hideSpinner(spinnerRef.current as HTMLElement);
setLoading(false);
};
return (
<div>
<button onClick={load} disabled={loading}>Start</button>
{/* aria-hidden hides the loading region from assistive tech while loading */}
<div
ref={spinnerRef}
aria-hidden={loading}
style={{ height: '200px', position: 'relative' }}
>
{!loading && (
<div>
<button>Interactive Button 1</button>
<button>Interactive Button 2</button>
</div>
)}
</div>
</div>
);
}
export default FocusManagedSpinner;---
Accessible Spinner Pattern
A complete, production-ready accessible spinner implementation:
import { createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-react-popups';
import * as React from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
interface AccessibleSpinnerProps {
loadingLabel?: string;
onLoad: () => Promise<void>;
children: React.ReactNode;
}
function AccessibleSpinnerRegion({
loadingLabel = 'Loading, please wait',
onLoad,
children
}: AccessibleSpinnerProps) {
const regionRef = useRef<HTMLDivElement>(null);
const triggerRef = useRef<HTMLButtonElement>(null);
const [loading, setLoading] = useState(false);
const [liveMessage, setLiveMessage] = useState('');
useEffect(() => {
if (regionRef.current) {
createSpinner({
target: regionRef.current,
label: loadingLabel,
width: '36px'
});
}
}, [loadingLabel]);
const handleLoad = useCallback(async () => {
setLoading(true);
setLiveMessage(loadingLabel);
showSpinner(regionRef.current as HTMLElement);
try {
await onLoad();
setLiveMessage('Content loaded.');
} catch {
setLiveMessage('Failed to load content.');
} finally {
hideSpinner(regionRef.current as HTMLElement);
setLoading(false);
triggerRef.current?.focus();
}
}, [onLoad, loadingLabel]);
return (
<div>
{/* Screen reader live announcement */}
<div
role="status"
aria-live="polite"
aria-atomic="true"
style={{ position: 'absolute', width: 1, height: 1, overflow: 'hidden', clip: 'rect(0,0,0,0)' }}
>
{liveMessage}
</div>
<button
ref={triggerRef}
onClick={handleLoad}
disabled={loading}
aria-busy={loading}
>
{loading ? 'Loading...' : 'Refresh'}
</button>
<div
ref={regionRef}
aria-busy={loading}
aria-label="Content region"
style={{ minHeight: '200px', position: 'relative' }}
>
{!loading && children}
</div>
</div>
);
}
export default AccessibleSpinnerRegion;---
WCAG 2.1 Compliance Notes
| WCAG Criterion | Guidance |
|---|---|
| 1.4.3 Contrast | Use type: 'HighContrast' for high contrast environments; ensure label text has sufficient contrast |
| 2.1.1 Keyboard | Ensure the trigger element (button) is keyboard-operable; spinner itself needs no keyboard interaction |
| 2.4.3 Focus Order | Return focus to trigger element after spinner hides |
| 4.1.2 Name, Role, Value | Use aria-busy on the loading region; use aria-live region for announcements |
| 1.3.1 Info and Relationships | The label property provides a programmatic name for the spinner |
Checklist:
- [ ] Use
<button>(not<div>) for spinner triggers - [ ] Set
aria-busy="true"on the loading region while spinner is shown - [ ] Provide an
aria-liveregion to announce loading start/end - [ ] Return focus to the trigger after loading completes
- [ ] Use
type: 'HighContrast'or detectforced-colorsmedia query - [ ] Provide a meaningful
labelincreateSpinnerfor context - [ ] Set
aria-hidden="true"on the spinner container to avoid double-announcing
API Reference — React Spinner
Source:@syncfusion/ej2-react-popups/@syncfusion/ej2-popups
Official Docs: https://ej2.syncfusion.com/react/documentation/spinner/
The Syncfusion React Spinner is not a component class — it is a set of utility functions exported from @syncfusion/ej2-react-popups. There is no SpinnerComponent class.
Table of Contents
1. Import Paths 2. createSpinner 3. showSpinner 4. hideSpinner 5. setSpinner 6. SpinnerArgs Interface 7. SetSpinnerArgs Interface 8. SpinnerType Values 9. Quick Reference Table
---
Import Paths
// React (recommended)
import {
createSpinner,
showSpinner,
hideSpinner,
setSpinner
} from '@syncfusion/ej2-react-popups';
// Core JavaScript/TypeScript
import {
createSpinner,
showSpinner,
hideSpinner,
setSpinner
} from '@syncfusion/ej2-popups';---
createSpinner
Creates a spinner overlay on the specified target element.
function createSpinner(args: SpinnerArgs): void;Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
args | SpinnerArgs | ✅ Yes | Configuration object. See SpinnerArgs. |
Example
import { createSpinner, showSpinner } from '@syncfusion/ej2-react-popups';
import * as React from 'react';
import { useEffect } from 'react';
function App() {
useEffect(() => {
createSpinner({
target: document.getElementById('container') as HTMLElement
});
showSpinner(document.getElementById('container') as HTMLElement);
}, []);
return <div id="container" style={{ height: '200px' }} />;
}With Options
createSpinner({
target: document.getElementById('myDiv') as HTMLElement,
width: '34px',
label: 'Loading...',
cssClass: 'custom-spinner',
type: 'Bootstrap5'
});---
showSpinner
Makes the spinner visible on the target element.
function showSpinner(container: HTMLElement): void;Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
container | HTMLElement | ✅ Yes | The DOM element where the spinner was created. |
Example
showSpinner(document.getElementById('container') as HTMLElement);---
hideSpinner
Hides the spinner on the target element. The spinner is not destroyed, only hidden.
function hideSpinner(container: HTMLElement): void;Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
container | HTMLElement | ✅ Yes | The DOM element where the spinner was created. |
Example
hideSpinner(document.getElementById('container') as HTMLElement);---
setSpinner
Changes spinners globally across the entire page from the application level. Call before creating individual spinners to apply a global default.
function setSpinner(args: SetSpinnerArgs): void;Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
args | SetSpinnerArgs | ✅ Yes | Global spinner configuration. See SetSpinnerArgs. |
Example
import { setSpinner } from '@syncfusion/ej2-react-popups';
// Call before createSpinner calls
setSpinner({ type: 'Bootstrap5', cssClass: 'global-spinner' });---
SpinnerArgs Interface
Arguments used with createSpinner().
interface SpinnerArgs {
target: HTMLElement;
width?: string | number;
label?: string;
cssClass?: string;
template?: string;
type?: SpinnerType;
}Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
target | HTMLElement | ✅ Yes | — | The DOM element to render the spinner on. |
width | `string \ | number` | ❌ No | theme default |
label | string | ❌ No | — | Text label displayed alongside the spinner. |
cssClass | string | ❌ No | '' | One or more CSS class names added to the spinner root for custom styling. |
template | string | ❌ No | — | Custom HTML string to replace the default spinner animation. |
type | SpinnerType | ❌ No | auto (from theme) | Spinner visual style/theme. See SpinnerType Values. |
Example with All Properties
createSpinner({
target: document.getElementById('myElement') as HTMLElement,
width: '50px',
label: 'Please wait...',
cssClass: 'e-spin-overlay',
type: 'Material3'
});---
SetSpinnerArgs Interface
Arguments used with setSpinner() for global spinner configuration.
interface SetSpinnerArgs {
template?: string;
cssClass?: string;
type?: SpinnerType;
}Properties
| Property | Type | Required | Description |
|---|---|---|---|
template | string | ❌ No | Custom HTML string to replace the default spinner animation globally. |
cssClass | string | ❌ No | CSS class(es) added to the spinner root element across all spinners. |
type | SpinnerType | ❌ No | Spinner visual theme to apply globally. |
Example
// Apply Bootstrap5 theme globally before any createSpinner calls
setSpinner({ type: 'Bootstrap5' });
// Later create spinners — they pick up the global setting
createSpinner({ target: document.getElementById('div1') as HTMLElement });
createSpinner({ target: document.getElementById('div2') as HTMLElement });---
SpinnerType Values
The type property accepts one of the following string values:
| Value | Description |
|---|---|
'Material' | Google Material Design spinner |
'Material3' | Material Design 3 (You) spinner |
'Fabric' | Microsoft Fabric / Office 365 style |
'Bootstrap' | Bootstrap 3 spinner |
'Bootstrap4' | Bootstrap 4 spinner |
'Bootstrap5' | Bootstrap 5 spinner |
'HighContrast' | High contrast accessibility spinner |
'Tailwind' | Tailwind CSS spinner |
'Tailwind3' | Tailwind CSS v3 spinner |
'Fluent' | Microsoft Fluent Design spinner |
'Fluent2' | Microsoft Fluent Design 2 spinner |
Usage
// Explicit type selection
createSpinner({
target: document.getElementById('container') as HTMLElement,
type: 'Fluent2'
});
// Global type for all spinners on the page
setSpinner({ type: 'Bootstrap5' });---
Quick Reference Table
| Function | Signature | When to Use |
|---|---|---|
createSpinner | (args: SpinnerArgs) => void | Initialize a spinner on a DOM element |
showSpinner | (container: HTMLElement) => void | Show an existing (hidden) spinner |
hideSpinner | (container: HTMLElement) => void | Hide a visible spinner |
setSpinner | (args: SetSpinnerArgs) => void | Set global spinner defaults for the whole page |
---
CSS Theme Imports
/* Tailwind 3 (recommended) */
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-react-popups/styles/tailwind3.css";
/* Material */
@import "../node_modules/@syncfusion/ej2-base/styles/material.css";
@import "../node_modules/@syncfusion/ej2-react-popups/styles/material.css";
/* Bootstrap 5 */
@import "../node_modules/@syncfusion/ej2-base/styles/bootstrap5.css";
@import "../node_modules/@syncfusion/ej2-react-popups/styles/bootstrap5.css";
/* Fluent 2 */
@import "../node_modules/@syncfusion/ej2-base/styles/fluent2.css";
@import "../node_modules/@syncfusion/ej2-react-popups/styles/fluent2.css";⚠️ Always importej2-basetheme beforeej2-react-popupstheme.
---
Common Gotchas
❌ Invalid: SpinnerComponent does not exist
// WRONG — there is no class-based SpinnerComponent
import { SpinnerComponent } from '@syncfusion/ej2-react-popups'; // ❌✅ Correct: Use utility functions only
import { createSpinner, showSpinner, hideSpinner, setSpinner } from '@syncfusion/ej2-react-popups'; // ✅❌ Invalid: calling showSpinner before createSpinner
showSpinner(el); // ❌ spinner not yet created
createSpinner({ target: el });✅ Correct: create before show
createSpinner({ target: el }); // ✅ create first
showSpinner(el); // then show❌ Invalid: properties that don't exist
// WRONG — these properties do not exist on SpinnerArgs
createSpinner({ target: el, color: '#fff', size: 'large', visible: true }); // ❌✅ Valid SpinnerArgs properties only
createSpinner({
target: el,
width: '34px', // ✅
label: 'Loading', // ✅
cssClass: 'my', // ✅
type: 'Fluent2', // ✅
template: '<div>' // ✅
});