@pplancq/svg-react
v3.0.1
Published
A React component designed to load SVG files efficiently
Readme
@pplancq/svg-react
A React component designed to efficiently load SVG files into your web applications, while following best practices for performance, accessibility, and eco-design.
⬆️ Migration Guides
Migrating from v1 to v2
- React 19 only: Version 2 no longer supports React 18. Please ensure you are using React 19 before upgrading.
- New use() API: The
Svgcomponent leverages React 19'suse()API internally. Your existing code may require minor adjustments to align with this approach. - No major interface changes: The component API remains similar, but the internal implementation benefits from the latest React features.
Migrating from v2 to v3
- No interface changes: The
<Svg />component API is completely unchanged — no modifications required in your application code. - Internal rewrite: The component now uses
useSyncExternalStoreinstead ofSuspense/use(). As a result, wrapping<Svg />in a<Suspense>boundary is no longer necessary (though harmless if already present). - ⚠️ Breaking change —
renderSuspenseremoved: The@pplancq/svg-react/testsexport and itsrenderSuspensehelper have been removed. If you were usingrenderSuspensein your tests, replace it with the standardrenderfrom@testing-library/react— see the Testing section below.
🚀 General Overview
@pplancq/svg-react allows you to integrate SVG images asynchronously and efficiently, directly into the DOM,
without converting your SVGs into React components. This approach reduces your bundle size, improves loading times,
and helps lower your application's carbon footprint.
This component is intended to be used in the same way as the HTML <img> tag, providing a simple and familiar API for developers used to working with standard images.
💡 Philosophy and Advantages
- Performance: SVGs are loaded on demand, preventing your JavaScript bundle from becoming bloated.
- Eco-design: Less transformation, less generated code, fewer resources consumed.
- Accessibility: Option to provide alternative text (
alt) for each SVG. - Flexibility: The component accepts all native SVG element props, making customization (size, color, etc.) easy.
- Interoperability: Works with remote URLs or local imports.
- Modern bundler compatibility: Also works with the inline mode of modern bundlers like Vite and Rspack, allowing you to import SVGs as optimized string assets.
📦 Installation
npm install @pplancq/svg-reactUsage in your React application
import { Svg } from '@pplancq/svg-react';
import mySvg from './my-svg.svg';
export const App = () => {
return <Svg src={mySvg} alt="mySvg" fill="red" />;
};📖 Usage Guide
This SVG component is designed to be as flexible and customizable as a native SVG element. It inherits all the props of a standard SVG component, so you can use it just like a regular SVG element.
🏷️ Props
🔒 Security: Custom Sanitization Configuration
By default, all SVG content is sanitized using DOMPurify to prevent XSS attacks. However, DOMPurify's default configuration may remove certain SVG elements or attributes that are safe in controlled environments, such as animation elements.
If you control your SVG sources and need to allow specific elements or attributes, you can use the sanitizeConfig prop:
import { Svg } from '@pplancq/svg-react';
<Svg
src="/spinner.svg"
alt="Loading animation"
sanitizeConfig={{
allowTags: ['animateTransform', 'animate'],
allowAttributes: ['to', 'from', 'dur', 'repeatCount'],
}}
/>Available Configuration Options
The sanitizeConfig prop accepts a SanitizeConfig object with the following properties:
allowTags: Array of additional tag names to allow (e.g.,['animateTransform', 'animate'])allowAttributes: Array of additional attribute names to allow (e.g.,['to', 'from', 'dur', 'repeatCount'])forbidTags: Array of tag names to explicitly forbid (e.g.,['script', 'iframe'])forbidAttributes: Array of attribute names to explicitly forbid (e.g.,['onerror', 'onclick'])allowDataAttributes: Boolean to allowdata-*attributes (default:false)
⚠️ Security Warning
IMPORTANT: The sanitizeConfig option should only be used when:
- You control and trust the source of your SVG files
- You understand the security implications of allowing specific elements/attributes
- You have validated that your configuration doesn't introduce XSS vulnerabilities
DO NOT use custom sanitization configurations with user-uploaded SVGs or SVGs from untrusted sources.
Common Use Cases
Allowing SVG animations:
<Svg
src="/animated-icon.svg"
alt="Animated icon"
sanitizeConfig={{
allowTags: ['animate', 'animateTransform', 'animateMotion'],
allowAttributes: ['from', 'to', 'dur', 'repeatCount', 'values', 'keyTimes'],
}}
/>Allowing data attributes for JavaScript interactions:
<Svg
src="/interactive.svg"
alt="Interactive graphic"
sanitizeConfig={{
allowDataAttributes: true,
}}
/>✅ Best Practices
- Use the
altprop to improve accessibility. - Prefer asynchronous loading for large or non-critical SVGs.
- Customize your SVGs via props (
fill,width,height, etc.) for optimal integration. - You can also style your SVGs by applying CSS classes (
className) to manage styles centrally. - Security: Keep the default sanitization settings unless you have a specific need and fully control your SVG sources. Only use
sanitizeConfigwith trusted SVGs.
🛠️ Use Cases
- Dynamic or themed icons.
- Remote or local SVG illustrations.
- Eco-friendly replacement for SVG imports transformed into React components.
🧑🔬 Tests
📝 Testing components using <Svg />
Since version 3, the <Svg /> component uses useSyncExternalStore internally — no Suspense boundary is required. Standard render from @testing-library/react is all you need.
The @testing-library/react’s waitFor utility handles asynchronous updates from the store automatically.
📋 Example usage with a custom component
Suppose you have an IconButton component that uses the <Svg /> component to display an icon:
import { Svg } from '@pplancq/svg-react';
export function IconButton() {
return (
<button>
<Svg src="/icon.svg" alt="button icon" width={24} height={24} />
Action
</button>
);
}To test this component, use render and waitFor from @testing-library/react:
import { render, screen, waitFor } from '@testing-library/react';
import { IconButton } from './IconButton';
it('should render the button with its SVG icon', async () => {
render(<IconButton />);
await waitFor(() => {
expect(screen.getByRole('img', { name: 'button icon' })).toBeInTheDocument();
});
expect(screen.getByRole('button', { name: /action/i })).toBeInTheDocument();
});🏆 Best practices for testing
- Use
renderfrom@testing-library/reactdirectly — no wrapper needed. - Use
waitForto assert on the state after the SVG has loaded. - To simulate loading or failure of an SVG, mock
fetchin your tests (e.g. withvi.fn()ormsw).
For more examples, see the package’s test files.
