From d9f890696588b56ef181e361c8435b1313cabad5 Mon Sep 17 00:00:00 2001 From: Katherine Jensen Date: Fri, 17 Jul 2026 10:41:33 -0700 Subject: [PATCH 1/3] fix(PT-4157): inline resource name keeps its ellipsis in narrow panes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The verse-row inline name used a fixed-width, non-shrinking label (max-w-24 shrink-0). In a verse pane narrower than the 96px cap, the label overflowed the pane and its truncation ellipsis was pushed off-screen, so a clipped name showed a hard cut with no "…" (per Tom's review of #2541). Switch shrink-0 -> min-w-0 so the label still caps at max-w-24 when there is room but shrinks to the visible width when the pane is narrow, keeping the ellipsis at the visible edge. Add a narrow-pane Storybook story as a visual/Chromatic guard (grid cell layout is not measurable in jsdom), plus an optional `width` prop on the local CellBox story helper to drive it. Re-applied onto current main after the ScriptureTextGrid zoom/drag-handle rewrite; the fix lands in the (unchanged) inline verse-row branch. Co-authored-by: Claude Opus 4.8 (1M context) --- .../resource-cell-view.component.stories.tsx | 28 +++++++++++++++++-- .../resource-cell-view.component.tsx | 8 +++--- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.stories.tsx b/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.stories.tsx index 7ea8e874634..f73aa0b5dc7 100644 --- a/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.stories.tsx +++ b/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.stories.tsx @@ -57,9 +57,12 @@ function CellRowBox({ children }: { children: React.ReactNode }) { return
{children}
; } -/** Wraps one cell in a bounded column (preserves single-cell stories). */ -function CellBox({ children }: { children: React.ReactNode }) { - return
{children}
; +/** + * Wraps one cell in a bounded column (preserves single-cell stories). `width` overrides the default + * column width for stories that need a narrower pane. + */ +function CellBox({ children, width }: { children: React.ReactNode; width?: string }) { + return
{children}
; } /** Stand-in for the read-only `Editorial` the connected cell supplies once the chapter is ready. */ @@ -320,6 +323,25 @@ export const VerseLongName: Story = { ), }; +/** + * Verse mode, long name in a pane narrower than the label's width cap — the inline name must still + * show its truncation "…" at the visible edge (not a hard cut); hover reveals the full name. + */ +export const VerseLongNameNarrowPane: Story = { + render: () => ( + + } + /> + + ), +}; + /** Verse mode, RTL long name — truncates on the inline-start (right) side; tooltip reveals it. */ export const VerseLongNameRightToLeft: Story = { render: () => ( diff --git a/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.tsx b/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.tsx index 47168bb25af..a448580adb7 100644 --- a/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.tsx +++ b/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.tsx @@ -287,11 +287,11 @@ export function ResourceCellView({ {nameDisplay === 'inline' ? ( // Verse-row cell: hang the name at the inline-start beside the verse text. `dir` on the row // makes flex place the name on the resource's own inline-start (right in RTL). The name is a - // shrink-0, width-capped column; the verse text flows and scrolls in the remaining min-w-0 - // column, so the hanging name stays pinned even when the verse overflows. Only the verse - // text scales with zoom; the hanging name keeps a fixed size (as in header mode). + // width-capped column (max-w-24) that can shrink (min-w-0, not shrink-0) so its truncation + // "…" stays at the visible edge in a narrow pane; the verse text flows and scrolls in the + // remaining min-w-0 column. Only the verse text scales with zoom; the hanging name is fixed.
- +
{stateContent}
From f58dfe09910953cafc60eef1108cfc98ea2b05d2 Mon Sep 17 00:00:00 2001 From: Katherine Jensen Date: Fri, 17 Jul 2026 10:55:10 -0700 Subject: [PATCH 2/3] =?UTF-8?q?refactor(PT-4157):=20address=20#2557=20revi?= =?UTF-8?q?ew=20=E2=80=94=20alphabetize=20cell=20strings,=20drop=20"offlin?= =?UTF-8?q?e"=20wording?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fold in the cleanup from Tom's review of #2557, adapted to the current ScriptureTextGrid file shapes: - Alphabetize the `scriptureTextGrid_cell_*` localization keys within each contiguous run (en and es kept in sync), fixing the not_installed/ unavailable and status_* ordering Tom flagged. - Replace inaccurate "offline" wording in comments with accurate terms now that a real `unavailable` state exists: "status and action labels", "unavailable placeholder", "availability wiring", "non-ready cell", and drop the stray "offline" from the ScriptureTextGrid story blurb. Kept the one legitimate causal use ("failed to download (e.g. offline)"). Co-authored-by: Claude Opus 4.8 (1M context) --- .../contributions/localizedStrings.json | 20 +++++++++---------- .../resource-cell-view.component.stories.tsx | 6 +++--- .../resource-cell-view.component.tsx | 6 +++--- .../scripture-text-grid.component.stories.tsx | 5 ++--- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/extensions/src/platform-scripture-editor/contributions/localizedStrings.json b/extensions/src/platform-scripture-editor/contributions/localizedStrings.json index 4dc94911dcf..fb1a6d24a7c 100644 --- a/extensions/src/platform-scripture-editor/contributions/localizedStrings.json +++ b/extensions/src/platform-scripture-editor/contributions/localizedStrings.json @@ -140,22 +140,22 @@ "%webView_scriptureTextGrid_title_multiple%": "Text Collection", "%webView_scriptureTextGrid_emptyState_prompt%": "No texts to display. Open {viewOptionsLabel} to choose which texts to show.", "%webView_scriptureTextGrid_cell_accessibleName%": "{resourceName}, {reference}", + "%webView_scriptureTextGrid_cell_not_installed%": "Resource not installed", "%webView_scriptureTextGrid_cell_reorderAnnouncement%": "Moved {resourceName} to position {position} of {total}", "%webView_scriptureTextGrid_cell_reorderHandle%": "Reorder {resourceName}", "%webView_scriptureTextGrid_cell_reorderHint%": "Drag or press arrow keys to reorder", - "%webView_scriptureTextGrid_cell_status_loading%": "Resource is loading…", "%webView_scriptureTextGrid_cell_status_downloading%": "Downloading…", "%webView_scriptureTextGrid_cell_status_failed%": "Download failed", + "%webView_scriptureTextGrid_cell_status_loading%": "Resource is loading…", "%webView_scriptureTextGrid_cell_unavailable%": "Resource unavailable", - "%webView_scriptureTextGrid_cell_not_installed%": "Resource not installed", "%webView_scriptureTextGrid_cell_verse_empty%": "No text for this verse", "%webView_scriptureTextGrid_aria_chapterContextClosed%": "Chapter view closed", "%webView_scriptureTextGrid_aria_chapterContextOpened%": "Chapter view opened for {resourceReference}", - "%webView_scriptureTextGrid_cell_zoomIn%": "Zoom in", - "%webView_scriptureTextGrid_cell_zoomOut%": "Zoom out", + "%webView_scriptureTextGrid_cell_copy%": "Copy", "%webView_scriptureTextGrid_cell_resetZoom%": "Reset zoom", + "%webView_scriptureTextGrid_cell_zoomIn%": "Zoom in", "%webView_scriptureTextGrid_cell_zoomOptions%": "Zoom options for {resourceName}", - "%webView_scriptureTextGrid_cell_copy%": "Copy", + "%webView_scriptureTextGrid_cell_zoomOut%": "Zoom out", "%webView_scriptureTextGrid_chapterContext_close%": "Close chapter view", "%webView_scriptureTextGrid_viewOptions_adminSharedLock%": "Shared by administrator", "%webView_scriptureTextGrid_viewOptions_chapter%": "Chapter", @@ -286,22 +286,22 @@ "%webView_scriptureTextGrid_title_multiple%": "Colección de textos", "%webView_scriptureTextGrid_emptyState_prompt%": "No hay textos para mostrar. Abra {viewOptionsLabel} para elegir qué textos mostrar.", "%webView_scriptureTextGrid_cell_accessibleName%": "{resourceName}, {reference}", + "%webView_scriptureTextGrid_cell_not_installed%": "Recurso no instalado", "%webView_scriptureTextGrid_cell_reorderAnnouncement%": "Se movió {resourceName} a la posición {position} de {total}", "%webView_scriptureTextGrid_cell_reorderHandle%": "Reordenar {resourceName}", "%webView_scriptureTextGrid_cell_reorderHint%": "Arrastre o presione las teclas de flecha para reordenar", - "%webView_scriptureTextGrid_cell_status_loading%": "El recurso se está cargando…", "%webView_scriptureTextGrid_cell_status_downloading%": "Descargando…", "%webView_scriptureTextGrid_cell_status_failed%": "Error de descarga", + "%webView_scriptureTextGrid_cell_status_loading%": "El recurso se está cargando…", "%webView_scriptureTextGrid_cell_unavailable%": "Recurso no disponible", - "%webView_scriptureTextGrid_cell_not_installed%": "Recurso no instalado", "%webView_scriptureTextGrid_cell_verse_empty%": "No hay texto para este versículo", "%webView_scriptureTextGrid_aria_chapterContextClosed%": "Vista de capítulo cerrada", "%webView_scriptureTextGrid_aria_chapterContextOpened%": "Vista de capítulo abierta mostrando {resourceReference}", - "%webView_scriptureTextGrid_cell_zoomIn%": "Acercar", - "%webView_scriptureTextGrid_cell_zoomOut%": "Alejar", + "%webView_scriptureTextGrid_cell_copy%": "Copiar", "%webView_scriptureTextGrid_cell_resetZoom%": "Restablecer zoom", + "%webView_scriptureTextGrid_cell_zoomIn%": "Acercar", "%webView_scriptureTextGrid_cell_zoomOptions%": "Opciones de zoom para {resourceName}", - "%webView_scriptureTextGrid_cell_copy%": "Copiar", + "%webView_scriptureTextGrid_cell_zoomOut%": "Alejar", "%webView_scriptureTextGrid_chapterContext_close%": "Cerrar vista de capítulo", "%webView_scriptureTextGrid_viewOptions_adminSharedLock%": "Compartido por el administrador", "%webView_scriptureTextGrid_viewOptions_chapter%": "Capítulo", diff --git a/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.stories.tsx b/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.stories.tsx index f73aa0b5dc7..8c149b1155d 100644 --- a/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.stories.tsx +++ b/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.stories.tsx @@ -272,7 +272,7 @@ export const VerseNotInstalled: Story = { ), }; -/** Verse mode, downloading — the inline name stays beside the offline placeholder + spinner. */ +/** Verse mode, downloading — the inline name stays beside the unavailable placeholder + spinner. */ export const VerseDownloading: Story = { render: () => ( @@ -360,8 +360,8 @@ export const VerseLongNameRightToLeft: Story = { /** * Partial-failure row smoke: ready, failed, unavailable, and downloading cells side by side. - * Neighbors stay independent — one offline cell does not blank its siblings. The `unavailable` cell - * shows "Resource not installed" (not "Download failed") so the two failure modes are + * Neighbors stay independent — one non-ready cell does not blank its siblings. The `unavailable` + * cell shows "Resource not installed" (not "Download failed") so the two failure modes are * distinguishable at a glance. */ export const PartialFailureRow: Story = { diff --git a/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.tsx b/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.tsx index a448580adb7..c59772088d8 100644 --- a/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.tsx +++ b/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.tsx @@ -25,7 +25,7 @@ import { import { ResourceCellState } from './resource-cell.utils'; /** - * Localization keys for the ResourceCell offline states. Import to resolve them via + * Localization keys for the ResourceCell's status and action labels. Import to resolve them via * `useLocalizedStrings` (in the app) or `getLocalizedStrings` (in Storybook). */ export const UNAVAILABLE_KEY = '%webView_scriptureTextGrid_cell_unavailable%'; @@ -177,9 +177,9 @@ function ResourceNameLabel({ label, className }: { label: string; className?: st /** * Presentational ResourceCell: renders the resource name (inline label or header band), per-cell - * text direction, and either the editor (`ready`) or the offline placeholder + * text direction, and either the editor (`ready`) or the unavailable placeholder * (`downloading`/`failed`/`unavailable`). Data-free so Storybook can drive every state; - * `ResourceCell` wraps it with the PAPI fetch/direction/offline wiring. + * `ResourceCell` wraps it with the PAPI fetch/direction/availability wiring. * * All role, focus, activation, and accessible-name concerns are handled by the parent verse * `listitem` in `ScriptureTextGrid` — this component is purely presentational. It adds only the diff --git a/extensions/src/platform-scripture-editor/src/scripture-text-grid/scripture-text-grid.component.stories.tsx b/extensions/src/platform-scripture-editor/src/scripture-text-grid/scripture-text-grid.component.stories.tsx index 91b7b3f108a..b6e7066c67c 100644 --- a/extensions/src/platform-scripture-editor/src/scripture-text-grid/scripture-text-grid.component.stories.tsx +++ b/extensions/src/platform-scripture-editor/src/scripture-text-grid/scripture-text-grid.component.stories.tsx @@ -16,9 +16,8 @@ import type { ResourceZoomController } from './use-resource-zoom.hook'; * The Scripture Text Grid row: one cell per shown resource, all synced to the active scrRef, laid * out as a horizontal row. Clicking a verse cell opens a resizable chapter-context panel beside the * row. In Storybook the connected `ResourceCell` runs against inert PAPI stubs, so every cell - * renders its "Downloading…" offline state (the real `Editorial` never mounts) — these stories - * capture the row layout, the chapter-context split, and the close button rather than live - * scripture content. + * renders its "Downloading…" state (the real `Editorial` never mounts) — these stories capture the + * row layout, the chapter-context split, and the close button rather than live scripture content. */ const meta: Meta = { title: 'Bundled Extensions/platform-scripture-editor/ScriptureTextGrid', From aae2e375368ed033e815dad9e3c066a0c99b1e82 Mon Sep 17 00:00:00 2001 From: Katherine Jensen Date: Fri, 17 Jul 2026 11:11:33 -0700 Subject: [PATCH 3/3] test(PT-4157): add RTL narrow-pane Storybook story The ellipsis fix is direction-dependent (RTL truncates on the opposite, inline-start/right edge), so guard the RTL half of the same bug with a VerseLongNameNarrowPaneRightToLeft story mirroring the LTR narrow-pane case. Co-authored-by: Claude Opus 4.8 (1M context) --- .../resource-cell-view.component.stories.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.stories.tsx b/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.stories.tsx index 8c149b1155d..84bbfcb30c9 100644 --- a/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.stories.tsx +++ b/extensions/src/platform-scripture-editor/src/scripture-text-grid/resource-cell-view.component.stories.tsx @@ -358,6 +358,25 @@ export const VerseLongNameRightToLeft: Story = { ), }; +/** + * Verse mode, RTL long name in a pane narrower than the label's width cap — the truncation "…" must + * still show at the visible inline-start (right) edge, mirroring the LTR narrow-pane case. + */ +export const VerseLongNameNarrowPaneRightToLeft: Story = { + render: () => ( + + } + /> + + ), +}; + /** * Partial-failure row smoke: ready, failed, unavailable, and downloading cells side by side. * Neighbors stay independent — one non-ready cell does not blank its siblings. The `unavailable`