Skip to content

feat(ui): UE polish — graded toasts, button loading, copy feedback, keyboard (v1.16) - #40

Merged
argszero merged 1 commit into
mainfrom
feat/ui-polish-ue
Aug 17, 2026
Merged

argszero merged 1 commit into
mainfrom
feat/ui-polish-ue

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

Interaction (UE) polish (rant 2026-08-17T15:50:05, section B) — final PR of the UI/UE polish wave:

  1. toast 分级 (B.8): toast(msg, type) — success / error / info styles (border + text color); all 39 call sites classified (validation failures → error, confirmations → success, informational → info).
  2. 按钮 loading 态 (B.8): new withLoading(btn, fn) helper (spinner + disable, restores after simulated feedback) applied to 充值 / 申请加额 / 部门确认 / 上架提交 buttons.
  3. 复制反馈 (B.10): API Key 复制按钮短暂变「已复制 ✓」(1.2s 恢复);降级路径显示「请 Ctrl+C」。
  4. 键盘可达 (B.9): Enter 提交(充值金额 / 加额金额·原因 / 部门名称·配额)、Esc 关闭行内卡片(topup/raise/dept)、打开时自动聚焦。

Acceptance criteria for rant 15:50:05 now all satisfied: modal→inline (PR #38), visual polish (PR #39), and interaction polish (this PR) — wave complete.

Self-verified: node --check + DOM smoke test (init path runs clean) + all $("#id") refs ↔ HTML ids cross-checked + cargo test passes.

Related Issue

(no issue — host rant driven: 2026-08-17T15:50:05)

Changes

  • toast 分级 / 按钮 loading / 复制反馈 / 键盘可达(B.8/B.9/B.10)
  • docs/user-stories.md v1.16、ui/README 交互约定同步

Tests

  • cargo test 全部通过(1 passed)
  • cargo fmt --check 通过(无 Rust 改动)
  • UI 自测:node --check + DOM 冒烟 + id 交叉校验无缺失

Checklist

  • 分支命名符合约定(feat/ui-polish-ue)
  • Commit message 使用 Conventional Commits 格式
  • 单一职责,改动最小化

…eyboard (v1.16)

rant 2026-08-17T15:50:05 (UI polish & UE, section B interaction):
- toast grading: toast(msg, type) with success/error/info styles; all 39
  call sites classified (validation errors, success confirmations, info)
- button loading state: withLoading(btn, fn) spinner + disable for topup /
  raise / dept confirm and share-form submit
- copy feedback: API Key copy button flashes copied state for 1.2s
  (fallback path shows Ctrl+C hint)
- keyboard accessibility: Enter submits topup/raise/dept inline forms;
  Esc closes topup/raise/dept cards; focus managed on open
- docs: user-stories v1.16, ui/README interaction conventions
@argszero
argszero merged commit e65caa3 into main Aug 17, 2026
1 check passed
@argszero
argszero deleted the feat/ui-polish-ue branch August 17, 2026 08:06
argszero added a commit that referenced this pull request Sep 22, 2026
…es (#290)

The forgot-password success branch called

    toast(T("forgot.done"), "ok");

reusing the API response's own status literal (`if (r.status === "ok")`, same
branch) as a toast *level*. `toast()` concatenates `type` into the element's
class with no validation:

    el.className = "toast" + (type ? " " + type : "");      // ui/js/app.js:38

and `ui/css/style.css` declares `.toast.success` / `.toast.error` /
`.toast.info` only — `.toast.ok` exists solely in the design prototype
(`docs/prototype/aitokenpool-console.html`, whose own calls use `ok`/`warn`).
So the app's only password-reset success message silently fell back to the
base `.toast` style. `#40` introduced the product vocabulary and migrated the
call sites; `8ac018b` (forgot/reset password, three days later) wrote one new
call site back in the prototype's words.

Fix: use `"success"`, the word the running app already uses for a genuine
success on the same auth card, and say why the argument is a level.

The new static gate `state_gate::every_toast_level_is_a_level_the_sheet_declares`
pins the shape with three derived rules (no hand-written rosters):
  1. every literal level at a `toast(...)` call site is in the sheet's
     `.toast.<x>` rule set minus the state classes the function body applies
     itself via `classList.add`;
  2. that vocabulary equals, both ways, the contract line in `ui/README.md`;
  3. conversely, every graded rule has a call site (no dead level).

`the_r92_rules_have_teeth` and `the_r92_rules_separate_the_variants` prove each
rule has its own tooth and declare each leg's verdict; the competitive fix
("leave the call site, add a `.toast.ok` rule") is rejected by rule 2, and the
jsdom probe rejects it too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant