Kalıplar
Toplu işlemler
Birden çok satırı seçip tek eylemle işlemek; çubuğun ne zaman görüneceği, sayının nasıl bildirileceği ve silmenin nasıl onaylanacağı.
Toplu işlem, kullanıcının birçok satıra aynı eylemi tek adımda uygulamasını sağlar. Bu kalıp seçimi, eylem çubuğunu ve sonucun bildirilmesini sabitler.
Ne zaman kullanılır
Bölüm başlığı “Ne zaman kullanılır”- Kullanıcının tablo ya da listede aynı eylemi çok sayıda satıra uygulaması gerektiğinde.
- Eylemler seçili öğelerin tümü için anlamlıysa: arşivleme, dışa aktarma, silme.
- Tek satırlık eylemler için satır eylemlerini kullanın; çubuk gerekmez.
Canlı örnek
Bölüm başlığı “Canlı örnek”Satırları seçin. Çubuk ilk seçimle belirir ve sayıyı gösterir. “Arşivle” seçimi temizler ve sonucu “Geri al” eylemli bir bildirimle söyler. “Sil” önce bir onay penceresi açar. Çubukta Escape seçimi temizler.
| Durum | |||
|---|---|---|---|
| Öğe 1 | 50 | ||
| Öğe 2 | 100 | ||
| Öğe 3 | 150 | ||
| Öğe 4 | 200 | ||
| Öğe 5 | 250 | ||
| Öğe 6 | 300 | ||
| Öğe 7 | 350 | ||
| Öğe 8 | 400 |
import { ActionBar, AlertDialog, createDataTableColumnHelper, DataTable, Link, Stack, StatusBadge, Text, ToolbarButton, useToast, type DataTableRowSelection } from '@bigbang/ui';import { useMemo, useState } from 'react';import { type Lang, LangProvider } from '../lang';
const copy = { tr: { caption: 'Öğe listesi', name: 'Ad', status: 'Durum', count: 'Adet', item: 'Öğe', archive: 'Arşivle', export: 'Dışa aktar', delete: 'Sil', selected: (count: number) => `${count} öğe seçildi`, archived: (count: number) => `${count} öğe arşivlendi`, exported: (count: number) => `${count} öğe dışa aktarıldı`, deleted: (count: number) => `${count} öğe silindi`, undo: 'Geri al', confirmTitle: (count: number) => `${count} öğe silinsin mi?`, confirmText: 'Seçili öğeler listeden kaldırılır. Bu işlem geri alınamaz.', confirmLabel: (count: number) => `${count} öğeyi sil`, cancel: 'Vazgeç', rule: (count: number) => `Silme, sayıyı düğmede gösteren bir onay ister: “${count} öğeyi sil”.`, ruleLink: 'Onay kalıbı', confirmHref: '/patterns/confirmation/', }, en: { caption: 'Item list', name: 'Name', status: 'Status', count: 'Count', item: 'Item', archive: 'Archive', export: 'Export', delete: 'Delete', selected: (count: number) => `${count} selected`, archived: (count: number) => `${count} ${count === 1 ? 'item' : 'items'} archived`, exported: (count: number) => `${count} ${count === 1 ? 'item' : 'items'} exported`, deleted: (count: number) => `${count} ${count === 1 ? 'item' : 'items'} deleted`, undo: 'Undo', confirmTitle: (count: number) => `Delete ${count} ${count === 1 ? 'item' : 'items'}?`, confirmText: 'The selected items are removed from the list. This cannot be undone.', confirmLabel: (count: number) => `Delete ${count} ${count === 1 ? 'item' : 'items'}`, cancel: 'Cancel', rule: (count: number) => `Deleting asks for a confirmation that shows the count on the button: “Delete ${count} ${count === 1 ? 'item' : 'items'}”.`, ruleLink: 'Confirmation pattern', confirmHref: '/en/patterns/confirmation/', },};
type Row = { id: string; name: string; status: 'active' | 'pending' | 'draft' | 'archived'; count: number };const statusOrder = ['active', 'pending', 'draft'] as const;const helper = createDataTableColumnHelper<Row>();
/** * A table with row selection and an action bar. The bar appears with the first selected row and says how many are selected. * An action runs on all selected rows, clears the selection and reports the result in a toast; archive offers Undo. * Delete asks for confirmation first, with the count in the dialog title and on its button. */export function BulkActionsDemo({ lang = 'tr' }: { lang?: Lang }) { return ( <LangProvider lang={lang}> <BulkTable lang={lang} /> </LangProvider> );}
function BulkTable({ lang }: { lang: Lang }) { const t = copy[lang]; const toast = useToast(); const [rows, setRows] = useState<Row[]>(() => Array.from({ length: 8 }, (_, index) => ({ id: `row-${index + 1}`, name: `${t.item} ${index + 1}`, status: statusOrder[index % statusOrder.length] ?? 'draft', count: (index + 1) * 50 })), ); const [selection, setSelection] = useState<DataTableRowSelection>({}); const [confirmOpen, setConfirmOpen] = useState(false); const count = Object.keys(selection).length;
const columns = useMemo( () => [ helper.accessor('name', { header: t.name, meta: { rowHeader: true } }), helper.accessor('status', { header: t.status, enableSorting: false, cell: (context) => <StatusBadge status={context.getValue()} /> }), helper.accessor('count', { header: t.count, meta: { numeric: true } }), ], [t], );
const archive = () => { const previous = new Map(rows.filter((row) => selection[row.id]).map((row) => [row.id, row.status])); setRows((current) => current.map((row) => (previous.has(row.id) ? { ...row, status: 'archived' } : row))); toast.show({ title: t.archived(count), tone: 'success', action: { label: t.undo, onClick: () => setRows((current) => current.map((row) => (previous.has(row.id) ? { ...row, status: previous.get(row.id) ?? row.status } : row))) }, }); setSelection({}); }; const exportRows = () => { toast.show({ title: t.exported(count), tone: 'success' }); setSelection({}); }; const deleteRows = () => { setRows((current) => current.filter((row) => !selection[row.id])); toast.show({ title: t.deleted(count), tone: 'success' }); setSelection({}); };
return ( <> <Stack gap="md"> <ActionBar placement="inline" count={count} countLabel={t.selected} onClear={() => setSelection({})}> <ToolbarButton label={t.archive} icon="file" onClick={archive} /> <ToolbarButton label={t.export} icon="download" onClick={exportRows} /> <ToolbarButton label={t.delete} icon="trash" onClick={() => setConfirmOpen(true)} /> </ActionBar> <DataTable<Row> columns={columns} data={rows} getRowId={(row) => row.id} getRowLabel={(row) => row.name} caption={t.caption} captionHidden selectionMode="multiple" rowSelection={selection} onRowSelectionChange={setSelection} // The action bar announces the count; the table stays quiet so it is read once. messages={{ 'selected-count': '' }} /> <Text size="sm" tone="subtle"> {t.rule(Math.max(count, 3))} <Link href={t.confirmHref}>{t.ruleLink}</Link> </Text> </Stack> <AlertDialog open={confirmOpen} onOpenChange={setConfirmOpen} title={t.confirmTitle(count)} description={t.confirmText} confirmLabel={t.confirmLabel(count)} cancelLabel={t.cancel} tone="danger" onConfirm={deleteRows} /> </> );}Kurallar
Bölüm başlığı “Kurallar”| Kural | Değer |
|---|---|
| Çubuk | Yalnızca en az 1 seçim varken görünür. |
| Yerleşim | Sayfa uzunsa placement="floating" (görünüm alanının altına sabit); tablonun üstünde sabit alan varsa placement="inline". Örnekte inline. |
| Eylem sayısı | 3 ile 5 arası. Sık kullanılan eylem solda, yıkıcı eylem en sonda. |
| Sayı | Çubukta “3 öğe seçildi”; ekran okuyucuya bir kez duyurulur. |
| Escape | Çubuk içinde seçimi temizler. |
| Başlık onay kutusu | Görünen sayfadaki satırları seçer. |
| Tüm sayfalar | “Tüm 1.000 öğeyi seç” bağlantısı sunulur; sayfaya özgü seçimle karışmaz. |
| Eylem sonrası | Seçim temizlenir; sonuç bir Toast ile bildirilir: “3 öğe arşivlendi”. Geri alınabilen eylemde bildirim “Geri al” sunar. |
| Yıkıcı eylem | AlertDialog ile onay ister; sayı başlıkta ve düğmede yer alır: “3 öğe silinsin mi?”, “3 öğeyi sil”. Bkz. Onay. |
3 öğe arşivlendi
İşlem tamamlandı
Davranış
Bölüm başlığı “Davranış”- Kullanıcı bir satır ya da başlık onay kutusunu seçer. Başlık onay kutusu yalnızca görünen sayfayı seçer.
- Çubuk belirir ve seçili sayıyı gösterir. Birden çok sayfa varsa “Tüm N öğeyi seç” bağlantısı sunulur.
- Kullanıcı bir eylem seçer. Eylem tüm seçili satırlara uygulanır.
- Eylem bitince seçim temizlenir, çubuk kapanır ve bir bildirim sonucu söyler. Arşivleme gibi geri alınabilir eylemde bildirim “Geri al” sunar.
- Silme önce onay ister: sayıyı başlıkta ve düğmede taşıyan, tehlike tonlu bir
AlertDialogaçılır. Odak “Vazgeç”te başlar; vazgeçilirse satırlar ve seçim yerinde kalır. Onay iletişim kutusunun ayrıntıları Onay kalıbında tanımlıdır.
Erişilebilirlik
Bölüm başlığı “Erişilebilirlik”- Çubuk, “Toplu eylemler” adlı bir araç çubuğudur; oklar eylemler arasında gezdirir.
- Seçili sayı bir durum bölgesinde nazikçe ve bir kez okunur. Tablonun kendi seçim duyurusu, örnekte kapatılır; böylece sayı iki kez okunmaz.
- “Seçimi temizle” ilk düğmedir; Escape ile aynı işi yapar.
- Her satır onay kutusu satırı adıyla söyler: “Öğe 1 satırını seç”.
- Eylem sonucu, odak değişmeden “Bildirimler” bölgesinde nazikçe duyurulur (WCAG 4.1.3). Geri al eylemi bildirimin içinde bir düğmedir.
- Onay penceresi
alertdialogrolündedir; dışarı tıklamayla kapanmaz.
İçerik
Bölüm başlığı “İçerik”- Eylem adları fiildir: “Arşivle”, “Dışa aktar”, “Sil”.
- Sonuç sayıyı ve fiili verir: “3 öğe arşivlendi”.
- Yıkıcı onay düğmesi sayıyı taşır: “3 öğeyi sil”.
- Tüm sayfalar bağlantısı toplamı söyler: “Tüm 1.000 öğeyi seç”.
Hareket
Bölüm başlığı “Hareket”| Öğe | Hareket | Preset |
|---|---|---|
| Çubuğun belirmesi | 240 ms, 8 px yukarı kayma ve solma | motion.toast |
| Sayı değişimi | 110 ms çapraz solma; sayaç animasyonu yok | motion.reveal |
| Eylem düğmeleri | Basınca 0,97 ölçek | motion.press |
Hareketi azaltma tercihinde kayma kalkar, yalnızca solma kalır.
Kullanılan bileşenler
Bölüm başlığı “Kullanılan bileşenler”DataTable, ActionBar, Toolbar, Toast, AlertDialog, StatusBadge, Link, Button. İlgili kalıplar: Onay, Filtreleme, Veri dışa aktarma.