Adopt platform-bible-react components in place of raw HTML (Tier 2) - #174
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthrough
ChangesWipe scope radio-group
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Replace the hand-rolled two-radio group in WipeModal with platform RadioGroup/RadioGroupItem + Label, preserving the wipe-scope-book / wipe-scope-all test ids, the disabled-when-no-book rule, and the scope descriptions. Extend the platform-bible-react jest mock with RadioGroup/RadioGroupItem stubs. The Tier 2 content-sized gloss inputs are intentionally left raw; see the PR description for the verification that platform Input's injected form-field styling can't preserve their field-sizing/compact layout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fb30289 to
8926290
Compare
alex-rawlings-yyc
left a comment
There was a problem hiding this comment.
@alex-rawlings-yyc reviewed 2 files and all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on imnasnainaec).
Resolves Tier 2 of #165.
What & why
platform-bible-reactships equivalents for elements the WebView hand-rolled as raw HTML. Migrating to the platform components gives visual/behavioral consistency with the host app, theming, and accessibility for free. Tier 1 (#168) covered the mechanical<button>/<input>/<textarea>/<label>swaps; this PR takes the one Tier 2 item that lands cleanly and records the verification result for the rest.Changes (Tier 2)
WipeModalradio group →RadioGroup/RadioGroupItem(src/components/modals/WipeModal.tsx)The destructive-wipe dialog's two
<input type="radio">options (current book / entire draft) are now a platformRadioGroupwithRadioGroupItems, each paired with aLabel. This gets us Radix's roving-tabindex arrow-key navigation, RTL support, and proper radio a11y semantics for free. Preserved verbatim:data-testid="wipe-scope-book"/wipe-scope-all(unit tests and thewipeDrafte2e helper drive them by test id).disabled={!hasActiveBook}rule on the current-book option and the whole-draft default when no book is loaded.tw:ps-6 tw:text-muted-foreground), still aligned under the option label.onValueChangenarrows to theWipeScopeunion without a cast (the repo'sno-type-assertionrule forbidsas).Test mock — extended
__mocks__/platform-bible-react.tsxwithRadioGroup/RadioGroupItemstubs. The group shares its selected value + change handler via context; each item renders a native<input type="radio">so jest-dom'stoBeChecked/toBeDisabledmatchers anduserEvent.clickwork unchanged. All existingWipeModaltests pass without edits (6/6), and the full suite is green (1578/1578).Deferred, with rationale — the content-sized gloss inputs
The issue gates the gloss-input migration (
PhraseBox.tsx,MorphemeBox.tsx,TokenChip.tsx,SegmentFreeTranslationInput.tsx) on verifying that platformInputforwardsclassName/stylesofield-sizing: content(and TokenChip's ARIA-combobox wiring) survives. Verified — and the answer is to keep these raw:Inputdoes forwardclassName(merged viacn),style, ARIA attributes, event handlers, andref(React 19 ref-as-prop). So the forwarding itself is fine.Inputalso injects a full form-field baseline:tw:h-8(fixed 2rem height),tw:rounded-lg,tw:border tw:border-input,tw:bg-transparent,tw:px-2.5 tw:py-1,tw:text-base,tw:min-w-0,focus-visible:ring-3, etc. The gloss inputs are the opposite — borderless-ish,text-xs/text-sm,px-1-tight, centered, content-sized inline editors styled by the custom@utility gloss-input.gloss-inputis a custom utility token,tailwind-mergecan't recognize it as conflicting with the injected standard utilities, so it can't dedupe them. In particular the injectedtw:h-8sets an explicitheightthat overridesfield-sizing: content's intrinsic height — the compact inline inputs would jump to 2rem tall and break interlinear row alignment.Inputlook right would mean passing overrides to neutralize essentially all of its injected styling (h-auto,rounded,px-1,border-border,bg-background, …), which defeats the purpose of adopting it and adds fragility (futureInputrestyles would leak in). That's exactly the issue's stated non-goal: "Any element whose custom behavior can't be preserved on the platform component — keep raw and note why rather than regress UX."SegmentFreeTranslationInputis the one of the four that isn't content-sized (it's aw-fullbordered box), so it's the most migratable if the team later wants the hostInputlook there. I've left it with the group for now to avoid a lone restyle that would look inconsistent next to the raw compact gloss inputs in the same segment view.The repo's
AGENTS.mdalready documents this reserve-raw decision (Tier 1 added a "Components" note that namesfield-sizing: contentgloss inputs as the canonical keep-raw example), so no doc change is needed here.Tier 3 (
ViewOptionsDropdown→Popover; theSuggestionDropdown/TokenChipcombobox) remains out of scope for this PR, per the issue's suggested sequencing.Minor behavior note
In the old markup the entire option (title and description) was one
<label>, so clicking the description text also selected the radio. With the shadcn-idiomaticRadioGroupItem+Labelpattern (matching the platform's own RadioGroup story), the click target is the radio dot and its title label; the description span is not clickable. This mirrors the platform component's documented usage and is the only intentional UX change.Drafted by Claude Opus 5
Devin: https://app.devin.ai/review/sillsdev/interlinearizer-extension/pull/174
This change is
Summary by CodeRabbit