mirror of
https://github.com/projectsend/projectsend.git
synced 2026-09-16 16:45:07 +00:00
6e47d76ba6
Client file sharing, rebuilt from the ground up: a private area per client, resumable uploads, folders, groups and categories, sharing with expiry dates and download limits, comments, file versions, an activity log, a REST API, and sixteen languages. This repository begins here. ProjectSend 2 was developed privately, and that development history is not published — the previous generation remains available, with its own history, at projectsend/legacy. Free software under the GNU General Public License v2, or (at your option) any later version.
66 lines
2.4 KiB
TypeScript
66 lines
2.4 KiB
TypeScript
import { type ReactNode } from 'react';
|
|
|
|
/**
|
|
* A header cell. A plain string is a visible label; `null` is the unlabelled
|
|
* column that holds row actions; the object form is for a label that should
|
|
* be read out but not shown.
|
|
*/
|
|
export type TableColumn = string | null | { label: string; srOnly: true };
|
|
|
|
interface TableShellProps {
|
|
columns: TableColumn[];
|
|
/** Shown in place of the rows when there are none. */
|
|
emptyMessage: ReactNode;
|
|
isEmpty: boolean;
|
|
children: ReactNode;
|
|
}
|
|
|
|
/**
|
|
* The bordered, horizontally-scrollable table every list page is built from:
|
|
* the frame, the header row, and the centred "nothing here" message.
|
|
*
|
|
* Rows stay with the page that owns them -- the columns genuinely differ from
|
|
* one list to the next, and that is the part worth reading in context.
|
|
*/
|
|
export function TableShell({ columns, emptyMessage, isEmpty, children }: TableShellProps) {
|
|
return (
|
|
<div className="overflow-x-auto rounded-lg border">
|
|
<table className="w-full text-sm">
|
|
<thead>
|
|
<tr className="bg-muted/50 border-b text-left">
|
|
{columns.map((column, index) => {
|
|
if (column === null) {
|
|
return <th key={index} className="px-4 py-2.5" />;
|
|
}
|
|
|
|
if (typeof column === 'object') {
|
|
return (
|
|
<th key={index} className="px-4 py-2.5">
|
|
<span className="sr-only">{column.label}</span>
|
|
</th>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<th key={index} className="px-4 py-2.5 font-medium">
|
|
{column}
|
|
</th>
|
|
);
|
|
})}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{isEmpty && (
|
|
<tr>
|
|
<td colSpan={columns.length} className="text-muted-foreground px-4 py-8 text-center">
|
|
{emptyMessage}
|
|
</td>
|
|
</tr>
|
|
)}
|
|
{children}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
}
|