From swiftui-dev
Building data visualizations in SwiftUI using Apple's Swift Charts framework.
npx claudepluginhub arustydev/aiThis skill uses the workspace's default tool permissions.
Building data visualizations in SwiftUI using Apple's Swift Charts framework.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
Building data visualizations in SwiftUI using Apple's Swift Charts framework.
import Charts
import SwiftUI
struct TimeSeriesView: View {
let data: [DataPoint]
var body: some View {
Chart(data) { point in
LineMark(
x: .value("Date", point.date),
y: .value("Value", point.value)
)
}
.chartXAxis {
AxisMarks(values: .stride(by: .month)) { value in
AxisValueLabel(format: .dateTime.month(.abbreviated))
}
}
}
}
struct CategoryChart: View {
let sales: [CategorySales]
var body: some View {
Chart(sales) { item in
BarMark(
x: .value("Category", item.category),
y: .value("Sales", item.amount)
)
.foregroundStyle(by: .value("Category", item.category))
}
.chartLegend(.hidden)
}
}
struct ScatterView: View {
let points: [Observation]
var body: some View {
Chart(points) { point in
PointMark(
x: .value("X", point.x),
y: .value("Y", point.y)
)
.foregroundStyle(by: .value("Cluster", point.cluster))
.symbolSize(point.weight * 10)
}
}
}
struct StackedAreaChart: View {
let data: [CategoryTimeSeries]
var body: some View {
Chart(data) { series in
ForEach(series.values) { point in
AreaMark(
x: .value("Date", point.date),
y: .value("Value", point.value)
)
}
.foregroundStyle(by: .value("Category", series.category))
}
.chartForegroundStyleScale([
"Sales": .blue,
"Expenses": .red,
"Profit": .green
])
}
}
struct CombinedChart: View {
let data: [DataPoint]
var body: some View {
Chart(data) { point in
// Line for trend
LineMark(
x: .value("Date", point.date),
y: .value("Value", point.value)
)
.foregroundStyle(.blue)
// Points for individual values
PointMark(
x: .value("Date", point.date),
y: .value("Value", point.value)
)
.foregroundStyle(.blue)
// Rule for average
RuleMark(y: .value("Average", average))
.foregroundStyle(.red.opacity(0.5))
.lineStyle(StrokeStyle(dash: [5, 5]))
}
}
var average: Double {
data.map(\.value).reduce(0, +) / Double(data.count)
}
}
struct RangeChart: View {
let data: [RangeData]
var body: some View {
Chart(data) { item in
// Show range
RectangleMark(
x: .value("Category", item.category),
yStart: .value("Min", item.min),
yEnd: .value("Max", item.max)
)
.opacity(0.3)
// Show median
PointMark(
x: .value("Category", item.category),
y: .value("Median", item.median)
)
}
}
}
struct InteractiveChart: View {
let data: [DataPoint]
@State private var selectedDate: Date?
var body: some View {
Chart(data) { point in
LineMark(
x: .value("Date", point.date),
y: .value("Value", point.value)
)
if let selected = selectedDate,
let point = data.first(where: { Calendar.current.isDate($0.date, inSameDayAs: selected) }) {
RuleMark(x: .value("Selected", point.date))
.foregroundStyle(.gray.opacity(0.3))
PointMark(
x: .value("Date", point.date),
y: .value("Value", point.value)
)
.foregroundStyle(.red)
.symbolSize(100)
}
}
.chartXSelection(value: $selectedDate)
.chartOverlay { proxy in
GeometryReader { geometry in
if let selected = selectedDate,
let point = data.first(where: { Calendar.current.isDate($0.date, inSameDayAs: selected) }),
let position = proxy.position(forX: point.date) {
VStack {
Text(point.date, format: .dateTime.month().day())
Text(point.value, format: .number)
.bold()
}
.padding(8)
.background(.ultraThinMaterial)
.cornerRadius(8)
.position(x: position, y: 20)
}
}
}
}
}
struct ScrollableChart: View {
let data: [DataPoint]
@State private var scrollPosition: Date = .now
var body: some View {
Chart(data) { point in
LineMark(
x: .value("Date", point.date),
y: .value("Value", point.value)
)
}
.chartScrollableAxes(.horizontal)
.chartXVisibleDomain(length: 3600 * 24 * 30) // 30 days
.chartScrollPosition(x: $scrollPosition)
}
}
Chart(data) { point in
BarMark(
x: .value("Category", point.category),
y: .value("Value", point.value)
)
.foregroundStyle(by: .value("Category", point.category))
}
.chartForegroundStyleScale([
"Category A": Color.blue,
"Category B": Color.green,
"Category C": Color.orange
])
Chart(data) { point in
LineMark(
x: .value("Date", point.date),
y: .value("Value", point.value)
)
}
.chartXAxis {
AxisMarks(preset: .aligned) { value in
AxisGridLine()
AxisTick()
AxisValueLabel(format: .dateTime.month())
}
}
.chartYAxis {
AxisMarks(position: .leading) { value in
AxisGridLine()
AxisValueLabel {
if let intValue = value.as(Int.self) {
Text("$\(intValue)")
}
}
}
}
Chart(data) { point in
LineMark(
x: .value("X", point.x),
y: .value("Y", point.y)
)
}
.chartPlotStyle { plotArea in
plotArea
.background(.gray.opacity(0.1))
.border(.gray, width: 1)
}
// For datasets > 1000 points
struct LargeDatasetChart: View {
let points: [Point] // Thousands of points
var body: some View {
Chart {
PointPlot(points, x: \.x, y: \.y)
.foregroundStyle(.blue)
}
}
}
struct AggregatedChart: View {
let rawData: [DataPoint]
var aggregatedData: [DataPoint] {
// Aggregate to reasonable number of points
Dictionary(grouping: rawData) { point in
Calendar.current.startOfDay(for: point.date)
}
.map { date, points in
DataPoint(
date: date,
value: points.map(\.value).reduce(0, +) / Double(points.count)
)
}
.sorted(by: { $0.date < $1.date })
}
var body: some View {
Chart(aggregatedData) { point in
LineMark(
x: .value("Date", point.date),
y: .value("Value", point.value)
)
}
}
}
import Charts
struct Scatter3DView: View {
let points: [Point3D]
var body: some View {
Chart3D(points) { point in
PointMark3D(
x: .value("X", point.x),
y: .value("Y", point.y),
z: .value("Z", point.z)
)
.foregroundStyle(by: .value("Cluster", point.cluster))
}
.chart3DStyle(.interactive) // Allows rotation
}
}
struct ChartWithEmptyState: View {
let data: [DataPoint]
var body: some View {
if data.isEmpty {
ContentUnavailableView(
"No Data",
systemImage: "chart.bar.xaxis",
description: Text("Add some data to see the chart")
)
} else {
Chart(data) { point in
LineMark(
x: .value("Date", point.date),
y: .value("Value", point.value)
)
}
}
}
}
struct ChartWithLoading: View {
let data: [DataPoint]?
let isLoading: Bool
var body: some View {
ZStack {
if let data {
Chart(data) { point in
LineMark(
x: .value("Date", point.date),
y: .value("Value", point.value)
)
}
}
if isLoading {
ProgressView()
}
}
}
}