SPB Git

spb/qwhpi Public

QHPI — Quebec Housing Price Index: quality-adjusted, hierarchically pooled housing price indexes.

Python 63.9% TypeScript 25.4% CSS 5.5% TeX 3.5% SQL 0.8% Makefile 0.5% Dockerfile 0.5%
1.8 KB · 62 lines tsx
Raw Blame History
1/**2 * =============================================================================3 * QWHPI — Quebec Weekly Housing Price Index4 * Author  : Simon-Pierre Boucher5 * Contact : contact@spboucher.ai6 * File    : web/components/Skeleton.tsx7 * Purpose : Shimmer skeleton loaders — tiles, charts, tables (no "Loading…").8 * =============================================================================9 */1011export function SkeletonBlock({ h = 20, w = "100%", style = {} }: {12  h?: number; w?: number | string; style?: React.CSSProperties;13}) {14  return (15    <div className="skeleton" aria-hidden16         style={{ height: h, width: w, ...style }} />17  );18}1920export function TileSkeleton() {21  return (22    <div className="card stat-tile" aria-busy="true">23      <SkeletonBlock h={11} w="55%" />24      <SkeletonBlock h={32} w="70%" style={{ marginTop: 8 }} />25      <SkeletonBlock h={12} w="45%" style={{ marginTop: 6 }} />26    </div>27  );28}2930export function ChartSkeleton({ height = 340 }: { height?: number }) {31  return (32    <div className="card" aria-busy="true" aria-label="Chart loading">33      <SkeletonBlock h={14} w={220} />34      <SkeletonBlock h={height - 60} style={{ marginTop: 14 }} />35    </div>36  );37}3839export function TableSkeleton({ rows = 8 }: { rows?: number }) {40  return (41    <div className="card" aria-busy="true" style={{ padding: "10px 14px" }}>42      {Array.from({ length: rows }, (_, i) => (43        <SkeletonBlock key={i} h={16}44                       style={{ marginTop: i ? 12 : 4, opacity: 1 - i * 0.09 }} />45      ))}46    </div>47  );48}4950export function DashboardSkeleton() {51  return (52    <>53      <div className="grid cols-4" style={{ marginTop: 24 }}>54        {Array.from({ length: 4 }, (_, i) => <TileSkeleton key={i} />)}55      </div>56      <div style={{ marginTop: 16 }}>57        <TableSkeleton rows={10} />58      </div>59    </>60  );61}62