Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions assets/packs/data_table/Skeleton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Creates a loading skeleton for the data table
*/
export function createTableSkeleton() {
const container = document.createElement("div");
container.innerHTML = `
<div class="w-full">
<table class="w-full border-separate border-spacing-0 mt-2 animate-pulse">
<tbody>
${createTableRow()}
${createTableRow()}
${createTableRow()}
${createTableRow()}
${createTableRow()}
</tbody>
</table>
</div>
`;
return container;
}

function createTableRow() {
return `
<tr>
${createDataCell("w-12")}
${createDataCell("w-32")}
${createDataCell("w-48")}
${createDataCell("w-20")}
</tr>
`;
}

function createDataCell(width) {
return `
<td class="p-2.5 border-b border-slate-100 ${width}">
<div class="bg-gradient-to-r from-gray-100 via-gray-200 to-gray-100 h-4 rounded">
</div>
</td>
`;
}
73 changes: 60 additions & 13 deletions assets/packs/data_table/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,66 @@ import "@glideapps/glide-data-grid/dist/index.css";
import React from "react";
import { createRoot } from "react-dom/client";
import { App } from "./App";
import { createTableSkeleton } from "./Skeleton";

export async function init(ctx, data) {
// In Firefox and Safari, during the first load (uncached), the data
// grid renders the default font and the font is only updated after
// hovering the grid. Ensuring the font is loaded helps in Firefox.
await ctx.importCSS(
"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap",
);
ctx.importCSS(
"https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap",
);
ctx.importCSS("main.css");

const root = createRoot(ctx.root);
root.render(<App ctx={ctx} data={data} />);
ctx.root.appendChild(createTableSkeleton());

try {
await loadStyles(ctx);
} finally {
const root = createRoot(ctx.root);
root.render(<App ctx={ctx} data={data} />);
}
}

async function loadStyles(ctx) {
const cssPromises = [
ctx.importCSS(
"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap",
),
ctx.importCSS(
"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap",
),
ctx.importCSS("main.css"),
];

// We force all fonts to be loaded by adding an invisible element,
// and then we explicitly wait for the fonts to finish loading.
// This is important on first uncached render. If we don't wait
// and render the table with fallback fonts, the columns get wrong
// default widths. Also, on Firefox ans Safari, once the font is
// loaded, the table only updates on hover, which is bad UX.

const fontPreloader = document.createElement("div");
fontPreloader.setAttribute("aria-hidden", "true");
fontPreloader.style.cssText = `
position: absolute;
visibility: hidden;
left: -9999px;
`;
fontPreloader.innerHTML = `
<span style="font-family: 'JetBrains Mono'">
<span style="font-weight: 400">preload</span>"
<span style="font-weight: 500">preload</span>"
<span style="font-weight: 600">preload</span>"
</span>"
<span style="font-family: 'Inter'">
<span style="font-weight: 400">preload</span>"
<span style="font-weight: 500">preload</span>"
<span style="font-weight: 600">preload</span>"
</span>"
`;

document.body.appendChild(fontPreloader);

try {
await Promise.all(cssPromises);

if (document.fonts && document.fonts.ready) {
await document.fonts.ready;
}
} finally {
document.body.removeChild(fontPreloader);
}
}
Loading