diff --git a/apps/client/src/features/base/components/base-table-skeleton.tsx b/apps/client/src/features/base/components/base-table-skeleton.tsx new file mode 100644 index 00000000..dfcae12f --- /dev/null +++ b/apps/client/src/features/base/components/base-table-skeleton.tsx @@ -0,0 +1,84 @@ +import { Skeleton } from "@mantine/core"; +import gridClasses from "@/features/base/styles/grid.module.css"; +import classes from "@/features/base/styles/base-table-skeleton.module.css"; + +const ROW_NUMBER_WIDTH = 64; +const COLUMN_WIDTH = 180; +const COLUMN_COUNT = 6; +const ROW_COUNT = 10; + +// Deterministic per-cell widths so the skeleton doesn't flicker between +// renders. Values are rough normal distribution around 55-85 % of cell. +const CELL_WIDTH_RATIOS = [0.78, 0.62, 0.84, 0.55, 0.71, 0.66]; +const HEADER_WIDTH_RATIOS = [0.42, 0.58, 0.5, 0.64, 0.46, 0.54]; + +export function BaseTableSkeleton() { + const gridTemplateColumns = [ + `${ROW_NUMBER_WIDTH}px`, + ...Array.from({ length: COLUMN_COUNT }, () => `${COLUMN_WIDTH}px`), + ].join(" "); + + return ( +
+
+
+ + + +
+
+ + + + +
+
+ +
+
+
+
+ +
+
+ {Array.from({ length: COLUMN_COUNT }).map((_, colIndex) => ( +
+
+ + +
+
+ ))} + + {Array.from({ length: ROW_COUNT }).map((_, rowIndex) => ( +
+
+
+ +
+
+ {Array.from({ length: COLUMN_COUNT }).map((_, colIndex) => ( +
+
+ +
+
+ ))} +
+ ))} +
+
+
+ ); +} diff --git a/apps/client/src/features/base/styles/base-table-skeleton.module.css b/apps/client/src/features/base/styles/base-table-skeleton.module.css new file mode 100644 index 00000000..d610f867 --- /dev/null +++ b/apps/client/src/features/base/styles/base-table-skeleton.module.css @@ -0,0 +1,47 @@ +.toolbar { + display: flex; + align-items: center; + gap: var(--mantine-spacing-xs); + padding: var(--mantine-spacing-xs) 0; + margin-bottom: var(--mantine-spacing-xs); +} + +.toolbarTabs { + display: flex; + gap: 6px; + flex: 1; +} + +.toolbarActions { + display: flex; + gap: var(--mantine-spacing-xs); + margin-left: auto; +} + +.gridWrapper { + overflow: hidden; + flex: 1; + border-top: 1px solid + light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-4)); +} + +.grid { + display: grid; +} + +.cellInner { + display: flex; + align-items: center; + height: 100%; + width: 100%; + padding: 0 8px; +} + +.headerCellInner { + display: flex; + align-items: center; + gap: 6px; + height: 100%; + width: 100%; + padding: 0 8px; +}