Skip to content

Convert Collection Selector from Modal to Route#1006

Open
TheNonPirate wants to merge 13 commits into
sillsdev:mainfrom
TheNonPirate:update/collection-as-route
Open

Convert Collection Selector from Modal to Route#1006
TheNonPirate wants to merge 13 commits into
sillsdev:mainfrom
TheNonPirate:update/collection-as-route

Conversation

@TheNonPirate

@TheNonPirate TheNonPirate commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

In preparation for #593, the collection selector was changed from a modal to a route to better match the native app. In the process, the styling was also fixed, so it fixes #1002.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added a dedicated collections layout-selection page with tabs, an apply (check) button, and back/cancel behavior.
    • Introduced a revamped collection layout modal for selecting double-pane vs verse-by-verse.
  • Bug Fixes

    • Updated navigation entry points (sidebar/content/text) to route to the new collections page instead of using the older modal flow.
  • Style

    • Improved collections list layout/spacing and expanded click targets.
    • Refreshed layout option cards with imagery and clearer emphasis.
  • Documentation

    • No user-facing documentation changes.

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cd74ce15-9604-4880-92bc-475fc9a87ccb

📥 Commits

Reviewing files that changed from the base of the PR and between b190c3e and fc2d518.

📒 Files selected for processing (2)
  • src/lib/components/CollectionModal.svelte
  • src/lib/components/LayoutOptions.svelte
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/components/LayoutOptions.svelte
  • src/lib/components/CollectionModal.svelte

📝 Walkthrough

Walkthrough

The PR migrates collections/layout selection from a modal (CollectionSelector component with ModalType.Collection) to a dedicated SvelteKit route at /collections. The old modal component and its dispatch type are removed, all entry points are updated to navigate to the new route, and the new CollectionModal component handles inline double-pane/verse-by-verse selection. Minor markup and styling updates polish CollectionList, LayoutOptions, and TabsMenu.

Changes

Collections layout selection: modal to route migration

Layer / File(s) Summary
Remove CollectionSelector modal and ModalType.Collection
src/lib/data/stores/view.ts, src/routes/+layout.svelte
Removes Collection: 'collection' from the ModalType constant/union, deletes the CollectionSelector import, state variable, old modal-dispatch switch branch, and UI markup from the root layout.
New CollectionModal component
src/lib/components/CollectionModal.svelte
Builds and filters allDocSets from scriptureConfig.bookCollections, tracks viewType (double-pane or verse-by-verse), implements handleClick to update selected layout arrays and avoid duplicates, and exports showModal to open the modal with state. Renders CollectionList filtered by layout type and blank-option visibility.
New /collections route page
src/routes/collections/+page.svelte
Creates the page with TypeScript to compute visible layout tabs, preselect doc sets from $refs.docSet, define handleOk (writes to $refs/$layout, navigates to /) and backNavigation (restores prior $selectedLayouts, navigates to /). Renders Navbar with confirmation button and TabsMenu with Single/Two/VerseByVerse tabs, icon snippets, and LayoutOptions content.
Wire CollectionModal into root layout
src/routes/+layout.svelte
Adds new ModalType.Collection dispatch case that invokes collectionModal?.showModal(...) with typed data payload, replaces the collectionSelector state with collectionModal, and instantiates the CollectionModal component.
Update LayoutOptions for modal-driven selection
src/lib/components/LayoutOptions.svelte
Imports modal utilities and eager illustrations asset map, adds font-bold to layout headers, and replaces per-collection dropdown UI with clickable items that call modal.open (passing type and showBlank parameters) for double-pane and verse-by-verse modes.
Update navigation call sites to /collections route
src/lib/components/Sidebar.svelte, src/routes/text/+page.svelte, src/routes/contents/[id]/+page.svelte
Replaces every ModalType.Collection modal-open call with goto(resolve('/collections')) in the sidebar Layout menu, text-page first-launch handler, overflow menu button, collection viewer badge, and contents-page linkLocation: 'layout' branch.
Polish CollectionList markup and TabsMenu configurability
src/lib/components/CollectionList.svelte, src/lib/components/TabsMenu.svelte
Reworks CollectionList template by adding responsive centering (max-w-screen-md mx-auto), switching item container from <a> to <div onclick>, updating layout classes, and restructuring the image wrapper. Adds optional styleType prop to TabsMenu (defaults to 'ui.selector.tabs') and updates styling expression to use the configurable prop.

Sequence Diagram

sequenceDiagram
  participant User
  participant EntryPoint as Sidebar / TextPage / ContentsPage
  participant Router as SvelteKit Router
  participant CollectionsPage as /collections Page
  participant LayoutOptions
  participant CollectionModal
  participant Stores as $refs / $layout

  User->>EntryPoint: tap Layout / Collection Selector
  EntryPoint->>Router: goto(resolve('/collections'))
  Router->>CollectionsPage: render page
  CollectionsPage->>Stores: read $refs.docSet, $selectedLayouts
  CollectionsPage->>User: show Navbar + TabsMenu (Single/Two/VerseByVerse)
  User->>CollectionsPage: select layout tab
  CollectionsPage->>LayoutOptions: render active layout options
  User->>LayoutOptions: click collection item (Two Pane / Verse By Verse)
  LayoutOptions->>CollectionModal: modal.open(type, showBlank, index)
  CollectionModal->>User: show modal with CollectionList
  User->>CollectionModal: select doc set, click item
  CollectionModal->>Stores: update $selectedLayouts[viewType]
  CollectionModal->>User: close modal
  User->>CollectionsPage: tap confirm (handleOk)
  CollectionsPage->>Stores: write selected layout + doc sets to $refs/$layout
  CollectionsPage->>Router: goto(/)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • sillsdev/appbuilder-pwa#831: Modifies CollectionList.svelte's clickable item markup and onclick handling alongside related selector components.
  • sillsdev/appbuilder-pwa#960: Directly edits src/lib/data/stores/view.ts's ModalType mapping, the same object this PR modifies by removing Collection: 'collection'.
  • sillsdev/appbuilder-pwa#963: Also modifies src/lib/data/stores/view.ts's exported ModalType constant, overlapping with this PR's modal-type refactoring.

Suggested reviewers

  • chrisvire
  • FyreByrd

🐰 A modal once ruled the layout land,
but now a route takes it by the hand.
goto('/collections') hops the way,
the selector page has come to stay!
Bold fonts and divs—a cleaner burrow,
the rabbit approves this tidy furrow. 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the primary change: converting the collection selector from a modal interface to a route-based approach.
Linked Issues check ✅ Passed The PR addresses issue #1002 by applying proper styling to CollectionList using div.layout-* classes and convertStyle utilities, fixing dark mode display issues.
Out of Scope Changes check ✅ Passed All changes are directly related to converting the collection selector from modal to route and addressing the #1002 styling issue; no unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/lib/components/CollectionModal.svelte

Oops! Something went wrong! :(

ESLint: 9.39.4

The requested operation requires ESLint to serialize configuration data,
but the configuration key "0.markup" contains a function value,
which cannot be serialized.

Please double-check your configuration for errors.

If you still have problems, please stop by https://eslint.org/chat/help to chat
with the team.

src/lib/components/LayoutOptions.svelte

Oops! Something went wrong! :(

ESLint: 9.39.4

The requested operation requires ESLint to serialize configuration data,
but the configuration key "0.markup" contains a function value,
which cannot be serialized.

Please double-check your configuration for errors.

If you still have problems, please stop by https://eslint.org/chat/help to chat
with the team.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@TheNonPirate TheNonPirate changed the title Converted Collection Selector from Modal to Route Convert Collection Selector from Modal to Route Jun 16, 2026
@TheNonPirate TheNonPirate requested a review from FyreByrd June 16, 2026 21:42

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/lib/components/CollectionList.svelte (1)

40-47: ⚡ Quick win

Consider using <button> or adding keyboard event handlers for better accessibility.

The switch from <a> to <div role="button"> with suppressed a11y_click_events_have_key_events and a11y_interactive_supports_focus warnings degrades keyboard navigation. Users relying on keyboard-only interaction may not be able to activate these collection items.

♿ Recommended fix: use a native button element
-            <div
+            <button
                 onclick={() => handleClick(d)}
                 style:background-color={selectedLayouts?.id === d.id
                     ? $themeColors['LayoutItemSelectedBackgroundColor']
                     : ''}
                 class="flex justify-between layout-item-block rounded-none"
-                role="button"
             >

If you must keep the <div>, add an onkeydown handler to support Enter/Space key activation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/components/CollectionList.svelte` around lines 40 - 47, Replace the
`<div role="button">` element with a native `<button>` element to improve
keyboard accessibility. Remove the `role="button"` attribute since native
buttons have built-in keyboard support for Enter and Space keys. Keep the
existing `onclick` handler (or convert to `on:click` for Svelte conventions). If
you must retain the `<div>`, add an `onkeydown` event handler that triggers the
`handleClick(d)` function when Enter or Space keys are pressed to support
keyboard-only users.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/components/TabsMenu.svelte`:
- Line 43: The TabsMenu component unconditionally applies the ui.selector.tabs
style at line 47, preventing it from being used with the ui.dialog style
required by the collection selector. Add a `style` prop parameter to the
TabsMenu component that allows callers to customize the styling. Modify the
styling logic where ui.selector.tabs is currently hardcoded to use this prop
value instead, with ui.selector.tabs as the default fallback when the prop is
not provided. This will enable the `/collections` page to pass ui.dialog as the
style prop when needed while maintaining backward compatibility with existing
usages.

In `@src/routes/collections/`+page.svelte:
- Around line 27-37: The `tabMenuActive` variable is hardcoded to
`Layout.Single` but the code below (showSinglePane, showSideBySide,
showVerseByVerse checks) determines which layouts are actually enabled. If
Layout.Single is disabled, this creates an invalid initial state. Instead of
hardcoding Layout.Single, initialize `tabMenuActive` by checking which layout is
actually enabled first using the boolean flags that are already being computed
(showSinglePane, showSideBySide, showVerseByVerse). Use a fallback logic to
select the first available enabled layout rather than assuming Layout.Single is
always valid.

---

Nitpick comments:
In `@src/lib/components/CollectionList.svelte`:
- Around line 40-47: Replace the `<div role="button">` element with a native
`<button>` element to improve keyboard accessibility. Remove the `role="button"`
attribute since native buttons have built-in keyboard support for Enter and
Space keys. Keep the existing `onclick` handler (or convert to `on:click` for
Svelte conventions). If you must retain the `<div>`, add an `onkeydown` event
handler that triggers the `handleClick(d)` function when Enter or Space keys are
pressed to support keyboard-only users.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b95f2f51-d909-4b73-b125-bde8bc9ca6f1

📥 Commits

Reviewing files that changed from the base of the PR and between 59640a4 and c41c23e.

📒 Files selected for processing (10)
  • src/lib/components/CollectionList.svelte
  • src/lib/components/CollectionSelector.svelte
  • src/lib/components/LayoutOptions.svelte
  • src/lib/components/Sidebar.svelte
  • src/lib/components/TabsMenu.svelte
  • src/lib/data/stores/view.ts
  • src/routes/+layout.svelte
  • src/routes/collections/+page.svelte
  • src/routes/contents/[id]/+page.svelte
  • src/routes/text/+page.svelte
💤 Files with no reviewable changes (3)
  • src/lib/data/stores/view.ts
  • src/lib/components/CollectionSelector.svelte
  • src/routes/+layout.svelte

Comment thread src/lib/components/TabsMenu.svelte Outdated
Comment on lines +27 to +37
let tabMenuActive = $state(Layout.Single);

// values of selectedLayouts before user makes changes
const restoreDocSets = JSON.stringify($selectedLayouts);

// ToDo: If showSinglePane false, provide first availible visible option instead
const showSinglePane = !!scriptureConfig.layouts?.find((x) => x.mode === Layout.Single)
?.enabled;
const showSideBySide = !!scriptureConfig.layouts?.find((x) => x.mode === Layout.Two)?.enabled; //Not yet implemented
const showVerseByVerse = !!scriptureConfig.layouts?.find((x) => x.mode === Layout.VerseByVerse)
?.enabled; //Not yet implemented

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Initialize the active tab from enabled/current layout instead of hardcoding Layout.Single.

Line 27 always defaults to Layout.Single, but Lines 33-37 allow Single to be disabled. In that state, getSelectedLayout() (Line 39+) can resolve an invalid/empty selection and Line 51 can overwrite $refs.docSet with an empty value.

Proposed fix
-    let tabMenuActive = $state(Layout.Single);
-
-    // values of selectedLayouts before user makes changes
-    const restoreDocSets = JSON.stringify($selectedLayouts);
-
-    // ToDo: If showSinglePane false, provide first availible visible option instead
-    const showSinglePane = !!scriptureConfig.layouts?.find((x) => x.mode === Layout.Single)
-        ?.enabled;
-    const showSideBySide = !!scriptureConfig.layouts?.find((x) => x.mode === Layout.Two)?.enabled; //Not yet implemented
-    const showVerseByVerse = !!scriptureConfig.layouts?.find((x) => x.mode === Layout.VerseByVerse)
-        ?.enabled; //Not yet implemented
+    // values of selectedLayouts before user makes changes
+    const restoreDocSets = JSON.stringify($selectedLayouts);
+
+    const showSinglePane = !!scriptureConfig.layouts?.find((x) => x.mode === Layout.Single)?.enabled;
+    const showSideBySide = !!scriptureConfig.layouts?.find((x) => x.mode === Layout.Two)?.enabled; //Not yet implemented
+    const showVerseByVerse = !!scriptureConfig.layouts?.find((x) => x.mode === Layout.VerseByVerse)?.enabled; //Not yet implemented
+
+    const enabledModes = [
+        showSinglePane && Layout.Single,
+        showSideBySide && Layout.Two,
+        showVerseByVerse && Layout.VerseByVerse
+    ].filter(Boolean) as Layout[];
+
+    let tabMenuActive = $state(
+        enabledModes.includes($layout.mode) ? $layout.mode : (enabledModes[0] ?? Layout.Single)
+    );
@@
     function handleOk() {
         const selectedLayout = getSelectedLayout();
+        if (!selectedLayout.primaryDocSet) return;
         $refs.docSet = selectedLayout.primaryDocSet;
         $layout = selectedLayout;
         goto(resolve(`/`));
     }

Also applies to: 39-43, 50-53

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/collections/`+page.svelte around lines 27 - 37, The
`tabMenuActive` variable is hardcoded to `Layout.Single` but the code below
(showSinglePane, showSideBySide, showVerseByVerse checks) determines which
layouts are actually enabled. If Layout.Single is disabled, this creates an
invalid initial state. Instead of hardcoding Layout.Single, initialize
`tabMenuActive` by checking which layout is actually enabled first using the
boolean flags that are already being computed (showSinglePane, showSideBySide,
showVerseByVerse). Use a fallback logic to select the first available enabled
layout rather than assuming Layout.Single is always valid.

@FyreByrd FyreByrd left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not sure if this is in scope or if a separate issue should be opened, but changing the collection changes the interface font. (repro: select ASV).

Comment thread src/lib/components/CollectionList.svelte Outdated
Comment thread src/lib/components/TabsMenu.svelte Outdated
Comment thread src/routes/collections/+page.svelte Outdated
{#if mode === Layout.Single}
<SinglePaneIcon
color="black"
/><!--From what I can tell, the icons seem to be hardcoded to black in the native app, although I might just be missing the correct color setting to change-->

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did you try using the black theme in the native app?? The icons were white on my end at least.

@TheNonPirate TheNonPirate Jun 17, 2026

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.

I can now see that they aren't hardcoded to black, but I can't figure out what setting does affect them. I tried every color I could find in Appearance->Colors->Main Colors that was dark in Normal and Sepia and light in Dark, changed the color in Sepia to some bright, flashy color, and then build and installed the Android app and found that the icons were still dark in normal and sepia modes. Do you have any idea what the color setting for them is?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Have you tried inspecting the CSS through USB debugging?

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.

I can't figure out how to inspect the part of the screen that has the selector at the top with the icons. The only things that show up in the dev tools inspection are the tabs themselves for single pane and verse on image (I have the two-pane view disabled right now) and several unrendered pages of Scripture text.

<!-- Single Pane -->
{#if layoutOption === Layout.Single}
<p class="py-2" style:color={$themeColors['LayoutTitleColor']}>
<p class="py-2 font-bold" style:color={$themeColors['LayoutTitleColor']}>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

On larger screens, this "header" is all the way to the left, instead of aligned with the sort-of-centered , which doesn't look all that great. I'd recommend removing the centering from and moving it to LayoutOptions instead. Then you have slightly more control over the 's sizing across multiple places where you are using it (i.e. the dropdown for side by side or verse by verse). The selectors for side by side and verse by verse can then also be size-constrained and centered in the same stroke.

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.

What would you recommend removing the centering from and moving to LayoutOptions? Or were you suggesting moving the "header" from LayoutOptions to somewhere else?

Comment thread src/lib/components/LayoutOptions.svelte Outdated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is probably out of scope, but can you add a little padding around this? It turns out a bit cramped.

Image

Comment thread src/lib/components/LayoutOptions.svelte Outdated
@TheNonPirate

Copy link
Copy Markdown
Contributor Author

Changing the collection changes the interface font on the native app as well, so I think it's intended behavior.

@TheNonPirate

Copy link
Copy Markdown
Contributor Author

Also, I thought that the 2-pane feature and verse on image were both currently disabled. How did you access them in the collections page?

@FyreByrd

Copy link
Copy Markdown
Collaborator

Changing the collection changes the interface font on the native app as well, so I think it's intended behavior.

I stand corrected. Please disregard lol.

@FyreByrd

Copy link
Copy Markdown
Collaborator

Also, I thought that the 2-pane feature and verse on image were both currently disabled. How did you access them in the collections page?

I manually changed the relevant values in config.ts

@TheNonPirate

Copy link
Copy Markdown
Contributor Author

I manually changed the relevant values in config.ts

Ah. I have not yet implemented those features at all, so they have not been properly styled. I'll get to work on those.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/components/CollectionList.svelte (1)

40-47: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use a real button for collection row actions (keyboard access is currently broken).

Line 40 uses a div with onclick and role="button" but no keyboard handler/tab focus support. This blocks keyboard activation for collection changes.

Suggested fix
-            <div
-                onclick={() => handleClick(d)}
+            <button
+                type="button"
+                onclick={() => handleClick(d)}
                 style:background-color={selectedLayouts?.id === d.id
                     ? $themeColors['LayoutItemSelectedBackgroundColor']
                     : ''}
                 class="flex justify-between layout-item-block rounded-none"
-                role="button"
             >
@@
-            </div>
+            </button>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/components/CollectionList.svelte` around lines 40 - 47, Replace the
div element at line 40 with a real button element to restore keyboard
accessibility. The current div has onclick handler with handleClick(d) and
role="button" but lacks keyboard support. Convert the div to a button element,
remove the role="button" attribute since a real button has built-in keyboard
support, preserve all the style bindings (background-color), class names (flex,
justify-between, layout-item-block, rounded-none), and the onclick handler with
handleClick(d) to maintain the current functionality while enabling keyboard
navigation and activation via Enter/Space keys.
♻️ Duplicate comments (1)
src/routes/collections/+page.svelte (1)

27-53: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Initialize active layout from enabled modes before saving selection.

Line 27 still hardcodes Layout.Single. If single-pane is disabled, getSelectedLayout() (Line 38 onward) can resolve an empty primaryDocSet, and handleOk() (Line 49 onward) persists that empty value to $refs.docSet.

Proposed minimal fix
-    let tabMenuActive = $state(Layout.Single);
+    const enabledModes = [
+        showSinglePane && Layout.Single,
+        showSideBySide && Layout.Two,
+        showVerseByVerse && Layout.VerseByVerse
+    ].filter(Boolean) as Layout[];
+
+    let tabMenuActive = $state(
+        enabledModes.includes($layout.mode) ? $layout.mode : (enabledModes[0] ?? Layout.Single)
+    );
@@
     function handleOk() {
         const selectedLayout = getSelectedLayout();
+        if (!selectedLayout.primaryDocSet) return;
         $refs.docSet = selectedLayout.primaryDocSet;
         $layout = selectedLayout;
         goto(resolve(`/`));
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/collections/`+page.svelte around lines 27 - 53, The tabMenuActive
variable is hardcoded to Layout.Single, which can cause getSelectedLayout() to
return an empty primaryDocSet if single-pane is disabled, and handleOk() will
then persist this invalid value to $refs.docSet. Instead of hardcoding
Layout.Single, initialize tabMenuActive by selecting the first enabled layout
mode from the available options, checking showSinglePane, showSideBySide, and
showVerseByVerse flags in order to determine which layout should be active by
default. This ensures that getSelectedLayout() will always have a valid enabled
layout to work with.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/components/TabsMenu.svelte`:
- Line 78: Remove the stray debug text "Hello" that is being rendered on line 78
in the TabsMenu.svelte component. This literal text is appearing in the
production UI and should be deleted entirely from the tab content rendering
logic.

---

Outside diff comments:
In `@src/lib/components/CollectionList.svelte`:
- Around line 40-47: Replace the div element at line 40 with a real button
element to restore keyboard accessibility. The current div has onclick handler
with handleClick(d) and role="button" but lacks keyboard support. Convert the
div to a button element, remove the role="button" attribute since a real button
has built-in keyboard support, preserve all the style bindings
(background-color), class names (flex, justify-between, layout-item-block,
rounded-none), and the onclick handler with handleClick(d) to maintain the
current functionality while enabling keyboard navigation and activation via
Enter/Space keys.

---

Duplicate comments:
In `@src/routes/collections/`+page.svelte:
- Around line 27-53: The tabMenuActive variable is hardcoded to Layout.Single,
which can cause getSelectedLayout() to return an empty primaryDocSet if
single-pane is disabled, and handleOk() will then persist this invalid value to
$refs.docSet. Instead of hardcoding Layout.Single, initialize tabMenuActive by
selecting the first enabled layout mode from the available options, checking
showSinglePane, showSideBySide, and showVerseByVerse flags in order to determine
which layout should be active by default. This ensures that getSelectedLayout()
will always have a valid enabled layout to work with.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f45b9e16-abf3-45f7-a588-123ca4199bf5

📥 Commits

Reviewing files that changed from the base of the PR and between c41c23e and 2c15d0f.

📒 Files selected for processing (3)
  • src/lib/components/CollectionList.svelte
  • src/lib/components/TabsMenu.svelte
  • src/routes/collections/+page.svelte

Comment thread src/lib/components/TabsMenu.svelte Outdated
@TheNonPirate TheNonPirate marked this pull request as draft June 18, 2026 22:35
Replaced collection selector modal with collections route
Also implement the buttons used for navigation
out of the collection selection route
Also fix issue with current collection not being
selected in the collection selector.
Work started on a modal that allows the user to
select a collection for one of the selections for
verse-by-verse or double pane.
Selecting a collection for verse-by-verse that is
already selected now changes the duplicate to the
first collection that hasn't already been selected.
@TheNonPirate TheNonPirate force-pushed the update/collection-as-route branch from f9540c2 to b190c3e Compare June 19, 2026 18:03
@TheNonPirate TheNonPirate marked this pull request as ready for review June 19, 2026 18:13

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/components/CollectionModal.svelte`:
- Around line 58-60: The filter operation at line 58 and line 75 assigns
undefined to $selectedLayouts.sideBySide[i] and $selectedLayouts.sideBySide[1]
when no unused collection is available, which causes crashes later when
accessing .id or .image properties. Before assigning filter(...)[0], check that
the filter result array has at least one element and only perform the assignment
if a valid element exists, otherwise skip the assignment or handle it
appropriately to prevent undefined values from entering the selectedLayouts
state.

In `@src/lib/components/LayoutOptions.svelte`:
- Around line 114-117: The modal payload passed to modal.open for
ModalType.Collection does not match the contract expected by
CollectionModal.showModal, which requires a showBlank property. In the
modal.open call around line 114-117, add the missing showBlank property with a
value of false to the payload object alongside the existing type and number
properties, ensuring the dispatcher receives the complete payload structure that
showModal expects.
- Around line 109-113: The interactive elements with the class layout-item-block
that suppress accessibility checks are non-focusable divs with onclick handlers,
preventing keyboard users from accessing them. Replace both instances of these
div elements with semantically appropriate button elements instead of divs,
remove the svelte-ignore comments since buttons are natively accessible, and
ensure the onclick handlers are properly converted to button click handlers.
This will make the collection selectors keyboard-accessible without needing to
suppress accessibility warnings.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1940be3f-b91a-4b78-afbf-4e4a3a9c702e

📥 Commits

Reviewing files that changed from the base of the PR and between 2c15d0f and b190c3e.

📒 Files selected for processing (11)
  • src/lib/components/CollectionList.svelte
  • src/lib/components/CollectionModal.svelte
  • src/lib/components/CollectionSelector.svelte
  • src/lib/components/LayoutOptions.svelte
  • src/lib/components/Sidebar.svelte
  • src/lib/components/TabsMenu.svelte
  • src/lib/data/stores/view.ts
  • src/routes/+layout.svelte
  • src/routes/collections/+page.svelte
  • src/routes/contents/[id]/+page.svelte
  • src/routes/text/+page.svelte
💤 Files with no reviewable changes (1)
  • src/lib/components/CollectionSelector.svelte
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/routes/contents/[id]/+page.svelte
  • src/routes/text/+page.svelte
  • src/lib/components/Sidebar.svelte
  • src/routes/collections/+page.svelte
  • src/lib/data/stores/view.ts
  • src/lib/components/CollectionList.svelte

Comment thread src/lib/components/CollectionModal.svelte Outdated
Comment on lines +109 to +113
<!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
class="flex justify-between layout-item-block rounded-none cursor-pointer"
onclick={() => {

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use keyboard-accessible controls for collection selectors.

Line 109 and Line 157 suppress accessibility checks, but the interactive element is still a non-focusable <div onclick>. Keyboard users cannot reliably open these selectors.

Suggested fix
- <div
-     class="flex justify-between layout-item-block rounded-none cursor-pointer"
-     onclick={() => {
+ <button
+     type="button"
+     class="flex w-full justify-between layout-item-block rounded-none cursor-pointer text-left"
+     onclick={() => {
          modal.open(ModalType.Collection, {
              type: 'double-pane',
              number: i
          });
      }}
- >
+ >
   ...
- </div>
+ </button>

Also applies to: 157-161

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/components/LayoutOptions.svelte` around lines 109 - 113, The
interactive elements with the class layout-item-block that suppress
accessibility checks are non-focusable divs with onclick handlers, preventing
keyboard users from accessing them. Replace both instances of these div elements
with semantically appropriate button elements instead of divs, remove the
svelte-ignore comments since buttons are natively accessible, and ensure the
onclick handlers are properly converted to button click handlers. This will make
the collection selectors keyboard-accessible without needing to suppress
accessibility warnings.

Comment thread src/lib/components/LayoutOptions.svelte
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.

CollectionList not styled

2 participants