Components
Charts
Charts organise data to communicate information with clarity, insight, and visual appeal. In the Instagram system, chart chrome stays quiet while colour, motion, and labels help people understand what changed and why it matters.
Overview
Charts turn raw metrics into decisions
Charts highlight key information in a dataset. They help people understand patterns, compare values, track change, monitor progress, and decide what to do next.
Creator analytics
Show the post formats, audience segments, and posting windows that move performance.
Post reach
Compare how feed posts, reels, carousels, and collaborations travel across audiences.
Engagement trends
Track likes, comments, shares, saves, replies, and profile actions over time.
Audience growth
Reveal follower growth, churn, geographic shifts, and active-hour patterns.
Ad performance
Monitor spend, impressions, click-through rate, conversions, and cost per result.
Story interactions
Understand taps forward, exits, replies, sticker taps, and completion rate.
Anatomy
Every chart has a job, a structure, and a reading path
A chart is more than marks inside a box. It needs a plot, scale, labels, legends, annotations, and accessibility labels that all support the same message.
Plot area
The bounded space where values are encoded. Keep it larger than supporting chrome.
Marks
Bars, lines, points, areas, stacks, and combinations that encode the dataset.
Axes
Scales that map values or categories to position.
Ticks
Small reference stops that divide an axis into readable intervals.
Grid lines
Quiet reference lines for comparison; they should never dominate the marks.
Axis value labels
Short labels that clarify units, dates, or categories.
Titles
The chart's main message in plain language.
Subtitles
Scope, date range, unit, or comparison context.
Annotations
Direct notes on notable shifts, peaks, or anomalies.
Legends
A decoding key for colour, texture, or shape when direct labels are not enough.
Accessibility labels
Programmatic names, summaries, mark labels, and interactive value announcements.
Marks
Choose marks by the question people need answered
Instagram charts should use the simplest mark that communicates the insight. Brand colour and motion can add energy, but the mark must carry the meaning first.
Bar Marks
- When to use
- Use bars to compare discrete categories, rankings, or short time buckets such as post reach by format.
- Communicates best
- Bars communicate magnitude and difference quickly because every mark shares a common baseline.
- Mistakes to avoid
- Do not truncate the baseline when magnitude comparison is the main message. Avoid dense labels on every bar in compact cards.
- Instagram treatment
- Use flat rounded rectangles, subtle grid lines, and one Instagram gradient or tokenized accent for the selected series. Colour, shape, labels, and motion should support comprehension before they express style.
Line Marks
- When to use
- Use lines for continuous change over time, such as audience growth, weekly reach, or story completion rate.
- Communicates best
- Lines communicate direction, pace, turning points, and trend continuity.
- Mistakes to avoid
- Do not imply precision with too many points or use a line for unrelated categories.
- Instagram treatment
- Use a confident 2px to 3px stroke, rounded joins, compact points only where inspection is useful, and no heavy chart frame. Colour, shape, labels, and motion should support comprehension before they express style.
Point Marks
- When to use
- Use points to show individual observations, outliers, or relationships between two measures.
- Communicates best
- Points communicate distribution, clusters, and exceptions without hiding the original observations.
- Mistakes to avoid
- Do not rely on colour alone to distinguish groups; shape, label, or position must help.
- Instagram treatment
- Use circular targets with a larger invisible hit area so touch and keyboard inspection feel forgiving. Colour, shape, labels, and motion should support comprehension before they express style.
Area Marks
- When to use
- Use areas to emphasize accumulated volume or the weight of a trend, such as total impressions over a campaign window.
- Communicates best
- Areas communicate scale and continuity when the filled region has a meaningful baseline.
- Mistakes to avoid
- Do not stack many translucent areas or let the fill obscure labels and grid lines.
- Instagram treatment
- Use a soft Instagram gradient fill under a clear line, with opacity low enough to keep data readable. Colour, shape, labels, and motion should support comprehension before they express style.
Stacked Marks
- When to use
- Use stacked marks when the total and the contribution of each segment both matter.
- Communicates best
- Stacks communicate composition, such as reach from followers, non-followers, ads, and shares.
- Mistakes to avoid
- Do not compare inner segments across many stacks unless the chart also provides labels or summaries.
- Instagram treatment
- Use compact rounded stacks, clear legends, and restrained separators between segments. Colour, shape, labels, and motion should support comprehension before they express style.
Combined Marks
- When to use
- Use combined marks when two related measures need one shared context, such as reach bars plus engagement-rate line.
- Communicates best
- Combined marks communicate relationship and divergence between volume and rate.
- Mistakes to avoid
- Do not combine unrelated metrics or use dual axes without explicit units and labels.
- Instagram treatment
- Give each metric a distinct mark shape and label so colour is supportive, not required. Colour, shape, labels, and motion should support comprehension before they express style.
Axes
Axis ranges should make comparison honest
Axes define what difference means. Keep them stable when people compare charts, and only make them dynamic when the page explains the narrower focus.
Use zero as the lower bound for bars and other length-based comparisons. A truncated bar baseline can exaggerate small differences. For line charts, a non-zero lower bound is acceptable when the chart is about variation inside a range, but the subtitle or annotation must say so.
Tick density should match the available plot width. Use familiar sequences such as 0, 25K, 50K, 75K or 0%, 25%, 50%, 75%, 100%. Keep grid lines subtle and align the chart edges with nearby text, cards, and controls so the chart feels integrated with the surrounding Instagram interface.
Fixed range
Use a fixed range when people compare the same metric across posts, creators, or time windows.
Dynamic range
Use a dynamic range when the chart's job is to reveal small movement inside a narrow performance band.
Compact labels
Use short labels in cards: 1.2K, 4 PM, Mon, Q3, or 8.4%. Expand the unit in the subtitle.
Responsive web
Keep four familiar ticks, full labels, and enough plot width for comparison.
Mobile web
Reduce tick density and show the summary before the chart, not after a tooltip.
Embedded cards
Use a spark chart plus the actual value; omit low-value axis chrome.
Descriptive content
Write the message before drawing the chart
Every chart should have a clear main message before people inspect the details. Titles, subtitles, annotations, summaries, labels, and legends should reduce interpretation work.
Title
Lead with the insight: Reels drove the largest reach lift, not Reach by format.
Subtitle
State scope and unit: Last 28 days, accounts reached.
Annotation
Name the cause or event: Remix sharing increased after launch week.
Summary
Give a text version of the takeaway for complex charts and screen readers.
Legend
Use direct labels when possible; use a legend only when it makes comparison easier.
Tone
Use Instagram language that is specific, optimistic, and concrete: Saves rose fastest among carousel posts.
Interaction
Inspection should clarify, not hide the truth
Hover, tap, focus, and scrubbing can reveal exact values, but critical information must remain visible without interaction.
Story interactions
Thu: 25K reach, 1.2K engagementsHover and tap
Highlight the nearest mark and show a value tooltip. Tap should pin the selection until another mark is chosen.
Scrubbing
Let the entire plot area act as the target on touch screens; the visible point can stay small.
Selected marks
Use shape, border, label, or position in addition to colour.
Keyboard
Order focus by reading direction. Arrow keys or range controls can support sequential inspection.
Reduced motion
Disable animated drawing and looping pulse effects. Preserve instant state changes.
Tooltips
Keep values short, include units, and ensure the same information is available in text.
Colour
Use the documented palette without inventing chart hues
Data marks should use semantic Instagram tokens. Reserve the brand gradient for whole-surface treatments and gradient examples, matching the Colour manual instead of creating partial chart-only ramps.
Primary emphasis
Use the exact five-stop spectrum for whole-surface brand moments, not a new chart-specific gradient.
Neutral comparison
Use secondary text, separators, highlights, and elevated backgrounds for inactive series and reference values.
Secondary cues
Pair semantic colour with labels, shape, separators, texture, direct annotations, or selected outlines.
Accessibility
Charts need more than one image alt label
Accessible charts expose purpose, structure, values, and interaction state. Treat the text summary as part of the chart, not an afterthought.
Purpose
Chart showing how story interactions changed across the last seven days.
Axis
Horizontal axis: day of week. Vertical axis: account reach, from 0 to 30 thousand.
Mark
Saturday: 29.2K reach and 1.4K engagements, highest engagement in the week.
Grouped mark
Reels: 42K follower reach, 30K non-follower reach, 8K paid reach.
Legend
Gradient bars show organic reach. Grey bars show paid reach.
Interactive value
Selected value: Thursday, 24.6K reach, 1.2K engagements.
Screen readers
Use labelled figures, summaries, and interactive mark labels. Do not expose only an unlabeled SVG.
Keyboard navigation
Make marks or an equivalent scrubber reachable in logical order.
Reduced motion
Remove animated drawing, shimmer, pulse, and looped transitions unless the user opts in.
High contrast
Preserve visible borders, selected states, and labels when gradients flatten.
Non-colour interpretation
Use text labels, patterns, separators, annotations, and direct values for meaning.
Good label
Saturday: 29.2K reach and 1.4K engagements, highest engagement in the week.
<figure aria-labelledby="reach-title" aria-describedby="reach-summary">
<h3 id="reach-title">Reels drove the largest reach lift</h3>
<p id="reach-summary">
Last 28 days. Reels reached 72K accounts, posts reached 48K,
stories reached 34K, and ads reached 64K.
</p>
<div role="img" aria-label="Bar chart comparing reach by format">
<button aria-label="Reels, 72 thousand accounts reached">72K</button>
<button aria-label="Posts, 48 thousand accounts reached">48K</button>
<button aria-label="Stories, 34 thousand accounts reached">34K</button>
<button aria-label="Ads, 64 thousand accounts reached">64K</button>
</div>
</figure>Best practices
Best Practices
Data first
Make the data more prominent than supporting chrome; axes, containers, and legends exist to clarify the marks.
Subtle reference lines
Keep grid lines quiet and use familiar tick sequences such as 0, 25K, 50K, 75K.
Compact width
Maximise plot width in compact layouts before adding extra panels, controls, or decorative frames.
Visible change
Make important changes noticeable with a direct label, annotation, or selected mark treatment.
No hidden essentials
Never require interaction to reveal the critical value, decision, or warning.
Clear alignment
Align chart edges with surrounding text, cards, and controls so the surface feels native to Instagram.
Concise labels
Keep labels short, concrete, and close to the thing they describe.
Actual values
Use actual numbers and units rather than subjective descriptions such as good, low, or impressive.
Unambiguous formats
Avoid ambiguous dates and units; write Jun 29, 4 PM, 29.2K reach, or 8.4% completion.
Text summaries
Use summaries for complex charts so people understand the takeaway before inspecting details.
Do
- Make the data more prominent than supporting chrome.
- Keep grid lines subtle and use familiar tick sequences.
- Maximise plot width in compact layouts and align charts with surrounding content.
- Use actual values, clear units, concise labels, and summaries for complex charts.
- Make important changes noticeable with labels or annotations.
Don’t
- Never require interaction to reveal critical information.
- Do not use ambiguous date or unit formats.
- Do not make colour the only way to understand a group, state, or trend.
- Do not add dashboard chrome that competes with the marks.
Platform
Platform Considerations
The same chart should adapt its density and inspection model to the surface it lives in.
Responsive web
Let the plot width grow first. Move legends below the chart before shrinking label text.
Mobile web
Prefer one insight, one chart, and one inspection gesture. Keep touch targets larger than the visible mark.
Desktop
Support richer comparison: hover, keyboard focus, visible legends, and persistent selected values.
Embedded cards
Use glanceable summaries and a compact spark chart. Never hide the only important number in a tooltip.
Implementation
Implementation Notes
Build charts from reusable primitives so anatomy, accessibility, interaction, and token usage stay consistent across analytics surfaces.
import PageContainer from "@/components/docs/PageContainer";
import Section from "@/components/docs/Section";
import ChartInspector from "./ChartInspector";
import styles from "./charts.module.css";
function ChartPage({ children }) {
return <PageContainer>{children}</PageContainer>;
}
function ChartHero({ title, summary, children }) {
return (
<section className={styles.hero} aria-labelledby="chart-page-title">
<div>
<h1 id="chart-page-title">{title}</h1>
<p>{summary}</p>
</div>
{children}
</section>
);
}
function ChartLegend({ items }) {
return (
<div className={styles.legend} aria-label="Chart legend">
{items.map((item) => <span key={item.label}>{item.label}</span>)}
</div>
);
}
function ChartAccessibilityNote({ children }) {
return <aside className={styles.accessNote}>{children}</aside>;
}
export default function CreatorReachChart({ data }) {
const maxReach = Math.max(...data.map((datum) => datum.reach));
return (
<ChartPage>
<ChartHero
title="Reels drove the largest reach lift"
summary="Last 28 days, accounts reached by content format."
>
<ChartInspector />
</ChartHero>
<Section title="Reach by format">
<figure aria-labelledby="reach-title" aria-describedby="reach-summary">
<h3 id="reach-title">Reels drove the largest reach lift</h3>
<p id="reach-summary">
Last 28 days, accounts reached. Reels reached 72K accounts,
the highest value in the range.
</p>
<div className="chart-bars" aria-label="Reach by content format">
{data.map((datum) => (
<button
key={datum.id}
type="button"
className="chart-mark"
style={{ "--height": (datum.reach / maxReach) * 100 + "%" }}
aria-label={datum.format + ", " + datum.reach.toLocaleString() + " accounts reached"}
>
<span>{datum.label}</span>
</button>
))}
</div>
<ChartLegend items={[{ label: "Organic reach" }, { label: "Paid reach" }]} />
</figure>
<ChartAccessibilityNote>
Keep the takeaway available as text; interaction only adds precision.
</ChartAccessibilityNote>
</Section>
</ChartPage>
);
}.chart-bars {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
align-items: flex-end;
gap: 12px;
min-height: 180px;
border-bottom: 1px solid rgb(var(--ig-separator));
}
.chart-mark {
height: var(--height);
min-height: 28px;
border: 0;
border-radius: var(--radius-md) var(--radius-md) 0 0;
background: rgba(var(--ig-secondary-text), 0.32);
transition: transform 150ms cubic-bezier(0, 0, .1, 1);
}
.chart-mark[aria-current="true"],
.chart-mark:hover,
.chart-mark:focus-visible {
background: rgb(var(--ig-primary-button));
transform: translateY(-3px);
}