The Lookup sheet: Entry carousel, painted Surface Form, and the three nothings #12

Closed
opened 2026-08-10 09:27:08 +00:00 by aiko · 1 comment
Owner

Parent

#1

What to build

The sheet becomes the thing it was designed as, and the two halves of the screen start talking to each other.

One Entry per panel, swipe for the rest. The sheet shows a single Entry at reading size — Headword, reading, part of speech, slang and colloquial tags, Reason Chain, senses — with runners-up one swipe away and the position shown as 1/4. Same scroll-snap mechanism as the Cue strip. Ranking is right most of the time, so alternatives are an escape hatch and should not cost vertical space on every tap. The position indicator matters: without it there is no way to tell whether there is anything to swipe to.

Inset the strip from the screen edges and set overscroll-behavior-x: contain, or a rightward swipe near the left edge triggers the Android back gesture and leaves the app.

Show what matched. The Surface Form the Lookup resolved is painted in the Cue above using the CSS Custom Highlight API — a Range over the existing text node, no DOM change, no per-character spans.

Slang comes from JMdict, not a second dictionary. Its sl, col, net-sl, and vulg sense tags are rendered next to the part of speech.

A Lookup freezes the Cue strip, sharing the frozen state and catch-up control built in #10. The tapped Cue stays put while you read instead of scrolling away underneath the sheet.

Three nothings, three different answers:

  1. Tap landed on punctuation, whitespace, or latin text — ignore it entirely. No sheet, no highlight, no freeze. Nothing happened because nothing should have.
  2. Tap landed on Japanese but no Candidate survived — highlight the tapped character for about a second under a no entry label. No sheet, no freeze. A miss and a mis-tap are otherwise indistinguishable, and the highlight is what tells you where your finger actually landed.
  3. The Lookup could not run — dictionary still building, or the server did not answer — open the sheet, freeze, and say which. This is the app being wrong rather than the tap, and it should not be a flash you might miss.

Acceptance criteria

  • One Entry per panel, swipeable, with the position shown
  • Only one Candidate means the indicator says so and there is nothing to swipe to
  • A rightward swipe near the left edge does not navigate away from the app
  • The matched Surface Form is painted in the Cue without adding elements to it
  • Slang and colloquial tags from JMdict are rendered
  • Opening a Lookup freezes the Cue strip; dismissing it returns to live
  • Punctuation, whitespace, and latin taps produce no visible response at all
  • A Japanese tap with no surviving Candidate highlights that character briefly and does not freeze
  • A Lookup that cannot run opens the sheet and distinguishes building from unreachable

Blocked by

## Parent #1 ## What to build The sheet becomes the thing it was designed as, and the two halves of the screen start talking to each other. **One Entry per panel, swipe for the rest.** The sheet shows a single Entry at reading size — Headword, reading, part of speech, slang and colloquial tags, Reason Chain, senses — with runners-up one swipe away and the position shown as `1/4`. Same scroll-snap mechanism as the Cue strip. Ranking is right most of the time, so alternatives are an escape hatch and should not cost vertical space on every tap. The position indicator matters: without it there is no way to tell whether there is anything to swipe to. Inset the strip from the screen edges and set `overscroll-behavior-x: contain`, or a rightward swipe near the left edge triggers the Android back gesture and leaves the app. **Show what matched.** The Surface Form the Lookup resolved is painted in the Cue above using the CSS Custom Highlight API — a `Range` over the existing text node, no DOM change, no per-character spans. **Slang comes from JMdict**, not a second dictionary. Its `sl`, `col`, `net-sl`, and `vulg` sense tags are rendered next to the part of speech. **A Lookup freezes the Cue strip**, sharing the frozen state and catch-up control built in #10. The tapped Cue stays put while you read instead of scrolling away underneath the sheet. **Three nothings, three different answers:** 1. Tap landed on punctuation, whitespace, or latin text — ignore it entirely. No sheet, no highlight, no freeze. Nothing happened because nothing should have. 2. Tap landed on Japanese but no Candidate survived — highlight the tapped character for about a second under a `no entry` label. No sheet, no freeze. A miss and a mis-tap are otherwise indistinguishable, and the highlight is what tells you where your finger actually landed. 3. The Lookup could not run — dictionary still building, or the server did not answer — open the sheet, freeze, and say which. This is the app being wrong rather than the tap, and it should not be a flash you might miss. ## Acceptance criteria - [ ] One Entry per panel, swipeable, with the position shown - [ ] Only one Candidate means the indicator says so and there is nothing to swipe to - [ ] A rightward swipe near the left edge does not navigate away from the app - [ ] The matched Surface Form is painted in the Cue without adding elements to it - [ ] Slang and colloquial tags from JMdict are rendered - [ ] Opening a Lookup freezes the Cue strip; dismissing it returns to live - [ ] Punctuation, whitespace, and latin taps produce no visible response at all - [ ] A Japanese tap with no surviving Candidate highlights that character briefly and does not freeze - [ ] A Lookup that cannot run opens the sheet and distinguishes building from unreachable ## Blocked by - #11 - #10
Author
Owner

This was generated by AI during triage.

Merged to main in 168b131.

One Entry per panel in a scroll-snapped strip with a 1/4 position indicator, inset from the screen edges with overscroll-behavior-x: contain so a rightward swipe does not fire the Android back gesture. The matched Surface Form is painted with the CSS Custom Highlight API — a Range over the existing text node, no DOM change. JMdict's sl/col/net-sl/vulg tags render next to the part of speech.

A Lookup freezes the Cue strip through cueStrip.ts's existing state — no second notion of frozen.

The three nothings behave differently, which was the point: punctuation and latin are ignored outright; Japanese with no surviving Candidate highlights the tapped character for NO_ENTRY_HIGHLIGHT_MS with no sheet and no freeze, so a genuine miss is distinguishable from a fat-fingered mis-tap; a Lookup that could not run opens the sheet and says whether the dictionary is building or the server is silent.

34 new tests, 179 total. Reviewer caught one real bug: a Lookup in flight when the episode changes would paint a Range over a detached text node — fixed by capturing the strip at tap time.

Carried to #13, all "judge it on the phone" items: halfwidth katakana falls into the silent nothing rather than the no entry one; swiping the Cue strip while the sheet is open leaves the pre-lookup position stale so dismissing may not return to live; and the 1/4 indicator is not sticky, so a long Entry scrolls it out of view.

> *This was generated by AI during triage.* Merged to `main` in 168b131. One Entry per panel in a scroll-snapped strip with a `1/4` position indicator, inset from the screen edges with `overscroll-behavior-x: contain` so a rightward swipe does not fire the Android back gesture. The matched Surface Form is painted with the CSS Custom Highlight API — a `Range` over the existing text node, no DOM change. JMdict's `sl`/`col`/`net-sl`/`vulg` tags render next to the part of speech. A Lookup freezes the Cue strip through `cueStrip.ts`'s existing state — no second notion of frozen. The three nothings behave differently, which was the point: punctuation and latin are ignored outright; Japanese with no surviving Candidate highlights the tapped character for `NO_ENTRY_HIGHLIGHT_MS` with no sheet and no freeze, so a genuine miss is distinguishable from a fat-fingered mis-tap; a Lookup that could not run opens the sheet and says whether the dictionary is building or the server is silent. 34 new tests, 179 total. Reviewer caught one real bug: a Lookup in flight when the episode changes would paint a Range over a detached text node — fixed by capturing the strip at tap time. **Carried to #13**, all "judge it on the phone" items: halfwidth katakana falls into the silent nothing rather than the `no entry` one; swiping the Cue strip while the sheet is open leaves the pre-lookup position stale so dismissing may not return to live; and the `1/4` indicator is not sticky, so a long Entry scrolls it out of view.
aiko closed this issue 2026-08-10 10:59:38 +00:00
aiko referenced this issue from a commit 2026-08-10 12:13:58 +00:00
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
mobrule/kurageyomi#12
No description provided.