Skip to content

Link tokens#91

Open
alex-rawlings-yyc wants to merge 53 commits into
mainfrom
link-tokens
Open

Link tokens#91
alex-rawlings-yyc wants to merge 53 commits into
mainfrom
link-tokens

Conversation

@alex-rawlings-yyc

@alex-rawlings-yyc alex-rawlings-yyc commented May 29, 2026

Copy link
Copy Markdown
Contributor

This change is Reviewable

Summary by CodeRabbit

  • New Features

    • Phrase management: Create, edit, delete, and merge phrases with visual arcs connecting phrase tokens.
    • Phrase glosses: Add and edit language-specific glosses for phrases.
    • Token linking: Link and unlink adjacent word tokens with new button controls.
    • View options dropdown: New gear menu for display preferences (continuous scroll, link button visibility, phrase simplification).
    • Token-based navigation replacing phrase-index navigation.
  • Bug Fixes

    • Improved orphaned token link cleanup when editing glosses.

@alex-rawlings-yyc alex-rawlings-yyc self-assigned this May 29, 2026
@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

Adds phrase-mode and Redux phrase CRUD/selectors, new phrase hooks, arc geometry/overlays, token grouping utilities, enhanced TokenChip/TokenLinkIcon, rewrites PhraseBox/SegmentView/ContinuousView for focus-token navigation, wires Interlinearizer/Loader with phraseMode, and updates tests, config, and styles.

Changes

Phrase Editing, Arcs, and Focus-Driven Views

Layer / File(s) Summary
Phrase mode and Redux phrase operations
src/types/phrase-mode.ts, src/types/typeGuards.ts, src/store/analysisSlice.ts, src/__tests__/store/*
Adds PhraseMode, moves isWordToken, implements phrase create/update/delete/gloss and selectors with tests.
AnalysisStore phrase hooks and dispatch
src/components/AnalysisStore.tsx, src/__tests__/components/AnalysisStore.test.tsx
Exposes phrase link/gloss read hooks and CRUD/gloss dispatchers; validates onSave and provider usage.
Arc geometry, measurement hook, and split helpers
src/utils/phrase-arc.ts, src/hooks/useArcPaths.ts, src/hooks/useArcSplitHandler.ts, src/__tests__/utils/phrase-arc.test.ts, src/__tests__/hooks/useArcPaths.test.ts, src/__tests__/hooks/useArcSplitHandler.test.ts
Computes arc paths/levels/styling, measures with ResizeObserver, and provides split/preview utilities with tests.
Token grouping and render-unit utilities
src/utils/token-layout.ts, src/__tests__/utils/token-layout.test.ts
Resolves focus/slot focus, groups tokens, and builds render units with tests.
Enhanced TokenChip and new TokenLinkIcon
src/components/TokenChip.tsx, src/components/TokenLinkIcon.tsx, src/__tests__/components/TokenChip.test.tsx, src/__tests__/components/TokenLinkIcon.test.tsx, __mocks__/lucide-react.tsx
Adds disabled/remove/split-free UI, link/unlink logic and previews, and supporting icon mocks with tests.
PhraseStrip context and strip rendering
src/components/PhraseStripContext.tsx, src/components/PhraseStripParts.tsx, src/hooks/useCandidatePhraseIds.ts, src/hooks/usePhraseHoverState.ts, src/__tests__/components/PhraseStripContext.test.tsx, src/__tests__/components/PhraseStripParts.test.tsx, src/__tests__/hooks/*, src/__tests__/test-helpers.ts
Provides shared strip context, slot/group rendering, candidate ids and hover-state hooks with tests.
Arc overlay rendering and interactions
src/components/ArcOverlay.tsx, src/__tests__/components/ArcOverlay.test.tsx
Renders layered arcs with split controls; hover differentiates free vs reshape; tested interactions/styling.
PhraseBox rewrite with phrase-mode interactions
src/components/PhraseBox.tsx, src/__tests__/components/PhraseBox.test.tsx
Phrase-aware box with gloss input, edit/view/unlink behaviors, token add/remove, and extensive tests.
SegmentView phrase-aware rendering
src/components/SegmentView.tsx, src/__tests__/components/SegmentView.test.tsx
Switches to grouped phrase rendering with PhraseStrip and ArcOverlay; adds edit/hover and measurements.
ContinuousView focus-token windowed rendering
src/components/ContinuousView.tsx, src/__tests__/components/ContinuousView.test.tsx
Implements focus-token navigation, windowed groups, fade-lag, and arrow behavior with updated tests.
Interlinearizer and loader wiring
src/components/Interlinearizer.tsx, src/components/InterlinearizerLoader.tsx, src/__tests__/components/Interlinearizer*.test.tsx
Threads phraseMode and focus-token sync; adds sticky edit/unlink overlays; updates tests.
Edit/Unlink controls components
src/components/EditPhraseControls.tsx, src/components/UnlinkPhraseConfirm.tsx, src/__tests__/components/*
Adds inline Done/Cancel and unlink confirm components with interaction tests.
Config and styling updates
src/tailwind.css, jest.config.ts, jest.setup.resize-observer.js, .github/workflows/lint.yml, src/components/*Modal*.tsx
Adds shared Tailwind utilities, Jest setup/transform/coverage tweak, ResizeObserver stub, workflow tweak, and shared input styles.

Sequence Diagram(s)

sequenceDiagram
  participant UI as Interlinearizer UI
  participant Store as AnalysisStore/Redux
  participant Overlay as ArcOverlay
  participant Utils as phrase-arc utils
  UI->>Store: usePhraseLinkMap/usePhraseDispatch
  UI->>Overlay: arcPaths, candidatePhraseIds, hover/focus
  Overlay->>Utils: computeSplitFreeRefs(...)
  Overlay->>Store: splitPhraseAtBoundary via useArcSplitHandler
  Store-->>UI: updated phrase links/gloss
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested labels

🟥High

Suggested reviewers

  • imnasnainaec
  • jasonleenaylor

Poem

A rabbit taps keys in a meadow of code,
Weave arcs over phrases, a shimmering road.
Tokens form groups, then glide into view—
Click, split, or link, with a stroke’s subtle hue.
Glosses now whisper, “we’re saved!” with delight—
Hop, hop, ship it—our prose feels just right. 🐇✨

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch link-tokens

@alex-rawlings-yyc alex-rawlings-yyc linked an issue May 29, 2026 that may be closed by this pull request
…om lint git workflow (it was causing a failure)
coderabbitai[bot]

This comment was marked as outdated.

Replace the token-ref-keyed linear search (`[...map.values()].find(l => l.analysisId === id)`) with a new `selectPhraseLinkByAnalysisId` selector and `usePhraseLinkByIdMap` hook, giving O(1) phrase lookup by id in `ArcOverlay`, `useArcSplitHandler`, and `SegmentView`.

Also:
- Move the phrase-revert effect from `PhraseBox` up to `InterlinearizerInner` so it fires even when all tokens are removed from the phrase
- Fix `TokenChip` state sync to use `useEffect` instead of inline mutation during render
- Fix `useArcPaths` dep array to use a version counter instead of a spread to satisfy the rules of hooks
- Reset `phraseMode` on project switch in `InterlinearizerLoader`
- Use a stable empty map constant in `PhraseBox` to avoid breaking memo
- Improve arc key to include `phraseId` and `splitAfterTokenRef`
coderabbitai[bot]

This comment was marked as outdated.

@alex-rawlings-yyc alex-rawlings-yyc left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alex-rawlings-yyc resolved 4 discussions.
Reviewable status: 0 of 44 files reviewed, all discussions resolved (waiting on alex-rawlings-yyc).

@alex-rawlings-yyc

This comment was marked as outdated.

@coderabbitai

This comment was marked as outdated.

@alex-rawlings-yyc alex-rawlings-yyc marked this pull request as ready for review June 2, 2026 15:33
coderabbitai[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

…dow in ContinuousView, improve handling of settings in InterlinearizerLoader, add dedicated mergePhrases reducer to analysisSlice, emit data-last-token-read on all render paths
coderabbitai[bot]

This comment was marked as outdated.

@imnasnainaec imnasnainaec left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@imnasnainaec partially reviewed 5 files and all commit messages, and made 1 comment.
Reviewable status: 15 of 75 files reviewed, 1 unresolved discussion (waiting on alex-rawlings-yyc).


AGENTS.md line 72 at r8 (raw file):

All UI uses Tailwind CSS (via `src/tailwind.css`). Every Tailwind class is prefixed `tw:` to avoid collisions with Platform.Bible's own styles (configured in `tailwind.config.ts`). For modifier variants the prefix comes first: `tw:hover:px-3`, not `hover:tw-px-3`.

Tailwind v4 at-rules (`@utility`, `@apply`, `@theme`, `@config`, `@custom-variant`, `@layer`, `@source`, `@plugin`, etc.) are **already whitelisted** in [.stylelintrc.js](.stylelintrc.js)'s `scss/at-rule-no-unknown` `ignoreAtRules` list. Do **not** flag these as Stylelint violations, and do not suggest adding them to the config or adding `stylelint-disable` comments — they already pass. If you believe a lint rule is firing, run `npm run lint` and cite the actual output rather than inferring it from the rule name.

It might be more fitting for things like this to go in a new REVIEW.md file, assuming Coderabbitai looks at that.

@alex-rawlings-yyc alex-rawlings-yyc left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alex-rawlings-yyc resolved 1 discussion.
Reviewable status: 15 of 75 files reviewed, all discussions resolved (waiting on alex-rawlings-yyc and imnasnainaec).

coderabbitai[bot]

This comment was marked as outdated.

* Merge mostly redundant tests

* Update settings for VSCode to match our stylelint use

* Add JSDocs

* Fix pump() overwriting observerCallback via stub constructor

new ResizeObserver(() => {}) inside pump() was invoking the stub
constructor, replacing the stored observerCallback with a no-op on
every call after the first. Replace with a pre-declared stubObserver
plain object so pump() never touches the constructor again.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Sort cspell words

* Fix brit spelling now covered in AGENTS.md

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

@imnasnainaec imnasnainaec left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@imnasnainaec made 1 comment.
Reviewable status: 15 of 78 files reviewed, 5 unresolved discussions (waiting on alex-rawlings-yyc).


a discussion (no related file):
🐛 Linking is misaligned when out-of-segment links are hidden:
image.png
image copy 1.png

@alex-rawlings-yyc alex-rawlings-yyc left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alex-rawlings-yyc resolved 3 discussions.
Reviewable status: 15 of 78 files reviewed, 1 unresolved discussion (waiting on imnasnainaec).

@alex-rawlings-yyc

Copy link
Copy Markdown
Contributor Author
Previously, imnasnainaec (D. Ror.) wrote…

🐛 Linking is misaligned when out-of-segment links are hidden:
image.png
image copy 1.png

Would we rather the links become invisible and leave space or the gaps be closed? I'm leaning towards the gaps being closed, but it will be more work

@alex-rawlings-yyc

Copy link
Copy Markdown
Contributor Author
Previously, alex-rawlings-yyc (Alex Rawlings) wrote…

Would we rather the links become invisible and leave space or the gaps be closed? I'm leaning towards the gaps being closed, but it will be more work

Never mind, this is a redraw timing issue. Fix is simple

coderabbitai[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

@imnasnainaec imnasnainaec left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@imnasnainaec reviewed 5 files and all commit messages, and made 1 comment.
Reviewable status: 20 of 78 files reviewed, 1 unresolved discussion (waiting on alex-rawlings-yyc).


a discussion (no related file):

Previously, alex-rawlings-yyc (Alex Rawlings) wrote…

Never mind, this is a redraw timing issue. Fix is simple

The arcs still surf all over the place when "Hide out-of-segment link buttons" is toggled on and off. I think it's fine to keep the space there rather than close the gap.

@imnasnainaec imnasnainaec left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@imnasnainaec partially reviewed 24 files.
Reviewable status: 44 of 78 files reviewed, 1 unresolved discussion (waiting on alex-rawlings-yyc).

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.

Link tokens together into the same phrase

2 participants