AstrolUI AstrolUI
Yellow Orange Red Green Blue Purple Custom color
Light mode
Interaction

Dates with zoom, annotations, events and changing data, custom tooltip and export to image.

Each example is a complete component: copy its code (markup and @code), including the sample data, and replace it with yours.

1. Dates and zoom

Date axis (XAxisType.Datetime) with zoom: drag over the chart to zoom in; the toolbar resets it.
Daily orders9090858580807575707065656060555550504545404001 Jan01 Jan20 Jan20 Jan10 Feb10 Feb01 Mar01 Mar20 Mar20 Mar
Download SVG
Download PNG
Download CSV
@using AstrolCharts
 
@* Date axis: X goes as Unix milliseconds. Drag over the chart to zoom; the toolbar resets it. *@
<AstrolChart TItem="DailyValue" Title="Daily orders" XAxisType="XAxisType.Datetime" Options="options" Height="@(320)">
 <AstrolPointSeries TItem="DailyValue"
 Items="values"
 Name="Orders"
 SeriesType="SeriesType.Area"
 XValue="e => e.Date.ToUnixTimeMilliseconds()"
 YValue="e => e.Orders" />
</AstrolChart>
 
@code {
 private readonly AstrolChartOptions<DailyValue> options = new()
 {
 Chart = new Chart
 {
 Zoom = new Zoom { Enabled = true, Type = AxisType.X, AutoScaleYaxis = true },
 Toolbar = new Toolbar { Show = true },
 },
 Xaxis = new XAxis { Labels = new XAxisLabels { Format = "dd MMM" } },
 DataLabels = new DataLabels { Enabled = false },
 Stroke = new Stroke { Width = 2 },
 };
 
 // Deterministic sample: 90 days
 private readonly List<DailyValue> values = Enumerable.Range(0, 90)
 .Select(i => new DailyValue
 {
 Date = new DateTimeOffset(2026, 1, 1, 0, 0, 0, TimeSpan.Zero).AddDays(i),
 Orders = 40 + (i * 7 % 23) + i / 3,
 })
 .ToList();
 
 public class DailyValue
 {
 public DateTimeOffset Date { get; set; }
 public decimal Orders { get; set; }
 }
}

2. Annotations

Options.Annotations: a horizontal line (goal) and a vertical band (campaign). They can also be added from code.
Weekly sales650650600600550550500500450450400400350350300300W1W1W2W2W3W3W4W4W5W5W6W6W7W7W8W8GoalCampaign
Download SVG
Download PNG
Download CSV
@using AstrolCharts
 
@* Annotations: a horizontal line (goal) and a vertical band (campaign). *@
<AstrolChart TItem="WeeklySale" Title="Weekly sales" Options="options" Height="@(320)">
 <AstrolPointSeries TItem="WeeklySale"
 Items="sales"
 Name="Sales"
 SeriesType="SeriesType.Line"
 XValue="e => e.Week"
 YValue="e => e.Amount" />
</AstrolChart>
 
@code {
 private readonly AstrolChartOptions<WeeklySale> options = new()
 {
 Stroke = new Stroke { Width = 3 },
 Annotations = new Annotations
 {
 Yaxis = new List<AnnotationsYAxis>
 {
 new AnnotationsYAxis
 {
 Y = 500,
 BorderColor = "#12ba38",
 Label = new Label { Text = "Goal", Style = new Style { Background = "#12ba38", Color = "#fff" } },
 },
 },
 Xaxis = new List<AnnotationsXAxis>
 {
 new AnnotationsXAxis
 {
 X = "W4",
 X2 = "W6",
 FillColor = "#ffd800",
 Opacity = 0.2,
 Label = new Label { Text = "Campaign", Style = new Style { Background = "#ffd800", Color = "#222" } },
 },
 },
 },
 };
 
 private readonly List<WeeklySale> sales = new()
 {
 new() { Week = "W1", Amount = 320 },
 new() { Week = "W2", Amount = 360 },
 new() { Week = "W3", Amount = 340 },
 new() { Week = "W4", Amount = 450 },
 new() { Week = "W5", Amount = 560 },
 new() { Week = "W6", Amount = 610 },
 new() { Week = "W7", Amount = 480 },
 new() { Week = "W8", Amount = 470 },
 };
 
 public class WeeklySale
 {
 public string Week { get; set; } = string.Empty;
 public decimal Amount { get; set; }
 }
}

3. Events and changing data

Click a column (OnDataPointSelection), generate new data (UpdateSeriesAsync) or hide a series (ToggleSeriesAsync).
Won
Lost
Results by team1414121210108866442200LionsLionsEaglesEaglesSharksSharksWolvesWolves
Download SVG
Download PNG
Download CSV

Click a column.

@using AstrolCharts
@using Astrol.Component.Basic.Button
@using Astrol.Entities.Basic.UI
 
@* Click a column (OnDataPointSelection), change the data (UpdateSeriesAsync) or hide a series (ToggleSeriesAsync). *@
<AstrolChart @ref="chart"
 TItem="TeamResult"
 Title="Results by team"
 Height="@(300)"
 OnDataPointSelection="OnSelected">
 <AstrolPointSeries TItem="TeamResult"
 Items="results"
 Name="Won"
 SeriesType="SeriesType.Bar"
 XValue="e => e.Team"
 YValue="e => e.Won" />
 <AstrolPointSeries TItem="TeamResult"
 Items="results"
 Name="Lost"
 SeriesType="SeriesType.Bar"
 XValue="e => e.Team"
 YValue="e => e.Lost" />
</AstrolChart>
 
<div style="padding:5px 10px">
 <AstrolButton Icon="astrol-arrows-cw" Text="New data" Style="AstrolStyle.Blue" OnClick="NewData" />
 <AstrolButton Icon="astrol-eye" Text="Show / hide Lost" Style="AstrolStyle.White" OnClick="ToggleLost" />
 <p aria-live="polite">@message</p>
</div>
 
@code {
 private AstrolChart<TeamResult>? chart;
 private string message = "Click a column.";
 private int round;
 
 private readonly List<TeamResult> results = new()
 {
 new() { Team = "Lions", Won = 12, Lost = 4 },
 new() { Team = "Eagles", Won = 9, Lost = 7 },
 new() { Team = "Sharks", Won = 14, Lost = 2 },
 new() { Team = "Wolves", Won = 6, Lost = 10 },
 };
 
 private void OnSelected(SelectedData<TeamResult> selected)
 {
 var team = selected.DataPoint.Items.First();
 message = selected.IsSelected
 ? $"{selected.Series.Name} - {team.Team}: won {team.Won}, lost {team.Lost}"
 : "Selection cleared.";
 }
 
 private async Task NewData()
 {
 round++;
 foreach (var (team, i) in results.Select((t, i) => (t, i)))
 {
 team.Won = (round * 5 + i * 3) % 15 + 2;
 team.Lost = (round * 3 + i * 7) % 12 + 1;
 }
 
 // The list is the same object: tell the chart to read it again
 await chart!.UpdateSeriesAsync(animate: true);
 }
 
 private Task ToggleLost() => chart!.ToggleSeriesAsync("Lost");
 
 public class TeamResult
 {
 public string Team { get; set; } = string.Empty;
 public decimal Won { get; set; }
 public decimal Lost { get; set; }
 }
}

4. Custom tooltip

AstrolPointTooltip renders the tooltip with Blazor; context.DataPoint.Items holds the objects of the point. The series go in <ChildContent>.
Top products60060050050040040030030020020010010000KeyboardKeyboardMouseMouseMonitorMonitorHeadsetHeadset
Download SVG
Download PNG
Download CSV
@using AstrolCharts
 
@* AstrolPointTooltip: Blazor content of the tooltip. context.DataPoint.Items are the items of the point.
 With a tooltip, the series go inside <ChildContent>. *@
<AstrolChart TItem="Product" Title="Top products" Height="@(300)">
 <ChildContent>
 <AstrolPointSeries TItem="Product"
 Items="products"
 Name="Units sold"
 SeriesType="SeriesType.Bar"
 XValue="e => e.Name"
 YValue="e => e.Units" />
 </ChildContent>
 <AstrolPointTooltip>
 @{ var product = context.DataPoint.Items.First(); }
 <div style="padding:10px; min-width:160px">
 <b>@product.Name</b>
 <div>Units: @product.Units</div>
 <div>Price: @product.Price.ToString("C")</div>
 <div>Revenue: <b>@((product.Units * product.Price).ToString("C"))</b></div>
 </div>
 </AstrolPointTooltip>
</AstrolChart>
 
@code {
 private readonly List<Product> products = new()
 {
 new() { Name = "Keyboard", Units = 320, Price = 35 },
 new() { Name = "Mouse", Units = 540, Price = 18 },
 new() { Name = "Monitor", Units = 120, Price = 210 },
 new() { Name = "Headset", Units = 260, Price = 49 },
 };
 
 public class Product
 {
 public string Name { get; set; } = string.Empty;
 public decimal Units { get; set; }
 public decimal Price { get; set; }
 }
}

5. Export to image

GetDataUriAsync returns the chart as a PNG (data URI) to show it, save it or include it in a report.
Search
Social
Email
Referral
Leads by channel
@using AstrolCharts
@using Astrol.Component.Basic.Button
@using Astrol.Entities.Basic.UI
 
@* GetDataUriAsync returns the chart as a PNG (data URI) to show it, save it or put it in a report. *@
<AstrolChart @ref="chart" TItem="Channel" Title="Leads by channel" Height="@(260)">
 <AstrolPointSeries TItem="Channel"
 Items="channels"
 Name="Leads"
 SeriesType="SeriesType.Donut"
 XValue="e => e.Name"
 YValue="e => e.Leads" />
</AstrolChart>
 
<div style="padding:5px 10px">
 <AstrolButton Icon="astrol-picture" Text="Get image" Style="AstrolStyle.Blue" OnClick="Export" />
 @if (image != null)
 {
 <img src="@image" alt="Exported chart" style="max-width:100%; border:1px solid var(--color-gray-a); margin-top:5px" />
 }
</div>
 
@code {
 private AstrolChart<Channel>? chart;
 private string? image;
 
 private async Task Export()
 {
 image = await chart!.GetDataUriAsync(new DataUriOptions { Scale = 1 });
 }
 
 private readonly List<Channel> channels = new()
 {
 new() { Name = "Search", Leads = 420 },
 new() { Name = "Social", Leads = 310 },
 new() { Name = "Email", Leads = 180 },
 new() { Name = "Referral", Leads = 95 },
 };
 
 public class Channel
 {
 public string Name { get; set; } = string.Empty;
 public decimal Leads { get; set; }
 }
}
Markdown for AI © 2026 AstrolUI v10.0.13