mrkeyoor.com_
Tue 22 Sept 22:36 UTC
npmWeb Frontendupdated 22 Sept 2026

@visx/group review

@visx/group 4.0.0 exports one React component that renders an SVG `<g>`. Numeric `left` and `top` props become `translate(left, top)`, a custom `transform` can replace that translation, `innerRef` exposes the `SVGGElement`, and remaining SVG group props pass through. It always adds the `visx-group` class. Group creates no chart, scale, axis, layout, animation, tooltip, accessibility description, or responsive container. Version 4 requires React 18 or 19, publishes package-root import and require entries, removes generated runtime PropTypes, and targets modern browsers; React 16, React 17, and IE11 users are told to stay on visx 3.

Verdict

@visx/group 4.0.0 installed in 1.8 seconds, used 1 MB, passed npm audit, and added 1.2 KB gzipped to our browser build. It is worth installing inside a visx 4 chart system that repeats translated groups; a standalone chart or a couple of native `<g>` elements do not justify it.

We installed it

Lab card: what happened when we installed @visx/groupScreenshot of @visx/group documentation
Install✓ · 1.8s3 packages on disk · 1 MB
ImportESM import works · require() works · CommonJS package with exports map
Browser1.2 KBgzipped (2.4 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does @visx/group install cleanly?

Yes. In a fresh container with an empty cache, npm install @visx/group finished in 2 seconds, leaving 3 packages and 1 MB on disk. npm audit reported no known vulnerabilities.

How much does @visx/group add to a browser bundle?

1.2 KB gzipped (2.4 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does @visx/group work with both ESM and CommonJS?

Yes. Both import '@visx/group' and require('@visx/group') worked in Node 22 in our run. The package is published as CommonJS with an exports map.

Does @visx/group include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

@visx/group or recharts: which should you use?

recharts: Use it for composed React charts with axes, legends, tooltips, responsiveness, and animation included. @visx/group 4.0.0 installed in 1.8 seconds, used 1 MB, passed npm audit, and added 1.2 KB gzipped to our browser build.

When should you not use @visx/group?

Only 1 or 2 translated groups exist. A native <g transform=...> shows the complete behavior and avoids another package.

API stability4/5Group has 1 component and a small visible prop contract: `top`, `left`, `transform`, `className`, children, `innerRef`, plus normal SVG group props. Version 4 keeps that runtime behavior but changes the platform boundary to React 18 or 19, modern browsers, package-root exports, and no generated PropTypes. Existing v3 component code is mostly familiar, while peer versions, deep imports, and runtime type inspection require deliberate migration.
Docs4/5The package page returned HTTP 200 and states that Group is a simplified SVG `<g>` with `top`, `left`, and `className`. The monorepo README supplies a full bar-chart example, and the v4 migration guide covers React peers, matching TypeScript types, root imports, PropTypes removal, modern browser targets, and coordinated upgrades. The brief package page does not explain transform precedence, `translate(0, 0)`, ref timing, or accessibility duties.
Maintenance5/5npm published 4.0.0 on June 11, 2026, and GitHub records a repository push on June 22, 2026. The unarchived visx monorepo has 21,021 stars and 148 open issues and pull requests. Version 4 includes migration instructions, React 19 support, modern entry points, and coordinated package changes. The monorepo structure means release health is strong, though applications should align every installed visx package on major 4.
Ecosystem5/5The npm endpoint counted 5,362,416 downloads in the week ending August 24, 2026. Group sits in a visx collection covering scales, shapes, axes, grids, text, gradients, tooltips, responsive sizing, events, and examples. It also accepts native React SVG children rather than imposing proprietary mark objects. Our check found both module entries, bundled declarations, and a 1.2 KB gzipped browser result, so it integrates cheaply when React is already present.

Use it if

  • A React chart already uses visx primitives and needs the same `left` and `top` convention for axes, marks, or margins.
  • Nested SVG coordinate systems appear often enough that a named typed component is clearer than repeated transform strings.
  • The underlying `<g>` needs ordinary SVG attributes, React event handlers, data attributes, or an explicit element ref.
  • The team wants low-level composition and will own chart layout, interaction, motion, and accessibility.
Skip it if

Setup reality

We installed @visx/group 4.0.0 in a fresh Node 22 Bookworm sandbox in 1.8 seconds. It left 3 packages and 1 MB on disk. npm audit reported 0 known vulnerabilities. The package has 1 direct dependency, 2 peer dependencies, bundled TypeScript declarations, an exports map, and 60 KB unpacked. Both CommonJS require() and ESM import worked on Node 22.23.2. Our browser build measured 2.4 KB minified and 1.2 KB gzipped.

React 18 or 19 is required. TypeScript projects should install the matching @types/react, which v4 declares as an optional peer rather than bundling. Upgrade all @visx/* packages to the same major and replace internal deep imports with package-root imports. The package itself installs only classnames; shapes, scales, axes, tooltips, responsive helpers, and text remain separate packages. The v4 migration also removed generated PropTypes, so code that inspected component propTypes at runtime must provide its own validation.

Group does not create an <svg>. Outside an SVG tree, its <g> has no useful chart rendering. Missing offsets default to 0 and still produce translate(0, 0). A truthy custom transform wins over left and top; include translation inside that string when it must combine with rotation or scale. className is merged with the permanent visx-group class, and other SVG props are spread after the explicit attributes. The documented ref prop is innerRef, not React's ordinary ref.

Server rendering produces plain SVG markup, but browser geometry such as getBBox() exists only after layout. Measure in an effect and rerun when data or fonts change. Group forwards pointer and keyboard handlers without supplying a role, focusability, key behavior, title, description, or data-table fallback. Interactive marks need those semantics from the application. Clip-path IDs also live at document scope, so repeated or server-rendered charts need unique IDs to avoid collisions.

Patterns

Offset SVG children translate-group

import { Group } from '@visx/group';

<svg width={320} height={180}>
  <Group left={24} top={16}>
    <circle cx={20} cy={20} r={12} fill={'tomato'} />
  </Group>
</svg>

Group writes a 24 by 16 translation. It does not resize the 320 by 180 viewport or reserve layout space.

Create an inner plotting area apply-margins

const margin = { top: 20, right: 16, bottom: 32, left: 48 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;

<svg width={width} height={height}>
  <Group left={margin.left} top={margin.top}>
    <rect width={innerWidth} height={innerHeight} fill={'none'} />
  </Group>
</svg>

Group applies only 1 translation. Your code must subtract margins from scale ranges and mark dimensions.

Build nested coordinate systems nest-coordinates

<Group left={margin.left} top={margin.top}>
  <Group left={plotX} top={plotY}>
    {points.map((point) => (
      <circle key={point.id} cx={point.x} cy={point.y} r={3} />
    ))}
  </Group>
</Group>

SVG composes both translations. Each point is positioned relative to the 2 parent groups.

Provide a complete transform set-transform

<Group transform={'translate(120 80) rotate(-30) scale(1.2)'}>
  <rect x={-20} y={-8} width={40} height={16} />
</Group>

A truthy `transform` overrides both offsets. Include `translate` yourself when rotation or scale also needs positioning.

Group each data series render-series

{series.map((item, index) => (
  <Group
    key={item.id}
    className={'chart-series'}
    top={index * rowHeight}
    data-series-id={item.id}
  >
    <path d={item.path} fill={item.color} />
  </Group>
))}

The custom class is combined with `visx-group`. Data attributes and other SVG props pass through to each `<g>`.

Share SVG presentation attributes inherit-styles

<Group fill={'#64748b'} stroke={'currentColor'} opacity={0.7}>
  <circle cx={10} cy={10} r={4} />
  <circle cx={30} cy={20} r={4} />
</Group>

Many SVG presentation attributes inherit through 1 group. An explicit child value can override the inherited fill, stroke, or opacity.

Make a group keyboard operable handle-keyboard

<Group
  role={'button'}
  tabIndex={0}
  aria-label={`Select ${series.name}`}
  onClick={() => selectSeries(series.id)}
  onKeyDown={(event) => {
    if (event.key === 'Enter' || event.key === ' ') selectSeries(series.id);
  }}
>
  {marks}
</Group>

Group supplies 0 interaction semantics. Add focus, a name, and keyboard behavior whenever a grouped mark acts like a control.

Describe an SVG group label-graphic

<Group role={'img'} aria-labelledby={'revenue-title revenue-desc'}>
  <title id={'revenue-title'}>Monthly revenue</title>
  <desc id={'revenue-desc'}>Bars from January through June</desc>
  {bars}
</Group>

The component creates no title or description. Test the 2 references with the target browsers and assistive technologies.

Clip marks to plot bounds clip-marks

<svg width={width} height={height}>
  <defs>
    <clipPath id={clipId}><rect width={innerWidth} height={innerHeight} /></clipPath>
  </defs>
  <Group left={margin.left} top={margin.top} clipPath={`url(#${clipId})`}>
    {marks}
  </Group>
</svg>

Clip-path IDs are document-wide. Generate a unique `clipId` for each repeated or server-rendered chart.

Measure after browser layout measure-group

const groupRef = useRef<SVGGElement>(null);
useLayoutEffect(() => {
  const bounds = groupRef.current?.getBBox();
  if (bounds) setBounds(bounds);
}, [marks]);

return <Group innerRef={groupRef}>{marks}</Group>;

`getBBox()` is unavailable during server rendering. Use `innerRef` and measure after mount, then repeat after data or fonts change.

Place a bottom axis position-axis

import { AxisBottom } from '@visx/axis';

<Group left={margin.left} top={margin.top}>
  {marks}
  <Group top={innerHeight}>
    <AxisBottom scale={xScale} />
  </Group>
</Group>

`@visx/axis` is a separate installation. Keep it on major 4 and reuse the same scale that positions the marks.

Use a plain group for one offset use-native-svg

const transform = `translate(${left}, ${top})`;

<g className={'series'} transform={transform}>
  {children}
</g>

Native SVG covers the main translation behavior with 0 package imports. Prefer it when the application does not otherwise use visx conventions.

Alternatives

PackageRegistryPick it when
rechartsnpmUse it for composed React charts with axes, legends, tooltips, responsiveness, and animation included.
victorynpmUse it when a declarative React chart suite fits better than assembling SVG primitives.
d3-selectionnpmUse it when D3 rather than React owns SVG elements, data joins, and DOM updates.

More web frontend guides

postcss · react · react-dom · tailwindcss · htmlparser2 · tailwind-merge · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.