Skip to content

Charts

Open-to-close Chart

An ordered series that highlights the movement from each opening value to its closing value.

When to use it: Use it for compact open-versus-close comparisons when high and low values are not part of the story.

On this page

Example

Loading example…
Open-to-close Chart.tsxtsx
import {
  ChartDescription,
  ChartTable,
  ChartTitle,
  ChartTooltip,
  OpenToCloseChart,
  OpenToCloseChartPlot,
  OpenToCloseChartRange,
} from "@comp0/react";

const prices = [
  { x: 1, open: 98, close: 104 },
  { x: 2, open: 104, close: 101 },
  { x: 3, open: 101, close: 110 },
  { x: 4, open: 110, close: 108 },
] as const;

const formatPrice = (value: number) => `$${value}`;

export function Example() {
  return (
    <OpenToCloseChart
      values={prices}
      xLabel="Trading day"
      yLabel="Share price"
      formatX={(value) => `Day ${value}`}
      formatY={formatPrice}
      className="w-full max-w-2xl rounded-lg has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-4 has-[:focus-visible]:outline-teal-600 dark:has-[:focus-visible]:outline-teal-400"
    >
      <ChartTitle className="text-base font-semibold text-zinc-950 dark:text-zinc-50">
        Opening to closing price
      </ChartTitle>
      <OpenToCloseChartPlot
        aria-label="Open-to-close chart showing four trading days"
        className="mx-auto mt-5 aspect-square w-full max-w-md overflow-visible"
      >
        {(range) => (
          <OpenToCloseChartRange range={range} className="group outline-none">
            <line
              x1={range.x}
              x2={range.x}
              y1={range.openY}
              y2={range.closeY}
              className="stroke-teal-600 group-data-[direction=down]:stroke-rose-600 dark:stroke-teal-400 dark:group-data-[direction=down]:stroke-rose-400"
              strokeWidth="3"
              vectorEffect="non-scaling-stroke"
            />
            <line
              x1={range.x - range.width / 2}
              x2={range.x + range.width / 2}
              y1={range.openY}
              y2={range.openY}
              className="stroke-zinc-700 dark:stroke-zinc-300"
              strokeWidth="2"
              vectorEffect="non-scaling-stroke"
            />
            <circle
              cx={range.x}
              cy={range.closeY}
              r="2.4"
              className="fill-zinc-950 dark:fill-white"
            />
          </OpenToCloseChartRange>
        )}
      </OpenToCloseChartPlot>
      <ChartDescription className="mt-5 text-sm text-zinc-600 dark:text-zinc-400">
        Day three produced the strongest upward move; day two closed below its open.
      </ChartDescription>
      <ChartTable className="mt-4 w-full border-collapse text-left text-sm [&_td]:border-t [&_td]:border-zinc-200 [&_td]:py-2 [&_th]:border-zinc-200 [&_th]:py-2 dark:[&_td]:border-zinc-800 dark:[&_th]:border-zinc-800">
        <caption className="sr-only">Opening and closing prices</caption>
        <thead>
          <tr>
            <th scope="col">Day</th>
            <th scope="col">Open</th>
            <th scope="col">Close</th>
          </tr>
        </thead>
        <tbody>
          {prices.map((price) => (
            <tr key={price.x}>
              <th scope="row">Day {price.x}</th>
              <td>{formatPrice(price.open)}</td>
              <td>{formatPrice(price.close)}</td>
            </tr>
          ))}
        </tbody>
      </ChartTable>
      <ChartTooltip className="pointer-events-none z-50 rounded-md bg-zinc-950 px-2 py-1 text-sm text-white shadow-lg dark:bg-zinc-50 dark:text-zinc-950" />
    </OpenToCloseChart>
  );
}

Anatomy

Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.

A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.

  1. OpenToCloseChart

    Native figure sharing ordered opening and closing values with every part. Owns a DOM element.

  2. ChartTitle

    Native figcaption that visibly names the figure. Owns a DOM element.

  3. OpenToCloseChartPlot / OpenToCloseChartRange

    Ordered SVG ranges with explicit open and close endpoints. Owns a DOM element.

  4. ChartDescription

    Visible prose summarizing the movement. Owns a DOM element.

  5. ChartTable

    Native table with exact open and close values. Owns a DOM element.

  6. ChartTooltipOptional

    Optional floating open/close pair label shown on hover or focus. Owns a DOM element.

Step by step

  1. 1

    Add the main part

    Start OpenToCloseChart with strictly increasing x values and explicit open and close labels.

  2. 2

    Add the supporting parts

    Render each range with OpenToCloseChartRange so the direction and both endpoints are keyboard reachable.

  3. 3

    Make the behavior clear

    Describe upward and downward movement with shape or position as well as color, and list both values in a native table.

    Exampletsx
    <OpenToCloseChart values={prices} xLabel="Trading day" yLabel="Share price">
      <ChartTitle>Opening to closing price</ChartTitle>
      <OpenToCloseChartPlot aria-label="Open-to-close chart showing trading days">
        {(range) => (
          <OpenToCloseChartRange range={range}>
            <line x1={range.x} x2={range.x} y1={range.openY} y2={range.closeY} />
          </OpenToCloseChartRange>
        )}
      </OpenToCloseChartPlot>
      <ChartTable>
        <caption>Opening and closing prices</caption>
      </ChartTable>
      <ChartTooltip />
    </OpenToCloseChart>;

Keyboard

Enters the chart at its current range and leaves with one more Tab.
Moves to the next range without wrapping.
Moves to the previous range without wrapping.
Home
Moves to the first range.
End
Moves to the last range.
Esc
Dismisses an open ChartTooltip.

Forms and accessibility

Charts are descriptive content and do not create form values.

Accessibility checklist

  • Keep both axis labels visible and use the same formatters for x values, open values, close values, and the table.
  • Wrap each range in OpenToCloseChartRange so its open and close values are one roving tab stop.
  • Announce the explicit open and close labels and use shape or position as well as color for direction.
  • Include both endpoints in a native table; ChartTooltip must not be the only source of exact values.

API reference

Importtsx
import { ChartDescription, ChartTable, ChartTitle, ChartTooltip, OpenToCloseChart, OpenToCloseChartPlot, OpenToCloseChartRange } from "@comp0/react";

OpenToCloseChart

DOM element

Native figure sharing ordered opening and closing values with every part.

PropTypeDescription
valuesreadonly OpenToCloseChartValue[]Strictly increasing x values with finite open and close values.
xLabelstringVisible headings for time and value axes.
yLabelstringVisible headings for time and value axes.
openLabelstringAccessible and table labels for each endpoint.
closeLabelstringAccessible and table labels for each endpoint.
formatX(value) => stringFormatters shared by ticks and table cells.
formatY(value) => stringFormatters shared by ticks and table cells.

ChartTitle

DOM element

Native figcaption that visibly names the figure.

OpenToCloseChartPlot / OpenToCloseChartRange

DOM element

Ordered SVG ranges with explicit open and close endpoints.

PropTypeDescription
aria-labelstringConcise text alternative naming the series and period.
yMinnumberOptional vertical bounds and tick count.
yMaxnumberOptional vertical bounds and tick count.
yTickCountnumberOptional vertical bounds and tick count.
children(range: OpenToCloseChartRangeState) => ReactNodeCustom range renderer.
rangeOpenToCloseChartRangeStateRange state passed to the mark.

ChartDescription

DOM element

Visible prose summarizing the movement.

ChartTable

DOM element

Native table with exact open and close values.

ChartTooltip

OptionalDOM element

Optional floating open/close pair label shown on hover or focus.

Style hooks

Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.

OpenToCloseChartPlot / OpenToCloseChartRange

Style hookMeaning
[data-direction]Whether close is up, down, or unchanged from open.
[data-active]The range currently reached by pointer or keyboard.

ChartTooltip

Style hookMeaning
[data-open]A value tooltip is visible.

Keep exploring