Summary
The WebView UI hand-rolls a number of interactive/form elements as raw HTML
(<button>, <input>, <textarea>, <label>, custom dropdowns) even though
platform-bible-react ships equivalents. Several of these raw elements are paired
with bespoke tw: CSS utilities (pill-btn-*, modal-form-input, modal-form-label,
icon-button) that duplicate styling the platform component already provides.
Migrating to the platform components improves visual/behavioral consistency with
the host app, lets us delete duplicated CSS, and gets us themeing/a11y for free.
The extension is already partly on-platform: Button (most modals), Tooltip
family, Label/Switch, Popover, and TabToolbar. There are no raw
<select>/<option> elements and no native title= tooltips — those are
already clean. This issue covers the remaining tail.
Scope
Tier 1 — direct swaps (start here; highest value, lowest risk)
<button> → Button (map existing tw:pill-btn-* / tw:icon-button classes to variant/size):
src/components/controls/EditPhraseControls.tsx:37,46 — Done / Cancel
src/components/modals/UnlinkPhraseConfirm.tsx:45,53 — Unlink / Cancel (sibling modals already use Button)
src/components/modals/MorphemeEditor.tsx:198,209,216 — Delete / Cancel / Done
src/components/ContinuousView.tsx:969,1053, src/components/SegmentListView.tsx:376 — icon nav buttons
- Icon buttons in
PhraseBox.tsx:352,362, TokenChip.tsx:357,405,491,
TokenLinkIcon.tsx:251,320, ArcOverlay.tsx:324, SegmentListView.tsx:67,
PhraseStripParts.tsx:50 (BoundaryButton) → Button variant="ghost" + icon
<input>/<textarea>/<label> → Input/Textarea/Label (all use tw:modal-form-input / tw:modal-form-label):
src/components/modals/CreateProjectModal.tsx
src/components/modals/ProjectMetadataModal.tsx
src/components/modals/SaveAsProjectModal.tsx
Once these land, remove the now-unused pill-btn-* / modal-form-* utilities from src/tailwind.css.
Tier 2 — needs care
src/components/modals/WipeModal.tsx:64–83 — raw two-radio group → RadioGroup/RadioGroupItem.
- Content-sized gloss inputs in
PhraseBox.tsx:51, MorphemeBox.tsx:189,
TokenChip.tsx:442, SegmentFreeTranslationInput.tsx:51 → Input, only if
platform Input forwards className/style so field-sizing: content (and,
for TokenChip, the ARIA combobox wiring) survives. Verify before swapping.
Tier 3 — reimplemented platform patterns (design review, not mechanical)
src/components/controls/ViewOptionsDropdown.tsx:197–210 — raw backdrop <div>
- portaled
role="dialog" panel positioned via getBoundingClientRect →
platform Popover (already a proven dependency here). Good standalone cleanup.
src/components/SuggestionDropdown.tsx + the TokenChip.tsx combobox — portaled
role="listbox"/role="option" popup with manual positioning, active-descendant
highlighting, and keyboard nav. Platform ships ComboBox/Command/Select, but
this is a real refactor with bespoke focus/keyboard UX — evaluate fit before
committing, may warrant its own issue.
Suggested sequencing
- Tier 1: three project modals + confirm-bar buttons (
EditPhraseControls,
UnlinkPhraseConfirm), then delete the duplicated CSS utilities.
- Tier 3:
ViewOptionsDropdown → Popover.
- Tier 2 gloss inputs /
WipeModal radios, gated on a props check of platform
Input/RadioGroup.
- Split the combobox migration out if it proves nontrivial.
Out of scope / non-goals
- Test doubles under
src/__tests__/** and __mocks__/**.
- Any element whose custom behavior can't be preserved on the platform component —
keep raw and note why rather than regress UX.
Acceptance
- Raw elements in Tier 1 replaced with platform components; duplicated
tw:
utilities removed; existing tests pass (mock __mocks__/platform-bible-react.tsx
extended for any newly-used components).
- Tier 2/3 either done or explicitly deferred with rationale.
Summary
The WebView UI hand-rolls a number of interactive/form elements as raw HTML
(
<button>,<input>,<textarea>,<label>, custom dropdowns) even thoughplatform-bible-reactships equivalents. Several of these raw elements are pairedwith bespoke
tw:CSS utilities (pill-btn-*,modal-form-input,modal-form-label,icon-button) that duplicate styling the platform component already provides.Migrating to the platform components improves visual/behavioral consistency with
the host app, lets us delete duplicated CSS, and gets us themeing/a11y for free.
The extension is already partly on-platform:
Button(most modals),Tooltipfamily,
Label/Switch,Popover, andTabToolbar. There are no raw<select>/<option>elements and no nativetitle=tooltips — those arealready clean. This issue covers the remaining tail.
Scope
Tier 1 — direct swaps (start here; highest value, lowest risk)
<button>→Button(map existingtw:pill-btn-*/tw:icon-buttonclasses tovariant/size):src/components/controls/EditPhraseControls.tsx:37,46— Done / Cancelsrc/components/modals/UnlinkPhraseConfirm.tsx:45,53— Unlink / Cancel (sibling modals already useButton)src/components/modals/MorphemeEditor.tsx:198,209,216— Delete / Cancel / Donesrc/components/ContinuousView.tsx:969,1053,src/components/SegmentListView.tsx:376— icon nav buttonsPhraseBox.tsx:352,362,TokenChip.tsx:357,405,491,TokenLinkIcon.tsx:251,320,ArcOverlay.tsx:324,SegmentListView.tsx:67,PhraseStripParts.tsx:50(BoundaryButton) →Button variant="ghost"+ icon<input>/<textarea>/<label>→Input/Textarea/Label(all usetw:modal-form-input/tw:modal-form-label):src/components/modals/CreateProjectModal.tsxsrc/components/modals/ProjectMetadataModal.tsxsrc/components/modals/SaveAsProjectModal.tsxOnce these land, remove the now-unused
pill-btn-*/modal-form-*utilities fromsrc/tailwind.css.Tier 2 — needs care
src/components/modals/WipeModal.tsx:64–83— raw two-radio group →RadioGroup/RadioGroupItem.PhraseBox.tsx:51,MorphemeBox.tsx:189,TokenChip.tsx:442,SegmentFreeTranslationInput.tsx:51→Input, only ifplatform
InputforwardsclassName/stylesofield-sizing: content(and,for TokenChip, the ARIA combobox wiring) survives. Verify before swapping.
Tier 3 — reimplemented platform patterns (design review, not mechanical)
src/components/controls/ViewOptionsDropdown.tsx:197–210— raw backdrop<div>role="dialog"panel positioned viagetBoundingClientRect→platform
Popover(already a proven dependency here). Good standalone cleanup.src/components/SuggestionDropdown.tsx+ theTokenChip.tsxcombobox — portaledrole="listbox"/role="option"popup with manual positioning, active-descendanthighlighting, and keyboard nav. Platform ships
ComboBox/Command/Select, butthis is a real refactor with bespoke focus/keyboard UX — evaluate fit before
committing, may warrant its own issue.
Suggested sequencing
EditPhraseControls,UnlinkPhraseConfirm), then delete the duplicated CSS utilities.ViewOptionsDropdown→Popover.WipeModalradios, gated on a props check of platformInput/RadioGroup.Out of scope / non-goals
src/__tests__/**and__mocks__/**.keep raw and note why rather than regress UX.
Acceptance
tw:utilities removed; existing tests pass (mock
__mocks__/platform-bible-react.tsxextended for any newly-used components).