Sale
Northwind
Trail runner
$89.00was $120.00, −26% off
Products as ProductCards in a grid that fits as many across as there is room for, from a list of records.
Click Add to cart on any card.
It needs theme.qwe, as every component does, and price.qwe and product_card.qwe; 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/price.qwe$ curl -O https://quillolang.org/components/ui/product_card.qwe$ curl -O https://quillolang.org/components/ui/product_grid.qweimport ui/theme.qwe use theme_cssuse ui/product_grid.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>The code of the preview above.
let product_grid_demo_items = [ { id: 1, name: "Trail runner", brand: "Northwind", price: 89, old: 120, image: "https://picsum.photos/seed/runner/400/300", rating: 4.5, reviews: 128, badge: "Sale", badge_tone: "danger" }, { id: 2, name: "Wool beanie", brand: "Northwind", price: 24, image: "https://picsum.photos/seed/beanie/400/300", rating: 4, reviews: 37, stock: "low" }, { id: 3, name: "Insulated bottle", price: 32.5, image: "https://picsum.photos/seed/bottle/400/300", rating: 3.8, reviews: 9, badge: "New" }, { id: 4, name: "Rain jacket", price: 149, image: "https://picsum.photos/seed/jacket/400/300", stock: "out" }, { id: 5, name: "Day pack, 22 l", price: 64, image: "https://picsum.photos/seed/pack/400/300", rating: 4.7, reviews: 211 }, { id: 6, name: "Merino socks, 3 pairs", price: 29, old: 36, image: "https://picsum.photos/seed/socks/400/300", rating: 4.2, reviews: 54 },]component ProductGridDemoLive() { state last = null <div.demo-stack> <ProductGrid products={product_grid_demo_items} size={180} card_size="sm" on_add={(p) => { last = p.name }}/> <p.demo-note>{last == null ? "Click Add to cart on any card." : `Added "${last}" (on_add is given the product).`}</p> </div>}view ProductGridDemo() = <div.demo-stack> <ProductGridDemoLive/> <ProductGrid products={[]} /> </div>// ProductGrid: products as ProductCards in a grid that fits as many across as// there is room for (this file needs product_card.qwe and price.qwe).//// <ProductGrid products={db.query("select * from products")} action="/cart" currency="EUR"/>// <ProductGrid products={picks} size={200} on_add={(p) => { cart = cart | push(p) }}/>//// products: a list of maps with ProductCard's props (id, name, price, old, image,// alt, href, brand, rating, reviews, badge, badge_tone, stock); other fields are// ignored. currency, locale, cents, action, add_label, ratio, card_size ("sm" or// "md"): the same for every card. size: each column's width at least, in pixels// (220). gap: between cards, in pixels (16). empty: what to say with no products// ("No products"). label: what screen readers call the grid ("Products").// on_add(product): inside one of your components, given the product's map when// its button is clicked (without an action).import ui/product_card.qwe use ProductCardimport ui/theme.qwe use ui_clslet product_grid_css = css`.ui-product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(var(--s, 220px), 100%), 1fr)); gap: var(--g, 16px); margin: 0; padding: 0; list-style: none; }.ui-product-grid > li { display: flex; min-width: 0; }.ui-product-grid > li > .ui-product { flex: 1; }.ui-product-grid-empty { padding: 32px; border: 1px dashed var(--ui-border); border-radius: var(--ui-radius); color: var(--ui-muted); font: 14px/1.4 var(--ui-font); text-align: center; }`view ProductGrid(products: list = [], size: int = 220, gap: int = 16, currency: str = "USD", locale: str? = null, cents: bool = true, action: str? = null, add_label: str = "Add to cart", ratio: str = "4/3", card_size: str = "md", empty: str = "No products", label: str = "Products", on_add = null, class: str? = null) { style global product_grid_css len(products) == 0 ? <div class={ui_cls(["ui-product-grid-empty", class])} role="status">{empty}</div> : <ul class={ui_cls(["ui-product-grid", class])} style={`--s: ${size}px; --g: ${gap}px`} aria-label={label}> {for [i, p] in enumerate(products) => <li key={get(p, "id") ?? i}> <ProductCard {...p} id={get(p, "id") != null ? str(p.id) : null} currency={get(p, "currency") ?? currency} locale={locale} cents={cents} action={action} add_label={add_label} ratio={ratio} size={card_size} on_add={() => { on_add && on_add(p) }}/> </li>} </ul>}On ProductGrid: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.