Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

Globe

Locations on a globe the reader turns by dragging. Markers can share one size or scale with a value, and you choose which side faces the reader first.

Charting library: TanStack Charts

Preview

Preview width

Installation

The command adds the example above to components/charts/ and, the first time, the chart kit to components/ui/charts/. Both are source files in your project from then on: read them, change them, delete what you don't use.

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.

Usage

Rows need a longitude and a latitude, plus a name for the tooltip. The land is worldCountries, installed in components/charts/data/ with any example that uses it.

import { worldCountries } from "@/components/charts/data/world-countries";
import {
  GlobeChart,
  GlobeLand,
  GlobeMarkers,
  GlobeSphere,
  GlobeTooltip,
} from "@/components/ui/charts";

const offices = [
  { latitude: 51.51, longitude: -0.13, name: "London" },
  { latitude: 52.52, longitude: 13.4, name: "Berlin" },
  { latitude: 40.71, longitude: -74.01, name: "New York" },
  { latitude: 1.35, longitude: 103.82, name: "Singapore" },
];

export const OfficesGlobe = () => (
  <GlobeChart
    ariaLabel="Our offices"
    center={[10, 30]}
    data={offices}
    geography={worldCountries}
  >
    <GlobeSphere />
    <GlobeLand />
    <GlobeMarkers />
    <GlobeTooltip />
  </GlobeChart>
);

Anatomy

The layers stack in a fixed order: the ocean, the graticule, the land, then the markers.

<GlobeChart center={[12, 30]} data={regions} geography={worldCountries}>
  <GlobeSphere />
  <GlobeGraticule />
  <GlobeLand />
  <GlobeMarkers />
  <GlobeTooltip />
</GlobeChart>
  • GlobeChart: Holds the places, the countries and the projection, and turns it on drag.
  • GlobeSphere: The ocean and the globe's rim.
  • GlobeGraticule: Lines of longitude and latitude, every 20° by default.
  • GlobeLand: The countries from geography.
  • GlobeMarkers: A dot on each place, one size or scaled by dataKey.
  • GlobeTooltip: The marker's name and, with dataKey, its value.

Turning the globe

center is the [longitude, latitude] that faces the reader, [10, 20] by default. A drag turns the globe from there, 0.35° per pixel, and the tilt stops at 80° so it never rolls over a pole.

Markers on the far side are hidden and take no hover until they come round. The tooltip is hidden while the globe turns.

Touch screens

On a touch screen, a finger on the globe turns it instead of scrolling the page or opening a tooltip. Where that gets in the way, for example in a narrow column on a phone, set draggable={false}: taps then show the tooltips.

Sized markers

Give <GlobeMarkers> a dataKey and each marker's area follows its value, the largest drawn at radius. Without a dataKey, every marker takes radius, 5 px by default.

The largest markers are drawn first, so small ones stay on top. The tooltip adds the value under the place's name.

Preview width

Customization

The kit is in your project, in components/ui/charts/: your framework's components over a shared core/. Change a default there and every chart picks it up.

className goes on the chart's container, so size and spacing are utility classes.

Every layer's colors are props: fill and stroke on <GlobeSphere>, fill, stroke and strokeWidth on <GlobeLand>, color on <GlobeMarkers>. content on <GlobeTooltip> gets the hovered row as marker.

<GlobeChart center={[-60, 15]} data={customers} geography={worldCountries}>
  <GlobeSphere fill="var(--muted)" />
  <GlobeLand fill="var(--chart-scale-03)" stroke="var(--muted)" />
  <GlobeMarkers color="var(--chart-2)" dataKey="customers" radius={14} />
  <GlobeTooltip
    content={({ marker }) => (
      <div className="px-3 py-2 text-sm">
        {String(marker.name)}: {Number(marker.customers).toLocaleString()}
      </div>
    )}
  />
</GlobeChart>

Where a part renders content of its own, you pass it in. In React:

  • GlobeTooltip: content={({ marker, index }) => …}

Loading state

With status="loading", a skeleton disc and the land's outline breathe in the globe's place under its graticule, with a few skeleton markers. Dragging and hover are off until "ready", when the globe grows in.

loadingLabel puts a short line of text over it.

Preview width

Animation

The globe grows in over 700 ms, the land fades in from 150 ms, and the markers pop in from 450 ms, largest first, spread over animationDuration (900 ms).

Dragging never replays it. animate={false} and reduced motion both draw the globe at rest.

Theming

Every color in the kit is one of your theme's tokens or a mix of them, except --chart-positive, a fixed green. A preset or the .dark class restyles the chart, and overriding a token in your CSS changes it everywhere.

The ocean is --chart-scale-01 and the land --chart-scale-02, both mixed from --chart-1 into --muted, so the globe follows your theme's first chart color. Country borders take the ocean's color and the rim is --border.

TokenDefaultPaints
--chart-1your theme'sthe first series
--chart-scale-01--chart-1 at 10% over --mutedthe low end of a color scale
--chart-graticule--chart-grida map's lines of longitude and latitude
--chart-background--carddot halos, the gaps between stacked marks
--chart-tooltip-background--popoverthe tooltip panel
globals.css
:root {
  --chart-background: var(--background);
  --chart-tooltip-background: var(--card);
}

Accessibility

The globe is announced as an image named by ariaLabel ("Globe" by default). Arrow keys move through the markers on the side facing the reader, left to right.

The keyboard can't turn the globe, and markers on the far side can't be focused. If those places matter, name them in ariaDescription or list them next to the chart.

Tab
Moves focus to the globe, on its leftmost visible marker.
Arrow Right
Moves to the next marker to the right. ArrowDown does the same.
Arrow Left
Moves to the previous marker. ArrowUp does the same.
Home
Jumps to the leftmost visible marker.
End
Jumps to the rightmost visible marker.

API reference

GlobeChart

PropType
data?readonly SpatialRow[]

The places to mark on the globe: one row per marker, with a longitude and a latitude.

geography?FeatureCollection<Geometry, Readonly<Record<string, unknown>> | null>

The countries to draw (GeoJSON; GlobeLand styles them), such as the kit's worldCountries.

Type
FeatureCollection<Geometry, Readonly<Record<string, unknown>> | null>
center?readonly [number, number]

The point that faces the reader, [longitude, latitude] in degrees.

Default
[10, 20]
draggable?boolean

Rotate the globe by dragging it (mouse, pen or touch).

Default
true
longitudeKey?string

Key of each row's longitude, in degrees.

Default
"longitude"
latitudeKey?string

Key of each row's latitude, in degrees.

Default
"latitude"
nameKey?string

Key of each row's name, the tooltip's title.

Default
"name"
aspectRatio?string

Aspect ratio of the chart as "width / height".

Default
"4 / 3"
margin?Partial<SpatialMargin>

Space around the plot in pixels. Any side you omit keeps its default.

Type
Partial<SpatialMargin>
animate?boolean

Play the entrance animation.

Default
true
animationDuration?number

Length of the entrance sweep in milliseconds: the time from the first mark starting to the last one.

Default
900
revealSignature?string

Changing this value replays the entrance animation.

status?ChartStatus

"loading" draws a pulsing skeleton of the chart's shape in place of its marks (the axes, grid and land stay) and ignores the pointer; switching to "ready" plays the entrance.

Default
"ready"
loadingLabel?string

Text shown centered over the chart, with a shimmer, while status is "loading". Nothing is shown when it is unset or empty.

className?string

Additional class name for the chart container.

children?ReactNode

The chart's carriers: its layers, axes, grid, tooltip and legend.

ariaLabel?string

Accessible label of the chart.

ariaDescription?string

Longer accessible description of the chart.

GlobeSphere

PropType
fill?string

Fill of the ocean.

Default
"var(--chart-scale-01)"
stroke?string

Color of the rim.

Default
"var(--border)"

GlobeLand

PropType
fill?string

Fill of the land.

Default
"var(--muted)"
stroke?string

Color of the borders between countries.

Default
"var(--chart-background)"
strokeWidth?number

Width of the borders, in pixels.

Default
0.5

GlobeGraticule

PropType
step?readonly [number, number]

Degrees between the lines, [longitude, latitude].

Default
[20, 20]
stroke?string

Color of the lines.

Default
"var(--chart-graticule)"
strokeWidth?number

Width of the lines, in pixels.

Default
0.5

GlobeMarkers

PropType
dataKey?string

Key of each row's value: a marker's area. Without it every marker takes radius.

radius?number

Radius of the markers (the largest, with dataKey), in pixels.

Default
5
color?string

Fill of the markers.

Default
"var(--chart-1)"
fadeOnHover?boolean

Dim the layer's other marks while one is hovered or focused.

Default
true
inactiveOpacity?number

Opacity of the other marks while one is hovered or focused.

Default
0.35

GlobeTooltip

PropType
content?(args: GlobeTooltipArgs) => ReactNode

Custom tooltip content. Replaces the default title and rows, inside the same panel.

Type
(args: GlobeTooltipArgs) => ReactNode
formatValue?(value: number) => string

Formats the value row of the default content.

Type
(value: number) => string
Default
the number with thousands separators
valueLabel?string

The label of the value row of the default content.

className?string

Additional class name for the tooltip panel.

panelStyle?CSSProperties

Inline styles merged onto the tooltip panel.

backgroundColor?string

Background color of the tooltip panel. Overrides the theme's popover color.

Examples

3 examples on React, each live with its code and its own install command.