SkeletonText
Grey lines in the shape of a paragraph, with a heading and several paragraphs if asked, while text loads.
Demo
Loading the article
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_text.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/skeleton_text.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/skeleton_text.qwe
view SkeletonTextDemo() = <div.demo-stack> <SkeletonText id="skeleton-text-demo-plain"/> <SkeletonText id="skeleton-text-demo-article" lines={4} heading={true} label="Loading the article"/> <div.demo-row style="align-items: flex-start; gap: 32px"> <div style="flex: 1; min-width: 200px"><SkeletonText id="skeleton-text-demo-small" paragraphs={2} lines={3} size="sm"/></div> <div style="flex: 1; min-width: 200px"><SkeletonText lines={2} size="lg" last={40}/></div> </div> </div>Source
ui/skeleton_text.qwe
// SkeletonText: grey lines in the shape of a paragraph, where text will be while// it loads. The lines vary in width as text does, the last one shorter. Hidden// from screen readers unless given a label, which they then hear (role="status").//// <SkeletonText/>// <SkeletonText lines={5} heading={true} label="Loading the article"/>// <SkeletonText paragraphs={3} lines={4} size="sm"/>//// lines: rows per paragraph (3). paragraphs: how many (1), with a gap between.// heading: a taller, shorter bar above the first paragraph. last: the last// line's width in percent (60). size: "sm", "md" (default) or "lg": the lines'// height and spacing, as a text size. label: what is loading, for screen// readers; without it the shape is aria-hidden, so say so elsewhere. The shimmer// stops with reduced motion.import ui/theme.qwe use ui_clslet skeleton_text_css = css`.ui-sktext { display: grid; gap: 16px; --l: .85em; --g: 9px; font-size: 15px; }.ui-sktext-sm { font-size: 13px; --g: 7px; }.ui-sktext-lg { font-size: 18px; --g: 11px; }.ui-sktext-p { display: grid; gap: var(--g); }.ui-sktext-line, .ui-sktext-h { display: block; height: var(--l); border-radius: 4px; 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-sktext-shine 1.4s ease-in-out infinite; }.ui-sktext-h { height: 1.4em; width: 45%; border-radius: 6px; }@keyframes ui-sktext-shine { from { background-position: 100% 0; } to { background-position: -100% 0; } }@media (prefers-reduced-motion: reduce) { .ui-sktext-line, .ui-sktext-h { animation: none; background: var(--ui-subtle); } }`// The widths, in percent, of `lines` lines of a paragraph: full-ish ones that// vary, and the last one `last` wide.fn skeleton_text_widths(lines: int, last: int) -> list { let pattern = [100, 94, 98, 91, 97, 89, 99, 93] range(lines) | map((i) => i == lines - 1 && lines > 1 ? last : pattern[i % len(pattern)])}view SkeletonText(lines: int = 3, paragraphs: int = 1, heading: bool = false, last: int = 60, size: str = "md", label: str? = null, id: str? = null, class: str? = null) { style global skeleton_text_css let widths = skeleton_text_widths(lines < 1 ? 1 : lines, last) <div class={ui_cls(["ui-sktext", size != "md" && `ui-sktext-${size}`, class])} id={id} role={label != null ? "status" : null} aria-hidden={label == null ? "true" : null}> {heading && <span.ui-sktext-h aria-hidden="true"></span>} {for p in range(paragraphs < 1 ? 1 : paragraphs) => <div.ui-sktext-p key={p} aria-hidden="true"> {for [i, w] in enumerate(widths) => <span.ui-sktext-line key={i} style={`width: ${w}%`}></span>} </div>} {label != null && <span.ui-sr>{label}</span>} </div>}Related
InlineMessageA small one-line message with an icon for its tone (info, success, warning, error), to sit in a form or beside a control.5 views · 7 downloadsLoadingDotsThree dots bouncing in turn, inline, for something short that is on its way; screen readers hear the label.5 views · 6 downloadsLoadingOverlayCovers its content with a spinner and a message while something is busy, keeping the content in place but out of reach.5 views · 5 downloadsProgressHow far along something is, as a bar or a ring, with its percentage, or indeterminate.5 views · 6 downloadsSkeletonGrey shapes where content will be while it loads: text lines, boxes, circles, and a card.6 views · 6 downloadsSkeletonTableA table of grey bars in rows and columns, with a header row, while a table's data loads.4 views · 7 downloads
Thread
Thread 0 posts
On SkeletonText: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.