Skip to main content

Squillify development is paused indefinitely. Read why, and discover what this experiment achieved. Read the story

MicroSkills Reference

Line chart

chart.line

ProductionBounded custom (Class B)Deterministicstrictfastv1.0.0
No network

Overview

Choose the domain type explicitly, pass an ascending x axis and one or more exact-decimal series. A null value breaks the line into a visible gap — we never draw it as zero or interpolate across it. Optional lower and upper arrays add an uncertainty band. Defaults include canvas 800×400. Too many points for the canvas are refused rather than downsampled. Do not use for unordered categories (use chart.bar) or single-number cards (use chart.kpi). svg is a complete static, script-free chart. Mark highlight, the dotted guide, and the value panel are not in that SVG, and entry motion, focus, and updates stay inactive there. Pass the entire output.behavior.artifact unchanged to SquillifyChartRuntime.mount(container, artifact, options), then call the returned handle's replay() once to play the entry. A later value change uses update(nextArtifact, {intent}). Injecting svg directly leaves hover and motion off. Interaction is on by default for every host chart: after mount, pointer and keyboard focus open the value panel and the dotted guide. Set behavior.interaction.enabled to false to turn that off. motion.preset accepts only the family's entrance.

Hand-built line SVG gets scales, gaps, and time axes subtly wrong. We pin UTC date handling and draw nulls as gaps so every reader sees the same story.

Reliability

Identical input always produces the same lines, gaps, and SVG. Declared failures: CHART_CAPACITY_EXCEEDED — trigger: too many points or series for the canvas at the chosen size and density; retryable: no; unchanged input: will not succeed; next: follow the recovery intent in the error details. CHART_OUTPUT_TOO_LARGE — trigger: the inline SVG byte budget would be exceeded at the requested size and data density; retryable: no; unchanged input: will not succeed; next: follow the recovery intent in the error details. CHART_THEME_UNKNOWN — trigger: theme or surface names a visual language we do not register for this chart family; retryable: no; unchanged input: will not succeed; next: follow the recovery intent in the error details. CHART_UNSAFE_OUTPUT — trigger: the finished SVG failed our final safety re-validation (this is on us, not your data); retryable: no; unchanged input: will not succeed; next: contact support with the request id — retrying the same input will not help. CHART_OUTPUT_TOO_COMPLEX — trigger: the render hit a structural complexity ceiling (elements, depth, text volume, or path commands) separate from the byte budget; retryable: no; unchanged input: will not succeed; next: contact support with the request id — retrying the same input will not help.

Context footprint

You receive a refusal with CHART_CAPACITY_EXCEEDED when the ordered data cannot remain legible and CHART_BEHAVIOR_CAPACITY_EXCEEDED when the bounded host artifact is too large. The SVG remains complete and static until the entire output.behavior.artifact is verified and mounted; resolve artifact.runtimeRequirement, never motionPlan.requiredRuntime. One call replaces ad-hoc scale math and SVG. A successful call costs 3 execution credits.

When to use it

When you need a trend chart over an ordered axis such as time.

When the x axis is unordered categories or there are more points than the canvas can resolve.

Scope

Note
Line charts over an ordered x axis — numbers, UTC dates, or labels — with visible gaps for missing values and an optional uncertainty band.

Non-goals

  • Smoothing, interpolation, or downsampling — the drawn line is your data
  • Unordered category comparison (use chart.bar)
  • Part-of-whole shares or flow ribbons

Properties

IdempotentRetry safeStreaming supportedFile input supportedRequires external service

Capabilities

generationimage-processing

Cost & billing

Flat rate per invocation

MetercallsBillable onsuccessCost per call3 credits

File handling

Accepts file_refProduces file_refMax input390.6 KB

How we handle your data

Sensitive output possible
What this means

This skill may receive sensitive content and may return submitted, transformed, extracted, or reformatted content.

Squillify guarantees
  • Runs inside Squillify
  • This skill runs inside Squillify.
  • Payloads are not sent to an external service by this skill.
  • Squillify does not permanently store submitted payloads.
  • Telemetry records metadata only, not submitted content.
  • Submitted payloads are not used for training.
  • Submitted payloads are not reviewed by humans.
  • This skill does not target sensitive data.
  • The response may contain submitted or transformed content.
Your responsibility

Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.

Read the Microskill Data Handling Policy

Input schema

FieldTypeRequiredDescription
domainTypestringYesRequired ordered-domain kind: number, time, or label. The skill never guesses.
xarrayYesTwo to 5,000 homogeneous positions. Number positions are exact decimal strings; time positions are all dates or all explicit-offset RFC 3339 instants; labels are unique non-empty strings. Caller order must already be ascending.
seriesarrayYesOne to 24 closed objects {id,label,values,lower?,upper?,meaning?}. Quantitative entries are exact decimal strings or null gaps; lower and upper are paired.
curvestringNoLine interpolation: straight (default), stepBefore, stepAfter, or shape-preserving monotone.
markersstringNonever only (default when omitted); line charts use an uninterrupted marker-free trace.
valueScaleobjectNoClosed scale object. type is linear (default), log10, or symlog; symlog requires a positive exact decimal string constant.
indexingobjectNoOptional {mode:'baseline100',baselineIndex}. Every series baseline must be finite and non-zero.
referenceLinesarrayNoUp to 24 combined exact reference lines/bands; omitted means none.
referenceBandsarrayNoUp to 24 combined exact reference lines/bands; omitted means none.
annotationsarrayNoUp to 32 renderer-owned point or domain annotations; omitted means none.
widthintegerNoCanvas width in pixels, 100..1600 (optional; default 800). Outside that range the request is refused as invalid input rather than clamped. The ceiling is the size a chart is read at — a full-HD dashboard or a report page; beyond it the canvas stops being what limits how much fits, and type sized for the canvas is illegible once the export is displayed smaller. It applies per side, so a tall portrait canvas for a long horizontal ranking is allowed.
heightintegerNoCanvas height in pixels, 100..1600 (optional; default 400). Outside that range the request is refused as invalid input rather than clamped. The ceiling is the size a chart is read at — a full-HD dashboard or a report page; beyond it the canvas stops being what limits how much fits, and type sized for the canvas is illegible once the export is displayed smaller. It applies per side, so a tall portrait canvas for a long horizontal ranking is allowed.
themestringNoVisual language: basic, modern or squillify (optional; default squillify). An unregistered value is rejected with the registered names listed — we never substitute silently.
surfacestringNoSurface the theme renders on: dark or light (optional; default light).
densitystringNoHow tightly the chrome is packed: compact, standard or spacious (optional; default standard). Density scales spacing only — it never lowers a legibility minimum.
visualProfilestringNoWhat the SVG promises about the host font: portable or certified (optional; default portable). The default is layout-deterministic and tolerates substitution; certified refuses text the certified metrics cannot fully measure.
titlestringNoHeading drawn above the plot (optional; at most 1024 code points). Omit it and the chart renders untitled — we never invent a title from your data. One code point past that ceiling is refused as TOOL_INPUT_INVALID.
subtitlestringNoSecond line under the title, useful for the period covered or the unit (optional; at most 1024 code points). Omit it and no second line is drawn.
legendobjectNoClosed {visible,directEndLabels}; visible defaults true for multiple series.
styleobjectNoOptional bounded paint and typography styling; omit it to use the selected theme defaults. text.size is expressed in normalized design pixels at an 800-pixel reference width, so equivalent roles match at equal CSS width. It never changes data or accessibility. 'contract' selects the published semantics. 'tokens' sets design tokens; 'rules' applies typed properties to a role and optional series/category facets; 'palette' accepts a digest-checked palette; 'css' is a bounded post-layout stylesheet. The styleCapabilities section publishes this family's accepted roles, properties and copyable examples. For Bar, target one mark with role 'bar' plus seriesIndex and categoryIndex; categoryIndex alone targets that category across series. A minimal rule is {"target":{"role":"bar"},"set":{"paint.fill":"#2563eb"}}. Unsupported typed rules are refused; unsupported CSS is dropped and reported. Do not discover the grammar through trial calls: style validation failures are currently billable. Before calling, read this contract's styleSurface and styleCapabilities sections for the complete rule shape, accepted roles and properties, limits, and copyable examples.
behaviorobjectNoOptional closed motion and interaction settings. Default: omission enables the family's certified entry motion, tooltip, focus, and crosshair with reduced motion respected; set both nested enabled flags false for a static-only result. svg is a complete static, script-free chart. Mark highlight, the dotted guide, and the value panel are not in that SVG, and entry motion, focus, and updates stay inactive there. Pass the entire output.behavior.artifact unchanged to SquillifyChartRuntime.mount(container, artifact, options), then call the returned handle's replay() once to play the entry. A later value change uses update(nextArtifact, {intent}). Injecting svg directly leaves hover and motion off. Interaction is on by default for every host chart: after mount, pointer and keyboard focus open the value panel and the dotted guide. Set behavior.interaction.enabled to false to turn that off. motion.preset accepts only the family's entrance.
outputobjectNoOutput scoping. output.idNamespace ([a-z][a-z0-9-]{0,31}) is prefixed onto every generated element id so several charts can share one host document without colliding; omit it for a standalone chart. An invalid value is rejected, never corrected.

Output schema

FieldTypeRequiredDescription
svgstringYesAllowlist-checked script-free SVG. svg is a complete static, script-free chart. Mark highlight, the dotted guide, and the value panel are not in that SVG, and entry motion, focus, and updates stay inactive there. Pass the entire output.behavior.artifact unchanged to SquillifyChartRuntime.mount(container, artifact, options), then call the returned handle's replay() once to play the entry. A later value change uses update(nextArtifact, {intent}). Injecting svg directly leaves hover and motion off. Interaction is on by default for every host chart: after mount, pointer and keyboard focus open the value panel and the dotted guide. Set behavior.interaction.enabled to false to turn that off. motion.preset accepts only the family's entrance.
widthintegerYesRendered width in pixels.
heightintegerYesRendered height in pixels.
viewBoxstringYesSVG viewBox string (for example "0 0 800 400").
domainResultsarrayYesInput-order domain positions with canonical normalized values and retained offsets.
seriesResultsarrayYesInput-order exact raw values, optional indexed values, extrema, gaps, and band presence.
renderSummaryobjectYesBounded summary of the resolved domain, curve, series, points, gaps, and bands.
accessibilityobjectYesAccessible title, resolved detail rung, and deterministic data description.
transformationSummaryobjectYesWhether baseline indexing was applied and the selected baseline index.
behaviorobjectYesResolved default-on motion and interaction report. Includes the digest-bound host artifact when behavior is enabled and always preserves a complete script-free SVG. svg is a complete static, script-free chart. Mark highlight, the dotted guide, and the value panel are not in that SVG, and entry motion, focus, and updates stay inactive there. Pass the entire output.behavior.artifact unchanged to SquillifyChartRuntime.mount(container, artifact, options), then call the returned handle's replay() once to play the entry. A later value change uses update(nextArtifact, {intent}). Injecting svg directly leaves hover and motion off. Interaction is on by default for every host chart: after mount, pointer and keyboard focus open the value panel and the dotted guide. Set behavior.interaction.enabled to false to turn that off. motion.preset accepts only the family's entrance.
styleReportobjectNoPresent only when a 'style' input was supplied. Reports tokensApplied, rulesApplied, typedRulesApplied, typedAssignmentsApplied, rulesDropped, declarationsDropped and, when anything was dropped, a bounded list of reasons — so a stylesheet that was modified never looks like one that was applied whole.
warningsarrayNoPresent when the render succeeded with a known degradation. Each entry is an object with a stable code, a message and details. Every chart can emit FONT_SUBSTITUTION_POSSIBLE under visualProfile 'portable', FONT_GLYPH_UNMEASURED when a code point falls outside the certified metrics, and CHART_STYLE_PARTIALLY_APPLIED when part of your styling was dropped — styleReport then names which part and why. Codes are stable for agent routing.

API contract

POST /v1/execute
curl
curl -sS -X POST "$BASE/v1/execute" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"skillKey":"chart.line","input":{"domainType":"label","x":["Mon","Tue","Wed"],"series":[{"id":"signups","label":"Signups","values":["12","18","15"]}]}}'
Integrations
TypeScript SDK
import { Squillify } from "@squillify/sdk";

const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });

const { output } = await sq.execute("chart.line", {"x":["Mon","Tue","Wed","Thu"],"domainType":"label","series":[{"id":"signups","label":"Signups","values":["40","43",null,"52"]}]});

Errors

CodeHTTPRetryableDescription
VALIDATION_ERROR400NoThe request payload failed schema validation.
UNAUTHORIZED401NoMissing or invalid API key.
SKILL_NOT_ACCESSIBLE403NoThe API key is not granted access to this skill.
SKILL_NOT_AVAILABLE_FOR_PLAN403NoThis skill is not included in your current plan.
PLAN_ELIGIBILITY_UNAVAILABLE503YesPlan eligibility could not be decided. Retry after backoff.
SKILL_NOT_FOUND404NoThe requested skill or version does not exist.
TENANT_RATE_LIMITED429YesRequest rate limit exceeded. Retry after backoff.
QUOTA_EXCEEDED429YesPlan quota exhausted. Retryable once the quota period resets.
EXECUTION_TIMEOUT504YesExecution exceeded the allowed time budget.
CHART_CAPACITY_EXCEEDED429NoA size, quota, rate, or time limit was exceeded.
CHART_OUTPUT_TOO_LARGE429NoA size, quota, rate, or time limit was exceeded.
CHART_THEME_UNKNOWN400NoThe request payload failed this skill's input validation.
CHART_UNSAFE_OUTPUT500NoThe skill encountered an unexpected execution failure.
CHART_OUTPUT_TOO_COMPLEX500NoThe skill encountered an unexpected execution failure.

Other limits

LimitValue
Recommended inline bytes32 KiB

Limitations

  • Smoothing, interpolation, or downsampling — the drawn line is your data
  • Unordered category comparison (use chart.bar)
  • Part-of-whole shares or flow ribbons
  • Unordered categories (use chart.bar)
  • Tens of thousands of points on a small canvas — we refuse those
  • Brushing or linked multi-chart selection

How to call

POST /v1/execute (requires authentication)

Request bodyjson
{
  "skillKey": "chart.line",
  "input": {
    "x": [
      "Mon",
      "Tue",
      "Wed",
      "Thu"
    ],
    "domainType": "label",
    "series": [
      {
        "id": "signups",
        "label": "Signups",
        "values": [
          "40",
          "43",
          null,
          "52"
        ]
      }
    ]
  }
}

Examples

Daily signups with a three-day gap

Inputjson
{
  "x": [
    "Mon",
    "Tue",
    "Wed",
    "Thu"
  ],
  "domainType": "label",
  "series": [
    {
      "id": "signups",
      "label": "Signups",
      "values": [
        "40",
        "43",
        null,
        "52"
      ]
    }
  ]
}
Expected outputjson
{
  "transformationSummary": {
    "applied": false,
    "mode": "raw"
  },
  "domainResults": [
    {
      "input": "Mon",
      "normalized": "Mon"
    },
    {
      "input": "Tue",
      "normalized": "Tue"
    },
    {
      "input": "Wed",
      "normalized": "Wed"
    },
    {
      "input": "Thu",
      "normalized": "Thu"
    }
  ],
  "height": 400,
  "viewBox": "0 0 800 400",
  "renderSummary": {
    "domainType": "label",
    "curve": "straight",
    "seriesCount": 1,
    "pointCount": 4,
    "gapCount": 1,
    "bandsRendered": false
  },
  "width": 800,
  "behavior": {
    "motion": {
      "enabled": true,
      "finalState": "static-equivalent",
      "reducedMotion": "respect",
      "preset": "enter_trace"
    },
    "interaction": {
      "enabled": true,
      "capabilities": [
        "crosshair",
        "focus",
        "tooltip"
      ]
    }
  },
  "svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"800\" height=\"400\" viewBox=\"0 0 800 400\" role=\"img\" class=\"sq-chart sq-chart--line sq-family--cartesian sq-theme--squillify sq-surface--light sq-density--standard\" data-sq-style-contract=\"CHART_STYLE@1\" data-sq-chart=\"line\" data-sq-family=\"cartesian\" data-sq-theme=\"squillify\" data-sq-theme-version=\"1\" data-sq-surface=\"light\" data-sq-density=\"standard\" data-sq-a11y-detail=\"full\" aria-labelledby=\"sq-4f34dc330326-title-0 sq-4f34dc330326-desc-1\"><title id=\"sq-4f34dc330326-title-0\">line chart with 1 series</title><desc id=\"sq-4f34dc330326-desc-1\">line chart. 1 series over 4 ordered points. Signups: Mon 40, Tue 43, Wed no value, Thu 52. All values are listed.</desc><style>.sq-chart{--sq-chart-axis:#c9d1df;--sq-chart-font-family:'Squillify Mono', 'IBM Plex Mono', monospace;--sq-chart-grid:#d8dee9;--sq-chart-surface:#ffffff;--sq-chart-text-muted:#667085;--sq-chart-text-primary:#101828;--sq-series-1:#2563eb;--sq-series-2:#6d5ce7;--sq-series-3:#168a5b;--sq-series-4:#c45412;--sq-series-5:#d92d20;--sq-series-6:#667085;font-family:var(--sq-chart-font-family);font-weight:500;}.sq-chart .sq-background{fill:var(--sq-chart-surface);}.sq-chart .sq-grid{stroke:var(--sq-chart-grid);}.sq-chart .sq-axis{stroke:var(--sq-chart-axis);}.sq-chart .sq-tick-label{fill:var(--sq-chart-text-muted);}.sq-chart .sq-line[data-sq-palette-index=\"0\"]{stroke:var(--sq-series-1);}</style><rect x=\"0\" y=\"0\" width=\"800\" height=\"400\" fill=\"#ffffff\" class=\"sq-background\" data-sq-role=\"background\"/><g class=\"sq-plot\" data-sq-role=\"plot\"><line x1=\"49\" y1=\"372\" x2=\"788\" y2=\"372\" stroke=\"#d8dee9\" stroke-width=\"1\" class=\"sq-grid\" data-sq-role=\"grid-line\"/><text x=\"43\" y=\"375.5\" font-size=\"10\" text-anchor=\"end\" textLength=\"30\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">40.00</text><line x1=\"49\" y1=\"252\" x2=\"788\" y2=\"252\" stroke=\"#d8dee9\" stroke-width=\"1\" class=\"sq-grid\" data-sq-role=\"grid-line\"/><text x=\"43\" y=\"255.5\" font-size=\"10\" text-anchor=\"end\" textLength=\"30\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">45.00</text><line x1=\"49\" y1=\"132\" x2=\"788\" y2=\"132\" stroke=\"#d8dee9\" stroke-width=\"1\" class=\"sq-grid\" data-sq-role=\"grid-line\"/><text x=\"43\" y=\"135.5\" font-size=\"10\" text-anchor=\"end\" textLength=\"30\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">50.00</text><line x1=\"49\" y1=\"12\" x2=\"788\" y2=\"12\" stroke=\"#d8dee9\" stroke-width=\"1\" class=\"sq-grid\" data-sq-role=\"grid-line\"/><text x=\"43\" y=\"15.5\" font-size=\"10\" text-anchor=\"end\" textLength=\"30\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">55.00</text><line x1=\"49\" y1=\"372\" x2=\"788\" y2=\"372\" stroke=\"#c9d1df\" stroke-width=\"1.5\" class=\"sq-axis\" data-sq-role=\"axis-line\"/><line x1=\"49\" y1=\"372\" x2=\"49\" y2=\"378\" stroke=\"#c9d1df\" stroke-width=\"1\" class=\"sq-tick\" data-sq-role=\"axis-line\"/><text x=\"49\" y=\"388\" font-size=\"10\" text-anchor=\"middle\" textLength=\"18\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">Mon</text><line x1=\"295.333\" y1=\"372\" x2=\"295.333\" y2=\"378\" stroke=\"#c9d1df\" stroke-width=\"1\" class=\"sq-tick\" data-sq-role=\"axis-line\"/><text x=\"295.333\" y=\"388\" font-size=\"10\" text-anchor=\"middle\" textLength=\"18\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">Tue</text><line x1=\"541.667\" y1=\"372\" x2=\"541.667\" y2=\"378\" stroke=\"#c9d1df\" stroke-width=\"1\" class=\"sq-tick\" data-sq-role=\"axis-line\"/><text x=\"541.667\" y=\"388\" font-size=\"10\" text-anchor=\"middle\" textLength=\"18\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">Wed</text><line x1=\"788\" y1=\"372\" x2=\"788\" y2=\"378\" stroke=\"#c9d1df\" stroke-width=\"1\" class=\"sq-tick\" data-sq-role=\"axis-line\"/><text x=\"788\" y=\"388\" font-size=\"10\" text-anchor=\"end\" textLength=\"18\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">Thu</text><line x1=\"49\" y1=\"12\" x2=\"49\" y2=\"372\" class=\"sq-mark\" data-sq-role=\"plot\" data-sq-target-key=\"t-point-3a9c0e1c589f383c\"/><line x1=\"295.333\" y1=\"12\" x2=\"295.333\" y2=\"372\" class=\"sq-mark\" data-sq-role=\"plot\" data-sq-target-key=\"t-point-011534887c320c7a\"/><line x1=\"541.667\" y1=\"12\" x2=\"541.667\" y2=\"372\" class=\"sq-mark\" data-sq-role=\"plot\" data-sq-target-key=\"t-point-0e20f93d3fcdfecf\"/><line x1=\"788\" y1=\"12\" x2=\"788\" y2=\"372\" class=\"sq-mark\" data-sq-role=\"plot\" data-sq-target-key=\"t-point-5c4256692598f943\"/><path d=\"M 49 372 L 295.333 300 M 788 84 L 788 84\" fill=\"none\" stroke=\"#2563eb\" stroke-width=\"2\" class=\"sq-mark sq-line\" data-sq-role=\"line\" data-sq-target-key=\"t-series-6d7e15e53fc71bba\" data-sq-series-index=\"0\" data-sq-palette-index=\"0\"/></g></svg>",
  "seriesResults": [
    {
      "maximum": {
        "value": "52",
        "index": 3
      },
      "hasBand": false,
      "label": "Signups",
      "rawValues": [
        "40",
        "43",
        null,
        "52"
      ],
      "id": "signups",
      "meaning": "neutral",
      "gapRuns": [
        {
          "fromIndex": 2,
          "toIndex": 2
        }
      ],
      "minimum": {
        "value": "40",
        "index": 0
      }
    }
  ],
  "accessibility": {
    "title": "line chart with 1 series",
    "detail": "full",
    "description": "line chart. 1 series over 4 ordered points. Signups: Mon 40, Tue 43, Wed no value, Thu 52. All values are listed."
  }
}

A forecast drawn with its uncertainty band

Inputjson
{
  "x": [
    "Q1",
    "Q2",
    "Q3"
  ],
  "domainType": "label",
  "series": [
    {
      "values": [
        "120",
        "128",
        "133"
      ],
      "label": "Forecast demand",
      "lower": [
        "112",
        "117",
        "119"
      ],
      "id": "forecast",
      "upper": [
        "128",
        "139",
        "147"
      ]
    }
  ]
}
Expected outputjson
{
  "transformationSummary": {
    "applied": false,
    "mode": "raw"
  },
  "domainResults": [
    {
      "input": "Q1",
      "normalized": "Q1"
    },
    {
      "input": "Q2",
      "normalized": "Q2"
    },
    {
      "input": "Q3",
      "normalized": "Q3"
    }
  ],
  "height": 400,
  "viewBox": "0 0 800 400",
  "renderSummary": {
    "domainType": "label",
    "curve": "straight",
    "seriesCount": 1,
    "pointCount": 3,
    "gapCount": 0,
    "bandsRendered": true
  },
  "width": 800,
  "behavior": {
    "motion": {
      "enabled": true,
      "finalState": "static-equivalent",
      "reducedMotion": "respect",
      "preset": "enter_trace"
    },
    "interaction": {
      "enabled": true,
      "capabilities": [
        "crosshair",
        "focus",
        "tooltip"
      ]
    }
  },
  "svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"800\" height=\"400\" viewBox=\"0 0 800 400\" role=\"img\" class=\"sq-chart sq-chart--line sq-family--cartesian sq-theme--squillify sq-surface--light sq-density--standard\" data-sq-style-contract=\"CHART_STYLE@1\" data-sq-chart=\"line\" data-sq-family=\"cartesian\" data-sq-theme=\"squillify\" data-sq-theme-version=\"1\" data-sq-surface=\"light\" data-sq-density=\"standard\" data-sq-a11y-detail=\"full\" aria-labelledby=\"sq-7f60cd3751d0-title-0 sq-7f60cd3751d0-desc-1\"><title id=\"sq-7f60cd3751d0-title-0\">line chart with 1 series</title><desc id=\"sq-7f60cd3751d0-desc-1\">line chart. 1 series over 3 ordered points, with uncertainty bands. Forecast demand: Q1 120, Q2 128, Q3 133. All values are listed.</desc><style>.sq-chart{--sq-chart-axis:#c9d1df;--sq-chart-font-family:'Squillify Mono', 'IBM Plex Mono', monospace;--sq-chart-grid:#d8dee9;--sq-chart-surface:#ffffff;--sq-chart-text-muted:#667085;--sq-chart-text-primary:#101828;--sq-series-1:#2563eb;--sq-series-2:#6d5ce7;--sq-series-3:#168a5b;--sq-series-4:#c45412;--sq-series-5:#d92d20;--sq-series-6:#667085;font-family:var(--sq-chart-font-family);font-weight:500;}.sq-chart .sq-background{fill:var(--sq-chart-surface);}.sq-chart .sq-grid{stroke:var(--sq-chart-grid);}.sq-chart .sq-axis{stroke:var(--sq-chart-axis);}.sq-chart .sq-tick-label{fill:var(--sq-chart-text-muted);}.sq-chart .sq-band[data-sq-palette-index=\"0\"]{fill:var(--sq-series-1);}.sq-chart .sq-line[data-sq-palette-index=\"0\"]{stroke:var(--sq-series-1);}</style><rect x=\"0\" y=\"0\" width=\"800\" height=\"400\" fill=\"#ffffff\" class=\"sq-background\" data-sq-role=\"background\"/><g class=\"sq-plot\" data-sq-role=\"plot\"><line x1=\"55\" y1=\"372\" x2=\"788\" y2=\"372\" stroke=\"#d8dee9\" stroke-width=\"1\" class=\"sq-grid\" data-sq-role=\"grid-line\"/><text x=\"49\" y=\"375.5\" font-size=\"10\" text-anchor=\"end\" textLength=\"36\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">110.00</text><line x1=\"55\" y1=\"282\" x2=\"788\" y2=\"282\" stroke=\"#d8dee9\" stroke-width=\"1\" class=\"sq-grid\" data-sq-role=\"grid-line\"/><text x=\"49\" y=\"285.5\" font-size=\"10\" text-anchor=\"end\" textLength=\"36\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">120.00</text><line x1=\"55\" y1=\"192\" x2=\"788\" y2=\"192\" stroke=\"#d8dee9\" stroke-width=\"1\" class=\"sq-grid\" data-sq-role=\"grid-line\"/><text x=\"49\" y=\"195.5\" font-size=\"10\" text-anchor=\"end\" textLength=\"36\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">130.00</text><line x1=\"55\" y1=\"102\" x2=\"788\" y2=\"102\" stroke=\"#d8dee9\" stroke-width=\"1\" class=\"sq-grid\" data-sq-role=\"grid-line\"/><text x=\"49\" y=\"105.5\" font-size=\"10\" text-anchor=\"end\" textLength=\"36\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">140.00</text><line x1=\"55\" y1=\"12\" x2=\"788\" y2=\"12\" stroke=\"#d8dee9\" stroke-width=\"1\" class=\"sq-grid\" data-sq-role=\"grid-line\"/><text x=\"49\" y=\"15.5\" font-size=\"10\" text-anchor=\"end\" textLength=\"36\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">150.00</text><line x1=\"55\" y1=\"372\" x2=\"788\" y2=\"372\" stroke=\"#c9d1df\" stroke-width=\"1.5\" class=\"sq-axis\" data-sq-role=\"axis-line\"/><line x1=\"55\" y1=\"372\" x2=\"55\" y2=\"378\" stroke=\"#c9d1df\" stroke-width=\"1\" class=\"sq-tick\" data-sq-role=\"axis-line\"/><text x=\"55\" y=\"388\" font-size=\"10\" text-anchor=\"middle\" textLength=\"12\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">Q1</text><line x1=\"421.5\" y1=\"372\" x2=\"421.5\" y2=\"378\" stroke=\"#c9d1df\" stroke-width=\"1\" class=\"sq-tick\" data-sq-role=\"axis-line\"/><text x=\"421.5\" y=\"388\" font-size=\"10\" text-anchor=\"middle\" textLength=\"12\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">Q2</text><line x1=\"788\" y1=\"372\" x2=\"788\" y2=\"378\" stroke=\"#c9d1df\" stroke-width=\"1\" class=\"sq-tick\" data-sq-role=\"axis-line\"/><text x=\"788\" y=\"388\" font-size=\"10\" text-anchor=\"end\" textLength=\"12\" lengthAdjust=\"spacing\" fill=\"#667085\" class=\"sq-label sq-tick-label\" data-sq-role=\"tick-label\">Q3</text><line x1=\"55\" y1=\"12\" x2=\"55\" y2=\"372\" class=\"sq-mark\" data-sq-role=\"plot\" data-sq-target-key=\"t-point-3a9c0e1c589f383c\"/><line x1=\"421.5\" y1=\"12\" x2=\"421.5\" y2=\"372\" class=\"sq-mark\" data-sq-role=\"plot\" data-sq-target-key=\"t-point-011534887c320c7a\"/><line x1=\"788\" y1=\"12\" x2=\"788\" y2=\"372\" class=\"sq-mark\" data-sq-role=\"plot\" data-sq-target-key=\"t-point-0e20f93d3fcdfecf\"/><path d=\"M 55 210 L 421.5 111 L 788 39 L 788 291 L 421.5 309 L 55 354 Z\" fill=\"#2563eb\" fill-opacity=\"0.18\" class=\"sq-mark sq-band\" data-sq-role=\"band\" data-sq-series-index=\"0\" data-sq-palette-index=\"0\"/><path d=\"M 55 282 L 421.5 210 L 788 165\" fill=\"none\" stroke=\"#2563eb\" stroke-width=\"2\" class=\"sq-mark sq-line\" data-sq-role=\"line\" data-sq-target-key=\"t-series-6d7e15e53fc71bba\" data-sq-series-index=\"0\" data-sq-palette-index=\"0\"/></g></svg>",
  "seriesResults": [
    {
      "maximum": {
        "value": "133",
        "index": 2
      },
      "hasBand": true,
      "label": "Forecast demand",
      "rawValues": [
        "120",
        "128",
        "133"
      ],
      "id": "forecast",
      "meaning": "neutral",
      "gapRuns": [],
      "minimum": {
        "value": "120",
        "index": 0
      }
    }
  ],
  "accessibility": {
    "title": "line chart with 1 series",
    "detail": "full",
    "description": "line chart. 1 series over 3 ordered points, with uncertainty bands. Forecast demand: Q1 120, Q2 128, Q3 133. All values are listed."
  }
}
Tip
lower and upper turn a single line into a line plus a shaded band; both arrays must be the same length as values
  • Show a metric's trend over time or another ordered dimension
  • Compare a handful of series on a shared axis
  • Show a forecast or measurement with its uncertainty band

Avoid for

  • Unordered categories (use chart.bar)
  • Tens of thousands of points on a small canvas — we refuse those
  • Brushing or linked multi-chart selection

Composable with

Safety & privacy

  • Runs without calling any external service.
  • Your payloads are never stored permanently.
  • Telemetry captures metadata only — never your payload contents.
  • We never train models on your payloads.
  • No human reviews your payloads.

Tags

chartvisualizationtime-seriessvgline-chart