Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelog App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip
ARC UI ARC Radiant Components
v3.2 Docs Components Tokens Synthesizer
Getting StartedFrameworksServer Rendering Design TokensThemingTheme SynthesizerTypographyUtilities All ComponentsAccessibilityBrowser SupportChangelogContributingStats App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip

Image Hotspots

An annotated image with glowing pin markers, each opening a small popover of detail content. Built for product-feature callouts, annotated screenshots, and simple maps.

Components Image Hotspots
content interactive
<arc-image-hotspots>

Overview

Image Hotspots lays glowing pins over a picture and gives each pin a popover. Slot the image and the `<arc-hotspot>` children together — every pin positions itself from its own x and y attributes, given as percentages of the image, so source order never matters and the markup stays a flat list of facts about the picture. Each pin is a real button: keyboard-focusable, labeled for screen readers, and carrying `aria-expanded` popover semantics. Clicking or activating a pin opens its popover anchored above the pin, flipping to fit near viewport edges. The parent keeps one popover open at a time, and an open popover closes on Escape, on a click anywhere else, or on a second click of its pin. The pins render server-side at their coordinates because positioning is pure CSS derived from attributes; only the popover interaction needs JavaScript. Every hotspot reports its activity through `arc-open` and `arc-close` events that bubble to the parent, with `detail.value` carrying the hotspot's label — or its index when no label is set.

Guidelines

When to use

  • Give every hotspot a label — it names the pin for screen readers, heads the popover, and identifies the hotspot in events
  • Keep popover content to a sentence or two; link out for anything longer
  • Place pins on the feature they describe, not beside it — coordinates are the whole message
  • Use a handful of pins per image; three to six is the comfortable range
  • Constrain the component to a readable width so pin targets stay comfortably apart

When not to use

  • Do not crowd pins so close together that their popovers cover each other's targets
  • Do not put critical information only in a popover — undiscovered pins go unread
  • Do not use Image Hotspots for step-by-step onboarding — that is Guided Tour's job
  • Do not rely on pixel positions in your head; x and y are percentages of the image box

Features

  • Percentage-based pin coordinates — responsive by construction, no measuring
  • Pulsing accent pins with a glow that rises on hover and focus
  • One popover open at a time, coordinated by the parent
  • Escape and outside-click both dismiss the open popover
  • Popovers flip and shift to stay inside the viewport
  • Pins are real buttons: focusable, labeled, `aria-expanded` state
  • `arc-open` / `arc-close` events with `detail.value` naming the hotspot
  • Pins server-render at their positions; popovers stay closed without JS
  • Ambient pulse is suppressed under `prefers-reduced-motion`

Preview

Switch between projects without losing your place — every workspace keeps its own layout. Metrics stream in over WebSockets and render at 60fps, no refresh required. Send any panel to CSV, PNG, or a shared link with one click.

Usage

This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.

<arc-image-hotspots>
  <img src="/screenshots/dashboard.png" alt="Analytics dashboard" />
  <arc-hotspot x="18" y="30" label="Navigation">
    Jump between reports, alerts, and settings from one rail.
  </arc-hotspot>
  <arc-hotspot x="60" y="45" label="Live charts">
    Metrics stream in real time — no refresh required.
  </arc-hotspot>
  <arc-hotspot x="85" y="78" label="Exports">
    Any panel exports to CSV, PNG, or a shared link.
  </arc-hotspot>
</arc-image-hotspots>
import { ImageHotspots, Hotspot } from '@arclux/arc-ui-react';

export default function FeatureTour() {
  return (
    <ImageHotspots onArcOpen={(e) => console.log('opened', e.detail.value)}>
      <img src="/screenshots/dashboard.png" alt="Analytics dashboard" />
      <Hotspot x={18} y={30} label="Navigation">
        Jump between reports, alerts, and settings from one rail.
      </Hotspot>
      <Hotspot x={60} y={45} label="Live charts">
        Metrics stream in real time — no refresh required.
      </Hotspot>
      <Hotspot x={85} y={78} label="Exports">
        Any panel exports to CSV, PNG, or a shared link.
      </Hotspot>
    </ImageHotspots>
  );
}
<script setup>
import { ImageHotspots, Hotspot } from '@arclux/arc-ui-vue';
</script>

<template>
  <ImageHotspots>
    <img src="/screenshots/dashboard.png" alt="Analytics dashboard" />
    <Hotspot :x="18" :y="30" label="Navigation">
      Jump between reports, alerts, and settings from one rail.
    </Hotspot>
    <Hotspot :x="60" :y="45" label="Live charts">
      Metrics stream in real time — no refresh required.
    </Hotspot>
    <Hotspot :x="85" :y="78" label="Exports">
      Any panel exports to CSV, PNG, or a shared link.
    </Hotspot>
  </ImageHotspots>
</template>
<script>
  import { ImageHotspots, Hotspot } from '@arclux/arc-ui-svelte';
</script>

<ImageHotspots>
  <img src="/screenshots/dashboard.png" alt="Analytics dashboard" />
  <Hotspot x={18} y={30} label="Navigation">
    Jump between reports, alerts, and settings from one rail.
  </Hotspot>
  <Hotspot x={60} y={45} label="Live charts">
    Metrics stream in real time — no refresh required.
  </Hotspot>
  <Hotspot x={85} y={78} label="Exports">
    Any panel exports to CSV, PNG, or a shared link.
  </Hotspot>
</ImageHotspots>
import { Component } from '@angular/core';
import { ImageHotspots, Hotspot } from '@arclux/arc-ui-angular';

@Component({
  imports: [ImageHotspots, Hotspot],
  template: `
    <arc-image-hotspots>
      <img src="/screenshots/dashboard.png" alt="Analytics dashboard" />
      <arc-hotspot x="18" y="30" label="Navigation">
        Jump between reports, alerts, and settings from one rail.
      </arc-hotspot>
      <arc-hotspot x="60" y="45" label="Live charts">
        Metrics stream in real time — no refresh required.
      </arc-hotspot>
      <arc-hotspot x="85" y="78" label="Exports">
        Any panel exports to CSV, PNG, or a shared link.
      </arc-hotspot>
    </arc-image-hotspots>
  `,
})
export class FeatureTourComponent {}
import { ImageHotspots, Hotspot } from '@arclux/arc-ui-solid';

export default function FeatureTour() {
  return (
    <ImageHotspots>
      <img src="/screenshots/dashboard.png" alt="Analytics dashboard" />
      <Hotspot x={18} y={30} label="Navigation">
        Jump between reports, alerts, and settings from one rail.
      </Hotspot>
      <Hotspot x={60} y={45} label="Live charts">
        Metrics stream in real time — no refresh required.
      </Hotspot>
      <Hotspot x={85} y={78} label="Exports">
        Any panel exports to CSV, PNG, or a shared link.
      </Hotspot>
    </ImageHotspots>
  );
}
import { ImageHotspots, Hotspot } from '@arclux/arc-ui-preact';

export default function FeatureTour() {
  return (
    <ImageHotspots>
      <img src="/screenshots/dashboard.png" alt="Analytics dashboard" />
      <Hotspot x={18} y={30} label="Navigation">
        Jump between reports, alerts, and settings from one rail.
      </Hotspot>
      <Hotspot x={60} y={45} label="Live charts">
        Metrics stream in real time — no refresh required.
      </Hotspot>
      <Hotspot x={85} y={78} label="Exports">
        Any panel exports to CSV, PNG, or a shared link.
      </Hotspot>
    </ImageHotspots>
  );
}

Hotspot

<arc-hotspot>

A single glowing pin inside an Image Hotspots surface. The x and y attributes position it as percentages of the image, the label names it, and slotted children become the popover body.

x number 50
Horizontal position of the pin as a percentage of the image width, from 0 (left edge) to 100 (right edge). Values outside the range are clamped; a non-numeric value falls back to 50.
y number 50
Vertical position of the pin as a percentage of the image height, from 0 (top edge) to 100 (bottom edge). Values outside the range are clamped; a non-numeric value falls back to 50.
label string ''
Accessible name for the pin button, repeated as the heading of the popover. Always set it — without a label the pin announces nothing useful to a screen reader.
open boolean false
Whether the pin's popover is currently visible. Reflected as an attribute. Opens on click; closes on Escape, outside click, or a second click on the pin.

See Also