Arc
ComponentsBlocksScreensDocsPricingTry the demo
Get Pro
Saved

Docs

IntroductionInstallationThemingMotionAI and MCPChangelog

Components136

ButtonAction buttonSplit buttonButton groupFloating button groupExpanding button groupCopy buttonAction swapIcon morphConfirm morphTheme switcher

Hold to confirmSwipe actionsReactions

Dropdown menuContext menuUser menu

InputTextareaPassword fieldPassword strengthSearch fieldExpanding searchInline edit

Number fieldMoney inputPhone inputScrub inputTag inputMention inputShortcut recorder

SelectComboboxMulti-selectMorph selectChip group

Radio cardsBilling toggleCheckboxRadio groupSwitchSegmented controlRatingToggle group

SliderElastic sliderRange histogram sliderRuler sliderWindow rangeNewProLens rangeNewPro

CalendarDate pickerDate range pickerTime pickerColor pickerEmoji pickerPro

Rich text editorSignature padFile dropzoneAvatar uploadPro

TabsBreadcrumbPaginationMega menu morphProTable of contents progressPro

Scroll areaAccordionExpandable cardResizable panelsExpandable text

DialogDrawerBottom sheetPopoverHover cardTooltipShare accessProConfirm popoverPro

AlertToastToast stackAnnouncement barCookie consentUndo toastPro

ProgressSkeletonStepperCountdownUsage meterOnboarding checklist

AvatarAvatar groupBadgePresence stackPro

CardMetric cardEmpty stateMetric tickerPro

Line chartBar chartDonut chartStreamgraphBrush chartWaffle chartSlope chartSparklineGaugeActivity heatmapAnimated counterRidgelineTreemapSplit barPro

SunburstProSankey flowProFunnel chartProRadar chartProRealtime streamProRace bar chartProData gridPro

Sortable data tableTree tableTree viewReorderable listFilter toolbarCode blockJSON viewer

TimelineComment threadChat thread

Image compareCarouselCard stack

Text revealIn-view titleText morphText shimmer

Blocks122

KPI drilldownProMetric explorerProRevenue explorerProMRR waterfallProCohort retentionProUsage forecastProJourney flowProUptime statusProPivot builderProChoropleth explorerProConnected scatterProHorizon chartProAccount healthPro

Budget variancePro

Small multiplesProLine replayPro

AI chatProAI composerProAI answerProModel pickerProModel arenaProPrompt studioProDocument extractionProAgent memoryProAI side panelProAI inline editProResearch runProAI insight cardProCatch upProAI feature launchProAI search barProAI setup wizardProCall insightsProLead scoringPro

Agent runProAgent tasksProAgent approvalsProAgent routinesProAgent orchestratorProMCP serversProKnowledge baseProEval suiteProAgent builderProAgent galleryPro

SidebarPro4Page headerCommand paletteNotification centerSelection toolbarProEmpty statesSearch resultsPro

Login and sign up5, free and Pro variantsOnboarding illustrationProOTP inputMulti-step formProTwo-factor setupProMagic linkPro

Settings pageProSettings commandProSecurity settingsProBilling overviewProUsage billingProCancel flowProOnboarding surveyProSpend alertPro

Team membersProInvite peopleProRoles and permissionsProProfile pagePro

API keysProWebhooksProIntegrationsProImport wizardNewProEnvironment variablesProDomain verifyProWebhook testerPro

Plan comparisonPricing calculatorProUsage pricingProCart drawerProCheckout summaryProLive checkoutProSeat managerProCredit top-upPro

Wallet cardProDelivery trackerProSeat mapPro

Activity feedProSupport widgetProFeature votingPro

File uploadMedia playerPro

Availability pickerProRelease readinessProFeedback boardProSmart schedulerProTask breakdownProGoal trackerPro

Hero sectionHero signupPro

Scroll storyProSpotlight gridProFeature bentoProComparison table

Logo marqueeStudio perspectivesProStats band

Changelog feedFAQ sectionContact sectionTeam showcaseProBlog grid

Site headerSite footerCTA sectionNewsletter signup

Activity terrainProRevenue globeProCustomer galaxyProSemantic zoomProLayout morphProExploded viewPro

Screens14

Metrics dashboardProMarket terminalPro

Kanban boardProProject boardProGantt timelinePro

Week calendarProMonth calendarNewPro

Team directoryPro

Inbox triageProSupport conversationProHelp centerPro

Product listingProProduct detailProInvoice studioPro

Special components106

Share sheetProAction morphProMorph navProDockProLiquid tab barProOrbit menuPro

Glass menuProGlass segmentedProGlass cardProGlass tab barPro

Sheet stackProWallet stackProControl centerProHolo cardProCard to articleProLink unfurlPro

Product galleryProLightbox galleryProPhoto gridProCover flowPro

Voice orbProNow playingProVoice recorderPro

Booking pillProActivity ringsProTime dialProDate reelPro

Keycap keyboardProSlot textSand textProTypewriter terminalPro

Stretch refreshProMorph loaderProSkeleton morphProBlack holeProCharge sessionPro

Sticker peelProTicket tearProPage curlProOrbit logosProPrize wheelPro

Dot gridProImage trailProGravity wellProInk fluidProCursor trail drawPro

Agent statusProTool callProAgent planProAgent timelineProContext windowProReasoning blockProSource cardsProModel cardProAI workflowProCode suggestionProGhost textProImage generationProDictation buttonProSpeech playerProMeeting summaryProReply draftProAgent handoffProPII redactionProResponse feedbackProLLM cost calculatorProProvider keysProGeneration statsProAI translateProTL;DR toggleProConnector setupProSmart form fillProEnrich columnProTicket routerProAsk your dataProAgent cursorProProvider statusProTraining runProAI commandProStarter promptsProAI mascotProImage revealProAI sparkProPixel mascotProGhost mascotProCube mascotProTone tunerProUpgrade promptProReferral cardProTrial bannerProTeam switcherProLive visitorsProSocial proof toastProInstall snippetPro

Data flowProPayment flowProDNS resolutionProModel trainingProMulti-region failoverProVector searchProBranch graphProAgent loopProMixture of expertsProSpeculative decodingProPrompt cacheProReasoning treePro
What’s new4 new
BlocksConnected scatter

Connected scatter

Pro

A connected scatterplot of monthly CAC against LTV where the path draws itself in, a scrubber moves a head along the curve, and a channel switch morphs the path against a shaded 3x target line.

Live block · sample data

When to use

  • A growth or finance screen that shows whether unit economics are moving toward or away from a target ratio.
  • Comparing how a few segments or channels travelled through the same two metrics over the same months.
  • A report where specific months (a pricing change, a campaign) explain a turn and deserve a label on the path.

When not to use

  • Use line-chart or metric-explorer when time itself is the axis and one metric is enough.
  • Use efficient-frontier for risk against return of a portfolio you can change.
  • Use a plain scatter or beeswarm when points have no time order to connect.

Installation

Pro source and install commands unlock with a Pro plan.

Usage

Render <ConnectedScatter /> for the demo, or pass series (same number of points in each, in time order), xAxis, yAxis, targetRatio and formatValue for your own two metrics. Listen to onMonthChange to sync the month the head settles on.

example.tsx
1import { ConnectedScatter } from "@/components/arc/blocks/connected-scatter/connected-scatter";2 3export function UnitEconomics() {4  return (5    <ConnectedScatter6      defaultSeries="partners"7      onMonthChange={index => setSelectedMonth(index)}8    />9  );10}
Built fromSegmented controlButton

API reference

ConnectedScatter

A connected scatterplot of two metrics over time. Each month is a point, joined in time order by a smooth path with small direction arrows. The path draws itself in once, a head marks the selected month and a time scrubber moves it along the path, a channel switch morphs the path point by point to another series, and a dashed target line (LTV = 3x CAC) splits the plot with the healthy side lightly shaded. Hovering a point shows its date and both values.

PropTypeDefaultDescription
seriesScatterSeries[]SERIESSeries to switch between: id, name, points in time order ({ label, x, y }) and optional notes ({ index, text, side }) that label key months. Every series needs the same number of points so the path can morph.
defaultSeriesstring–Id of the series shown first. Defaults to the first series.
xAxisScatterAxisX_AXISHorizontal axis: short name for the readout, title printed on the axis, min, max and gridline step. The sample is CAC from $200 to $1,800.
yAxisScatterAxisY_AXISVertical axis, same shape. The sample is 12 month LTV from $2,000 to $6,000.
targetRationumber3Slope of the reference line y = targetRatio times x. The region above it is shaded as healthy and the readout says whether the selected month is above or below it.
formatValue(value: number) => stringwhole US dollarsFormats values in the readout, the tooltip, the axis ticks and the screen reader table.
titlestring"CAC and LTV by channel"Block heading.
descriptionstring–One line under the heading. Defaults to a sentence naming the metrics and the date range.
onMonthChange(index: number) => void–Called with the month index whenever the head settles on a month: a released scrub, a key press, a tap on a point, or the end of playback. Not called on every frame.
classNamestring–Class on the root element.

Keyboard interactions

Tab
Moves through the channel switch, the play button and the month scrubber.
Arrow leftorArrow right
On the scrubber, moves the head one month back or forward along the path.
Page uporPage down
On the scrubber, moves three months at a time.
HomeorEnd
On the scrubber, jumps to the first or last month.
Arrow keys in the channel switch
Switch channel; the path morphs to the new series.
EnterorSpace on the play button
Plays through the months from the head, pauses, or replays from the first month at the end.

Accessibility

  • The scrubber is role="slider" over the months, with a value text that reads the date, both values, the ratio and whether it is above or below the target.
  • A polite live region announces the month when the head settles and the new values when the channel changes. Playback announces only where it stops.
  • The readout is a description list, so the selected month, both values and the ratio are always available as text.
  • The chart drawing is hidden from assistive technology; a visually hidden table lists every month with both values and the ratio for the current channel.
  • Above or below target is written out beside a status dot, never shown by color alone.
  • Pointer focus draws no ring; keyboard focus shows Arc's shared focus ring. The focused scrubber fills and enlarges its thumb.

Motion

  • The first time the block scrolls into view, the head travels every month and the path draws in behind it; the dotted future path, arrows and labels fade in once it lands.
  • Scrubbing moves the head along the real curve, not a straight line between months. A press glides the head to the pointer once, then it follows one to one, and a release settles on the nearest month with the smooth spring, which never overshoots.
  • Switching channel morphs every point, arrow and the path itself on the smooth spring; the readout numbers count through the in between values and month labels crossfade.
  • Every moving part (path, trail length, head, guides, dots, arrows, scrubber thumb and readout values) is a motion value written once per frame, so none of it re-renders React.
  • Reduced motion shows the finished path at once, jumps the head to each month, steps playback month by month and swaps channels without a morph.

Responsive behavior

  • The block reflows against its own width with container queries: four readout cells in a row from 720px, two by two below it.
  • The chart draws in real pixels at every size, so text and strokes never stretch; the plot is 380px tall on wide layouts, 330px at tablet widths and 300px on phones.
  • Below 480px of plot width the notes, the target line label and the zone label hide (the key names both), x ticks thin to every other gridline, and edge labels flip inward.
  • The scrubber is 44px tall for touch and the play button is a full size control. On phones the play button sits above the scrubber, and quarter labels under the scrubber hide below 560px.
  • Tapping a point on a touch screen shows its values and moves the head there.

Performance

  • The path is traced as Catmull-Rom Béziers and sampled once per resize or per morph frame (24 samples per month), so moving the head is a lookup, not a curve solve.
  • Only month changes, hover changes and the play state re-render React; every frame writes motion values directly.
  • Comfortable up to a few dozen points per series; beyond that, thin the direction arrows or aggregate to quarters.

Notes for AI

Give your coding assistant the Markdown reference instead of screenshots.

  • Choose it when the story is how two metrics moved together over time, such as CAC against LTV, price against volume, or spend against conversions.
  • The sample data is monthly CAC and 12 month LTV for three acquisition channels, January 2025 to June 2026. Replace SERIES, X_AXIS and Y_AXIS with your own; keep the same number of points in every series.
  • Use notes sparingly (one or two per series) for events that explain a turn in the path; the first and last month are labelled automatically and narrow plots hide the notes.
  • The target line always passes through the origin, so it suits ratio targets. Set min on both axes to zoom into where the data lives; the shaded region is clipped to the plot.
  • The first render is server safe: it draws at a default size with the head on the first month, then measures and animates on the client.
/components/blocks/connected-scatter/markdown

The full library index for assistants is at /llms.txt.

Related

Metric explorerProBlockKPI cards that open into a scrubbable chart and morph between metrics and ranges.Segmented controlComponentSwitch between a small set of related views.Line chartComponentA multi-series line chart with a gliding crosshair, legend toggles, and paths that morph between ranges.
PreviousSmall multiplesNextHorizon chart
Arc · 122 block pagesllms.txt

On this page

  • Preview
  • When to use
  • When not to use
  • Installation
  • Usage
  • API reference
  • Keyboard
  • Accessibility
  • Motion
  • Responsive behavior
  • Performance
  • Notes for AI
  • Related
View as Markdown

CAC and LTV by channel

Monthly acquisition cost against 12 month lifetime value, January 2025 to June 2026.

Month
Jan 20251 of 18
CAC
$760Same as Jan 2025
LTV
$3,000Same as Jan 2025
LTV to CAC
3.9xAbove 3x target
12 month lifetime value
  • Paid search, in time order
  • LTV = 3x CAC
  • Healthy zone
$2k$3k$4k$5k$6k$200$400$600$800$1,000$1,200$1,400$1,600$1,8003x CACHealthy, above 3xJan 2025Jun 2026Broad match onAnnual plans
Customer acquisition cost
Jan 2025AprJulOctJan 2026Jun 2026
Paid search: Customer acquisition cost and 12 month lifetime value by month
MonthCACLTVRatio
Jan 2025$760$3,0003.9x
Feb 2025$800$3,0603.8x
Mar 2025$850$3,1103.7x
Apr 2025$905$3,0903.4x
May 2025$960$3,1403.3x
Jun 2025$1,030$3,1203.0x
Jul 2025$1,110$3,1002.8x
Aug 2025$1,190$3,0802.6x
Sep 2025$1,260$3,0602.4x
Oct 2025$1,300$3,1102.4x
Nov 2025$1,320$3,2002.4x
Dec 2025$1,290$3,3802.6x
Jan 2026$1,220$3,6203.0x
Feb 2026$1,150$3,9003.4x
Mar 2026$1,080$4,1503.8x
Apr 2026$1,030$4,3604.2x
May 2026$990$4,5204.6x
Jun 2026$960$4,6404.8x