Frontend: full custom cursor coverage across the dapp #60

Closed
opened 2026-04-24 06:29:21 +00:00 by PlasticDigits · 3 comments
PlasticDigits commented 2026-04-24 06:29:21 +00:00 (Migrated from gitlab.com)

Summary

Extend the issue #45 cursor pack so the dapp uses on-brand custom cursors consistently for every interaction class (idle pointer, loading, disabled/cancel, external links, text fields, etc.). Today only a subset of surfaces use image cursors; most rules still use the OS pointer, default, wait, and not-allowed.

Prior art / wiring: frontend/src/index.css (search for cursor: and .cursor-). Catalog: frontend/public/art/README.md § cursors. Backlog slots: docs/frontend/missing-art-assets.md § Cursor pack.

Constraints: Browsers reject cursor images >128px; always provide a CSS fallback (e.g. pointer, not-allowed, wait). Image cursors may be dropped on mobile / restricted contexts — document expected fallback behavior.


Cursor roles × assets

Use ✅ = file exists in repo; ❌ = not in repo (needs generation).

Role Typical CSS cursor Repo asset (under frontend/public/art/cursors/) Status
Primary CTA / high-priority click pointer (+ custom) primary-cta.png ✅
Danger / PvP / high-stakes surface crosshair (+ custom) danger-pvp.png ✅
Slider / drag thumb / range grab / grabbing (+ custom) slider-grab.png ✅
Default idle (whole app chrome) default (+ custom) default-pointer.png (intended path per missing-art-assets.md) ❌ needs generation
Generic clickable (links, secondary buttons, cards) pointer (+ custom) Decision: either reuse primary-cta.png or ship a quieter link-pointer.png variant ❌ needs generation if separate from primary CTA
Disabled / not allowed not-allowed (+ custom) disabled.png (intended path per missing-art doc) ❌ needs generation
Loading / busy / awaiting tx wait or progress (+ custom) loading.png (or spec animated cursor if feasible; otherwise static + motion in UI only) ❌ needs generation
Cancel / dismiss / “no” (modals, destructive cancel) not-allowed or pointer (+ custom) cancel.png (distinct from disabled; e.g. “back out” glyph) ❌ needs generation
Opens wallet / leaves dapp pointer (+ custom) external-link.png (intended path per missing-art doc) ❌ needs generation
Text caret (inputs, textareas) text (+ custom) text-caret.png (optional; may keep native I-beam) ❌ needs generation (optional)
Copy (addresses, read-only copy fields) copy (+ custom) copy.png ❌ needs generation
Help / hints (? tooltips) help (+ custom) help.png ❌ needs generation (optional)
Column / row resize (if any split panes) col-resize / row-resize resize-col.png / resize-row.png ❌ needs generation (only if UI uses resize)
Zoom (maps/charts if added) zoom-in / zoom-out zoom-in.png / zoom-out.png ❌ needs generation (only if UI uses zoom)

Generation workflow: add prompts → scripts/replicate-art/ → QA under frontend/public/art/pending_manual_review/ → promote to cursors/ and update frontend/public/art/README.md hotspots in lock-step with frontend/src/index.css.


Implementation notes (for the MR that closes this)

  • Replace scattered cursor: pointer / default / wait / not-allowed with utility classes or tokenized rules (same pattern as .cursor-primary-cta, .cursor-danger-pvp, .cursor-slider-grab).
  • Apply body / root layout idle cursor once default asset exists.
  • Ensure RainbowKit / wallet modal surfaces inherit or explicitly set cursors where overlays capture events.
  • Respect prefers-reduced-motion: if loading uses animation, provide a static fallback cursor.

Verification checklist (manual QA)

Complete on desktop Chromium and desktop Firefox (where image cursors are supported). Spot-check one mobile browser and confirm graceful fallback to native cursors.

  • Idle: Move mouse over non-interactive page background — custom default (or documented native fallback).
  • Primary CTA: Home + TimeCurve “Buy” / priority primary buttons — primary-cta.png.
  • Secondary / links: Nav links, footer links, in-app anchors — pointer variant visible (or documented reuse of primary).
  • External: “Open in new tab” / Telegram / X / docs badges — external-link.png once shipped.
  • Disabled: Disabled primary buttons, gated controls — disabled.png (or not-allowed + asset).
  • Loading / wait: Route fallback, indexer loading, tx-pending buttons — wait/progress + custom asset.
  • Cancel / dismiss: Modal close, “Cancel” on dialogs — cancel asset visible.
  • Danger / PvP: WarBow / steal / danger card hover — danger-pvp.png.
  • Slider / range: TimeCurve CHARM slider thumb — slider-grab.png (hover + active).
  • Native range inputs: Global input[type="range"] styling — grab cursor.
  • Text fields: At least one text + number + search + textarea — custom text caret or intentional native.
  • Copy affordance: Any copy-to-clipboard control — copy cursor if implemented.
  • Wallet overlay: Connect / account / network switch flows — cursor consistent with rest of app.
  • No cursor “flashing”: Rapid moves between nested interactive elements do not flicker wrong cursor.
  • Hotspot sanity: Click targets align with visible tip of each cursor (no systematic offset).

## Summary Extend the **issue #45** cursor pack so the dapp uses **on-brand custom cursors consistently** for every interaction class (idle pointer, loading, disabled/cancel, external links, text fields, etc.). Today only a subset of surfaces use image cursors; most rules still use the OS `pointer`, `default`, `wait`, and `not-allowed`. **Prior art / wiring:** [`frontend/src/index.css`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/src/index.css) (search for `cursor:` and `.cursor-`). **Catalog:** [`frontend/public/art/README.md` § cursors](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/public/art/README.md). **Backlog slots:** [`docs/frontend/missing-art-assets.md` § Cursor pack](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/docs/frontend/missing-art-assets.md). **Constraints:** Browsers reject cursor images **>128px**; always provide a CSS fallback (e.g. `pointer`, `not-allowed`, `wait`). Image cursors may be dropped on **mobile / restricted contexts** — document expected fallback behavior. --- ## Cursor roles × assets Use **✅** = file exists in repo; **❌** = not in repo (**needs generation**). | Role | Typical CSS `cursor` | Repo asset (under `frontend/public/art/cursors/`) | Status | |------|----------------------|---------------------------------------------------|--------| | Primary CTA / high-priority click | `pointer` (+ custom) | [`primary-cta.png`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/public/art/cursors/primary-cta.png) | ✅ | | Danger / PvP / high-stakes surface | `crosshair` (+ custom) | [`danger-pvp.png`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/public/art/cursors/danger-pvp.png) | ✅ | | Slider / drag thumb / range | `grab` / `grabbing` (+ custom) | [`slider-grab.png`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/public/art/cursors/slider-grab.png) | ✅ | | Default idle (whole app chrome) | `default` (+ custom) | `default-pointer.png` (intended path per [`missing-art-assets.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/docs/frontend/missing-art-assets.md)) | ❌ **needs generation** | | Generic clickable (links, secondary buttons, cards) | `pointer` (+ custom) | *Decision:* either reuse `primary-cta.png` or ship a quieter `link-pointer.png` variant | ❌ **needs generation** if separate from primary CTA | | Disabled / not allowed | `not-allowed` (+ custom) | `disabled.png` (intended path per missing-art doc) | ❌ **needs generation** | | Loading / busy / awaiting tx | `wait` or `progress` (+ custom) | `loading.png` (or spec **animated** cursor if feasible; otherwise static + motion in UI only) | ❌ **needs generation** | | Cancel / dismiss / “no” (modals, destructive cancel) | `not-allowed` or `pointer` (+ custom) | `cancel.png` (distinct from disabled; e.g. “back out” glyph) | ❌ **needs generation** | | Opens wallet / leaves dapp | `pointer` (+ custom) | `external-link.png` (intended path per missing-art doc) | ❌ **needs generation** | | Text caret (inputs, textareas) | `text` (+ custom) | `text-caret.png` (optional; may keep native I-beam) | ❌ **needs generation** (optional) | | Copy (addresses, read-only copy fields) | `copy` (+ custom) | `copy.png` | ❌ **needs generation** | | Help / hints (`?` tooltips) | `help` (+ custom) | `help.png` | ❌ **needs generation** (optional) | | Column / row resize (if any split panes) | `col-resize` / `row-resize` | `resize-col.png` / `resize-row.png` | ❌ **needs generation** (only if UI uses resize) | | Zoom (maps/charts if added) | `zoom-in` / `zoom-out` | `zoom-in.png` / `zoom-out.png` | ❌ **needs generation** (only if UI uses zoom) | **Generation workflow:** add prompts → `scripts/replicate-art/` → QA under `frontend/public/art/pending_manual_review/` → promote to `cursors/` and update [`frontend/public/art/README.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/public/art/README.md) hotspots in lock-step with [`frontend/src/index.css`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/src/index.css). --- ## Implementation notes (for the MR that closes this) - Replace scattered `cursor: pointer` / `default` / `wait` / `not-allowed` with **utility classes** or **tokenized rules** (same pattern as `.cursor-primary-cta`, `.cursor-danger-pvp`, `.cursor-slider-grab`). - Apply **`body`** / root layout idle cursor once default asset exists. - Ensure **RainbowKit / wallet modal** surfaces inherit or explicitly set cursors where overlays capture events. - Respect **`prefers-reduced-motion`**: if loading uses animation, provide a static fallback cursor. --- ## Verification checklist (manual QA) Complete on **desktop Chromium** and **desktop Firefox** (where image cursors are supported). Spot-check **one mobile browser** and confirm **graceful fallback** to native cursors. - [ ] **Idle:** Move mouse over non-interactive page background — custom default (or documented native fallback). - [ ] **Primary CTA:** Home + TimeCurve “Buy” / priority primary buttons — `primary-cta.png`. - [ ] **Secondary / links:** Nav links, footer links, in-app anchors — pointer variant visible (or documented reuse of primary). - [ ] **External:** “Open in new tab” / Telegram / X / docs badges — `external-link.png` once shipped. - [ ] **Disabled:** Disabled primary buttons, gated controls — `disabled.png` (or `not-allowed` + asset). - [ ] **Loading / wait:** Route fallback, indexer loading, tx-pending buttons — `wait`/`progress` + custom asset. - [ ] **Cancel / dismiss:** Modal close, “Cancel” on dialogs — cancel asset visible. - [ ] **Danger / PvP:** WarBow / steal / danger card hover — `danger-pvp.png`. - [ ] **Slider / range:** TimeCurve CHARM slider thumb — `slider-grab.png` (hover + active). - [ ] **Native range inputs:** Global `input[type="range"]` styling — grab cursor. - [ ] **Text fields:** At least one text + number + search + textarea — custom text caret or intentional native. - [ ] **Copy affordance:** Any copy-to-clipboard control — copy cursor if implemented. - [ ] **Wallet overlay:** Connect / account / network switch flows — cursor consistent with rest of app. - [ ] **No cursor “flashing”:** Rapid moves between nested interactive elements do not flicker wrong cursor. - [ ] **Hotspot sanity:** Click targets align with visible tip of each cursor (no systematic offset). --- ## Related - [Issue #44 — design pass](https://gitlab.com/PlasticDigits/yieldomega/-/issues/44) (context for integration) - [Issue #45 — raster / cursor pack](https://gitlab.com/PlasticDigits/yieldomega/-/issues/45)
PlasticDigits commented 2026-04-24 13:00:31 +00:00 (Migrated from gitlab.com)

mentioned in commit ff86bacf12

mentioned in commit ff86bacf1247c3f8cf284d512a0cec9db1c5cc3a
PlasticDigits commented 2026-04-24 13:01:31 +00:00 (Migrated from gitlab.com)

Shipped on main as ff86bac.

Cursors added (frontend/public/art/cursors/): link-pointer.png, loading.png, cancel.png, copy.png, help.png — initial pixels are tight Pillow resizes from existing icons; run scripts/replicate-art/issue60_batch.py with REPLICATE_API_TOKEN to refresh via gpt-image-2 (see issue60/prompts.json).

Wiring (frontend/src/index.css): link cursor on nav/brand, secondary buttons, wallet actions, footer in-app links, accordions, TimeCurve advanced summary, live-buy rows, modal “more”, deadline refresh; external cursor on target=_blank footer pills; loading cursor on .loading-state, busy indexer deadline strip, disabled modal load-more; cancel on modal close; utilities .cursor-link, .cursor-loading, .cursor-cancel, .cursor-copy, .cursor-help; RainbowKit [data-rk] buttons. TxHash outbound anchors use cursor-external-link; referral copy button uses cursor-copy. Reduced-motion disables float on loading mascot image only (static cursor).

Verification: npm run test -- --run and npm run typecheck (frontend) passed in the worktree before merge.

Work was done in git worktree yieldomega-worktrees/issue-60 on issue/60-cursor-pack, then fast-forwarded to main.

Shipped on `main` as **ff86bac**. **Cursors added** (`frontend/public/art/cursors/`): `link-pointer.png`, `loading.png`, `cancel.png`, `copy.png`, `help.png` — initial pixels are tight Pillow resizes from existing icons; run `scripts/replicate-art/issue60_batch.py` with `REPLICATE_API_TOKEN` to refresh via gpt-image-2 (see `issue60/prompts.json`). **Wiring** (`frontend/src/index.css`): link cursor on nav/brand, secondary buttons, wallet actions, footer in-app links, accordions, TimeCurve advanced summary, live-buy rows, modal “more”, deadline refresh; external cursor on `target=_blank` footer pills; loading cursor on `.loading-state`, busy indexer deadline strip, disabled modal load-more; cancel on modal close; utilities `.cursor-link`, `.cursor-loading`, `.cursor-cancel`, `.cursor-copy`, `.cursor-help`; RainbowKit `[data-rk]` buttons. `TxHash` outbound anchors use `cursor-external-link`; referral copy button uses `cursor-copy`. Reduced-motion disables float on loading mascot image only (static cursor). **Verification:** `npm run test -- --run` and `npm run typecheck` (frontend) passed in the worktree before merge. Work was done in git worktree `yieldomega-worktrees/issue-60` on `issue/60-cursor-pack`, then fast-forwarded to `main`.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-04-24 13:01:38 +00:00
PlasticDigits commented 2026-04-27 04:36:04 +00:00 (Migrated from gitlab.com)

mentioned in commit b63789f616

mentioned in commit b63789f61620e8bb5b700c256fff8a980a8e5c92
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/yieldomega#60
No description provided.