Kalıplar
Grafik galerisi
Hangi soruya hangi grafik; token temalı ECharts örnekleri, özet metni ve tablo yedeği.
Grafikler Chart bileşeniyle çizilir. ECharts teması DTCG token’larından üretilir; renkler, yazı tipleri ve hareket iki markada ve iki modda kendiliğinden değişir. Bu sayfa her grafik türünü ne zaman seçeceğinizi gösterir.
Ne zaman kullanılır
Bölüm başlığı “Ne zaman kullanılır”- Zaman içindeki eğilimi, kategoriler arası farkı ya da bütünün parçalarını göstermeniz gerektiğinde.
- Tek bir sayı yetiyorsa grafik yerine StatCard kullanın.
- Kullanıcı kesin değerleri okuyacak veya karşılaştıracaksa grafiğin yanında tablo da verin.
Canlı örnek
Bölüm başlığı “Canlı örnek”Her grafik Storybook’tan canlı yüklenir. Sayfa başlığındaki marka ve mod seçimi grafikleri de değiştirir; serinin üstüne gelince değerler görünür.
Çizgi: zaman içinde eğilim
Bölüm başlığı “Çizgi: zaman içinde eğilim”Alan: tek serinin hacmi
Bölüm başlığı “Alan: tek serinin hacmi”Çubuk: kategorileri karşılaştırma
Bölüm başlığı “Çubuk: kategorileri karşılaştırma”Yığılmış çubuk: zaman içinde bileşim
Bölüm başlığı “Yığılmış çubuk: zaman içinde bileşim”Halka: bütünün payları
Bölüm başlığı “Halka: bütünün payları”Gösterge ve değişim
Bölüm başlığı “Gösterge ve değişim”import { Chart, Grid, StatCard } from '@bigbang/ui';import type { ChartKind, ChartSeries } from '@bigbang/ui';import { type Lang, LangProvider } from '../lang';
const copy = { tr: { months: ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz'], categories: ['Kategori A', 'Kategori B', 'Kategori C', 'Kategori D', 'Kategori E'], first: 'Birinci seri', second: 'İkinci seri', third: 'Üçüncü seri', line: { title: 'Aylık kayıt sayısı', description: 'İki serinin altı aylık eğilimi.' }, area: { title: 'Toplam etkinlik', description: 'Tek serinin altı aylık hacmi.' }, bar: { title: 'Kategoriye göre kayıt', description: 'Beş kategorinin karşılaştırması.' }, stacked: { title: 'Aylık dağılım', description: 'Üç serinin aylara göre bileşimi.' }, donut: { title: 'Kategori payları', description: 'Bütünün beş kategoriye dağılımı.' }, kpis: ['Toplam kayıt', 'Açık görev', 'Ortalama süre'], period: 'önceki aya göre', days: '3,5 gün', table: { title: 'Kayıt sayısı, tablo görünümü', description: 'Grafikle aynı veri, tablo olarak.' }, }, en: { months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'], categories: ['Category A', 'Category B', 'Category C', 'Category D', 'Category E'], first: 'First series', second: 'Second series', third: 'Third series', line: { title: 'Records per month', description: 'Six-month trend of two series.' }, area: { title: 'Total activity', description: 'Six-month volume of one series.' }, bar: { title: 'Records by category', description: 'A comparison of five categories.' }, stacked: { title: 'Monthly breakdown', description: 'Composition of three series by month.' }, donut: { title: 'Category shares', description: 'How the whole splits across five categories.' }, kpis: ['Total records', 'Open tasks', 'Average cycle time'], period: 'against last month', days: '3.5 days', table: { title: 'Records per month, table view', description: 'The same data as the chart, as a table.' }, },};
// Round, neutral demo figures.const monthly = [[120, 150, 140, 180, 200, 240], [80, 90, 110, 100, 130, 150], [40, 50, 45, 60, 70, 80]] as const;const byCategory = [320, 250, 180, 120, 80];
const seriesOf = (lang: Lang, count: number): ChartSeries[] => { const t = copy[lang]; const labels = [t.first, t.second, t.third]; return monthly.slice(0, count).map((values, index) => ({ id: `s${index + 1}`, label: labels[index] ?? '', data: values.map((y, month) => ({ x: t.months[month] ?? '', y })), }));};
const categorySeries = (lang: Lang): ChartSeries[] => [ { id: 'categories', label: copy[lang].first, data: byCategory.map((y, index) => ({ x: copy[lang].categories[index] ?? '', y })) },];
type ExampleProps = { lang?: Lang };
function Example({ lang = 'tr', kind, part, series, table }: { lang?: Lang; kind: ChartKind; part: 'line' | 'area' | 'bar' | 'stacked' | 'donut' | 'table'; series: ChartSeries[]; table?: 'visible' }) { const t = copy[lang][part]; const number = new Intl.NumberFormat(lang === 'tr' ? 'tr-TR' : 'en-GB'); return ( <LangProvider lang={lang}> <div className="w-full"> <Chart kind={kind} title={t.title} description={t.description} series={series} height="md" formatValue={(value) => number.format(value)} {...(table ? { table } : {})} /> </div> </LangProvider> );}
export const LineExample = ({ lang = 'tr' }: ExampleProps) => <Example lang={lang} kind="line" part="line" series={seriesOf(lang, 2)} />;export const AreaExample = ({ lang = 'tr' }: ExampleProps) => <Example lang={lang} kind="area" part="area" series={seriesOf(lang, 1)} />;export const BarExample = ({ lang = 'tr' }: ExampleProps) => <Example lang={lang} kind="bar" part="bar" series={categorySeries(lang)} />;export const StackedBarExample = ({ lang = 'tr' }: ExampleProps) => <Example lang={lang} kind="stacked-bar" part="stacked" series={seriesOf(lang, 3)} />;export const DonutExample = ({ lang = 'tr' }: ExampleProps) => <Example lang={lang} kind="donut" part="donut" series={categorySeries(lang)} />;export const TableFallbackExample = ({ lang = 'tr' }: ExampleProps) => <Example lang={lang} kind="line" part="table" series={seriesOf(lang, 1)} table="visible" />;
/** A single key figure: StatCard with its change against the period; no chart needed. */export function KpiTrendExample({ lang = 'tr' }: ExampleProps) { const t = copy[lang]; const percent = (value: number) => (lang === 'tr' ? `%${value}` : `${value}%`); return ( <LangProvider lang={lang}> <Grid columns={{ base: 1, md: 3 }} gap="lg" className="w-full"> <StatCard label={t.kpis[0] ?? ''} value={new Intl.NumberFormat(lang === 'tr' ? 'tr-TR' : 'en-GB').format(1200)} delta={{ value: percent(8), direction: 'up' }} period={t.period} /> <StatCard label={t.kpis[1] ?? ''} value="140" delta={{ value: percent(3), direction: 'up', sentiment: 'negative' }} period={t.period} /> <StatCard label={t.kpis[2] ?? ''} value={t.days} delta={{ value: percent(5), direction: 'down', sentiment: 'positive' }} period={t.period} /> </Grid> </LangProvider> );}Tablo yedeği
Bölüm başlığı “Tablo yedeği”Grafikle aynı veri, tablo olarak.
| Kategori | Birinci seri |
|---|---|
| Oca | 120 |
| Şub | 150 |
| Mar | 140 |
| Nis | 180 |
| May | 200 |
| Haz | 240 |
Kurallar
Bölüm başlığı “Kurallar”| Soru | Grafik | Not |
|---|---|---|
| Zamanla nasıl değişti? | Çizgi (line) |
En çok 4 seri; daha fazlası için ayrı grafik. |
| Ne kadar birikti? | Alan (area) |
Tek seri; çok seride çizgi kullanın. |
| Hangisi büyük? | Çubuk (bar) |
Kategoriler büyükten küçüğe sıralanır. |
| Bileşim zamanla nasıl değişti? | Yığılmış çubuk (stacked-bar) |
En çok 4 parça. |
| Bütünün ne kadarı? | Halka (donut) |
En çok 5 parça; fazlası için çubuk. |
| Tek sayı ve değişimi | StatCard delta |
Yön metinle de okunur. |
| Kural | Değer |
|---|---|
| Seri sayısı | En çok 8; renkler chart.categorical-1…8, yüzeye karşı en az 3:1. |
| Başlık ve özet | Her grafikte title zorunlu, description önerilir; ekran okuyucu ikisini okur. |
| Tablo yedeği | table="toggle" varsayılan; kesin değerler gerekiyorsa visible. |
| Sayı biçimi | formatValue ile Intl.NumberFormat; Türkçede ondalık virgül. |
| Boş veri | emptyLabel metni; boş eksen çizilmez. |
| Gizli değerler | hideValues ile değerler •••• olur, şekil kalır. |
| CSP | SVG çizici satır içi stil yazar; sayfa CSP’sinde style-src-attr 'unsafe-inline' gerekir. |
Davranış
Bölüm başlığı “Davranış”- İlk çizimde seriler 400 ms içinde girer.
- Veri değişince geçiş 240 ms sürer; filtre veya sayfa değişiminde seriler yeniden girmez.
- Üstüne gelince veya klavyeyle odaklanınca değer kutusu görünür.
- Yüklenirken grafik kendi iskeletini gösterir; başlık yerinde kalır.
- Pencere boyutu değişince grafik kabına göre yeniden çizilir.
Erişilebilirlik
Bölüm başlığı “Erişilebilirlik”- Grafik
role="img"taşır; adı başlıktan, açıklaması özet metninden gelir. - “Veriyi tablo olarak göster” düğmesi aynı veriyi
thbaşlıklı bir tabloda açar. - Renk tek başına anlam taşımaz: lejant, değer kutusu ve tablo seri adını yazar.
- StatCard değişim yönünü ok ve gizli metinle (“arttı”, “azaldı”) birlikte okur.
İçerik
Bölüm başlığı “İçerik”- Başlık ne ölçüldüğünü söyler: “Aylık kayıt sayısı”; “Grafik 1” gibi adlar kullanmayın.
- Eksen etiketleri kısa tutulur; ay adları kısaltılır (Oca, Şub).
- Birim başlıkta veya değer biçiminde yazılır, eksende tekrar edilmez.
- Özet metni bir cümlede ana bulguyu verir.
Hareket
Bölüm başlığı “Hareket”| Öğe | Hareket | Preset |
|---|---|---|
| İlk çizim | 400 ms, cubicOut |
motionValues |
| Veri değişimi | 240 ms; filtrede yeniden giriş yok | motionValues |
| StatCard değeri | 110 ms çapraz solma; tutar saymaz | motion.reveal |
Hareketi azaltma tercihinde ECharts animasyonu kapanır (animation: false).
Kullanılan bileşenler
Bölüm başlığı “Kullanılan bileşenler”Chart, StatCard, Grid. Temel: Veri görselleştirme. Sıradaki bileşenler: Sparkline bileşen klasöründe var ama @bigbang/ui dışa aktarımında yok; açıldığında StatCard trend yuvasında küçük eğilim çizgisi gösterilecek.