Files
supabase/apps/design-system/registry/default/block/chart-composed-basic.tsx
7fce0a12d9 feat(design-system): first pass at db report chart colours (#46787)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

This is a first draft at introducing semantic colours to our
Observability charts. This moves away from just random colours being
assigned to prop after prop. They're only scoped to the Database reports
right now, but if it flows nice, we can open it up to the other reports
too.

This also aims to tone down some of the harsher colours in our charts,
such as the orange which sometimes can look like a warning metric/prop.

| Before | After |
|--------|--------|
| <img width="839" height="336" alt="Screenshot 2026-06-10 at 09 14 56"
src="https://github.com/user-attachments/assets/222747c5-973b-4165-aa53-df7b93412ad3"
/> | <img width="950" height="341" alt="Screenshot 2026-09-14 at 18 14
47"
src="https://github.com/user-attachments/assets/836f3ddd-4a97-4064-b8cf-3a3b435417ac"
/> |

cc @supabase/design for additional thoughts.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added semantic chart color roles with light and dark theme variants
for consistent visualizations.
* Standardized colors and fills across database, networking, storage,
and connection charts.
  * Maximum-value lines now use configured chart colors when available.
  * Added chart palette reference and stress-test examples.
* Added stacked bar charts, customizable margins, and gradient-filled
line charts.
* Improved multi-series bar chart focus and date-range footer alignment.

* **Documentation**
* Documented the chart palette, theme variants, accessibility guidance,
and usage recommendations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
2026-09-16 09:18:40 +01:00

143 lines
3.9 KiB
TypeScript

'use client'
import { BarChart2, ExternalLink } from 'lucide-react'
import { useEffect, useState } from 'react'
import {
Chart,
ChartActions,
ChartBar,
ChartCard,
ChartContent,
ChartEmptyState,
ChartHeader,
ChartLine,
ChartLoadingState,
ChartTitle,
} from 'ui-patterns/Chart'
export default function ComposedChartBasic() {
const [isLoading, setIsLoading] = useState(true)
const actions = [
{
label: 'Open in Logs Explorer',
onClick: () => {
alert('Ta da! You clicked me! 🎉')
},
icon: <ExternalLink size={12} />,
},
]
const data = Array.from({ length: 40 }, (_, i) => {
const date = new Date()
date.setMinutes(date.getMinutes() - i * 3) // Each point 3 minutes apart
const progress = i / 40
const standard_score = Math.floor(55 + progress * 55 + (Math.random() - 0.5) * 12)
const performance = Math.floor(35 + progress * 35 + (Math.random() - 0.5) * 10)
const efficiency = Math.floor(25 + progress * 25 + (Math.random() - 0.5) * 12)
return {
timestamp: date.toISOString(),
standard_score: Math.max(0, Math.min(100, standard_score)),
performance: Math.max(0, Math.min(100, performance)),
efficiency: Math.max(0, Math.min(100, efficiency)),
}
}).reverse()
const chartConfig = {
standard_score: {
label: 'Standard Score',
color: 'hsl(var(--brand-default))',
},
performance: {
label: 'Performance',
color: 'var(--chart-2)',
},
efficiency: {
label: 'Efficiency',
color: 'var(--chart-5)',
},
}
useEffect(() => {
setTimeout(() => {
setIsLoading(false)
}, 1000)
}, [])
return (
<div className="flex flex-col gap-6 w-8/12">
<Chart isLoading={isLoading}>
<ChartCard>
<ChartHeader>
<ChartTitle tooltip="This is a tooltip">Standard Bar Chart</ChartTitle>
<ChartActions actions={actions} />
</ChartHeader>
<ChartContent
isEmpty={data.length === 0}
emptyState={
<ChartEmptyState
icon={<BarChart2 size={16} />}
title="No data to show"
description="It may take up to 24 hours for data to refresh"
/>
}
loadingState={<ChartLoadingState />}
>
<div className="h-40">
<ChartBar
data={data}
dataKey="standard_score"
showGrid={false}
showYAxis={true}
YAxisProps={{
tickFormatter: (value) => `${value}k`,
width: 36,
}}
isFullHeight={true}
/>
</div>
</ChartContent>
</ChartCard>
</Chart>
<Chart isLoading={isLoading}>
<ChartCard>
<ChartHeader>
<ChartTitle tooltip="This is a tooltip">Standard Line Chart</ChartTitle>
<ChartActions actions={actions} />
</ChartHeader>
<ChartContent
isEmpty={data.length === 0}
emptyState={
<ChartEmptyState
icon={<BarChart2 size={16} />}
title="No data to show"
description="It may take up to 24 hours for data to refresh"
/>
}
loadingState={<ChartLoadingState />}
>
<div className="h-40">
<ChartLine
data={data}
dataKey="standard_score"
dataKeys={['standard_score', 'performance', 'efficiency']}
config={chartConfig}
showGrid={true}
showYAxis={true}
YAxisProps={{
tickFormatter: (value) => `${value}k`,
width: 36,
}}
isFullHeight={true}
/>
</div>
</ChartContent>
</ChartCard>
</Chart>
</div>
)
}