注文テーブルリストブロック
ListOrderTableコンポーネントは、ReactとTypeScriptで構築された完全にカスタマイズ可能でアクセシブルな注文テーブルインターフェースです。モダンなデザインパターン、ソート可能な列、アクションドロップダウン、タブ、ページネーションサポート、ローディング状態、および高度な注文管理アプリケーション向けの柔軟なカスタマイズオプションを備えた完全な表形式注文リスト体験を提供します。
🚀 インストール
npm install @nodeblocks/frontend-list-order-table-block@0.1.0
📖 使用法
import {ListOrderTable} from '@nodeblocks/frontend-list-order-table-block';
- 基本的な使用法
- 高度な使用法
function BasicListOrderTable() { const [currentTab, setCurrentTab] = useState('pending'); const [isLoading] = useState(false); const orderData = [ { id: '1', createdAt: '2024-01-15T10:30:00Z', orderName: 'ORD-001', title: 'オフィス用品注文', status: 'pending', }, { id: '2', createdAt: '2024-01-14T14:20:00Z', orderName: 'ORD-002', title: 'ソフトウェアライセンス', status: 'accepted', }, ]; const tabs = [{label: '保留中の注文'}, {label: '承認済み注文'}, {label: 'キャンセル済み注文'}]; const labels = { emptyStateMessage: '注文が見つかりません', actions: { headerAction: '注文作成' }, headerRow: { createdAt: '作成日', title: '注文タイトル', orderName: '注文ID' }, rowActions: { accepted: '注文承認', canceled: '注文キャンセル', processing: '処理中にマーク', }, }; const handleOrderAccepted = (orderId, title) => { console.log('注文が承認されました:', orderId, title); }; const handleOrderRejected = (orderId, title) => { console.log('注文が拒否されました:', orderId, title); }; const handleOrderProcessing = (orderId, title) => { console.log('注文処理中:', orderId, title); }; const handleNavigate = (path) => { console.log('ナビゲート先:', path); }; const getRowHref = (row) => `#${row.id}`; const getUpdateRowHref = (row) => `#${row.id}/edit`; return ( <ListOrderTable listOrderTableTitle="注文管理" labels={labels} isLoading={isLoading} onNavigate={handleNavigate} onOrderAccepted={handleOrderAccepted} onOrderRejected={handleOrderRejected} onOrderProcessing={handleOrderProcessing} data={orderData} rowHref={getRowHref} updateRowHref={getUpdateRowHref} tabs={tabs} currentTab={currentTab} onTabChange={setCurrentTab} createHref="#new" style={{ backgroundColor: 'white', padding: '8px', }} > <ListOrderTable.Header style={{display: 'flex', justifyContent: 'space-between'}}> <ListOrderTable.Title /> <ListOrderTable.Action /> </ListOrderTable.Header> <ListOrderTable.Content> {isLoading ? ( <ListOrderTable.Loader /> ) : ( <> <ListOrderTable.Tabs /> <ListOrderTable.Table /> </> )} </ListOrderTable.Content> </ListOrderTable> ); }
function AdvancedOrderTable() { const [currentTab, setCurrentTab] = useState('pending'); const [isLoading] = useState(false); const orderData = [ { id: '1', createdAt: '2024-01-15T10:30:00Z', orderName: '📦 ORD-2024-001', title: 'プレミアムオフィス用品パッケージ', status: 'pending', }, { id: '2', createdAt: '2024-01-14T14:20:00Z', orderName: '💻 ORD-2024-002', title: 'ソフトウェアライセンス更新バンドル', status: 'accepted', }, { id: '3', createdAt: '2024-01-13T09:15:00Z', orderName: '🔧 ORD-2024-003', title: 'IT機器メンテナンス契約', status: 'processing', }, ]; const tabs = [ {label: '⏳ 保留中の注文', key: 'pending'}, {label: '✅ 承認済み注文', key: 'accepted'}, {label: '🚫 キャンセル済み注文', key: 'canceled'}, ]; const labels = { emptyStateMessage: 'このカテゴリに注文はありません', actions: { headerAction: '✨ 新規注文作成', }, headerRow: { createdAt: '注文日', title: '注文詳細', orderName: '注文参照番号', }, rowActions: { accepted: '🎯 注文承認', canceled: '❌ 注文キャンセル', processing: '⚡ 処理開始', }, }; return ( <ListOrderTable listOrderTableTitle="🛒 エンタープライズ注文ダッシュボード" labels={labels} isLoading={isLoading} onNavigate={path => console.log('ナビゲート先:', path)} onOrderAccepted={(id, title) => console.log('注文承認中:', title)} onOrderRejected={(id, title) => console.log('注文キャンセル中:', title)} onOrderProcessing={(id, title) => console.log('注文処理中:', title)} data={orderData} rowHref={row => `#${row.id}`} updateRowHref={row => `#${row.id}/edit`} tabs={tabs} currentTab={currentTab} onTabChange={setCurrentTab} style={{ backgroundColor: 'white', padding: '8px', }} createHref="#new" > {({defaultBlocks, defaultBlockOrder}) => ({ blocks: { // Enhanced header with gradient styling header: { ...defaultBlocks.header, props: { ...defaultBlocks.header.props, style: { background: 'white', borderRadius: '20px', padding: '32px', color: 'black', width: 'calc(100% - 48px)', margin: '0 auto', marginTop: '12px', boxShadow: '0 15px 35px rgba(0,0,0,0.1)', border: '0.5px solid rgb(0, 0, 0)', }, }, }, // Enhanced content with modern styling content: { ...defaultBlocks.content, props: { ...defaultBlocks.content.props, style: { background: 'white', borderRadius: '16px', padding: '24px', boxShadow: '0 10px 30px rgba(0,0,0,0.05)', width: 'calc(100% - 48px)', margin: '0 auto', marginTop: '24px', border: '0.5px solid rgb(0, 0, 0)', }, }, }, }, blockOrder: defaultBlockOrder, })} </ListOrderTable> ); }
🔧 プロパティリファレンス
メインコンポーネントのプロパティ
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
listOrderTableTitle | ReactNode | 必須 | 注文テーブルセクションのタイトル |
labels | TableLabels | 必須 | テーブルヘッダー、アクション、メッセージのラベルオブジェクト |
isLoading | boolean | undefined | テーブルが現在読み込み中かどうか |
onNavigate | (to: string) => void | 必須 | ナビゲーション用のコールバック関数 |
onOrderAccepted | (id: string, title?: string) => void | 必須 | 注文が承認されたときのコールバック関数 |
onOrderRejected | (id: string, title?: string) => void | 必須 | 注文が拒否されたときのコールバック関数 |
onOrderProcessing | (id: string, title?: string) => void | 必須 | 注文が処理中としてマークされたときのコールバック関数 |
data | ListOrderTableRowData[] | 必須 | 注文データオブジェクトの配列 |
rowHref | (row: ListOrderTableRowData) => string | 必須 | 行リンクURLを生成する関数 |
updateRowHref | (row: ListOrderTableRowData) => string | 必須 | 更新行リンクURLを生成する関数 |
tabs | TabData[] | 必須 | タブ設定オブジェクトの配列 |
currentTab | string | undefined | 現在アクティブなタブ識別子 |
onTabChange | (tab: string) => void | undefined | タブが変更されたときのコールバック関数 |
createHref | string | 必須 | 新規注文作成用のURL |
pagination | {currentPage: number; onPageChange: (page: number) => void; totalPages: number} | undefined | ページネーション設定オブジェクト |
className | string | undefined | コンテナスタイリング用の追加CSSクラス名 |
children | BlocksOverride | undefined | デフォルトブロックをオーバーライドまたはカスタムコンポーネントレンダリングするための関数 |
注意: メインコンポーネントはMUI Stackプロパティを継承します。
サブコンポーネント
ListOrderTableコンポーネントは複数のサブコンポーネントを提供します。すべてのサブコンポーネントは、メインコンポーネントのコンテキストからデフォルト値を受け取り、プロパティを通じてこれらの値をオーバーライドできます。
ListOrderTable.Title
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | コンテキストから | タイトルコンテンツ - コンテキストのlistOrderTableTitleをオーバーライド |
listOrderTableTitle | ReactNode | コンテキストから | childrenが提供されない場合のタイトルテキスト |
variant | TypographyProps['variant'] | "h4" | MUI Typographyバリアント |
component | ElementType | "h1" | レンダリングするHTML要素 |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはすべてのMUI Typographyプロパティを継承します。
ListOrderTable.Action
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | undefined | デフォルトアクションレンダリングをオーバーライドするカスタムコンテンツ |
createHref | string | コンテキストから | 作成アクションボタンのURL |
labels | TableLabels | コンテキストから | アクションテキストのラベル |
onNavigate | (to: string) => void | コンテキストから | 作成ボタンのナビゲーションコールバック |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはMUI Stackプロパティを継承します(directionは"row"に固定)。
ListOrderTable.Header
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | undefined | デフォルトヘッダーレンダリングをオーバーライドするカスタムコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはMUI Stackプロパティを継承します。デフォルトレイアウトはdirection="row"でjustifyContent: 'space-between'とalignItems: 'center'です。
ListOrderTable.Loader
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | CircularProgress | カスタムローディングインジケーターコンテンツ |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはMUI Stackプロパティを継承します。デフォルトの整列はalignItems: 'center'です。
ListOrderTable.Content
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | undefined | デフォルトコンテンツレンダリングをオーバーライドするカスタムコンテンツ |
isLoading | boolean | コンテキストから | コンテキストからのローディング状態 |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはMUI Boxプロパティを継承します。カスタムchildrenを使用せずローディング中でない場合、spacing={3}のStack内にTabsとTableをレンダリングします。
ListOrderTable.Tabs
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
tabs | TabData[] | コンテキストから | タブ設定オブジェクトの配列 |
currentTab | string | コンテキストから | 現在アクティブなタブラベル |
onTabChange | (tab: string) => void | コンテキストから | タブ変更コールバック関数 |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはMUI Tabsプロパティを継承します(value、onChange、variantは内部で管理されます)。デフォルトでvariant="fullWidth"を使用します。
ListOrderTable.Table
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
labels | TableLabels | コンテキストから | テーブルヘッダー、アクション、メッセージのラベルオブジェクト |
data | ListOrderTableRowData[] | コンテキストから | テーブルデータの配列 |
rowHref | (row: ListOrderTableRowData) => string | コンテキストから | 行リンクURLを生成する関数 |
onNavigate | (to: string) => void | コンテキストから | 行クリック時のナビゲーションコールバック |
onOrderAccepted | DropdownItemAction | コンテキストから | 注文が承認されたときのコールバック |
onOrderRejected | DropdownItemAction | コンテキストから | 注文が拒否されたときのコールバック |
onOrderProcessing | DropdownItemAction | コンテキストから | 注文が処理中としてマークされたときのコールバック |
pagination | PaginationProps | コンテキストから | ページネーション設定オブジェクト |
spacing | number | 3 | 要素間のStackスペーシング |
className | string | undefined | スタイリング用の追加CSSクラス名 |
注意: このコンポーネントはMUI Stackプロパティを継承します。
🎨 設定例
Custom Header Styling
<ListOrderTable.Header
sx={{
bgcolor: 'primary.light',
borderRadius: 2,
p: 2
}}
/>
Custom Title Styling
<ListOrderTable.Title
variant="h3"
component="h2"
sx={{ color: 'primary.main', fontWeight: 700 }}
/>
Custom Action Button
<ListOrderTable.Action>
<Button variant="outlined" startIcon={<Add />}>
カスタム作成ボタン
</Button>
</ListOrderTable.Action>
Custom Table Styling
<ListOrderTable.Table
sx={{
'& .MuiTableCell-root': {
borderBottom: '2px solid',
borderColor: 'divider'
}
}}
/>
Using Block Override Pattern
<ListOrderTable {...props}>
{({defaultBlocks, defaultBlockOrder}) => ({
blocks: {
header: {
...defaultBlocks.header,
props: {
...defaultBlocks.header.props,
sx: {background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'},
},
},
},
blockOrder: defaultBlockOrder,
})}
</ListOrderTable>
🔧 TypeScriptサポート
包括的な型定義による完全なTypeScriptサポート:
import {ListOrderTable} from '@nodeblocks/frontend-list-order-table-block';
import {Stack} from '@mui/material';
import {ComponentProps, ReactNode} from 'react';
// Tab data interface
interface TabData {
key?: string;
label: string;
isDisabled?: boolean;
subtitle?: string;
}
// Main component interface
interface ListOrderTableProps<Tabs extends TabData[]> extends Omit<ComponentProps<typeof Stack>, 'children'> {
listOrderTableTitle: ReactNode;
labels: TableLabels;
isLoading?: boolean;
onNavigate: (to: string) => void;
onOrderAccepted: DropdownItemAction;
onOrderRejected: DropdownItemAction;
onOrderProcessing: DropdownItemAction;
data: ListOrderTableRowData[];
rowHref: (row: ListOrderTableRowData) => string;
updateRowHref: (row: ListOrderTableRowData) => string;
tabs: Tabs;
currentTab?: Tabs[number]['label'];
onTabChange?: (tab: Tabs[number]['label']) => void;
createHref: string;
pagination?: PaginationProps;
children?: BlocksOverride;
}
// Row data interface
export interface ListOrderTableRowData {
createdAt: string;
id: string;
orderName: string;
title: string;
status: string;
}
// Action callback type
export type DropdownItemAction = (
order: ListOrderTableRowData['id'],
title?: ListOrderTableRowData['title'],
) => void;
// Pagination props interface
export interface PaginationProps {
className?: string;
currentPage: number;
onPageChange: (page: number) => void;
totalPages: number;
}
// Labels interface
interface TableLabels {
emptyStateMessage: string;
actions?: {
headerAction: string;
};
headerRow: {
createdAt: string;
title: string;
orderName: string;
};
rowActions: {
canceled: string;
processing: string;
accepted: string;
};
}
// Usage example with full typing
function TypedListOrderTableExample() {
const [currentTab, setCurrentTab] = useState('pending');
const [isLoading] = useState(false);
const orders: ListOrderTableRowData[] = [
{
createdAt: '2024-01-15T10:30:00Z',
id: '1',
orderName: 'ORD-001',
title: '注文タイトル',
status: 'pending',
},
];
const tableTabs: TabData[] = [
{label: '保留中', key: 'pending'},
{label: '承認済み', key: 'accepted'},
{label: '拒否済み', key: 'rejected'},
];
const tableLabels: TableLabels = {
emptyStateMessage: '利用可能な注文がありません',
actions: {headerAction: '新規注文'},
headerRow: {
createdAt: '作成日',
title: '注文タイトル',
orderName: '注文番号',
},
rowActions: {
accepted: '承認',
canceled: '拒否',
processing: '処理',
},
};
const onAcceptOrder: DropdownItemAction = (id, title) => {
console.log('注文を承認:', id, title);
};
const onRejectOrder: DropdownItemAction = (id, title) => {
console.log('注文を拒否:', id, title);
};
const onProcessOrder: DropdownItemAction = (id, title) => {
console.log('注文を処理:', id, title);
};
return (
<ListOrderTable
listOrderTableTitle="注文ダッシュボード"
labels={tableLabels}
isLoading={isLoading}
onNavigate={path => console.log('ナビゲート:', path)}
onOrderAccepted={onAcceptOrder}
onOrderRejected={onRejectOrder}
onOrderProcessing={onProcessOrder}
data={orders}
rowHref={row => `/orders/${row.id}`}
updateRowHref={row => `/orders/${row.id}/edit`}
tabs={tableTabs}
currentTab={currentTab}
onTabChange={setCurrentTab}
createHref="#orders/create"
>
<ListOrderTable.Header />
<ListOrderTable.Content />
<ListOrderTable.Table />
</ListOrderTable>
);
}
📝 注意事項
- ルートコンポーネントはMUIの
Stackを使用し、デフォルトでspacing={3}とsx={{ p: 3 }}パディングを持ちます - 日付は
luxonライブラリを使用してyyyy/M/d HH:mm形式でフォーマットされます - 行タイトルにはホバー時に完全な日時を表示するツールチップがあります
- テーブルはMUI
Table、TableContainer、TableHead、TableBody、TableRowコンポーネントを使用します - 行アクションはMUI
MenuとMenuItemコンポーネントとアイコンを使用したドロップダウンメニューで表示されます Tabsコンポーネントはタブが提供されないか配列が空の場合はnullを返します- 空状態はlabelsの
emptyStateMessageとPersonアイコンを表示します - ページネーションはMUI
Paginationコンポーネントをvariant="outlined"とshape="rounded"で使用します rowHrefが有効なURLを返す場合、テーブル行はクリック可能です(カーソルがポインターに変わります)- すべてのサブコンポーネントはMUIコンポーネントプロパティを継承し、スタイリング用の
sxプロパティをサポートします - ブロックオーバーライドパターンにより、デフォルトブロックのカスタマイズ、置換、並べ替えが可能です
React、TypeScript、MUIを使用して❤️で構築されました。