Module:StreetBrawlItems: Difference between revisions

Wrap rendered groups in flex rows so cards and hero icons have consistent spacing (with help from vergir-bot LLM)
Vergir (talk | contribs)
Hero section: move styling to classes (Template:HeroStreetBrawl/styles.css), sort items by slot then cost then name, wrap groups for spacing (with help from vergir-bot LLM)
Line 4: Line 4:
local items = mw.loadJsonData("Data:ItemData.json")
local items = mw.loadJsonData("Data:ItemData.json")
local heroes = mw.loadJsonData("Data:HeroData.json")
local heroes = mw.loadJsonData("Data:HeroData.json")
-- Slot display order: Weapon -> Vitality (Armor) -> Spirit (Tech)
local SLOT_RANK = { Weapon = 1, Armor = 2, Tech = 3 }


local NAME_TO_KEY, KEY_TO_NAME, RELEASED = {}, {}, {}
local NAME_TO_KEY, KEY_TO_NAME, RELEASED = {}, {}, {}
Line 28: Line 31:
if it.StreetBrawl == true then return 5 end
if it.StreetBrawl == true then return 5 end
return it.Tier
return it.Tier
end
local function islot(code) local it = items[code]; return it and it.Slot end
local function icost(code)
local it = items[code]; local c = it and it.Cost
return type(c) == "number" and c or math.huge
end
-- Sort order: slot (Weapon -> Armor -> Tech), then cost ascending, then name.
local function item_less(a, b)
local ra = SLOT_RANK[islot(a)] or 99
local rb = SLOT_RANK[islot(b)] or 99
if ra ~= rb then return ra < rb end
local ca, cb = icost(a), icost(b)
if ca ~= cb then return ca < cb end
return (iname(a) or a) < (iname(b) or b)
end
end


Line 40: Line 58:
end
end


-- Lays rendered members out in a wrapping flex row with a consistent gap.
-- Lays rendered members out in a container with the given class (styled via CSS).
local function flexrow(parts, gap, center)
local function classdiv(parts, class)
if #parts == 0 then return "" end
if #parts == 0 then return "" end
local align = center and "center" or "flex-start"
return '<div class="' .. class .. '">' .. table.concat(parts) .. '</div>'
return '<div style="display:flex; flex-wrap:wrap; gap:' .. gap .. '; align-items:' .. align .. '">'
.. table.concat(parts) .. '</div>'
end
 
-- Wraps a rendered row with an optional bold label / italic note, or a collapsible box.
-- Returns "" when the row is empty, so nothing (not even the label) shows.
local function wrap(inner, label, note, collapse)
if inner == "" then return "" end
if collapse then
local header = (label and label ~= "") and label or "&nbsp;"
return '{| class="wikitable mw-collapsible mw-collapsed" style="width:100%"\n'
.. '! style="text-align:left" | ' .. header .. '\n|-\n| ' .. inner .. '\n|}'
end
local pre = ""
if label and label ~= "" then pre = pre .. "'''" .. label .. "'''<br>" end
if note and note ~= "" then pre = pre .. "''" .. note .. "''<br>" end
return pre .. inner
end
end


Line 97: Line 98:
if not style or style == "" then style = (group == "common") and "icon" or "card" end
if not style or style == "" then style = (group == "common") and "icon" or "card" end
local collapse = (frame.args.collapse == "yes" or frame.args.collapse == "true")
local collapse = (frame.args.collapse == "yes" or frame.args.collapse == "true")
local label = frame.args.label or ""


local favored, unfavored, special = hero_sets(hkey)
local favored, unfavored, special = hero_sets(hkey)
Line 109: Line 111:
if iok(c) and (tier == nil or itier(c) == tier) and pred(c) then codes[#codes + 1] = c end
if iok(c) and (tier == nil or itier(c) == tier) and pred(c) then codes[#codes + 1] = c end
end
end
table.sort(codes, function(a, b) return (iname(a) or a) < (iname(b) or b) end)
table.sort(codes, item_less)


local parts = {}
local parts = {}
for _, c in ipairs(codes) do local r = render_item(frame, c, style); if r then parts[#parts + 1] = r end end
for _, c in ipairs(codes) do local r = render_item(frame, c, style); if r then parts[#parts + 1] = r end end
local is_icon = (style == "icon")
if #parts == 0 then return "" end
local inner = flexrow(parts, is_icon and "4px 10px" or "8px", is_icon)
 
return wrap(inner, frame.args.label, nil, collapse)
if collapse then
local head = (label ~= "" and label) or "&nbsp;"
return '{| class="wikitable mw-collapsible mw-collapsed sb-common"\n'
.. '! class="sb-common-head" | ' .. head .. '\n|-\n| '
.. classdiv(parts, "sb-icons") .. '\n|}'
end
 
local row_class = (style == "icon") and "sb-icons" or "sb-cards"
local out = '<div class="sb-group">'
if label ~= "" then out = out .. '<div class="sb-label">' .. label .. '</div>' end
return out .. classdiv(parts, row_class) .. '</div>'
end
end


Line 127: Line 139:
for _, c in ipairs(counter) do if iok(c) then codes[#codes + 1] = c end end
for _, c in ipairs(counter) do if iok(c) then codes[#codes + 1] = c end end
if #codes == 0 then return "" end
if #codes == 0 then return "" end
table.sort(codes, function(a, b) return (iname(a) or a) < (iname(b) or b) end)
table.sort(codes, item_less)


local parts = {}
local parts = {}
Line 137: Line 149:
local note = frame.args.note
local note = frame.args.note
if note and note ~= "" then out[#out + 1] = "''" .. note .. "''" end
if note and note ~= "" then out[#out + 1] = "''" .. note .. "''" end
out[#out + 1] = flexrow(parts, "8px", false)
out[#out + 1] = classdiv(parts, "sb-cards")
return table.concat(out, "\n")
return table.concat(out, "\n")
end
end
Line 161: Line 173:
local parts = {}
local parts = {}
for _, k in ipairs(list) do local r = render_hero(frame, k); if r then parts[#parts + 1] = r end end
for _, k in ipairs(list) do local r = render_hero(frame, k); if r then parts[#parts + 1] = r end end
local inner = flexrow(parts, "4px 10px", true)
if #parts == 0 then return "" end
return wrap(inner, frame.args.label, frame.args.note, false)
 
local pre = ""
local label = frame.args.label
if label and label ~= "" then pre = pre .. "'''" .. label .. "'''<br>" end
local note = frame.args.note
if note and note ~= "" then pre = pre .. "''" .. note .. "''<br>" end
return pre .. classdiv(parts, "sb-icons")
end
end