Spacer

Empty space as an element. It exists for one job: pushing siblings apart inside a flex container.

Primitives Spacer.jsx Spacer.d.ts Spacer.md

Playground

Change a prop and watch it. The code below follows along.

Install and import

Spacer is in @dovetail-ds/react. Install it with React, if you haven't:

npm install @dovetail-ds/react react react-dom
import { Spacer } from "@dovetail-ds/react";

Import @dovetail-ds/react/styles.css once at your app's root, then your theme after it. Setup covers the stylesheets, fonts and dark mode.

Guidelines

Empty space as an element. It exists for one job: pushing siblings apart inside a flex container.

Use it flexible, rarely fixed

With no size, Spacer absorbs the remaining space: the clean way to push a trailing action to the far end of a toolbar without margin-left: auto scattered through the markup.

``jsx <Inline align="center"> <Heading>Members</Heading> <Spacer /> <Button variant="primary">Invite</Button> </Inline> ``

A fixed size is almost always the wrong tool. If two children need a gap, set gap on the Stack or Inline that holds them; the container should own the rhythm, not a sibling wedged between them. Reach for a fixed Spacer only when one gap in a set genuinely differs and you do not want to split the container in two.

Spacer is aria-hidden. It never carries content.

Props

The typed contract, from Spacer.d.ts.

import * as React from "react";

/** Flexible or fixed empty space inside a flex container. */
export interface SpacerProps extends React.HTMLAttributes<HTMLElement> {
  /** Fixed size from the space scale. Omit to absorb all remaining space. */
  size?: "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  /** @default "vertical" */
  axis?: "vertical" | "horizontal";
}

export declare function Spacer(props: SpacerProps): React.JSX.Element;

Tokens it reads

Every custom property Spacer.jsx resolves, read from the source: 7 semantic. Component tier first, because that is the one to reach for.

  • semantic Shared roles. Override one and everything using that role moves with it.
TokenTierDeclared as
--dt-space-stack-2xlsemanticvar(--dt-dim-16)
--dt-space-stack-2xssemanticvar(--dt-dim-1)
--dt-space-stack-lgsemanticvar(--dt-dim-6)
--dt-space-stack-mdsemanticvar(--dt-dim-4)
--dt-space-stack-smsemanticvar(--dt-dim-3)
--dt-space-stack-xlsemanticvar(--dt-dim-10)
--dt-space-stack-xssemanticvar(--dt-dim-2)

Source

React only, no dependencies, every value a token.

import React from "react";

const SIZES = { "2xs": "var(--dt-space-stack-2xs)", xs: "var(--dt-space-stack-xs)", sm: "var(--dt-space-stack-sm)", md: "var(--dt-space-stack-md)", lg: "var(--dt-space-stack-lg)", xl: "var(--dt-space-stack-xl)", "2xl": "var(--dt-space-stack-2xl)" };

export function Spacer({ size, axis = "vertical", style, ...rest }) {
  if (size === undefined) {
    return <div aria-hidden="true" style={{ flex: 1, ...style }} {...rest} />;
  }
  const value = SIZES[size] || SIZES.md;
  return <div aria-hidden="true" style={{ flex: "none", width: axis === "horizontal" ? value : undefined, height: axis === "vertical" ? value : undefined, ...style }} {...rest} />;
}

In context

Spacer also appears on the primitives reference cards, alongside the rest of its family.