Show checkboxes on hover instead of avatars (#46) - #49
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
💤 Files with no reviewable changes (1)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughUpdated IDE run configurations and README; refactored contacts list UI to show selection checkboxes on hover, implemented bulk-select controls and Alpine state sync, added server-rendered CSRF meta tags and an Htmx request injector, and adjusted related CSS and template markup. Changes
Sequence Diagram(s)sequenceDiagram
participant Browser
participant HTMX
participant Server
participant DB
Browser->>HTMX: User clicks bulk-delete / pagination
HTMX->>HTMX: Read CSRF meta header/token
HTMX->>Server: XHR with CSRF header + action payload
Server->>DB: Perform query/update (delete/list)
DB-->>Server: Result
Server-->>HTMX: HTML fragment or JSON response
HTMX-->>Browser: Swap updated fragment, trigger htmx:afterSwap
Browser->>Browser: Alpine syncSelectAll recalculates selected/total
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 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 |
* Add a "Select All" checkbox to the table header with Alpine.js logic for indeterminate and checked states * Update `x-data` and `x-init` to track both `selected` and `total` contact counts * Update table header styling and pagination controls to highlight when items are selected * Apply consistent styling to checkboxes in the indeterminate state via CSS
* Add `selectAll` and `deselectAll` Alpine.js methods to the contact list * Add selection dropdown with "All" and "None" options to the table header * Refactor hardcoded selection colors into CSS variables (`--color-selection`) * Remove unused `.thead-selected` CSS classes and simplify table header styling
* Add CSRF meta tags to layout template * Include CSRF token in HTMX request headers via `htmx:configRequest` listener
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.run/Spring Development.run.xml:
- Line 8: The pre-run task RunConfigurationTask (run_configuration_name "Docker
Compose Up") currently runs docker compose up -d which detaches immediately;
update the command used by that task to include the --wait flag (e.g., docker
compose up --wait -d or equivalent invocation supported by your environment) so
the pre-run step waits for services to be healthy before continuing, ensuring
Spring Boot doesn't race with dependencies.
In `@src/main/resources/templates/contacts/index.html`:
- Around line 56-58: The chevron dropdown button inside the form is currently a
plain <button> (the element with class "btn btn-ghost btn-xs px-0" and child
icon data-lucide="chevron-down") which defaults to type="submit" and can
accidentally submit the surrounding hx-delete form; change that button to an
explicit non-submitting button (set type="button") so clicks only toggle the
dropdown and do not submit the form.
- Line 47: The header checkbox currently uses `@change`="selected > 0 ?
deselectAll() : selectAll()", which treats the indeterminate state as "deselect
all"; change the condition to only deselect when everything is already selected
(e.g., selected === items.length or selected === contacts.length), otherwise
call selectAll() so clicking in the indeterminate state selects all; update the
`@change` handler to reference the collection size instead of just selected > 0
while keeping the existing deselectAll() and selectAll() calls.
- Line 35: x-init currently computes total once (selected and total variables in
the Alpine component) so total becomes stale after HTMX updates; update total
whenever the tbody is replaced by listening for HTMX swap/afterSwap (or
mutation) events on the same container and recompute total =
$el.querySelectorAll('input[name=selected_contact_slugs]').length and selected =
$el.querySelectorAll('input[name=selected_contact_slugs]:checked').length, then
call syncSelectAll() to re-evaluate the "select all" checkbox state; locate the
Alpine component initialized with x-init and the syncSelectAll() usage to add
this event handler.
In `@src/main/resources/templates/fragments/contact-list-rows.html`:
- Line 60: The fragment uses a static id="actions" inside the repeated row
(th:each), causing duplicated IDs; change it to a non-duplicated selector by
replacing id="actions" with a class (e.g., class="actions") or generate a unique
id using the th:each iteration (e.g., append ${iter.index} or the entity id) so
each row's actions element is uniquely addressable; locate the tag that
currently has id="actions" in contact-list-rows.html and update the attribute
and any JS/CSS references accordingly.
- Around line 39-49: The container that wraps the checkbox uses the "hidden"
utility which removes the input from the tab order; change the wrapper class on
the element that currently reads "absolute inset-0 hidden cursor-pointer
items-center justify-center group-hover/row:flex" to not use "hidden" but
instead use utilities that visually hide while preserving focusability (for
example "absolute inset-0 opacity-0 pointer-events-none items-center
justify-center group-hover/row:flex group-hover/row:opacity-100
group-hover/row:pointer-events-auto"), keep the `@click.stop` and `@change` handlers
and the input name "selected_contact_slugs" unchanged so keyboard users can tab
to and toggle the checkbox even when the row is not hovered.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 30eed9a6-7ce2-446e-ac6b-524872c70cd1
📒 Files selected for processing (7)
.run/Docker Compose Up.run.xml.run/Spring Development.run.xmlREADME.mdsrc/main/resources/static/css/input.csssrc/main/resources/templates/contacts/index.htmlsrc/main/resources/templates/fragments/contact-list-rows.htmlsrc/main/resources/templates/layout.html
💤 Files with no reviewable changes (1)
- README.md
| <div class="flex items-center"> | ||
| <label aria-label="Select all"> | ||
| <input | ||
| @change="selected > 0 ? deselectAll() : selectAll()" |
There was a problem hiding this comment.
Select-all toggle condition is wrong for partial selection.
At Line 47, any selected > 0 triggers deselectAll(). In indeterminate state, clicking the header checkbox should select all, not clear all.
Suggested fix
-@change="selected > 0 ? deselectAll() : selectAll()"
+@change="selected === total ? deselectAll() : selectAll()"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @change="selected > 0 ? deselectAll() : selectAll()" | |
| `@change`="selected === total ? deselectAll() : selectAll()" |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/resources/templates/contacts/index.html` at line 47, The header
checkbox currently uses `@change`="selected > 0 ? deselectAll() : selectAll()",
which treats the indeterminate state as "deselect all"; change the condition to
only deselect when everything is already selected (e.g., selected ===
items.length or selected === contacts.length), otherwise call selectAll() so
clicking in the indeterminate state selects all; update the `@change` handler to
reference the collection size instead of just selected > 0 while keeping the
existing deselectAll() and selectAll() calls.
* Use `docker compose up --wait` and remove the automatic Docker trigger from the Spring run configuration * Add `refreshCounts` to Alpine.js state and trigger it on `htmx:afterSwap` to sync counts after partial updates * Fix "Select All" checkbox logic to toggle based on total selection rather than partial selection * Improve checkbox visibility transitions using opacity and pointer-events instead of display toggles * Convert the actions container from an ID to a class in contact list rows
Closes #46
Summary by CodeRabbit
New Features
Style
Documentation
Chores