react-rubber-stamp
v1.0.0
Published
π Worn-out rubber stamp component for React. Any text length, no CSS import, no image assets.
Maintainers
Readme
react-rubber-stamp π
Worn-out rubber stamp component for React β any text length, no CSS import, no image assets.

Most "stamp" components are a rectangle with a border. This one masks the ink with generated fractal noise β blotches where the pad ran dry, scratches carved by the worn edges of the rubber, and flecks of stray ink around the text β so it looks pressed rather than drawn. Everything is generated rather than loaded from a bitmap, and it tiles at a size tied to the type, so Beta and Confidential β do not distribute outside the organization carry the same grain at any font size.
Install π¦
npm install react-rubber-stampReact 17 or newer is a peer dependency.
Usage π¨
import { Stamp } from "react-rubber-stamp";
<Stamp>Beta</Stamp>;That is the whole setup. There is no stylesheet to import β the component injects its CSS into <head> on first render.
<Stamp color="#1e6f3f" rotate={6}>Approved</Stamp>
<Stamp distress="heavy" speckle={4}>Confidential β internal use only</Stamp>
<Stamp distress="none">Draft</Stamp>Any text length βοΈ
The grain is tiled rather than stretched, so a single word and a full sentence wear the same way.

Distress π§½
How much ink the pad has lost.

<Stamp distress="none">Approved</Stamp>
<Stamp distress="heavy">Approved</Stamp>Speckle π¦
Stray flecks of ink around the text, on a five-step scale. They are clipped to the frame, so a fleck never escapes past it. Defaults to one step below the matching distress level.

<Stamp speckle={0}>Received</Stamp>
<Stamp speckle={4}>Received</Stamp>Colors and rotation π¨

<Stamp color="#1e6f3f" rotate={6}>Approved</Stamp>
<Stamp color="#2b4f9c" rotate={-14}>Received</Stamp>Scales with font-size π
Borders, corners, padding and grain are all sized in em, so one font-size scales the whole stamp and keeps its proportions.

<Stamp style={{ fontSize: "3rem" }}>Certified</Stamp>Props π
| Prop | Type | Default | Description |
| ----------- | ------------------------------------------ | ------------------ | -------------------------------------------------------------------- |
| children | ReactNode | β | Text to stamp. Any length. |
| color | string | #c62828 | Ink color. Any CSS color. |
| distress | "none" \| "light" \| "medium" \| "heavy" | "medium" | How worn out the ink looks. |
| speckle | 0 \| 1 \| 2 \| 3 \| 4 | follows distress | Stray flecks of ink around the text. 0 is a clean press. |
| rotate | number | -8 | Rotation in degrees. |
| seed | string \| number | the text | Varies the noise pattern. Same seed always renders the same pattern. |
| opacity | number | 0.85 | Ink coverage, 0β1. |
| blendMode | MixBlendMode | multiply | How the ink blends with what is underneath. |
| wrap | boolean | false | Let long text break across lines. |
Any other prop (className, id, aria-*, onClick, β¦) is forwarded to the underlying <span>, and ref is forwarded too.
Theming π¨
Every visual detail is a custom property, so you can restyle the stamp from your own CSS without touching the props:
.my-stamp {
--rrs-font-family: "Special Elite", cursive;
--rrs-border-width: 0.2em;
--rrs-letter-spacing: 0.2em;
--rrs-radius: 0.4em 0.1em 0.35em 0.15em;
}<Stamp className="my-stamp">Beta</Stamp>Available properties: --rrs-color, --rrs-border-width, --rrs-border-style, --rrs-radius, --rrs-padding, --rrs-font-size, --rrs-font-family, --rrs-font-weight, --rrs-font-stretch, --rrs-letter-spacing, --rrs-tile-size, --rrs-opacity, --rrs-blend-mode, --rrs-rotate.
[!TIP] Sizes are in
emon purpose. Overriding one with a pixel value pins it while everything else keeps scaling, which is usually not what you want.
Notes π
[!NOTE] The stamp is decorative by default. If it carries meaning your users need, keep the text readable and skip
aria-hidden; if it only repeats something already on the page, passaria-hidden="true".
[!NOTE]
seeddefaults to the stamped text, so server and client renders agree. Two stamps with the same text look identical on purpose β pass an explicitseedwhen you want them to differ.
Demo πΊ
npm run demoBuilds the package and opens a page with every prop side by side, each example showing the JSX that produced it.
License
The MIT License @ 2026
