From 40f7a3e4ca79ec97d7212883e8ea58575d74edfe Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Mon, 3 Aug 2026 18:18:02 -0400 Subject: [PATCH] feat(ui): add cardSide grid helper Square-card grids reflow on rotation, and the arithmetic is the same in every app that draws one. --- lua/lib/ui.lua | 16 ++++++++++++++++ lua/test/ui.lua | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/lua/lib/ui.lua b/lua/lib/ui.lua index cc80aa6..879630c 100644 --- a/lua/lib/ui.lua +++ b/lua/lib/ui.lua @@ -173,6 +173,22 @@ function ui.box(spec) return build(spec, "box") end +---Side length for a grid of square cards that fits the frame, and the column count that +---produced it. Landscape gets a wider grid, so the same screen reflows on rotation. +---@param count integer Cards to place. +---@param pad integer Padding outside the grid. +---@param gap integer Gap between cards. +---@param reserve? integer Height to leave free below the grid. +---@return integer side +---@return integer columns +function ui.cardSide(count, pad, gap, reserve) + local columns = gui.getWidth() >= gui.getHeight() and 4 or 3 + local rows = math.ceil(count / columns) + local byWidth = (gui.getWidth() - 2 * pad - (columns - 1) * gap) // columns + local byHeight = (gui.getHeight() - 2 * pad - (reserve or 0) - (rows - 1) * gap) // rows + return math.min(byWidth, byHeight), columns +end + ---@param spec UiSpec ---@return NodeId function ui.spacer(spec) diff --git a/lua/test/ui.lua b/lua/test/ui.lua index 7f3af17..8b3717a 100644 --- a/lua/test/ui.lua +++ b/lua/test/ui.lua @@ -187,4 +187,11 @@ assert(ui.getTheme() == "mono" and #invalidated == before + 1) assert(cleared == ui.theme.background) screen:draw() + +-- 320x480 portrait: three columns, and the reserve comes off the height budget. +local side, columns = ui.cardSide(5, 12, 8) +assert(columns == 3 and side == 93, "width is the binding constraint in portrait") +-- Five cards are two rows, so a reserve that eats the height budget shrinks the card. +assert(select(1, ui.cardSide(5, 12, 8, 300)) == 74, "height binds once the reserve is large") + print("ok")