ui: lay the EUICCInfo2 chip fields out in two columns

The short EUICCInfo2 fields (versions, card resources, category, PPRs, …)
were one per row in the wide right-hand box, wasting half of it.

- esimChipValueWide(): a row needs the full width when its value is a
  list or a long token (>24 chars or ', '), so short scalars pair up.
- esimChipBox() gained a twoColumns mode: rows in a responsive
  grid-cols-1 sm:grid-cols-2 grid with long values spanning both columns;
  the other boxes keep their single-column rows.
- esimRenderChip() renders the EUICCInfo2 box with two columns.
- style.css rebuilt (sm:grid-cols-2, sm:col-span-2).
- tests: the wide/short rule, the two-column markup and the render call;
  help EN/RU and AGENTS note the layout; sw.js simple-v233.
This commit is contained in:
2026-09-22 00:51:07 +03:00
parent cb63ff286d
commit bed1852110
6 changed files with 66 additions and 8 deletions
+18 -4
View File
@@ -1678,16 +1678,30 @@ function esimChipSectionRows(data) {
return esimFieldRows(data, '');
}
// One bordered chip-info box; no rows -> no box.
function esimChipBox(title, rows) {
// A chip-info row needs the full box width when its value is a list or a
// long token (hex identifiers, capability lists); short scalars share a row.
function esimChipValueWide(label, value) {
const v = String(value);
return v.length > 24 || v.indexOf(', ') >= 0;
}
// One bordered chip-info box; no rows -> no box. With `twoColumns` the short
// fields are laid out in a 2-column grid (single column on narrow screens)
// and long values span the full width, which keeps the big EUICCInfo2 box
// compact.
function esimChipBox(title, rows, twoColumns) {
if (!rows || !rows.length) return '';
let html = '<div class="border border-gray-200 dark:border-slate-700 rounded p-2 min-w-0">';
html += '<div class="mb-1 text-xs font-semibold text-gray-600 dark:text-slate-300">' + esc(title) + '</div>';
if (twoColumns) html += '<div class="grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-1">';
for (const [k, v] of rows) {
html += '<div class="flex gap-2 mb-0.5">';
const cls = twoColumns ? 'flex gap-2 min-w-0' : 'flex gap-2 mb-0.5';
html += '<div class="' + cls +
(twoColumns && esimChipValueWide(k, v) ? ' sm:col-span-2' : '') + '">';
if (k) html += '<span class="w-36 shrink-0 text-right text-gray-500 dark:text-slate-400 break-words">' + esc(k) + '</span>';
html += '<span class="font-mono break-words min-w-0">' + esc(v) + '</span></div>';
}
if (twoColumns) html += '</div>';
return html + '</div>';
}
@@ -1701,7 +1715,7 @@ function esimRenderChip() {
esimChipBox(t('Addresses'), esimChipSectionRows(c.addresses)),
esimChipBox(t('Rules authorisation table'), esimChipSectionRows(c.rat)),
].filter(Boolean);
const right = esimChipBox('EUICCInfo2', esimChipSectionRows(c.info2));
const right = esimChipBox('EUICCInfo2', esimChipSectionRows(c.info2), true);
if (!left.length && !right) {
el.innerHTML = '<span class="text-gray-400">' + esc(t('No data')) + '</span>';
return;