aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-30 16:20:57 -0700
committerAdam Soltys <[email protected]>2026-08-30 16:20:57 -0700
commitfbcb96a9ee16d44e5da6a39aa6b5cb16e4da24d5 (patch)
tree396dd500328950297411cb8d13a78401e622a982
parent431907c9959e6d414fe13e05f76d1a1a45f7828e (diff)
downloadcoinosv3-fbcb96a9ee16d44e5da6a39aa6b5cb16e4da24d5.tar.gz
coinosv3-fbcb96a9ee16d44e5da6a39aa6b5cb16e4da24d5.zip
The coins table stops wrapping into confetti on a phone: each coin is now a two-line row — the amount, then 'expires 26d · depth 6 · exit fee 1,844 · renew 117' riding inline — so there is no header row and no five-column horizontal budget to blow; the column-header strings retire
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
-rw-r--r--src/features/ark.js27
-rw-r--r--src/i18n.js6
2 files changed, 16 insertions, 17 deletions
diff --git a/src/features/ark.js b/src/features/ark.js
index df08e35..805701a 100644
--- a/src/features/ark.js
+++ b/src/features/ark.js
@@ -1634,8 +1634,6 @@ export function arkFeature(ctx) {
ui.arkCoinsSel = null;
back();
};
- const cell = (s, extra = '') => h('span', { class: 'small', style: 'flex:1;' + extra }, s);
- const head = (s, extra = '') => h('span', { class: 'small faint', style: 'flex:1;' + extra }, s);
const tick = (checked, onChange, title) => h('input', {
type: 'checkbox', checked, title, style: 'flex:0 0 auto;margin:0', onChange,
});
@@ -1644,29 +1642,34 @@ export function arkFeature(ctx) {
h('h3', { style: 'margin:0' }, t('arkCoinsTitle')),
h('p', { class: 'small muted', style: 'margin:0' },
t('arkCoinsIntro', { n: spend.length, total: fmtAmount(totalSat) + ' ' + unitLabel() })),
- h('div', { class: 'col', style: 'gap:4px;margin-top:4px' },
+ // One coin per row, two lines: the amount, then a terse meta line.
+ // Five flexed columns fit a laptop but wrap into confetti on a phone
+ // — labels riding inline with each value need no header row and no
+ // horizontal budget at all.
+ h('div', { class: 'col', style: 'gap:8px;margin-top:4px' },
h('div', { class: 'row gap6', style: 'align-items:center' },
tick(sel.size === ids.size, (e) => {
ui.arkCoinsSel = e.target.checked ? new Set(ids) : new Set();
render();
}, t('arkCoinsSelectAll')),
- head(t('arkCoinsColAmount')), head(t('arkCoinsColExpires'), 'text-align:center'),
- head(t('arkCoinsColDepth'), 'text-align:center'), head(t('arkCoinsColExitFee'), 'text-align:center'),
- head(t('arkCoinsColFee'), 'text-align:right')),
+ h('span', { class: 'small faint' }, t('arkCoinsSelectAll'))),
...spend.map((v) => {
const d = depthOf(v);
const f = feeNowOf(v);
const xf = exitFeeOf(v);
- return h('div', { class: 'row gap6', style: 'align-items:center' },
+ return h('div', { class: 'row gap6', style: 'align-items:flex-start' },
tick(sel.has(v.id), (e) => {
e.target.checked ? sel.add(v.id) : sel.delete(v.id);
render();
}),
- cell(fmtAmount(v.amountSat) + ' ' + unitLabel()),
- cell(expiresOf(v), 'text-align:center'),
- cell(d == null ? '—' : String(d), 'text-align:center'),
- cell(xf == null ? '—' : fmtAmount(xf), 'text-align:center'),
- cell(f > 0 ? fmtAmount(f) : t('arkDepthFree'), 'text-align:right'));
+ h('div', { class: 'col grow', style: 'gap:1px;min-width:0' },
+ h('span', { class: 'small' }, fmtAmount(v.amountSat) + ' ' + unitLabel()),
+ h('span', { class: 'small faint' }, t('arkCoinsRowMeta', {
+ exp: expiresOf(v),
+ d: d == null ? '—' : String(d),
+ exit: xf == null ? '—' : fmtAmount(xf),
+ renew: f > 0 ? fmtAmount(f) : t('arkDepthFree'),
+ }))));
})),
h('p', { class: 'small faint', style: 'margin:4px 0 0' }, t('arkCoinsExpiryNote'))),
h('div', { class: 'card col', style: 'gap:8px' },
diff --git a/src/i18n.js b/src/i18n.js
index 680b83e..ac2cf27 100644
--- a/src/i18n.js
+++ b/src/i18n.js
@@ -210,10 +210,7 @@ const STR = {
arkSpentElsewhereN: '{n} coins',
arkCoinsTitle: 'Spending coins',
arkCoinsIntro: 'Your Spending balance lives in {n} coins totalling {total}. Each can be pulled on-chain without the server’s help — at a cost that grows with the coin’s history.',
- arkCoinsColAmount: 'Amount',
- arkCoinsColExpires: 'Expires',
- arkCoinsColDepth: 'Depth',
- arkCoinsColExitFee: 'Exit fee',
+ arkCoinsRowMeta: 'expires {exp} · depth {d} · exit fee {exit} · renew {renew}',
arkCoinsExpiryNote: 'Past its expiry a coin can be reclaimed by the server — the wallet renews on its own well before that.',
arkCoinsExitTitle: 'Uncooperative exit',
arkCoinsExitDesc: 'If the server vanished today, publishing every transaction in each coin’s history would cost about {fee} sats in mining fees. After a renewal it would be one fresh coin, one hop: about {after} sats.',
@@ -224,7 +221,6 @@ const STR = {
arkCoinsRenewSome: 'Renew {n} selected for {fee}',
arkCoinsRenewNone: 'Select coins to renew',
arkCoinsSelectAll: 'Select all',
- arkCoinsColFee: 'Renew fee',
arkCoinsSpanDay: '1 day',
arkCoinsSpanDays: '{n} days',
arkCoinsSpanHour: '1 hour',