Feedback

SkeletonTable

A table of grey bars in rows and columns, with a header row, while a table's data loads.

#feedback#loading#table#data#no-js

Demo

Preview
Loading orders

Get it

It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.

$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/skeleton_table.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/skeleton_table.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/skeleton_table.qwe
view SkeletonTableDemo() =    <div.demo-stack>        <SkeletonTable id="skeleton-table-demo-plain"/>        <SkeletonTable id="skeleton-table-demo-orders" rows={4} columns={5} striped={true} label="Loading orders"/>        <SkeletonTable id="skeleton-table-demo-small" rows={3} columns={3} widths={[80, 40, 25]} header={false} size="sm"/>    </div>

Source

ui/skeleton_table.qwe
// SkeletonTable: a table of grey bars, the shape of rows and columns that are on// their way. Hidden from screen readers unless given a label, which they then// hear (role="status").////   <SkeletonTable/>//   <SkeletonTable rows={8} columns={5} label="Loading orders"/>//   <SkeletonTable columns={3} widths={[60, 90, 30]} header={false} size="sm"/>//// rows: body rows (5). columns: how many (4). header: a header row (true).// widths: each column's bar width in percent of its cell; a pattern by default,// and each row's bars vary a little, as values do. size: "sm", "md" (default) or// "lg": the rows' height. striped: every other row tinted (false). label: what is// loading, for screen readers; without it the table is aria-hidden, so say so// elsewhere. The shimmer stops with reduced motion.import ui/theme.qwe use ui_clslet skeleton_table_css = css`.ui-sktable { width: 100%; border-collapse: collapse; border: 1px solid var(--ui-border); border-radius: var(--ui-radius);  overflow: hidden; --h: 44px; }.ui-sktable-sm { --h: 36px; }.ui-sktable-lg { --h: 54px; }.ui-sktable table { width: 100%; border-collapse: collapse; }.ui-sktable th, .ui-sktable td { height: var(--h); padding: 0 14px; border-bottom: 1px solid var(--ui-border); text-align: left; }.ui-sktable tr:last-child td { border-bottom: 0; }.ui-sktable th { background: var(--ui-subtle); }.ui-sktable-striped tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--ui-subtle) 50%, transparent); }.ui-sktable-bar { display: block; height: .8em; border-radius: 4px; font-size: 15px;  background: linear-gradient(90deg, var(--ui-subtle) 0%, color-mix(in srgb, var(--ui-subtle) 55%, var(--ui-strong)) 50%, var(--ui-subtle) 100%);  background-size: 200% 100%; animation: ui-sktable-shine 1.4s ease-in-out infinite; }.ui-sktable th .ui-sktable-bar { height: .7em; background: linear-gradient(90deg, var(--ui-strong) 0%, color-mix(in srgb, var(--ui-strong) 60%, var(--ui-subtle)) 50%, var(--ui-strong) 100%);  background-size: 200% 100%; opacity: .6; }@keyframes ui-sktable-shine { from { background-position: 100% 0; } to { background-position: -100% 0; } }@media (prefers-reduced-motion: reduce) { .ui-sktable-bar { animation: none; background: var(--ui-subtle); } }`// The width of the bar in row r (0 is the header), column c, from the column's base width.fn skeleton_table_width(base: int, r: int, c: int) -> int {    let w = r == 0 ? base - 10 : base - (r * 7 + c * 5) % 23    w < 15 ? 15 : (w > 100 ? 100 : w)}view SkeletonTable(rows: int = 5, columns: int = 4, header: bool = true, widths: list = [], size: str = "md",                   striped: bool = false, label: str? = null, id: str? = null, class: str? = null) {    style global skeleton_table_css    let pattern = [70, 45, 85, 35, 60, 50]    let cols = range(columns < 1 ? 1 : columns) | map((c) => int(widths[c] ?? pattern[c % len(pattern)]) ?? 60)    <div class={ui_cls(["ui-sktable", size != "md" && `ui-sktable-${size}`, striped && "ui-sktable-striped", class])} id={id}         role={label != null ? "status" : null} aria-hidden={label == null ? "true" : null}>        <table aria-hidden="true">            {header && <thead><tr>                {for [c, w] in enumerate(cols) => <th key={c}><span.ui-sktable-bar style={`width: ${skeleton_table_width(w, 0, c)}%`}></span></th>}            </tr></thead>}            <tbody>                {for r in range(1, (rows < 1 ? 1 : rows) + 1) => <tr key={r}>                    {for [c, w] in enumerate(cols) => <td key={c}><span.ui-sktable-bar style={`width: ${skeleton_table_width(w, r, c)}%`}></span></td>}                </tr>}            </tbody>        </table>        {label != null && <span.ui-sr>{label}</span>}    </div>}
Thread
47Useful? Like it, or add to its thread below.

Thread 0 posts

On SkeletonTable: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.