
Company News
Socket Named Top Sales Organization by RepVue
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.
@isoterik/react-word-cloud
Advanced tools
A lightweight, interactable and customizable React word cloud library powered by d3-cloud, featuring built-in animations, tooltips, and flexible word rendering.
@isoterik/react-word-cloud is a lightweight and customizable React library for generating beautiful, animated word clouds. It leverages d3-cloud for layout calculations and provides a rich set of features, including built-in support for gradients, animated word renderers, and a powerful hook for total control over rendering.
AnimatedWordRenderer.Check out the live demo (playground) to see react-word-cloud in action and explore its capabilities.
Install via npm or yarn:
npm install @isoterik/react-word-cloud
# or
yarn add @isoterik/react-word-cloud
import { Word, WordCloud } from "@isoterik/react-word-cloud";
const words: Word[] = [
{ text: "React", value: 500 },
{ text: "WordCloud", value: 300 },
{ text: "D3", value: 1000 },
{ text: "JavaScript", value: 400 },
{ text: "TypeScript", value: 600 },
{ text: "Word", value: 800 },
{ text: "Cloud", value: 200 },
];
function App() {
return (
<div
style={{
width: "400px",
height: "400px",
}}
>
<WordCloud words={words} width={300} height={200} />
</div>
);
}
export default App;
Apply attractive linear or radial gradients to your word cloud.
import { Gradient, Word, WordCloud, WordCloudProps } from "@isoterik/react-word-cloud";
const words: Word[] = [
{ text: "React", value: 500 },
{ text: "WordCloud", value: 300 },
{ text: "D3", value: 1000 },
{ text: "JavaScript", value: 400 },
{ text: "TypeScript", value: 600 },
{ text: "Word", value: 800 },
{ text: "Cloud", value: 200 },
];
const gradients: Gradient[] = [
{
id: "gradient1",
type: "linear",
angle: 45, // in degrees
stops: [
{ offset: "0%", color: "#ff7e5f" },
{ offset: "100%", color: "#feb47b" },
],
},
{
id: "gradient2",
type: "radial",
stops: [
{ offset: "0%", color: "#6a11cb" },
{ offset: "100%", color: "#2575fc" },
],
},
];
const resolveFill: WordCloudProps["fill"] = (_word, index) => {
return index % 2 === 0 ? "url(#gradient1)" : "url(#gradient2)";
};
function App() {
return (
<div
style={{
width: "400px",
height: "400px",
}}
>
<WordCloud words={words} width={300} height={200} gradients={gradients} fill={resolveFill} />
</div>
);
}
export default App;
For smooth animations on word entrance, use the built-in AnimatedWordRenderer. It animates opacity and scale transitions for each word.
import { Word, WordCloud, WordCloudProps, AnimatedWordRenderer } from "@isoterik/react-word-cloud";
const words: Word[] = [
{ text: "React", value: 500 },
{ text: "WordCloud", value: 300 },
{ text: "D3", value: 1000 },
{ text: "JavaScript", value: 400 },
{ text: "TypeScript", value: 600 },
{ text: "Word", value: 800 },
{ text: "Cloud", value: 200 },
];
const animatedWordRenderer: WordCloudProps["renderWord"] = (data, ref) => (
<AnimatedWordRenderer ref={ref} data={data} animationDelay={(_word, index) => index * 50} />
);
function App() {
return (
<div
style={{
width: "400px",
height: "400px",
}}
>
<WordCloud words={words} width={300} height={200} renderWord={animatedWordRenderer} />
</div>
);
}
export default App;
Hint
- When using a custom renderer, you need to utilize the
refparameter provided to the function to set up the ref for the word element. This is required when you need tooltips, but it is recommended to always set thereffor the word element.- If you don't want to modify any properties of the
AnimatedWordRenderercomponent, you can import and use theanimatedWordRendererconstant from the library.
@isoterik/react-word-cloud includes a default tooltip implementation (powered by floating-ui) with animated transitions. You can enable it or completely override it with your own tooltip renderer for full customization.
Enable the default tooltip by setting the enableTooltip prop to true:
import { Word, WordCloud } from "@isoterik/react-word-cloud";
const words: Word[] = [
{ text: "React", value: 500 },
{ text: "WordCloud", value: 300 },
{ text: "D3", value: 1000 },
{ text: "JavaScript", value: 400 },
{ text: "TypeScript", value: 600 },
{ text: "Word", value: 800 },
{ text: "Cloud", value: 200 },
];
function App() {
return (
<div
style={{
width: "400px",
height: "400px",
}}
>
<WordCloud words={words} width={300} height={200} enableTooltip />
</div>
);
}
export default App;
You can customize the default tooltip styles by rendering the DefaultTooltip component using the renderTooltip prop:
import { DefaultTooltipRenderer, Word, WordCloud, WordCloudProps } from "@isoterik/react-word-cloud";
const words: Word[] = [
{ text: "React", value: 500 },
{ text: "WordCloud", value: 300 },
{ text: "D3", value: 1000 },
{ text: "JavaScript", value: 400 },
{ text: "TypeScript", value: 600 },
{ text: "Word", value: 800 },
{ text: "Cloud", value: 200 },
];
const animatedWordRenderer: WordCloudProps["renderTooltip"] = (data) => (
<DefaultTooltipRenderer
data={data}
placement="bottom"
transform={false}
containerStyle={{
borderRadius: "10px",
flexDirection: "column",
minWidth: "100px",
background: `${data.word?.fill}BF`, // 75% opacity
}}
textStyle={{
fontFamily: "Arial",
fontSize: "16px",
}}
/>
);
function App() {
return (
<div
style={{
width: "400px",
height: "400px",
}}
>
<WordCloud
words={words}
width={300}
height={200}
enableTooltip
renderTooltip={animatedWordRenderer}
/>
</div>
);
}
export default App;
Hint
TheDefaultTooltipRenderercomponent accepts additional props for customizing the tooltip includingUseFloatingOptionsprops used by theuseFloatinghook internally.
For full control over the tooltip rendering, you can provide your own custom tooltip renderer using the renderTooltip prop:
import { Word, WordCloud, WordCloudProps, TooltipRendererData, useTooltip } from "@isoterik/react-word-cloud";
const words: Word[] = [
{ text: "React", value: 500 },
{ text: "WordCloud", value: 300 },
{ text: "D3", value: 1000 },
{ text: "JavaScript", value: 400 },
{ text: "TypeScript", value: 600 },
{ text: "Word", value: 800 },
{ text: "Cloud", value: 200 },
];
const MyFloatingTooltip = ({ data }: { data: TooltipRendererData }) => {
const { refs, floatingStyles } = useTooltip({ data, placement: "top", transform: false });
return (
<div
ref={refs.setFloating}
style={{
background: "linear-gradient(135deg, rgba(50,50,50,0.95), rgba(30,30,30,0.95))",
color: "#fff",
padding: "10px 16px",
borderRadius: "8px",
boxShadow: "0 4px 8px rgba(0, 0, 0, 0.3)",
transform: "translate(12px, 12px)",
transition: "all 300ms ease-in-out",
pointerEvents: "none",
zIndex: 1000,
opacity: data.word ? 1 : 0,
...floatingStyles,
}}
>
<div style={{ fontWeight: "bold", fontSize: "14px", marginBottom: "4px" }}>
{data.word?.text}
</div>
{data.word && <div style={{ fontSize: "12px", opacity: 0.8 }}>Value: {data.word.value}</div>}
</div>
);
};
const tooltipRenderer: WordCloudProps["renderTooltip"] = (data) => (
<MyFloatingTooltip data={data} />
);
function App() {
return (
<div
style={{
width: "400px",
height: "400px",
}}
>
<WordCloud
words={words}
width={300}
height={200}
enableTooltip
renderTooltip={tooltipRenderer}
/>
</div>
);
}
export default App;
Hint
- The library comes with
@floating-ui/react-dominstalled for handling tooltips, and we recommend using it for consistent and accessible floating UIs.@floating-ui/react-domis not a peer dependency of@isoterik/react-word-cloud, and you can use any floating UI library of your choice but if you want to use it, theuseTooltiphook is provided for easy integration.- When using the
useTooltiphook, thereffor the word is configured automatically, but you still have to manage the tooltip's content and styles including setting thereffor the floating element (this is required).
You can handle mouse and computation events on words by providing event handlers to the WordCloud component:
import { Word, WordCloud, FinalWordData, ComputedWordData } from "@isoterik/react-word-cloud";
import { useCallback } from "react";
const words: Word[] = [
{ text: "React", value: 500 },
{ text: "WordCloud", value: 300 },
{ text: "D3", value: 1000 },
{ text: "JavaScript", value: 400 },
{ text: "TypeScript", value: 600 },
{ text: "Word", value: 800 },
{ text: "Cloud", value: 200 },
];
function App() {
const handleWordClick = useCallback((word: FinalWordData, index: number) => {
console.log("Clicked on word: ", word.text, index);
}, []);
const handleWordMouseOver = useCallback((word: FinalWordData, index: number) => {
console.log("Mouse over word: ", word.text, index);
}, []);
const handleWordMouseOut = useCallback((word: FinalWordData, index: number) => {
console.log("Mouse out word: ", word.text, index);
}, []);
const handleStartComputation = useCallback(() => {
console.log("Computation started..");
}, []);
const handleWordComputed = useCallback((word: ComputedWordData, index: number) => {
console.log("Computed word: ", word.text, index);
}, []);
const handleCompleteComputation = useCallback((words: ComputedWordData[]) => {
console.log("Computation completed..", words);
}, []);
return (
<div
style={{
width: "400px",
height: "400px",
}}
>
<WordCloud
words={words}
width={300}
height={200}
onWordClick={handleWordClick}
onWordMouseOver={handleWordMouseOver}
onWordMouseOut={handleWordMouseOut}
onStartComputation={handleStartComputation}
onWordComputed={handleWordComputed}
onCompleteComputation={handleCompleteComputation}
/>
</div>
);
}
export default App;
You can configure other properties of the word cloud, such as the font family, font size, random number generator function and padding, by passing them as props to the WordCloud component:
import { Word, WordCloud, WordCloudProps, defaultFontSize } from "@isoterik/react-word-cloud";
const words: Word[] = [
{ text: "React", value: 500 },
{ text: "WordCloud", value: 300 },
{ text: "D3", value: 1000 },
{ text: "JavaScript", value: 400 },
{ text: "TypeScript", value: 600 },
{ text: "Word", value: 800 },
{ text: "Cloud", value: 200 },
];
const fonts: string[] = ["Arial", "Courier New", "Cursive"];
const rotationWeights: number[] = [0, 0, 90, 270];
const resolveFont: WordCloudProps["font"] = (_word, index) => {
return fonts[index % fonts.length];
};
const resolveFontWeight: WordCloudProps["fontWeight"] = (word) => {
const value = word.value;
if (value < 400) {
return "normal";
} else if (value < 700) {
return "bold";
} else {
return "bolder";
}
};
const resolveRotate: WordCloudProps["rotate"] = () => {
return rotationWeights[Math.floor(Math.random() * rotationWeights.length)];
};
function App() {
return (
<div
style={{
width: "400px",
height: "400px",
}}
>
<WordCloud
words={words}
width={300}
height={200}
font={resolveFont}
fontWeight={resolveFontWeight}
fontSize={defaultFontSize}
rotate={resolveRotate}
fontStyle="normal"
spiral="rectangular"
transition="all .3s ease"
padding={2}
timeInterval={1}
random={Math.random}
svgProps={{
preserveAspectRatio: "xMidYMid slice",
}}
/>
</div>
);
}
export default App;
For ultimate flexibility, use the useWordCloud hook to handle layout computations asynchronously while you fully control how the words are rendered and how the SVG container is structured. The hook also accepts the timeInterval prop to control the maximum amount of time the browser spends on computations during each timestep and also similar props accepted by the WordCloud component.
import { defaultFill, defaultFontSize, useWordCloud, Word, WordCloudProps } from "@isoterik/react-word-cloud";
const words: Word[] = [
{ text: "React", value: 500 },
{ text: "WordCloud", value: 300 },
{ text: "D3", value: 1000 },
{ text: "JavaScript", value: 400 },
{ text: "TypeScript", value: 600 },
{ text: "Word", value: 800 },
{ text: "Cloud", value: 200 },
];
const fonts: string[] = ["Arial", "Courier New", "Cursive"];
const rotationWeights: number[] = [0, 0, 90, 270];
const resolveFont: WordCloudProps["font"] = (_word, index) => {
return fonts[index % fonts.length];
};
const resolveFontWeight: WordCloudProps["fontWeight"] = (word) => {
const value = word.value;
if (value < 400) {
return "normal";
} else if (value < 700) {
return "bold";
} else {
return "bolder";
}
};
const resolveRotate: WordCloudProps["rotate"] = () => {
return rotationWeights[Math.floor(Math.random() * rotationWeights.length)];
};
const WIDTH = 300;
const HEIGHT = 200;
function App() {
const { computedWords } = useWordCloud({
words,
width: WIDTH,
height: HEIGHT,
font: resolveFont,
fontWeight: resolveFontWeight,
fontSize: defaultFontSize,
rotate: resolveRotate,
fontStyle: "normal",
spiral: "rectangular",
padding: 2,
timeInterval: 1,
});
return (
<div
style={{
width: "400px",
height: "400px",
}}
>
<svg viewBox={`0 0 ${WIDTH} ${HEIGHT}`}>
<g transform={`translate(${WIDTH / 2},${HEIGHT / 2})`}>
{computedWords.map((word, index) => (
<text
key={index}
textAnchor="middle"
transform={`translate(${word.x}, ${word.y}) rotate(${word.rotate})`}
style={{
fontSize: word.size,
fontFamily: word.font,
fontWeight: word.weight,
fill: typeof defaultFill === "function" ? defaultFill(word, index) : defaultFill,
transform: `translate(${word.x}, ${word.y}) rotate(${word.rotate})`,
transition: "all 0.3s ease",
}}
>
{word.text}
</text>
))}
</g>
</svg>
</div>
);
}
export default App;
Word[] text property representing the word and a value property representing the word's weight.
Words with higher values are more important and will be considered before words with lower values during layout computations.number number number 1"archimedean" | "rectangular" "archimedean"number 1string | (word: Word, index: number) => string "Impact"number | (word: Word, index: number) => number (word) => Math.sqrt(word.value)string | (word: Word) => string "normal"string | (word: Word) => string "normal"(word: Word, index: number) => number () => (~~(Math.random() * 6) - 3) * 30() => number Math.randomstring | (word: Word, index: number) => string (_, index) => scaleOrdinal(schemeCategory10)(String(index))string | (word: Word) => string "all .5s ease"Gradient[] id property representing the gradient ID, a type property representing the gradient type (linear or radial), and a stops property representing the gradient stops.
This only applies when the fill prop is set to a function that returns a gradient fill.Omit<SVGProps<SVGSVGElement>, "ref" | "children"> React.ForwardedRef<SVGSVGElement> boolean true, a tooltip will be displayed when hovering over words. false(data: TooltipRendererData) => React.ReactNode <DefaultTooltipRenderer />(data: WordRendererData, ref?: Ref<SVGTextElement>) => React.ReactNode <DefaultWordRenderer />(word: FinalWordData, index: number, event: React.MouseEvent<SVGTextElement, MouseEvent>) => void (word: FinalWordData, index: number, event: React.MouseEvent<SVGTextElement, MouseEvent>) => void (word: FinalWordData, index: number, event: React.MouseEvent<SVGTextElement, MouseEvent>) => void () => void (word: ComputedWordData, index: number) => void (words: ComputedWordData[]) => void WordRendererData React.CSSProperties React.ForwardedRef<SVGTextElement> WordRendererData number | (word: Word, index: number) => number (_, index) => index * 10React.CSSProperties React.ForwardedRef<SVGTextElement> TooltipRendererData number 300React.CSSProperties React.CSSProperties React.CSSProperties This hook provides a way to perform layout computations asynchronously while retaining full control over the rendered SVG. It returns an object containing the computed words and other useful data. It computes and returns the words based on the provided parameters and the layout algorithm.
The parameters of the useWordCloud hook are the same as the props of the WordCloud component excluding the containerStyle, enableTooltip, renderTooltip, renderWord, onWordClick, onWordMouseOver, and onWordMouseOut props.
The return value of the useWordCloud hook is an object containing the computed words and the loading state of the layout computation:
ComputedWordData[] boolean true, the layout computation is still running, and all the computed words are not yet available.This hook provides a way to handle tooltip interactions with ease using @floating-ui/react-dom. It returns an object containing the tooltip refs and floating styles for positioning the tooltip.
TooltipRendererData UseFloatingOptions type provided by @floating-ui/react-dom.The return value of the useTooltip hook is an object containing the tooltip refs and floating styles for positioning the tooltip
TooltipRefs setFloating ref should be set on the floating element of the tooltip.React.CSSProperties UseFloatingResult type provided by @floating-ui/react-dom.A type representing a word object to be displayed in the word cloud.
string number A type representing a gradient object to be used for rendering words in the word cloud.
string "linear" | "radial" linear or radial).number GradientStop[] A type representing a gradient stop object to be used for rendering words in the word cloud.
string string A type representing the computed data of a word in the word cloud layout.
Word type.number number number string string number number string A type representing the final data of a word that can be rendered in the word cloud.
ComputedWordData type.string string A type representing the data object for rendering a word in the word cloud.
FinalWordData type.number (word: FinalWordData, index: number, event: React.MouseEvent<SVGTextElement, MouseEvent>) => void onWordClick event handler of the WordCloud component.(word: FinalWordData, index: number, event: React.MouseEvent<SVGTextElement, MouseEvent>) => void onWordMouseOver event handler of the WordCloud component.(word: FinalWordData, index: number, event: React.MouseEvent<SVGTextElement, MouseEvent>) => void onWordMouseOut event handler of the WordCloud component.A type representing the data object for rendering a tooltip in the word cloud.
FinalWordData | null SVGTextElement | null SVGSVGElement React.MouseEvent<SVGTextElement, MouseEvent> | null number number This library is built using Vite, yalc, and Vitest for development and testing. To get started, clone the repository and run the following commands:
# Install dependencies
npm install
# Run Tests
npm run test
npm run test:coverage
# Build and publish the package to yalc
npm run build:local
# Link the package to a local react application
yalc link @isoterik/react-word-cloud
# Unlink the package
yalc remove @isoterik/react-word-cloud
Contributions are welcome! Please read our Code of Conduct and Contributing guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.
FAQs
A lightweight, interactable and customizable React word cloud library powered by d3-cloud, featuring built-in animations, tooltips, and flexible word rendering.
The npm package @isoterik/react-word-cloud receives a total of 3,062 weekly downloads. As such, @isoterik/react-word-cloud popularity was classified as popular.
We found that @isoterik/react-word-cloud demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.

Security News
NIST will stop enriching most CVEs under a new risk-based model, narrowing the NVD's scope as vulnerability submissions continue to surge.

Company News
/Security News
Socket is an initial recipient of OpenAI's Cybersecurity Grant Program, which commits $10M in API credits to defenders securing open source software.