List Invites Block
The ListInvites Component is a fully customizable and accessible invite management interface built with React and TypeScript. It provides a complete tabular invite listing experience with modern design patterns, action dropdowns, pagination support, loading states, and flexible customization options for advanced invite management applications.
🚀 Installation
npm install @nodeblocks/frontend-list-invites-block
📖 Usage
import {ListInvites} from '@nodeblocks/frontend-list-invites-block';
- Basic Usage
- Advanced Usage
function BasicListInvites() { const [isLoading, setIsLoading] = useState(false); const inviteData = [ { id: '1', name: 'John Doe', email: 'john.doe@example.com', status: 'pending' }, { id: '2', name: 'Jane Smith', email: 'jane.smith@example.com', status: 'accepted' }, { id: '3', name: 'Bob Johnson', email: 'bob.johnson@example.com', status: 'expired' } ]; const labels = { emptyStateMessage: 'No invites found', actions: { inviteUser: 'Invite User' }, headerRow: { name: 'Name', email: 'Email', status: 'Status' }, rowActions: { reject: 'Reject Invite' }, unsetDateMessage: 'No date set' }; const handleItemReject = (inviteId) => { console.log('Reject invite:', inviteId); }; const handleClickAction = () => { console.log('Invite user clicked'); }; const handleNavigate = (path) => { console.log('Navigate to:', path); }; const getRowHref = (row) => `/invites/${row.id}`; return ( <ListInvites listInvitesTitle="Manage Invites" labels={labels} isLoading={isLoading} onNavigate={handleNavigate} onClickAction={handleClickAction} onItemReject={handleItemReject} data={inviteData} rowHref={getRowHref}> <ListInvites.Header style={{display: 'flex', justifyContent: 'space-between', padding: '16px'}}> <ListInvites.Title /> <ListInvites.Action /> </ListInvites.Header> <ListInvites.Content> {isLoading ? ( <ListInvites.Loader /> ) : ( <ListInvites.Table /> )} </ListInvites.Content> </ListInvites> ); }
function AdvancedListInvites() { const [isLoading, setIsLoading] = useState(false); const inviteData = [ { id: '1', name: '田中太郎', email: 'tanaka.taro@company.jp', status: '承認待ち' }, { id: '2', name: '佐藤花子', email: 'sato.hanako@company.jp', status: '承認済み' }, { id: '3', name: '鈴木次郎', email: 'suzuki.jiro@company.jp', status: '期限切れ' }, { id: '4', name: 'ロバート・ジョンソン', email: 'robert.johnson@global.com', status: '拒否済み' } ]; const labels = { emptyStateMessage: '招待状が見つかりません', actions: { inviteUser: '新しいメンバーを招待' }, headerRow: { name: '氏名', email: 'メールアドレス', status: 'ステータス' }, rowActions: { reject: '招待を取り消し' }, unsetDateMessage: '日付未設定' }; const handleItemReject = (inviteId) => { console.log('招待を拒否:', inviteId); }; const handleClickAction = () => { console.log('新しいメンバーを招待'); }; const handleNavigate = (path) => { console.log('ナビゲート:', path); }; const getRowHref = (row) => `/invites/${row.id}`; return ( <ListInvites listInvitesTitle="👥 チーム招待管理" labels={labels} isLoading={isLoading} onNavigate={handleNavigate} onClickAction={handleClickAction} onItemReject={handleItemReject} data={inviteData} rowHref={getRowHref} style={{ background: 'linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%)', borderRadius: '24px', padding: '24px', margin: '20px', boxShadow: '0 20px 60px rgba(0,0,0,0.12)', border: '1px solid rgba(255,255,255,0.3)' }}> {({ defaultBlocks, defaultBlockOrder }) => ({ blocks: { // Enhanced header with modern styling header: { ...defaultBlocks.header, props: { ...defaultBlocks.header.props, style: { background: 'rgba(255, 255, 255, 0.8)', borderRadius: '16px', padding: '24px', marginBottom: '24px', backdropFilter: 'blur(10px)', border: '1px solid rgba(255,255,255,0.4)', boxShadow: '0 8px 32px rgba(0,0,0,0.08)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } } }, // Enhanced title with gradient styling title: { ...defaultBlocks.title, props: { ...defaultBlocks.title.props, style: { background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', fontSize: window.innerWidth <= 800 ? '24px' : '32px', fontWeight: 'bold', margin: '0' } } }, // Enhanced action button action: { ...defaultBlocks.action, props: { ...defaultBlocks.action.props, style: { display: 'flex', alignItems: 'center', gap: '12px' }, children: ( <button onClick={handleClickAction} style={{ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', border: 'none', borderRadius: '12px', padding: '12px 24px', color: 'white', fontSize: '14px', fontWeight: 'bold', cursor: 'pointer', transition: 'all 0.3s ease', boxShadow: '0 4px 16px rgba(102, 126, 234, 0.3)', display: 'flex', alignItems: 'center', gap: '8px' }} onMouseOver={(e) => { e.target.style.transform = 'translateY(-2px)'; e.target.style.boxShadow = '0 8px 24px rgba(102, 126, 234, 0.4)'; }} onMouseOut={(e) => { e.target.style.transform = 'translateY(0)'; e.target.style.boxShadow = '0 4px 16px rgba(102, 126, 234, 0.3)'; }}> <span style={{ fontSize: '16px' }}>➕</span> {labels.actions.inviteUser} </button> ) } }, // Enhanced content container content: { ...defaultBlocks.content, props: { ...defaultBlocks.content.props, style: { background: 'rgba(255, 255, 255, 0.9)', borderRadius: '20px', padding: '0', backdropFilter: 'blur(10px)', border: '1px solid rgba(255,255,255,0.4)', boxShadow: '0 8px 32px rgba(0,0,0,0.08)', overflow: 'hidden' } } }, // Enhanced table with professional styling table: { ...defaultBlocks.table, props: { ...defaultBlocks.table.props, style: { borderRadius: '20px', overflow: 'hidden', boxShadow: '0 4px 20px rgba(0,0,0,0.08)' } } } }, blockOrder: defaultBlockOrder })} </ListInvites> ); }
🔧 Props Reference
Main Component Props
Prop | Type | Default | Description |
---|---|---|---|
listInvitesTitle | ReactNode | Required | Title for the invites section |
labels | TableLabels | Required | Labels object for table headers, actions, and messages |
isLoading | boolean | undefined | Whether the table is currently loading |
onNavigate | (to: string) => void | Required | Callback function for navigation |
onClickAction | () => void | Required | Callback function for the main action button |
onItemReject | (inviteId: string) => void | Required | Callback function when invite is rejected |
data | ListInvitesRowData[] | Required | Array of invite data objects |
rowHref | (row: ListInvitesRowData) => string | Required | Function to generate row link URLs |
pagination | {currentPage: number; onPageChange: (page: number) => void; totalPages: number} | From context | Pagination configuration |
className | string | undefined | Additional CSS class name for styling the container |
children | BlocksOverride | undefined | Custom block components to override default rendering |
Note: This component inherits all HTML div
element props.
Sub-Components
The ListInvites component provides several sub-components. All sub-components receive their default values from the main component's context and can override these values through props.
ListInvites.Header
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | undefined | Custom content to override default header rendering |
className | string | undefined | Additional CSS class name for styling |
Note: This component inherits all HTML div
element props.
ListInvites.Title
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | undefined | Custom content to override default title rendering |
size | enum | "3XL" | Typography size for the title |
weight | enum | "bold" | Typography weight |
type | enum | "heading" | Typography type |
color | enum | "low-emphasis" | Color theme for the title |
className | string | undefined | Additional CSS class name for styling |
Note: This component inherits all HTML span
element props.
ListInvites.Action
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | undefined | Custom content to override default action rendering |
direction | enum | "row" | Flex direction for action buttons |
alignItems | enum | "stretch" | Alignment of items in the container |
gapSize | enum | "S" | Gap between items in the container |
className | string | undefined | Additional CSS class name for styling |
ListInvites.Content
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | undefined | Custom content to override default content rendering |
className | string | undefined | Additional CSS class name for styling |
Note: This component inherits all HTML div
element props.
ListInvites.Loader
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | Circular progress indicator | Custom loading indicator content |
className | string | undefined | Additional CSS class name for styling |
Note: This component inherits all HTML div
element props.
ListInvites.Table
Prop | Type | Default | Description |
---|---|---|---|
className | string | undefined | Additional CSS class name for styling |
data | ListInvitesRowData[] | From context | Array of table data |
labels | TableLabels | Required | Labels object for table headers, actions, and messages |
dropdownMenuItems | (cell: ListInvitesRowData) => Array<DropDownMenuItems> | From context | Function to generate dropdown menu items |
dropdownMenuState | {openedDropdownMenuId: string} | From context | Currently opened dropdown menu |
setDropdownMenuState | ({openedDropdownMenuId: string}) => void | From context | Callback function when the opened dropdown menu changes |
emptyState | {icon?: IconType; message: string} | From context | Configuration for empty state |
isLoading | boolean | From context | Loading state |
onNavigate | (to: string) => void | From context | Navigation callback function |
pagination | {currentPage: number; onPageChange: (page: number) => void; totalPages: number} | From context | Pagination configuration |
rowHref | `(cell: ListInvitesRowData) => string | undefined | null` |
🔧 TypeScript Support
Full TypeScript support with comprehensive type definitions:
import {ListInvites} from '@nodeblocks/frontend-list-invites-block';
interface ListInvitesRowData {
id: string;
name: string;
email: string;
status: string;
}
interface CustomInviteTableProps {
invites: ListInvitesRowData[];
onRejectInvite: (inviteId: string) => void;
onInviteUser: () => void;
isTableLoading: boolean;
}
interface TableLabels {
emptyStateMessage: string;
actions: {
inviteUser: string;
};
headerRow: {
name: string;
email: string;
status: string;
};
rowActions: {
reject: string;
};
unsetDateMessage: string;
}
const InviteTableComponent = ({invites, onRejectInvite, onInviteUser, isTableLoading}: CustomInviteTableProps) => {
const tableLabels: TableLabels = {
emptyStateMessage: 'No invites available',
actions: {inviteUser: 'Send Invite'},
headerRow: {
name: 'Full Name',
email: 'Email Address',
status: 'Invite Status',
},
rowActions: {
reject: 'Reject Invitation',
},
unsetDateMessage: 'Date not set',
};
return (
<ListInvites
listInvitesTitle="Team Invitations"
labels={tableLabels}
isLoading={isTableLoading}
onNavigate={path => console.log('Navigate:', path)}
onClickAction={onInviteUser}
onItemReject={onRejectInvite}
data={invites}
rowHref={row => `/invites/${row.id}`}>
<ListInvites.Header />
<ListInvites.Content />
</ListInvites>
);
};
Built with ❤️ using React, TypeScript, and modern web standards.