Thumbnail
A small image in five sizes and three shapes, with a line of text over it, a "+N" veil, or a link.
Demo
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/thumbnail.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/thumbnail.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/thumbnail.qwe
// A product shot drawn in SVG, so the demo needs no image files.fn thumbnail_demo_pic(bg: str, fg: str) -> str { let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">` + `<rect width="200" height="200" fill="${bg}"/><circle cx="100" cy="90" r="46" fill="${fg}"/>` + `<rect x="40" y="140" width="120" height="26" rx="13" fill="${fg}" opacity=".7"/></svg>` `data:image/svg+xml,${url_encode(svg)}`}let thumbnail_demo_pics = [thumbnail_demo_pic("#fde2e4", "#c62a2f"), thumbnail_demo_pic("#e3f5ec", "#18794e"), thumbnail_demo_pic("#e5f1fc", "#0b6bcb"), thumbnail_demo_pic("#fdf0dc", "#a35200")]component ThumbnailDemoLive() { state picked = "none" <div.demo-row> {for [i, p] in enumerate(thumbnail_demo_pics) => <Thumbnail src={p} alt="" label={`Pick colour ${i + 1}`} size="sm" on_click={() => { picked = str(i + 1) }}/>} <p.demo-note id="thumbnail-demo-picked">Picked: {picked}</p> </div>}view ThumbnailDemo() = <div.demo-stack> <div.demo-row id="thumbnail-demo-sizes"> <Thumbnail src={thumbnail_demo_pics[0]} alt="Red" size="xs"/> <Thumbnail src={thumbnail_demo_pics[1]} alt="Green" size="sm"/> <Thumbnail src={thumbnail_demo_pics[2]} alt="Blue"/> <Thumbnail src={thumbnail_demo_pics[3]} alt="Orange" size="lg"/> <Thumbnail src={thumbnail_demo_pics[0]} alt="Red" size="xl"/> <Thumbnail src={thumbnail_demo_pics[1]} alt="Green" px={40}/> </div> <div.demo-row id="thumbnail-demo-shapes"> <Thumbnail src={thumbnail_demo_pics[2]} alt="" shape="square" size="lg"/> <Thumbnail src={thumbnail_demo_pics[3]} alt="" shape="circle" size="lg"/> <Thumbnail src={thumbnail_demo_pics[0]} alt="" size="lg" overlay="IMG_0412.jpg"/> <Thumbnail src={thumbnail_demo_pics[1]} alt="" size="lg" more={3}/> <Thumbnail src={thumbnail_demo_pics[2]} alt="" size="lg" fit="contain" href="https://quillolang.org" label="Open the album"/> </div> <ThumbnailDemoLive/> </div>Source
ui/thumbnail.qwe
// Thumbnail: a small image in a fixed size and shape, for lists, grids and// pickers: a product's picture beside its name, a row of files, the people// in a thread. It can carry a line of text over its bottom, a "+N" veil for// the ones not shown, and be a link.//// <Thumbnail src="/img/shoe-sm.jpg" alt="Red running shoe" size="sm"/>// <Thumbnail src="/img/cover.jpg" alt="" shape="circle" size="lg" href="/albums/7" label="Open the album"/>// <Thumbnail src="/img/4.jpg" alt="" more={3}/> the fourth of seven, veiled "+3"//// src, alt: the image (alt "" when the text beside it says what it is).// size: "xs" (32px), "sm" (48px), "md" (64px, default), "lg" (96px) or "xl" (128px);// px: a size in pixels instead. shape: "rounded" (default), "square" or "circle".// fit: "cover" (default) or "contain". overlay: a short line over its bottom.// more: a number N shown as "+N" over the image, for the ones not shown.// href makes it a link; label is then what screen readers call the link.// on_click(): inside one of your components, makes it a button that does that.import ui/theme.qwe use ui_clslet thumbnail_css = css`.ui-thumbnail { position: relative; display: inline-grid; flex: none; overflow: hidden; width: var(--s, 64px); height: var(--s, 64px); padding: 0; border: 1px solid var(--ui-border); border-radius: var(--ui-radius-sm); background: var(--ui-subtle); color: #fff; font: 500 12px/1.2 var(--ui-font); text-decoration: none; vertical-align: middle;}.ui-thumbnail-xs { --s: 32px; border-radius: 4px; }.ui-thumbnail-sm { --s: 48px; }.ui-thumbnail-lg { --s: 96px; }.ui-thumbnail-xl { --s: 128px; }.ui-thumbnail-square { border-radius: 0; }.ui-thumbnail-circle { border-radius: 50%; }.ui-thumbnail img { display: block; width: 100%; height: 100%; object-fit: cover; }.ui-thumbnail-contain img { object-fit: contain; }.ui-thumbnail-text { position: absolute; inset: auto 0 0 0; padding: 14px 6px 5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; background: linear-gradient(to top, rgba(0, 0, 0, .65), transparent); text-align: center; text-shadow: 0 1px 2px rgba(0, 0, 0, .5);}.ui-thumbnail-more { position: absolute; inset: 0; display: grid; place-items: center; background: rgba(0, 0, 0, .5); font-size: calc(var(--s, 64px) * .26); font-weight: 600; }a.ui-thumbnail, button.ui-thumbnail { cursor: pointer; transition: box-shadow .15s, border-color .15s; }a.ui-thumbnail:hover, button.ui-thumbnail:hover { border-color: var(--ui-strong); box-shadow: var(--ui-shadow); }.ui-thumbnail:focus-visible { outline: none; box-shadow: var(--ui-focus); }@media (prefers-reduced-motion: reduce) { a.ui-thumbnail, button.ui-thumbnail { transition: none; } }`view Thumbnail(src: str, alt: str = "", size: str = "md", px: int? = null, shape: str = "rounded", fit: str = "cover", overlay: str? = null, more: int? = null, href: str? = null, label: str? = null, on_click = null, class: str? = null) { style global thumbnail_css let cls = ui_cls(["ui-thumbnail", px == null && size != "md" && `ui-thumbnail-${size}`, shape != "rounded" && `ui-thumbnail-${shape}`, fit == "contain" && "ui-thumbnail-contain", class]) let sty = px != null ? `--s: ${px}px` : null let body = [ <img src={src} alt={alt} loading="lazy"/>, overlay != null && <span.ui-thumbnail-text>{overlay}</span>, more != null && more > 0 && <span.ui-thumbnail-more aria-label={`and ${more} more`}>+{more}</span>, ] href != null ? <a class={cls} style={sty} href={href} aria-label={label}>{body}</a> : on_click != null ? <button class={cls} style={sty} type="button" aria-label={label} @click={() => { on_click() }}>{body}</button> : <span class={cls} style={sty}>{body}</span>}Related
CameraCaptureTakes a photo with the camera into a hidden input as a data URL, with retake, and says so when there is no camera.6 views · 6 downloadsCoverImageA wide picture with a title, subtitle and actions over a gradient, in three heights.7 views · 7 downloadsFigureAn image (or anything) with a caption and a credit under it, as a figure with its figcaption.7 views · 8 downloadsImageAn image that keeps its shape while it loads, shimmering, and shows a fallback with its alt when it cannot.6 views · 8 downloadsImageCompareBefore and after pictures one over the other, with a divider to drag (or move with the keys) between them.6 views · 9 downloadsImageCropA crop box over a picture, dragged and resized by its corners or the keys, with the crop in hidden inputs a form sends.9 views · 6 downloads
Thread
Thread 0 posts
On Thumbnail: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.