Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ The merge control's **tooltip** runs its localized strings through `resolvedOrEm

## A `title` in a test assertion does not mean the code renders a `title` attribute

Every tooltip in this extension goes through the platform `Tooltip`/`TooltipContent`; none sets an HTML `title` attribute. Tests nevertheless assert `toHaveAttribute('title', …)` because the `Tooltip` stub in [\_\_mocks\_\_/platform-bible-react.tsx](__mocks__/platform-bible-react.tsx) reads its `TooltipContent` child's text and clones the trigger with that text as a `title`, which keeps the tooltip assertable without simulating hover in jsdom. The `title` **prop** some components take (the boundary button's, for one) is likewise just a prop name; it is rendered as `TooltipContent` children.
Every tooltip in this extension goes through the platform `Tooltip`/`TooltipContent`, with one documented exception: the usage counts in [src/components/CatalogRowView.tsx](src/components/CatalogRowView.tsx) sit inside the row's own button, where a tooltip trigger would nest one interactive element in another, so they carry a native `title` and repeat their label in screen-reader-only text. Outside that exception, no component sets an HTML `title` attribute. Tests nevertheless assert `toHaveAttribute('title', …)` because the `Tooltip` stub in [\_\_mocks\_\_/platform-bible-react.tsx](__mocks__/platform-bible-react.tsx) reads its `TooltipContent` child's text and clones the trigger with that text as a `title`, which keeps the tooltip assertable without simulating hover in jsdom. The `title` **prop** some components take (the boundary button's, for one) is likewise just a prop name; it is rendered as `TooltipContent` children.

So do not conclude from either signal that a control is limited to plain text — for instance, that it cannot hold a `Kbd` or any other element. Read the component's own JSX before claiming a render path is text-only.

Expand Down
14 changes: 14 additions & 0 deletions __mocks__/lucide-react.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,17 @@ export function Merge(props: Readonly<{ className?: string }>): ReactElement {
export function Split(props: Readonly<{ size?: number; className?: string }>): ReactElement {
return <svg data-testid="split-icon" {...props} />;
}

/**
* Stub for the ChevronRight icon, marking a collapsed catalog row.
*/
export function ChevronRight(props: Readonly<{ className?: string }>): ReactElement {
return <svg data-testid="chevron-right-icon" {...props} />;
}

/**
* Stub for the ChevronDown icon, marking an expanded catalog row.
*/
export function ChevronDown(props: Readonly<{ className?: string }>): ReactElement {
return <svg data-testid="chevron-down-icon" {...props} />;
}
25 changes: 25 additions & 0 deletions __mocks__/platform-bible-react.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ export const MOCK_WIPE_MENU_ITEM: MenuItemContainingCommand = {
localizeNotes: '',
};

/** Sentinel menu item passed by the mock toolbar when the analysis-catalog button is clicked. */
export const MOCK_OPEN_ANALYSIS_CATALOG_MENU_ITEM: MenuItemContainingCommand = {
label: '%interlinearizer_openAnalysisCatalog%',
command: 'interlinearizer.openAnalysisCatalog',
group: 'interlinearizer.viewActions',
order: 1,
localizeNotes: '',
};

/**
* Stub toolbar that renders project-menu and view-info buttons using sentinel menu items so tests
Expand Down Expand Up @@ -195,6 +203,15 @@ export function TabToolbar({
Wipe
</button>
)}
{onSelectProjectMenuItem && (
<button
type="button"
data-testid="tab-toolbar-analysis-catalog"
onClick={() => onSelectProjectMenuItem(MOCK_OPEN_ANALYSIS_CATALOG_MENU_ITEM)}
>
Analysis catalog
</button>
)}
{onSelectViewInfoMenuItem && (
<button
type="button"
Expand Down Expand Up @@ -327,6 +344,12 @@ export const Button = forwardRef<
'aria-controls'?: string;
'aria-hidden'?: boolean;
'data-testid'?: string;
/**
* Names the token a button acts on, so a list of buttons sharing one test id can be told apart
* by ref rather than by a visible label that may repeat. The real button spreads every unknown
* prop onto the element; this stub forwards the ones the extension sets.
*/
'data-token-ref'?: string;
}>
>(function ButtonImpl(
{
Expand All @@ -349,6 +372,7 @@ export const Button = forwardRef<
'aria-controls': ariaControls,
'aria-hidden': ariaHidden,
'data-testid': testId,
'data-token-ref': tokenRef,
},
ref,
) {
Expand All @@ -371,6 +395,7 @@ export const Button = forwardRef<
aria-controls={ariaControls}
aria-hidden={ariaHidden}
data-testid={testId}
data-token-ref={tokenRef}
disabled={disabled}
>
{children}
Expand Down
12 changes: 12 additions & 0 deletions contributions/localizedStrings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@
"%interlinearizer_saveAs%": "Save As…",
"%interlinearizer_wipe%": "Wipe…",

"%interlinearizer_menu_column_view%": "View",
"%interlinearizer_openAnalysisCatalog%": "Analysis Catalog",
"%interlinearizer_analysisCatalog_title%": "Analysis Catalog",
"%interlinearizer_analysisCatalog_close%": "Close analysis catalog",
"%interlinearizer_analysisCatalog_resize%": "Resize analysis catalog",
"%interlinearizer_analysisCatalog_empty%": "No analyses recorded yet.",
"%interlinearizer_analysisCatalog_noGloss%": "(no gloss)",
"%interlinearizer_analysisCatalog_usageCount%": "Uses in the whole draft",
"%interlinearizer_analysisCatalog_usageCountInBook%": "Uses in {book}",
"%interlinearizer_analysisCatalog_noUsages%": "Not used anywhere",
"%interlinearizer_analysisCatalog_showAllUsages%": "Show {count} more",

"%interlinearizer_projectSettings_title%": "Interlinearizer",
"%interlinearizer_projectSettings_continuousScroll%": "Continuous Scroll",
"%interlinearizer_projectSettings_continuousScrollDescription%": "Display tokens in a continuous horizontal scroll strip instead of chapter-segmented rows",
Expand Down
16 changes: 16 additions & 0 deletions contributions/menus.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
"label": "%interlinearizer_menu_column_project%",
"localizeNotes": "Interlinearizer top menu column for project actions",
"order": 1
},
"interlinearizer.view": {
"label": "%interlinearizer_menu_column_view%",
"localizeNotes": "Interlinearizer top menu column for opening views of the analysis",
"order": 2
}
},
"groups": {
Expand All @@ -35,6 +40,10 @@
"interlinearizer.draftActions": {
"column": "interlinearizer.project",
"order": 3
},
"interlinearizer.viewActions": {
"column": "interlinearizer.view",
"order": 1
}
},
"items": [
Expand Down Expand Up @@ -79,6 +88,13 @@
"group": "interlinearizer.draftActions",
"order": 1,
"command": "interlinearizer.wipe"
},
{
"label": "%interlinearizer_openAnalysisCatalog%",
"localizeNotes": "Interlinearizer top menu > Open the analysis catalog, listing every analysis recorded in the draft with its usage counts and locations",
"group": "interlinearizer.viewActions",
"order": 1,
"command": "interlinearizer.openAnalysisCatalog"
}
]
}
Expand Down
Loading