// A Discover section that lays slim cards in a fixed 4-column grid // (Popular albums, Recently Played). Non-paginated for now. // // GridLayout cannot host a `for`, so cards are absolutely positioned // inside a Rectangle whose height is derived from the row count. import { Theme } from "../foundation/semantic-colors.slint"; import { Typography } from "../foundation/typography.slint"; import { SlimItem } from "../state.slint"; import { SlimCard } from "SlimCard.slint"; export component GridSection inherits VerticalLayout { in property title; in property <[SlimItem]> items; callback item-clicked(string); property columns: 4; property gap: 8px; property row-height: 60px; property rows: Math.ceil(root.items.length / root.columns); spacing: 12px; Text { text: root.title; color: Theme.text-primary; font-size: 18px; font-weight: Typography.semibold; } grid := Rectangle { property cell-width: (self.width - (root.columns - 1) * root.gap) / root.columns; height: root.rows > 0 ? root.rows * root.row-height + (root.rows - 1) * root.gap : 0px; for item[i] in root.items: SlimCard { width: grid.cell-width; height: root.row-height; x: Math.mod(i, root.columns) * (grid.cell-width + root.gap); y: Math.floor(i / root.columns) * (root.row-height + root.gap); item: item; clicked(id) => { root.item-clicked(id); } } } }