components/skeleton/skeleton.react.tsx
49 lines and 5 functions in DrDustinEdwards/capsomer, at commit d3966cc on 2026-10-24. This file on GitHub.
Functions
| Function | Lines | Complexity | Covered | CRAP | Mutation |
|---|---|---|---|---|---|
| Arc | 15 to 20 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: mutation testing has not run on this repo yet |
| Spinner | 22 to 29 | 3 | No data: no coverage report in this map | No data: no coverage report in this map | No data: mutation testing has not run on this repo yet |
| Skeleton | 37 to 46 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: mutation testing has not run on this repo yet |
| <anonymous:41> | 41 to 43 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: mutation testing has not run on this repo yet |
| SkeletonBlock | 54 to 56 | 2 | No data: no coverage report in this map | No data: no coverage report in this map | No data: mutation testing has not run on this repo yet |
Imports
It imports no other module of this repo. Imported by components/empty/empty.react.tsx.
Source
import type { ReactElement } from "react";
export interface SpinnerProps {
// What is loading, in a word or two: "Loading", "Saving".
label?: string;
// The word is for screen readers only while the arc turns (inside a button that
// already says what it does). Under reduced motion the word always shows.
hideLabel?: boolean;
size?: "sm" | "lg";
// "page": centred in the space it is given, with its word under it, for a whole page or
// panel that has nothing else to show yet. It is a status region.
layout?: "page";
}
const Arc = () => (
<svg className="cap-spinner-arc" viewBox="0 0 16 16" aria-hidden="true" focusable="false">
<circle cx="8" cy="8" r="6" fill="none" stroke="currentColor" strokeWidth="2" opacity="0.25" />
<path fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" d="M8 2a6 6 0 0 1 6 6" />
</svg>
);
export function Spinner({ label = "Loading", hideLabel, size, layout }: SpinnerProps): ReactElement {
return (
<span className="cap-spinner" data-label={hideLabel ? "hidden" : undefined} data-size={size} data-layout={layout} role={layout === "page" ? "status" : undefined}>
<Arc />
<span className="cap-spinner-label">{label}</span>
</span>
);
}
export interface SkeletonProps {
lines?: number;
label?: string;
}
// Grey lines standing in for a page's content: busy, and "Loading" for a screen reader.
export function Skeleton({ lines = 3, label = "Loading" }: SkeletonProps): ReactElement {
return (
<div className="cap-skeleton" aria-busy="true">
<span className="cap-sr-only">{label}</span>
{Array.from({ length: lines }, (_, i) => (
<span className="cap-skeleton-line" aria-hidden="true" key={i} />
))}
</div>
);
}
export interface SkeletonBlockProps {
shape?: "block" | "circle" | "card";
}
// One shape on its own (shadcn's Skeleton): an avatar, a card. Decorative: put it inside a
// busy region that says "Loading".
export function SkeletonBlock({ shape = "block" }: SkeletonBlockProps): ReactElement {
return <span className="cap-skeleton-block" data-shape={shape === "block" ? undefined : shape} aria-hidden="true" />;
}