bug(frontend): /token/create desktop form wastes horizontal screenspace #669

Closed
opened 2026-08-26 04:19:22 +00:00 by PlasticDigits · 10 comments
PlasticDigits commented 2026-08-26 04:19:22 +00:00 (Migrated from gitlab.com)

Summary

On desktop /token/create, the create wizard is a single 520px centered column inside the 1080px .app-main shell. Most of the viewport is empty left and right. Short fields (Name, Symbol, Decimals, Treasury, Manager) stack full-width, so Paid features and the create / pay CTA sit below the fold on a typical 1280×720–1440×900 desktop.

Community report (anonymized, 2026-08): desktop Create Token — inefficient screenspace; the form is a narrow vertical card while ~60–70% of the horizontal main area is unused.

This is a layout bug. Invoice math, identity parsers, SKU hooks, and launcher execute stay unchanged (C593, C604, C605).

Related (do not regress): #593 create/manage, #604 identity + wallet helpers, #605 SKU init + percent taxes, #595 PayWithAnyToken, #653 one chrome layer, #489 copy, #488 tokens, #602 retail chrome. Phone-width stacking is in scope as a non-regression (keep a single column ≤767px). Do not fold Manage (/token/:addr/manage) or Migrate (/token/migrate) into this MR — those stay sibling pages.


Current codebase

Shell vs page cap

Layout.tsx mounts the page in .app-main-content. index.css already sizes the shell:

.app-main {
  width: min(100% - 24px, 1080px);
  max-width: 1080px;
  margin: 0 auto;
}

CreateTokenPage.tsx then re-caps the entire wizard (configured + unavailable stub) at max-w-[520px] mx-auto (data-testid="create-token-page"). On a 1280–1920 desktop that leaves ~280px unused on each side of a 520px card (1080 − 520 = 560px of empty main width). Swap stays a 500px card on purpose; Create Token is a long multi-section form, not a Pay/Receive ticket.

Field stack (today)

One shell-panel-strong space-y-4 holds every control. Only Buy tax / Sell tax already use grid grid-cols-2. Everything else is a full-width label.block:

Block Markup today Desktop waste
Name full-width Short alphanumeric; 3–50 chars
Symbol full-width 3–12 chars
Decimals full-width Default 6; integer 6–18
Buy / Sell tax grid-cols-2 Already paired
Treasury full-width + connected wallet helper Bech32; can sit beside Manager
Manager full-width + helper Same
Paid features 7 stacked checkboxes + hints Vertical list of SKUs
SKU init panels revealed one-after-another Max buy/sell/transfer and launch-guard fields also stack
Ack + free CTA / PayWithAnyToken bottom of the same panel Below the fold when SKUs are off; worse when SKUs are on

SKU catalog is COMMUNITY_TAX_SKUS in communityTaxSku.ts: Minting, Wallet-to-wallet tax, Split treasury, Auto liquidity, Extra exemptions, Change rates later, Launch guards. Uncheck still must drop that SKU’s init keys from the hook (C605-2).

Tests / docs today


Why this is needed

Create Token is the retail path to instantiate a community tax token (free 0-SKU or paid SKUs). On desktop the first screen should show identity + tax + wallets + the Paid features list without scrolling past a 520px chimney. Users cannot see SKU cost (N × 50 UST1) or the ack / CTA until they scroll — that is how people miss Minting (create-only) or enable the wrong SKU.

This is not “users should zoom out.” The shell already budgets 1080px. The page must use a responsive multi-column layout at md/lg and keep a single column on phone so 375 / 390 stay usable (same class of work as #651 for /tiers, opposite breakpoint).


Constraints / guardrails

  1. Layout only. Do not change launcher CreateToken / UST1 Receive hooks, invoice payee, SKU prices, or buildValidatedCreateArgs / buildCreateTokenHook field semantics (C593-3, C593-4, C593-10, C593-12).
  2. Identity + wallets stay C604. Name/symbol ^[A-Za-z0-9]+$; decimals 6–18; treasury/manager autofill connected wallet when empty; never clobber a typed address; ignore ?manager= / ?treasury= / ?payee=. Helper copy remains exactly connected wallet / not connected wallet.
  3. SKU init stays C605. Checkbox on reveals fields; uncheck hides and drops those keys from the hook. Percent taxes stay 2 dp; combined cap 25.00%; max_* combined ≤ 25.00% (C593-13). AutoLP still blocks when autolp_code_id is unset.
  4. One chrome layer (#653). Keep a single shell-panel-strong (or sibling panels, not nested). Do not wrap SKU tiles in a grid of card-glass / default StatBox. Hairline dividers / CSS grid only.
  5. Copy (#489). Do not add a screenspace essay or “use two columns on desktop” banner. Lead sentence + Migrate here stay. Labels ≤ ~5 words.
  6. Design system (#488). input-glass / label-glass / btn-primary. No *-neo. Light + dark.
  7. Phone / tablet. ≤767px stays one column; no horizontal page scroll at 320 / 375 / 390. Bech32 treasury/manager must wrap or break-all, not overflow the card. Buy/sell 2-col may stay if both fields remain ≥44px tap-wide; otherwise stack.
  8. Ack + CTA visible. Risk ack stays required. Do not hide ack behind a collapsed <details> that defaults closed. Free CTA / Pay card must remain in tab order after the form.
  9. Testids stable. Keep create-token-page, create-token-name, create-token-symbol, create-token-decimals, create-token-buy-pct, create-token-sell-pct, create-token-treasury, create-token-manager, create-token-sku-*, create-token-ack, create-token-free-cta, create-token-pay, helpers. Add layout testids only (create-token-desktop-grid or similar).
  10. Do not widen Swap / Create Pair to match. Those stay ticket-width. Do not implement Manage / Migrate density here.
  11. No e2e-tx. Playwright workers stay 5 for smoke. On-chain create stays existing community-tax tx specs.
  12. Create Token stays code-id-free on the card (M628-7). Do not print 11619 / 8654 / allowlist essays.

Relevant files

Primary

  • frontend-dapp/src/pages/CreateTokenPage.tsx — max-w-[520px] + stacked labels
  • frontend-dapp/src/pages/CreateTokenPage.test.tsx — extend with layout / grid contract
  • frontend-dapp/e2e/create-token-602.spec.ts — desktop width + phone non-regression
  • frontend-dapp/src/index.css — only if a shared form-grid utility is added (prefer Tailwind on the page)

Read, do not fork

  • frontend-dapp/src/utils/communityTaxCreateForm.ts / communityTaxIdentity.ts / communityTaxInvoice.ts / communityTaxSku.ts
  • frontend-dapp/src/components/payments/PayWithAnyToken.tsx
  • docs/frontend.md § Create Token
  • skills/AGENTS_FRONTEND_CREATE_TOKEN.md
  • skills/AGENTS_FRONTEND_CHROME_NESTING.md / skills/AGENTS_FRONTEND_DESIGN_SYSTEM.md / skills/AGENTS_FRONTEND_COPY_COGNITIVE_LOAD.md
  • QA_TEMPLATE.md § 11 (add a Create Token desktop + phone row)

Out of scope siblings

  • frontend-dapp/src/pages/ManageTokenPage.tsx (max-w-[640px])
  • frontend-dapp/src/pages/MigrateTokenPage.tsx (max-w-[520px])
  • frontend-dapp/src/pages/CreatePairPage.tsx (keep ticket width)

Ship one responsive layout on CreateTokenPage. Bundle (do not split into extra issues): (1) raise the desktop max-width, (2) pair short fields, (3) SKU checkbox grid, (4) pair SKU init numeric fields, (5) phone single-column non-regression.

A — Use the main shell on desktop

At md (≥768px) or lg (≥1024px), drop max-w-[520px] in favor of w-full (the 1080px .app-main is the cap) or max-w-[960px] / max-w-[1080px]. Unavailable stub may stay narrow.

B — Pair short fields (md+)

Suggested CSS grid (single panel, no nested chrome):

Row md+ <md
Name / Symbol / Decimals grid-cols-3 or Name+Symbol 2fr + Decimals 1fr stack
Buy tax / Sell tax keep grid-cols-2 keep or stack if tap targets shrink
Treasury / Manager grid-cols-2 stack
Paid features grid-cols-2 checkbox+hint cells stack
Variable rates max % grid-cols-3 stack
Launch guards max wallet / cooldown grid-cols-2 stack
AutoLP threshold / recipient grid-cols-2 stack
Split sinks keep existing 3-col row; wrap on phone
Ack + CTA / Pay full-width bottom of the same panel

Prefer one md:grid wrapper (data-testid="create-token-desktop-grid") with identity+tax+wallets in column 1 and Paid features + init + CTA in column 2 only if both columns stay in one shell-panel-strong and tab order stays Name → … → SKUs → ack → CTA. A single-column-but-wider card with paired rows is also OK if Paid features + CTA enter the first viewport at 1280×720 with 0 SKUs.

C — First-viewport bar

At 1280×720, disconnected or connected, 0 SKUs: heading, Name/Symbol/Decimals, Buy/Sell, Treasury/Manager, Paid features legend + at least the SKU list start, and ack/CTA (or a clear “scroll 1 short hop”) must not require scrolling past an empty 520px chimney. With several SKUs checked, init panels may extend — that is expected; do not virtualize / hide them.

D — Out of scope

  • Changing 50 UST1 SKU price, launcher address, or free-create execute.
  • Manage / Migrate / Create Pair width.
  • Sticky header CTA that covers the wallet chip or More menu.
  • New wizard steps that split create across routes.

Acceptance criteria

  • Desktop 1280×720 and 1440×900: create-token-page content width is > 700px (not still 520). Empty left/right main gutters shrink; the form uses the .app-main budget.
  • Desktop md+: Name+Symbol (and Decimals) share a row; Treasury+Manager share a row; Paid features is a 2-col checkbox grid (or equivalent density). Buy/Sell stay paired.
  • 1280×720, 0 SKUs: Paid features legend and the ack control are reachable without a long empty-margin scroll; CTA or connect prompt is in the first two viewports.
  • Phone 375×667 and 390×844: single column; no horizontal document scroll; treasury/manager bech32 does not overflow; tap targets ≥44px; existing P7/P8/P9 helpers still read connected wallet / not connected wallet.
  • SKU toggle: checking each of the 7 SKUs still reveals the matching panel; uncheck drops fields from the hook (invoice 0 / 50 / 150 still holds).
  • C593 / C604 / C605 unchanged: env unavailable stub; ignore query payee/manager/treasury; percent 2 dp + 25% cap errors still show; free CTA vs PayWithAnyToken launcher payee unchanged.
  • Light + dark. No nested shell-panel / SKU card-glass grid. No *-neo. No new lecture banner.
  • Docs: docs/frontend.md § Create Token notes desktop density + phone stack. QA_TEMPLATE.md gains a Create Token desktop/phone row. Skill playbook points at this issue.
  • Existing CreateTokenPage.test.tsx + make verify-issue-593 / 604 / 605 stay green.

Test plan (all paths)

Unit (CreateTokenPage.test.tsx)

Keep existing cases. Add:

  1. Desktop grid contract: with matchMedia('(min-width: 768px)') (or the breakpoint the page uses), root or create-token-desktop-grid has the documented md:grid / max-w class (not max-w-[520px] alone).
  2. Phone contract: max-width: 767px — no md:grid-cols-2 applied as the only layout; fields still in DOM order Name → Symbol → Decimals → buy → sell → treasury → manager → SKUs → ack.
  3. Unavailable stub still renders create-token-unavailable when env is off (width may stay narrow).
  4. SKU panels: toggle each create-token-sku-*; assert the matching *-panel / mint cap appears and disappears; invoice text 0 → 50 → 150 unchanged.
  5. Query ignore: render with ?payee= / ?manager= / ?treasury= (existing Pay tests already cover spoof payee on the pay card). Helpers still follow the connected wallet, not the query.
  6. Validation still blocks CTA: name with space; decimals 5; combined tax 20 + 20.
  7. P7–P9 wallet helpers after reflow (same strings).

Vitest (must stay green)

cd frontend-dapp && npm test -- --run \
  src/pages/CreateTokenPage.test.tsx \
  src/utils/communityTaxCreateForm.test.ts

Plus make verify-issue-593 make verify-issue-604 make verify-issue-605 (do not reopen those issues unless an invariant actually broke).

Playwright (e2e-smoke, 5 workers)

Extend e2e/create-token-602.spec.ts (or a sibling smoke spec — not e2e-tx):

  1. 1280×720 (existing): heading, no unavailable stub, More → Create Token.
  2. New desktop geometry: setViewportSize({ width: 1280, height: 720 }).
    • create-token-page getBoundingClientRect().width > 700.
    • Name and Symbol top (y) within ~48px of each other or both in the first viewport; Treasury and Manager same-row or adjacent columns.
    • Paid features legend y < 720 (first viewport) with 0 SKUs.
  3. 1440×900: same width floor; form does not stretch past .app-main (page width ≤ 1080 + padding).
  4. 375×667 and 390×844:
    • create-token-page width ≤ viewport − chrome; document.scrollingElement.scrollWidth ≤ clientWidth + 1.
    • Name y < Symbol y < Decimals y (stacked).
    • Fill a long bech32 in treasury; no horizontal page scroll.
  5. Connected (existing connectWallet): free CTA still appears after name/symbol/ack; one SKU still swaps to create-token-pay with 50 UST1.
  6. Do not add e2e-tx here.

Manual

  1. Desktop 1280 and 1920, dark + light: screenshot first viewport — identity + tax + wallets + SKU list visible; no 520px chimney.
  2. Resize 1920 → 768 → 375: columns collapse cleanly; no overlapping labels; no clipped errors.
  3. Check all 7 SKUs then uncheck: panels appear/disappear; invoice count matches; free CTA returns at 0.
  4. Connect / disconnect: helpers and autofill (C604-2).
  5. Paste a different treasury: not connected wallet; layout does not overflow.
  6. Keplr in-app / coarse pointer: checkbox + ack ≥44px.
  7. Unavailable env (unset launcher): stub still centered and readable.

Test plan (attack, hack, and abuse)

Layout sits on the instantiate + invoice path. Treat SKU checkboxes, addresses, and Pay as trust-boundary controls.

  1. Wrong-SKU tap. Two-column SKU grid must not stack hit targets so checking “Minting” toggles “Launch guards”. Each data-testid={create-token-sku-${id}} onChange maps to that sku.id only. Playwright/unit: click mid-list SKU; assert only that id is in the invoice count / panel.
  2. Query payee / manager spoof (C593-10 / C604-2). ?payee= / ?manager= / ?treasury= still ignored after reflow. Paid path payee remains env launcher. Unit already in PayWithAnyToken.test.tsx — keep green.
  3. Hidden ack. CSS grid / overflow: hidden must not clip the ack checkbox or show a enabled CTA without create-token-ack. CTA stays disabled until formOk && ack.
  4. Invoice amount vs visible SKUs. Reorder must not show “SKU invoice: 50” while two boxes are checked. create-token-sku-total stays skus.length × 50.
  5. XSS. Name/symbol/hints/errors render as text. No dangerouslySetInnerHTML on user or LCD strings. Exempt textarea stays a text control.
  6. Address overflow / clickjack. Long bech32 must not paint over the header CONNECT / More (z-index). New grid z-index stays below Connect / Legal / WalletConnect (z-[9999]).
  7. Disabled CTA remount. Reflow at the md breakpoint must not remount a fresh enabled free-CTA or Pay card mid-broadcast (freeCreate.isPending / pay pending still disables).
  8. Uncheck paid payload leak (C605-2 / C593-12). After unchecking a SKU, hook builders must omit that payload (existing create-form tests). Layout must not leave a hidden filled input that still serializes.
  9. Combined cap bypass via split columns. Buy 20% + Sell 20% still errors combined; max_* three-up grid still enforces 25.00% combined.
  10. Phone zoom / 200% text. Card grows vertically; fields do not overlap the next checkbox. No overflow: hidden that clips validation (create-token-error-*, decimals error).
  11. Focus order. Tab order stays visual order (no tabindex tricks that skip ack). Keyboard #488 :focus-visible on inputs/checkboxes/CTA.

Verification criteria

Done when:

  1. Manual desktop 1280 + 1440: form wider than 700px; paired rows; Paid features in the first viewport at 0 SKUs; light + dark.
  2. Manual phone 375 / 390: stacked; no horizontal scroll; helpers + SKU toggle still correct.
  3. CreateTokenPage.test.tsx covers grid contract + existing P2/P4/P7–P9/SKU math.
  4. Playwright 1280 width floor + 375/390 no scrollWidth overflow; existing #602 smoke green. No e2e-tx required.
  5. make verify-issue-593 make verify-issue-604 make verify-issue-605 green. python3 scripts/check_chrome_nesting.py clean if markup gained card-glass.
  6. docs/frontend.md + QA_TEMPLATE.md + create-token skill updated. No new on-chain / indexer surface.
# after implementation
bash scripts/with-node.sh --cwd frontend-dapp -- npm test -- --run src/pages/CreateTokenPage.test.tsx
make verify-issue-593
make verify-issue-604
make verify-issue-605
python3 scripts/check_chrome_nesting.py
make lint-frontend
# e2e-smoke (5 workers): frontend-dapp/e2e/create-token-602.spec.ts
## Summary On **desktop** `/token/create`, the create wizard is a single **520px** centered column inside the **1080px** `.app-main` shell. Most of the viewport is empty left and right. Short fields (Name, Symbol, Decimals, Treasury, Manager) stack full-width, so **Paid features** and the create / pay CTA sit below the fold on a typical 1280×720–1440×900 desktop. Community report (anonymized, 2026-08): desktop Create Token — inefficient screenspace; the form is a narrow vertical card while ~60–70% of the horizontal main area is unused. This is a **layout** bug. Invoice math, identity parsers, SKU hooks, and launcher execute stay unchanged (**C593**, **C604**, **C605**). Related (do not regress): [#593](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/593) create/manage, [#604](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/604) identity + wallet helpers, [#605](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/605) SKU init + percent taxes, [#595](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/595) PayWithAnyToken, [#653](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/653) one chrome layer, [#489](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/489) copy, [#488](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/488) tokens, [#602](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/602) retail chrome. Phone-width stacking is **in scope as a non-regression** (keep a single column ≤767px). Do **not** fold Manage (`/token/:addr/manage`) or Migrate (`/token/migrate`) into this MR — those stay sibling pages. --- ## Current codebase ### Shell vs page cap [`Layout.tsx`](frontend-dapp/src/components/common/Layout.tsx) mounts the page in `.app-main-content`. [`index.css`](frontend-dapp/src/index.css) already sizes the shell: ```css .app-main { width: min(100% - 24px, 1080px); max-width: 1080px; margin: 0 auto; } ``` [`CreateTokenPage.tsx`](frontend-dapp/src/pages/CreateTokenPage.tsx) then **re-caps** the entire wizard (configured + unavailable stub) at `max-w-[520px] mx-auto` (`data-testid="create-token-page"`). On a 1280–1920 desktop that leaves ~280px unused on each side of a 520px card (1080 − 520 = 560px of empty main width). Swap stays a 500px card on purpose; Create Token is a long multi-section form, not a Pay/Receive ticket. ### Field stack (today) One `shell-panel-strong space-y-4` holds every control. Only **Buy tax / Sell tax** already use `grid grid-cols-2`. Everything else is a full-width `label.block`: | Block | Markup today | Desktop waste | |-------|----------------|---------------| | Name | full-width | Short alphanumeric; 3–50 chars | | Symbol | full-width | 3–12 chars | | Decimals | full-width | Default `6`; integer 6–18 | | Buy / Sell tax | `grid-cols-2` | Already paired | | Treasury | full-width + `connected wallet` helper | Bech32; can sit beside Manager | | Manager | full-width + helper | Same | | Paid features | 7 stacked checkboxes + hints | Vertical list of SKUs | | SKU init panels | revealed one-after-another | Max buy/sell/transfer and launch-guard fields also stack | | Ack + free CTA / `PayWithAnyToken` | bottom of the same panel | Below the fold when SKUs are off; worse when SKUs are on | SKU catalog is `COMMUNITY_TAX_SKUS` in [`communityTaxSku.ts`](frontend-dapp/src/utils/communityTaxSku.ts): Minting, Wallet-to-wallet tax, Split treasury, Auto liquidity, Extra exemptions, Change rates later, Launch guards. Uncheck still must drop that SKU’s init keys from the hook (**C605-2**). ### Tests / docs today - Vitest: [`CreateTokenPage.test.tsx`](frontend-dapp/src/pages/CreateTokenPage.test.tsx) — env gate, SKU invoice 0/50/150, helpers, decimals, name space, `/create` next link. **No** width / grid / viewport assertions. - Playwright smoke: [`e2e/create-token-602.spec.ts`](frontend-dapp/e2e/create-token-602.spec.ts) — default **1280×720**; heading, More menu, free CTA vs pay card. Does not measure column width or fold. - Invariants: [`docs/frontend.md`](docs/frontend.md) § Create Token (**C593-1–C593-14**, **C604**, **C605**). No desktop density rule yet. - Playbook: [`skills/AGENTS_FRONTEND_CREATE_TOKEN.md`](skills/AGENTS_FRONTEND_CREATE_TOKEN.md). - QA: [`QA_TEMPLATE.md`](QA_TEMPLATE.md) has Create Pair mobile (**11.1.5**) but **no** Create Token desktop-width row. --- ## Why this is needed Create Token is the retail path to instantiate a community tax token (free 0-SKU or paid SKUs). On desktop the first screen should show **identity + tax + wallets + the Paid features list** without scrolling past a 520px chimney. Users cannot see SKU cost (`N × 50 UST1`) or the ack / CTA until they scroll — that is how people miss Minting (create-only) or enable the wrong SKU. This is not “users should zoom out.” The shell already budgets 1080px. The page must use a **responsive multi-column layout at `md`/`lg`** and keep a **single column on phone** so 375 / 390 stay usable (same class of work as [#651](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/651) for `/tiers`, opposite breakpoint). --- ## Constraints / guardrails 1. **Layout only.** Do not change launcher `CreateToken` / UST1 `Receive` hooks, invoice payee, SKU prices, or `buildValidatedCreateArgs` / `buildCreateTokenHook` field semantics (**C593-3**, **C593-4**, **C593-10**, **C593-12**). 2. **Identity + wallets stay C604.** Name/symbol `^[A-Za-z0-9]+$`; decimals 6–18; treasury/manager autofill connected wallet when empty; never clobber a typed address; ignore `?manager=` / `?treasury=` / `?payee=`. Helper copy remains exactly `connected wallet` / `not connected wallet`. 3. **SKU init stays C605.** Checkbox on reveals fields; uncheck hides and **drops those keys** from the hook. Percent taxes stay 2 dp; combined cap **25.00%**; `max_*` combined ≤ 25.00% (**C593-13**). AutoLP still blocks when `autolp_code_id` is unset. 4. **One chrome layer (#653).** Keep a **single** `shell-panel-strong` (or sibling panels, not nested). Do **not** wrap SKU tiles in a grid of `card-glass` / default `StatBox`. Hairline dividers / CSS grid only. 5. **Copy (#489).** Do not add a screenspace essay or “use two columns on desktop” banner. Lead sentence + **Migrate here** stay. Labels ≤ ~5 words. 6. **Design system (#488).** `input-glass` / `label-glass` / `btn-primary`. No `*-neo`. Light + dark. 7. **Phone / tablet.** ≤767px stays **one column**; no horizontal page scroll at 320 / 375 / 390. Bech32 treasury/manager must wrap or `break-all`, not overflow the card. Buy/sell 2-col may stay if both fields remain ≥44px tap-wide; otherwise stack. 8. **Ack + CTA visible.** Risk ack stays required. Do not hide ack behind a collapsed `<details>` that defaults closed. Free CTA / Pay card must remain in tab order after the form. 9. **Testids stable.** Keep `create-token-page`, `create-token-name`, `create-token-symbol`, `create-token-decimals`, `create-token-buy-pct`, `create-token-sell-pct`, `create-token-treasury`, `create-token-manager`, `create-token-sku-*`, `create-token-ack`, `create-token-free-cta`, `create-token-pay`, helpers. Add layout testids only (`create-token-desktop-grid` or similar). 10. **Do not widen Swap / Create Pair** to match. Those stay ticket-width. Do not implement Manage / Migrate density here. 11. **No `e2e-tx`.** Playwright workers stay **5** for smoke. On-chain create stays existing community-tax tx specs. 12. **Create Token stays code-id-free** on the card (**M628-7**). Do not print 11619 / 8654 / allowlist essays. --- ## Relevant files **Primary** - `frontend-dapp/src/pages/CreateTokenPage.tsx` — `max-w-[520px]` + stacked labels - `frontend-dapp/src/pages/CreateTokenPage.test.tsx` — extend with layout / grid contract - `frontend-dapp/e2e/create-token-602.spec.ts` — desktop width + phone non-regression - `frontend-dapp/src/index.css` — only if a shared form-grid utility is added (prefer Tailwind on the page) **Read, do not fork** - `frontend-dapp/src/utils/communityTaxCreateForm.ts` / `communityTaxIdentity.ts` / `communityTaxInvoice.ts` / `communityTaxSku.ts` - `frontend-dapp/src/components/payments/PayWithAnyToken.tsx` - `docs/frontend.md` § Create Token - `skills/AGENTS_FRONTEND_CREATE_TOKEN.md` - `skills/AGENTS_FRONTEND_CHROME_NESTING.md` / `skills/AGENTS_FRONTEND_DESIGN_SYSTEM.md` / `skills/AGENTS_FRONTEND_COPY_COGNITIVE_LOAD.md` - `QA_TEMPLATE.md` § 11 (add a Create Token desktop + phone row) **Out of scope siblings** - `frontend-dapp/src/pages/ManageTokenPage.tsx` (`max-w-[640px]`) - `frontend-dapp/src/pages/MigrateTokenPage.tsx` (`max-w-[520px]`) - `frontend-dapp/src/pages/CreatePairPage.tsx` (keep ticket width) --- ## Recommended direction Ship **one** responsive layout on `CreateTokenPage`. Bundle (do not split into extra issues): (1) raise the desktop max-width, (2) pair short fields, (3) SKU checkbox grid, (4) pair SKU init numeric fields, (5) phone single-column non-regression. ### A — Use the main shell on desktop At `md` (`≥768px`) or `lg` (`≥1024px`), drop `max-w-[520px]` in favor of `w-full` (the 1080px `.app-main` is the cap) or `max-w-[960px]` / `max-w-[1080px]`. Unavailable stub may stay narrow. ### B — Pair short fields (`md+`) Suggested CSS grid (single panel, no nested chrome): | Row | `md+` | `<md` | |-----|--------|--------| | Name / Symbol / Decimals | `grid-cols-3` or Name+Symbol `2fr` + Decimals `1fr` | stack | | Buy tax / Sell tax | keep `grid-cols-2` | keep or stack if tap targets shrink | | Treasury / Manager | `grid-cols-2` | stack | | Paid features | `grid-cols-2` checkbox+hint cells | stack | | Variable rates max % | `grid-cols-3` | stack | | Launch guards max wallet / cooldown | `grid-cols-2` | stack | | AutoLP threshold / recipient | `grid-cols-2` | stack | | Split sinks | keep existing 3-col row; wrap on phone | | Ack + CTA / Pay | full-width bottom of the same panel | Prefer **one** `md:grid` wrapper (`data-testid="create-token-desktop-grid"`) with identity+tax+wallets in column 1 and Paid features + init + CTA in column 2 **only if** both columns stay in one `shell-panel-strong` and tab order stays Name → … → SKUs → ack → CTA. A single-column-but-wider card with paired rows is also OK if Paid features + CTA enter the first viewport at 1280×720 with 0 SKUs. ### C — First-viewport bar At **1280×720**, disconnected or connected, **0 SKUs**: heading, Name/Symbol/Decimals, Buy/Sell, Treasury/Manager, Paid features legend + at least the SKU list start, and ack/CTA (or a clear “scroll 1 short hop”) must not require scrolling past an empty 520px chimney. With several SKUs checked, init panels may extend — that is expected; do not virtualize / hide them. ### D — Out of scope - Changing 50 UST1 SKU price, launcher address, or free-create execute. - Manage / Migrate / Create Pair width. - Sticky header CTA that covers the wallet chip or More menu. - New wizard steps that split create across routes. --- ## Acceptance criteria - [ ] **Desktop 1280×720 and 1440×900:** `create-token-page` content width is **> 700px** (not still 520). Empty left/right main gutters shrink; the form uses the `.app-main` budget. - [ ] **Desktop `md+`:** Name+Symbol (and Decimals) share a row; Treasury+Manager share a row; Paid features is a 2-col checkbox grid (or equivalent density). Buy/Sell stay paired. - [ ] **1280×720, 0 SKUs:** Paid features legend and the ack control are reachable without a long empty-margin scroll; CTA or connect prompt is in the first two viewports. - [ ] **Phone 375×667 and 390×844:** single column; no horizontal `document` scroll; treasury/manager bech32 does not overflow; tap targets ≥44px; existing P7/P8/P9 helpers still read `connected wallet` / `not connected wallet`. - [ ] **SKU toggle:** checking each of the 7 SKUs still reveals the matching panel; uncheck drops fields from the hook (invoice 0 / 50 / 150 still holds). - [ ] **C593 / C604 / C605 unchanged:** env unavailable stub; ignore query payee/manager/treasury; percent 2 dp + 25% cap errors still show; free CTA vs PayWithAnyToken launcher payee unchanged. - [ ] Light + dark. No nested `shell-panel` / SKU `card-glass` grid. No `*-neo`. No new lecture banner. - [ ] Docs: `docs/frontend.md` § Create Token notes desktop density + phone stack. `QA_TEMPLATE.md` gains a Create Token desktop/phone row. Skill playbook points at this issue. - [ ] Existing `CreateTokenPage.test.tsx` + `make verify-issue-593` / `604` / `605` stay green. --- ## Test plan (all paths) ### Unit (`CreateTokenPage.test.tsx`) Keep existing cases. Add: 1. **Desktop grid contract:** with `matchMedia('(min-width: 768px)')` (or the breakpoint the page uses), root or `create-token-desktop-grid` has the documented `md:grid` / `max-w` class (not `max-w-[520px]` alone). 2. **Phone contract:** `max-width: 767px` — no `md:grid-cols-2` applied as the only layout; fields still in DOM order Name → Symbol → Decimals → buy → sell → treasury → manager → SKUs → ack. 3. **Unavailable stub** still renders `create-token-unavailable` when env is off (width may stay narrow). 4. **SKU panels:** toggle each `create-token-sku-*`; assert the matching `*-panel` / mint cap appears and disappears; invoice text 0 → 50 → 150 unchanged. 5. **Query ignore:** render with `?payee=` / `?manager=` / `?treasury=` (existing Pay tests already cover spoof payee on the pay card). Helpers still follow the **connected** wallet, not the query. 6. **Validation still blocks CTA:** name with space; decimals `5`; combined tax `20` + `20`. 7. **P7–P9** wallet helpers after reflow (same strings). ### Vitest (must stay green) ```text cd frontend-dapp && npm test -- --run \ src/pages/CreateTokenPage.test.tsx \ src/utils/communityTaxCreateForm.test.ts ``` Plus `make verify-issue-593` `make verify-issue-604` `make verify-issue-605` (do not reopen those issues unless an invariant actually broke). ### Playwright (`e2e-smoke`, 5 workers) Extend [`e2e/create-token-602.spec.ts`](frontend-dapp/e2e/create-token-602.spec.ts) (or a sibling smoke spec — **not** `e2e-tx`): 1. **1280×720** (existing): heading, no unavailable stub, More → Create Token. 2. **New desktop geometry:** `setViewportSize({ width: 1280, height: 720 })`. - `create-token-page` `getBoundingClientRect().width` **> 700**. - Name and Symbol top (`y`) within ~48px of each other **or** both in the first viewport; Treasury and Manager same-row or adjacent columns. - Paid features legend `y` < 720 (first viewport) with 0 SKUs. 3. **1440×900:** same width floor; form does not stretch past `.app-main` (page width ≤ 1080 + padding). 4. **375×667 and 390×844:** - `create-token-page` width ≤ viewport − chrome; `document.scrollingElement.scrollWidth` ≤ `clientWidth` + 1. - Name `y` < Symbol `y` < Decimals `y` (stacked). - Fill a long bech32 in treasury; no horizontal page scroll. 5. **Connected** (existing `connectWallet`): free CTA still appears after name/symbol/ack; one SKU still swaps to `create-token-pay` with `50 UST1`. 6. Do **not** add `e2e-tx` here. ### Manual 1. Desktop 1280 and 1920, dark + light: screenshot first viewport — identity + tax + wallets + SKU list visible; no 520px chimney. 2. Resize 1920 → 768 → 375: columns collapse cleanly; no overlapping labels; no clipped errors. 3. Check all 7 SKUs then uncheck: panels appear/disappear; invoice count matches; free CTA returns at 0. 4. Connect / disconnect: helpers and autofill (**C604-2**). 5. Paste a different treasury: `not connected wallet`; layout does not overflow. 6. Keplr in-app / coarse pointer: checkbox + ack ≥44px. 7. Unavailable env (unset launcher): stub still centered and readable. --- ## Test plan (attack, hack, and abuse) Layout sits on the **instantiate + invoice** path. Treat SKU checkboxes, addresses, and Pay as trust-boundary controls. 1. **Wrong-SKU tap.** Two-column SKU grid must not stack hit targets so checking “Minting” toggles “Launch guards”. Each `data-testid={`create-token-sku-${id}`}` `onChange` maps to that `sku.id` only. Playwright/unit: click mid-list SKU; assert only that id is in the invoice count / panel. 2. **Query payee / manager spoof (C593-10 / C604-2).** `?payee=` / `?manager=` / `?treasury=` still ignored after reflow. Paid path payee remains env launcher. Unit already in `PayWithAnyToken.test.tsx` — keep green. 3. **Hidden ack.** CSS grid / `overflow: hidden` must not clip the ack checkbox or show a enabled CTA without `create-token-ack`. CTA stays `disabled` until `formOk && ack`. 4. **Invoice amount vs visible SKUs.** Reorder must not show “SKU invoice: 50” while two boxes are checked. `create-token-sku-total` stays `skus.length × 50`. 5. **XSS.** Name/symbol/hints/errors render as text. No `dangerouslySetInnerHTML` on user or LCD strings. Exempt textarea stays a text control. 6. **Address overflow / clickjack.** Long bech32 must not paint over the header CONNECT / More (`z-index`). New grid `z-index` stays below Connect / Legal / WalletConnect (`z-[9999]`). 7. **Disabled CTA remount.** Reflow at the `md` breakpoint must not remount a fresh enabled free-CTA or Pay card mid-broadcast (`freeCreate.isPending` / pay pending still disables). 8. **Uncheck paid payload leak (C605-2 / C593-12).** After unchecking a SKU, hook builders must omit that payload (existing create-form tests). Layout must not leave a hidden filled input that still serializes. 9. **Combined cap bypass via split columns.** Buy 20% + Sell 20% still errors `combined`; max_* three-up grid still enforces 25.00% combined. 10. **Phone zoom / 200% text.** Card grows vertically; fields do not overlap the next checkbox. No `overflow: hidden` that clips validation (`create-token-error-*`, decimals error). 11. **Focus order.** Tab order stays visual order (no `tabindex` tricks that skip ack). Keyboard `#488` `:focus-visible` on inputs/checkboxes/CTA. --- ## Verification criteria Done when: 1. Manual desktop 1280 + 1440: form wider than 700px; paired rows; Paid features in the first viewport at 0 SKUs; light + dark. 2. Manual phone 375 / 390: stacked; no horizontal scroll; helpers + SKU toggle still correct. 3. `CreateTokenPage.test.tsx` covers grid contract + existing P2/P4/P7–P9/SKU math. 4. Playwright 1280 width floor + 375/390 no `scrollWidth` overflow; existing #602 smoke green. No `e2e-tx` required. 5. `make verify-issue-593` `make verify-issue-604` `make verify-issue-605` green. `python3 scripts/check_chrome_nesting.py` clean if markup gained `card-glass`. 6. `docs/frontend.md` + `QA_TEMPLATE.md` + create-token skill updated. No new on-chain / indexer surface. ```bash # after implementation bash scripts/with-node.sh --cwd frontend-dapp -- npm test -- --run src/pages/CreateTokenPage.test.tsx make verify-issue-593 make verify-issue-604 make verify-issue-605 python3 scripts/check_chrome_nesting.py make lint-frontend # e2e-smoke (5 workers): frontend-dapp/e2e/create-token-602.spec.ts ```
PlasticDigits commented 2026-08-26 04:19:23 +00:00 (Migrated from gitlab.com)

marked as related to #593

marked as related to #593
PlasticDigits commented 2026-08-26 04:19:24 +00:00 (Migrated from gitlab.com)

marked as related to #604

marked as related to #604
PlasticDigits commented 2026-08-26 04:19:25 +00:00 (Migrated from gitlab.com)

marked as related to #605

marked as related to #605
PlasticDigits commented 2026-08-26 04:19:26 +00:00 (Migrated from gitlab.com)

marked as related to #653

marked as related to #653
PlasticDigits commented 2026-08-26 04:20:45 +00:00 (Migrated from gitlab.com)

mentioned in issue #670

mentioned in issue #670
PlasticDigits commented 2026-08-26 06:56:51 +00:00 (Migrated from gitlab.com)

mentioned in commit e4f808bd90

mentioned in commit e4f808bd908bc547a1f990d5c375073629e86044
PlasticDigits commented 2026-08-26 06:59:02 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1159

mentioned in merge request !1159
PlasticDigits commented 2026-08-26 08:12:29 +00:00 (Migrated from gitlab.com)

mentioned in commit 3c07848a04

mentioned in commit 3c07848a04a2c32f9693626cf5dc46b37c908024
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-08-26 08:12:31 +00:00
PlasticDigits commented 2026-08-26 09:30:53 +00:00 (Migrated from gitlab.com)

Merged to main via !1159.

Leftover: Create Token desktop uses app-main width after frontend rebuild. make verify-issue-669.

Merged to `main` via !1159. Leftover: Create Token desktop uses `app-main` width after frontend rebuild. `make verify-issue-669`.
PlasticDigits commented 2026-08-26 09:31:34 +00:00 (Migrated from gitlab.com)

mentioned in issue #673

mentioned in issue #673
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic#669
No description provided.