React-CRUD-Icons is a set of SVG icons for CRUD (Create, Read, Update, Delete) apps, implemented as a React component with light & dark themes and tooltip.
Check out React-CRUD-Icons live demo.
A set of icons for CRUD applications... hand-picked among thousands at Material Design Icons.
Themes: light, dark. Use theme="auto" to follow the user's system light/dark setting.
Only clickable icons (with onClick) have a hover effect. Set theme = "none" to render only the SVG, without CSS classes.
Sizes: tiny, small, medium, large, big, huge. Any other size can be set in pixels, for example size={20}.
For really large size icons, checkout the T-Shirts ;-)
The package can be installed via npm:
npm install react-crud-icons --save
React (version 17 or later) is a peer dependency and must be installed in your project.
To rebuild the library (Node.js 22.18+; source in src/Icon.tsx):
npm install
npm run build
To run the tests (Vitest and Testing Library, in test/):
npm test # run once
npm run test:watch # re-run on changes
npm run typecheck # type-check the library and the tests
npm run format # format the code with Prettier
See the CHANGELOG for what's new in each version.
To release a new version:
- Update the version in
package.json(anddemo/package.json) and the CHANGELOG, runnpm run build, and commit. - On GitHub, create a release with a tag matching the version (e.g.
2.0.0). Publishing the release runs the release workflow, which tests, builds, and publishes the package to npm.
To run or rebuild the demo (built with Vite into the docs folder):
cd demo
npm install
npm start # dev server
npm run build # production build into ../docs
Or from the project root: npm run build:demo. GitHub Pages serves the site from the docs folder of the main branch.
Below is a simple example of how to use the component in a React view. You will also need to include the CSS file from this package (or provide your own). The example below shows how to include the CSS from this package if your build system supports requiring CSS files (Webpack is one that does).
import React from "react";
import Icon from "react-crud-icons";
import "react-crud-icons/dist/css/react-crud-icons.css";
const ExampleComponent = () => (
<Icon
name="edit"
tooltip="Edit"
theme="light"
size="medium"
onClick={doSomething}
/>
);Notes:
- Icons with an "onClick" property render as
<button>elements: they take focus on tab and respond to Enter and Space. Disabled icons stay focusable (usingaria-disabled) so their tooltip remains readable. - Screen readers announce the
label(or thetooltip). Icons with neither a label, a tooltip, nor an onClick are treated as decorative and hidden from screen readers. - The component uses inline SVG for faster display.
- The package ships both ES module and CommonJS builds. The CSS can also be imported as
react-crud-icons/css.
The package is written in TypeScript and ships its own type definitions, so icon names are type-checked and autocompleted.
import Icon, { keys, sizes, createIconSet } from "react-crud-icons";
import type {
IconName,
IconProps,
IconSize,
IconTheme,
IconSet,
} from "react-crud-icons";
const name: IconName = "edit"; // "edti" would be a compile error| Prop | Description |
|---|---|
| name | Possible values: "account", "account-add", "add", "add2", "alert", "apps", "archive", "arrow-left", "arrow-right", "bars", "bell", "browse", "calendar", "cards", "check", "chevron-down", "chevron-up", "clone", "close", "collapse", "comment", "comments", "compare", "copy", "dashboard", "delete", "documentation", "dots", "dots-v", "down", "download", "drag", "edit", "error", "expand", "export", "favorite", "favorite-outline", "filter", "grid", "help", "hide", "history", "home", "home-circle", "image", "import", "info", "json", "link", "list", "list-bulleted", "lock", "lock-open", "logout", "map-marker", "moon", "paperclip", "pie", "print", "refresh", "remove", "save", "search", "settings", "share", "show", "sort", "sort-asc", "sort-desc", "stats", "sun", "tag", "treemap", "undo", "up", "upload", "wand". |
| path | Custom SVG path data instead of a name (a string, or an array of strings for multi-shape icons). Clickable icons with a custom path need a label or tooltip. |
| viewBox | SVG viewBox for custom paths (default "0 0 24 24"). |
| size | Possible values: "tiny", "small", "medium", "large", "big", "huge", or a number for the icon size in pixels (10px of padding is added around it, so size={26} matches "medium"). With theme="none", a number sets the SVG width and height. |
| theme | Possible values: "light", "dark", "auto" (follows the system light/dark setting). Use theme="none" to display raw SVG without the CSS classes and hover effect. |
| color | Icon color (any CSS color). Sets the --crud-icon-color CSS variable (or the SVG fill when theme="none"). |
| tooltip | Tooltip text shown on hover and keyboard focus (also used as the accessible label). |
| tooltipPlacement | Tooltip position: "bottom" (default), "top", "left", or "right". |
| label | Accessible label for screen readers. Defaults to the tooltip, then to the icon name for clickable icons. |
| disabled | Disable click event (icon in grey). The icon stays focusable so its tooltip remains readable. |
| active | Toggled-on state (e.g. favorite, lock): the icon is highlighted. Clickable icons also report it to screen readers (aria-pressed). |
| badge | Small count bubble on the corner (number or short text, e.g. 3 or "new"). Numbers above 99 show as "99+". The badge is included in the accessible label. |
| loading | Busy state: dims the icon, shows a spinner ring, and ignores clicks (e.g. while saving). |
| onClick | Callback function triggered when the icon is clicked (or activated with Enter or Space). Clickable icons render as buttons with a hover effect; icons without onClick have no hover effect. |
| className | Additional CSS class name. |
Any other standard HTML attribute (style, title, tabIndex, aria-*, data-*, onMouseEnter, onFocus, etc.) is passed through to the rendered element. A ref points to that element: a <button> for clickable icons, an <i> for static icons, or the <svg> when theme="none".
const ref = useRef(null);
<Icon
ref={ref}
name="delete"
tooltip="Delete"
onClick={onDelete}
data-testid="delete-btn"
style={{ marginLeft: 8 }}
/>;Wrap icons in an IconGroup to make an accessible toolbar with consistent spacing. Tab moves into and out of the group in one step, the arrow keys move between icons, and Home/End jump to the first and last icon.
import Icon, { IconGroup } from "react-crud-icons";
<IconGroup label="Record actions" size="small" theme="dark">
<Icon name="edit" tooltip="Edit" onClick={onEdit} />
<Icon name="save" tooltip="Save" onClick={onSave} loading={saving} />
<Icon
name="delete"
tooltip="Delete"
onClick={onDelete}
disabled={!canDelete}
/>
</IconGroup>;| Prop | Description |
|---|---|
| label | Accessible name of the toolbar (e.g. "Record actions"). |
| orientation | "horizontal" (default) or "vertical": layout and arrow-key direction. |
| gap | Space between icons: a number (pixels) or any CSS length (default 4px). Also settable with the --crud-icon-group-gap CSS variable. |
| size, theme, tooltipPlacement | Defaults for the icons in the group (each icon can still override them). Vertical groups place tooltips on the right by default. |
Other HTML attributes and ref are passed to the toolbar <div>. Only clickable icons take part in keyboard navigation; other controls in the toolbar (such as an input) keep their normal behavior.
Use any SVG path with the path prop. The built-in icons come from Material Design Icons, so the @mdi/js package (7,000+ icons as path strings) matches their style:
import Icon from "react-crud-icons";
import { mdiRocket } from "@mdi/js";
<Icon path={mdiRocket} label="Launch" onClick={launch} />;To use your own icons by name everywhere in an app, create an icon set. Names are type-checked and autocompleted in TypeScript:
// icons.js
import { createIconSet, defaultIcons } from "react-crud-icons";
import { mdiRocket, mdiTruck } from "@mdi/js";
export const Icon = createIconSet({
...defaultIcons, // keep the built-in icons (optional)
rocket: mdiRocket,
truck: mdiTruck,
});
// anywhere
<Icon name="rocket" tooltip="Launch" onClick={launch} />;Icon.names lists the names in a set.
The default Icon includes all the built-in icons (about 20 KB minified). Each built-in icon is also exported on its own, named icon + the icon name in PascalCase (edit → iconEdit, arrow-left → iconArrowLeft). An icon set built from just the icons you use lets bundlers (Vite, webpack, esbuild, Rollup...) drop all the others:
// icons.js
import {
createIconSet,
iconEdit,
iconSave,
iconDelete,
} from "react-crud-icons";
export const Icon = createIconSet({
edit: iconEdit,
save: iconSave,
delete: iconDelete,
});
// anywhere
<Icon name="save" tooltip="Save" onClick={save} />;With three icons, the library adds about 3-4 KB minified to an app instead of 20 KB. Tree-shaking needs the ES module build (used automatically by modern bundlers); require() always loads everything.
Colors can be customized with CSS variables, set on the icons or on any parent element (for example :root). Each variable falls back to the theme's default when not set.
| Variable | Description |
|---|---|
--crud-icon-color |
Icon color. |
--crud-icon-hover-color |
Icon color on hover and focus (defaults to --crud-icon-color when set). |
--crud-icon-hover-bg |
Background color on hover and focus. |
--crud-icon-disabled-color |
Icon color when disabled. |
--crud-icon-focus-ring |
Keyboard focus outline color. |
--crud-icon-tooltip-color |
Tooltip text color. |
--crud-icon-tooltip-bg |
Tooltip background color. |
--crud-icon-radius |
Corner radius of the hover background (default 50%). |
--crud-icon-active-color |
Icon color when active. |
--crud-icon-active-bg |
Background color when active. |
--crud-icon-badge-color |
Badge text color. |
--crud-icon-badge-bg |
Badge background color. |
--crud-icon-loading-color |
Spinner ring color (defaults to the icon color). |
.toolbar {
--crud-icon-color: #1565c0;
--crud-icon-hover-bg: #e3f2fd;
--crud-icon-radius: 6px;
}
/* different colors in the dark theme only */
.crud-icon.dark {
--crud-icon-hover-bg: #0d47a1;
}Copyright (c) 2026 Olivier Giulieri.
React-CRUD-Icons is Open Source with MIT license.
If you find React-CRUD-Icons useful, you can support its development by sponsoring me on GitHub.
To suggest a feature or report a bug: https://github.com/evoluteur/react-crud-icons/issues
Notes: React-CRUD-Icons was originally made for Evolutility-UI-React.