Episode 1
21 min
A strip that scrolls sideways and snaps to each item, with a slim scrollbar or none, and the keyboard.
21 min
24 min
27 min
30 min
33 min
36 min
39 min
42 min
45 min
48 min
51 min
54 min
Swipe, scroll sideways, or focus a strip and use the arrow keys. The first snaps to each card's start, the second to each day's middle, with no scrollbar.
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/reel.qweimport ui/theme.qwe use theme_cssuse ui/reel.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>The code of the preview above.
view ReelDemoCard(i: int) = <Card title={`Episode ${i}`} subtitle={`${18 + i * 3} min`} padding="sm"> <div style={`height: 70px; border-radius: var(--ui-radius-sm); background: linear-gradient(135deg, var(--ui-accent-soft), var(--ui-${i % 2 == 0 ? "info" : "success"}-soft))`}></div> </Card>view ReelDemo() = <div.demo-stack> <Reel id="reel-demo-episodes" label="Episodes" item_width="200px"> {for i in range(1, 13) => <ReelDemoCard i={i}/>} </Reel> <Reel id="reel-demo-days" label="Days" gap="sm" snap="center" bar={false} pad={4}> {for d in ["Mon 3", "Tue 4", "Wed 5", "Thu 6", "Fri 7", "Sat 8", "Sun 9", "Mon 10", "Tue 11", "Wed 12", "Thu 13", "Fri 14", "Sat 15", "Sun 16", "Mon 17", "Tue 18"] => <Button variant={d == "Wed 5" ? "soft" : "outline"} size="sm">{d}</Button>} </Reel> <p.demo-note>Swipe, scroll sideways, or focus a strip and use the arrow keys. The first snaps to each card's start, the second to each day's middle, with no scrollbar.</p> </div>// Reel: a strip of things that scrolls sideways: cards, photos, chips, a row of// days. It snaps to each item, scrolls with a swipe, a wheel or the keyboard (it// takes focus), and shows a slim scrollbar, or none. No script runs.//// <Reel label="Recently viewed" item_width="220px"> {for p in products => <ProductCard .../>} </Reel>// <Reel gap="sm" snap="center" bar={false}> {for d in days => <DayChip .../>} </Reel>//// item_width: every item's width, as CSS ("220px"; left out, each is as wide as it is).// gap: pixels (12, the default) or "none", "xs" (4), "sm" (8), "md" (12), "lg" (20), "xl" (32).// snap: where scrolling stops, each item's "start" (default) or "center", or "none".// bar: the scrollbar shows (true). pad: room inside, in pixels (0), kept by the snapping.// label: its name for screen readers; it then takes focus, so the arrow keys scroll it.// height: the strip's height, as CSS; then an <img> in it is that tall and as wide// as its shape says.import ui/theme.qwe use ui_clslet reel_css = css`.ui-reel { display: flex; gap: var(--ui-reel-gap, 12px); min-width: 0; padding: var(--ui-reel-pad, 0); overflow: auto hidden; overscroll-behavior-x: contain; scroll-snap-type: x proximity; scroll-padding-inline: var(--ui-reel-pad, 0); scrollbar-width: thin; scrollbar-color: var(--ui-strong) transparent; outline: none; border-radius: var(--ui-radius-sm);}.ui-reel > *, .ui-reel > quillo-raw > * { flex: none; width: var(--ui-reel-item, auto); min-width: 0; scroll-snap-align: start; }.ui-reel-center > *, .ui-reel-center > quillo-raw > * { scroll-snap-align: center; }.ui-reel-nosnap { scroll-snap-type: none; }.ui-reel-tall > img, .ui-reel-tall > quillo-raw > img { width: auto; height: var(--ui-reel-h); }.ui-reel-nobar { scrollbar-width: none; }.ui-reel-nobar::-webkit-scrollbar { display: none; }.ui-reel:focus-visible { box-shadow: var(--ui-focus); }@media (prefers-reduced-motion: no-preference) { .ui-reel { scroll-behavior: smooth; } }`fn reel_gap(gap) -> str = match gap { int as n => `${n}px` float as n => `${n}px` "none" => "0" "xs" => "4px" "sm" => "8px" "lg" => "20px" "xl" => "32px" _ => "12px" }view Reel(item_width: str? = null, gap = 12, snap: str = "start", bar: bool = true, pad: int = 0, label: str? = null, height: str? = null, id: str? = null, class: str? = null, children) { style global reel_css <div class={ui_cls(["ui-reel", snap == "center" && "ui-reel-center", snap == "none" && "ui-reel-nosnap", !bar && "ui-reel-nobar", height != null && "ui-reel-tall", class])} id={id} tabindex={label != null ? "0" : null} role={label != null ? "region" : null} aria-label={label} style={`--ui-reel-gap: ${reel_gap(gap)}; --ui-reel-item: ${item_width ?? "auto"}; --ui-reel-pad: ${pad}px${height != null ? `; --ui-reel-h: ${height}` : ""}`}> {children} </div>}On Reel: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.