npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tacet-react

v0.1.2

Published

Tacet icon set for React: 320 outline glyphs where the cut is data, self-drawing animation, four cut densities, 64 musical instruments.

Readme

tacet-react

React component for the Tacet icon set — 320 outline glyphs where the cut is data, not geometry.

Gallery and docs: tacet.smurov.com

npm i tacet-react
import { Icon } from "tacet-react";

<Icon name="rocket" />
<Icon name="bell" size={20} animateIn />
<Icon name="saxophone" size={32} variant="A" />
<Icon name="status-done" solid title="Done" />

Not using React? Take tacet-element (a custom element) or tacet-core (the engine on its own).

Props

Appearance

| Prop | Type | Default | What it does | |---|---|---|---| | name | IconName | — | Glyph name. Typed: a wrong name is a compile error | | size | number | 24 | Size in pixels, used for width and height | | variant | "A"|"B"|"C"|"D" | "D" | A — one cut · B — all cuts · C — one cut and accent · D — all and accent | | solid | boolean | per glyph | Solid contour: cuts are not drawn. Some glyphs are solid by default — status marks, for instance | | strokeWidth | number | — | Stroke width on screen, in pixels. Once set, size no longer affects it | | absoluteStroke | boolean | false | Stroke stops following size: 1.5px at any size | | zoom | boolean | true | Optical zoom. Turn it off when the actual size is unknown | | accentColor | string | var(--tacet-accent, currentColor) | Colour of accent details | | title | string | — | Accessible label. Without it the icon is aria-hidden |

Anything else — className, onClick, style, data-* — goes straight to the <svg>.

Animation

| Prop | Type | Default | What it does | |---|---|---|---| | animateIn | boolean | false | Play the draw-in on mount | | animateOnHover | boolean | false | Replay on hover — see the hover target below | | replayKey | number|string | — | Change the value to replay on demand | | animationDelay | number | 0 | Delay before the start, ms | | animationMode | "draw"|"spin"|"pop"|"fade" | per glyph | Override the glyph's preset | | duration | number | 620 | Duration, ms | | spinDeg | number | 90 | Rotation for spin, degrees | | stagger | number | 0 | Spread of stroke starts, ms: the contour assembles out of order | | seq | number | 0 | Strict queue of strokes, ms per stroke |

Every glyph carries its own preset — loading spins, waveform staggers. The props above override it.

Animation respects prefers-reduced-motion: with the preference on, nothing moves at all.

The hover target

animateOnHover listens on the nearest clickable ancestor — hover the whole button and the icon inside it animates:

<button>
  <Icon name="trash" animateOnHover /> Delete
</button>

Nothing clickable around? Mark the container with data-tacet-hover and it becomes the target. Aiming at a 24px glyph is no fun; a cell or a card is:

<figure className="cell" data-tacet-hover>
  <Icon name="saxophone" size={28} animateOnHover />
  <figcaption>saxophone</figcaption>
</figure>

With neither a clickable ancestor nor the attribute, the icon listens to itself — animateOnHover is an explicit request, so it is never silently ignored.

Recognised by default: button, a, [role="button"], [role="menuitem"], [role="tab"], [role="option"], label, and anything with data-tacet-hover.

Accent colour

Accent details use --tacet-accent. Without the variable the icon is monochrome, so the set drops into any palette as is:

:root { --tacet-accent: #2a78d6; }

Per icon: <Icon name="bell" accentColor="#c94a17" />.

Stroke width

Stroke follows size by a power law rather than proportionally, so a large icon does not turn into a heavy blueprint:

| size | on screen | |---|---| | 12px | 1.10 | | 24px | 1.50 | | 48px | 2.05 | | 128px | 3.19 |

Need a constant hairline at any size — pass absoluteStroke. Need an exact value — pass strokeWidth, given in screen pixels.

The component also measures its actual width: icons often get shrunk by a CSS class while the props stay at the default 24, and a stroke computed for 24 would become a thread after the shrink.

Choosing a glyph

Every glyph carries a note on what it is for and what it gets confused with — useful when the code is written by an agent that picks icons by name:

import { META, searchIcons, iconNames } from "tacet-core";

META["trash"].use;     // "Permanent deletion, the item is gone."
META["trash"].avoid;   // "If the item is only moved out of sight … that is `archive` …"
META["trash"].related; // ["archive", "ban", "x"]

searchIcons("удалить", iconNames()); // ["trash", …] — synonyms are bilingual

Same data as icons.json and llms.txt.

Also exported

import { Icon, TacetIcon, reverse, canAnimateOnMount } from "tacet-react";
  • TacetIcon — the same component under a longer name, for projects that already have an Icon of their own
  • reverse(svg) — erase the contour back out, for loaders and for icons leaving the screen. The next play brings it back
  • canAnimateOnMount(matches) — whether the entrance is worth playing on this device. On a phone icons appear during scrolling: the animation is barely seen and costs a lot — on a bench of 360 icons it measured 1718 ms against 857 ms
const animate = canAnimateOnMount(window.matchMedia.bind(window));
<Icon name="rocket" animateIn={animate} />

Notes

React is a peer dependency: the package pulls nothing into your tree. The engine lives in tacet-core and knows nothing about React — the component is a thin wrapper that calls it.

MIT © Ilya Smurov