Skip to content

fix(activities): clarify bulk selection - #2344

Merged
Asherlc merged 3 commits into
mainfrom
Asherlc/issue-2122-activity-bulk-selection
Jul 30, 2026
Merged

Asherlc merged 3 commits into
mainfrom
Asherlc/issue-2122-activity-bulk-selection

Conversation

@Asherlc

@Asherlc Asherlc commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Summary

  • rename every activity selection entry point to “Select activities”
  • explain the existing delete action and the web-only hidden-activity restore action
  • announce singular and plural selection counts on web and mobile
  • add focused tests and paired selection-mode stories

Validation

  • pnpm lint
  • pnpm tsc --noEmit
  • pnpm --dir packages/server exec tsc --noEmit
  • pnpm --dir packages/web typecheck
  • pnpm --dir packages/mobile typecheck
  • pnpm test (15,057 passed; 21 skipped)

Fixes #2122

Summary by Sourcery

Clarify activity bulk selection UI and announce accessible selection counts across web and mobile.

New Features:

  • Add explicit activity selection guidance messages for delete and restore flows on web and mobile.
  • Expose singular/plural activity selection counts as live status updates in web and mobile selection modes.
  • Add Storybook stories that demonstrate the activity selection mode interactions on web and mobile.

Enhancements:

  • Rename all visible activity selection entry points to use the consistent label “Select activities”.
  • Improve accessibility of activity selection controls with descriptive hints, live regions, and status outputs.

Documentation:

  • Add a TDD plan document describing the activity bulk selection behavior, scope, and test strategy.

Tests:

  • Extend web and mobile tests to cover selection guidance copy, accessible status semantics, and updated labels for activity bulk selection.

Summary by cubic

Clarifies bulk activity selection on web and mobile by renaming the entry point to "Select activities", adding clear per-surface guidance, and announcing selection counts as accessible status (including explicit iOS announcements). Also explains delete vs. restore for hidden activities on web. Fixes #2122.

  • New Features
    • Web (packages/web): Show "Select activities"; add guidance text with a unique id per control and link it via aria-describedby; expose the count via a polite, atomic output status; hidden view explains delete or restore.
    • Mobile (packages/mobile): Show "Select activities" with a hint; display guidance; announce the count with a polite live region and proper singular/plural text; on iOS, also announce count changes via AccessibilityInfo.announceForAccessibility.
    • Tests/Stories: Extend tests for guidance association, a11y status semantics, and iOS announcements; add selection-mode stories for the web list and mobile screen.

Written for commit 26876dc. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Accessibility

    • Improved activity selection guidance on web and mobile.
    • Added clear, singular/plural selection counts with live announcements.
    • Updated the action label to “Select activities” for better clarity.
    • Added guidance for choosing activities before deletion.
  • Documentation

    • Added a plan documenting the bulk-selection update and verification approach.

Copilot AI review requested due to automatic review settings July 30, 2026 07:31
@Asherlc Asherlc linked an issue Jul 30, 2026 that may be closed by this pull request
@cursor

cursor Bot commented Jul 30, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

@sourcery-ai sourcery-ai 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.

Sorry @Asherlc, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sourcery-ai

sourcery-ai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Clarifies and standardizes bulk activity selection UX across web and mobile, adding explicit guidance text, accessible live selection counts, and targeted tests/stories around the selection mode.

Sequence diagram for clarified bulk activity selection and live status updates

sequenceDiagram
  actor User
  participant ActivitiesPage
  participant ActivityControls
  participant ScreenReader

  User->>ActivitiesPage: fireEvent_click_Select_activities_button
  ActivitiesPage->>ActivityControls: onSelect
  ActivityControls->>ActivityControls: render_selectionGuidance
  ActivityControls->>ActivityControls: render_selectedCountLabel("0 activities selected")
  ActivityControls-->>ScreenReader: aria_live_update("0 activities selected")

  User->>ActivitiesPage: fireEvent_click_activity_card
  ActivitiesPage->>ActivityControls: update_selectedActivityIds
  ActivityControls->>ActivityControls: render_selectedCountLabel("1 activity selected")
  ActivityControls-->>ScreenReader: aria_live_update("1 activity selected")
Loading

File-Level Changes

Change Details Files
Clarified activity selection controls on the web Activities page and wired them to accessible guidance and live selection status.
  • Rename the page-level selection button label from the generic text to a specific selection label and adjust tests to use role/name queries.
  • Introduce contextual guidance text describing delete vs delete/restore actions and associate it with the selection control via aria-describedby.
  • Expose the selection count as a grammatically correct accessible status element with polite, atomic live region semantics and update tests to assert on role=status and text content.
packages/web/src/pages/ActivitiesPage.tsx
packages/web/src/pages/ActivitiesPage.test.tsx
Updated the reusable web ActivityList selection UX to explain bulk deletion and expose an accessible live selection count, with Storybook coverage.
  • Add guidance text for bulk deletion with a generated id, and wire it to the selection button via aria-describedby.
  • Change the selection button label to the specific selection label and update tests to rely on accessible roles/names.
  • Replace the passive selected count text with an output element that announces a plural-aware count via a polite, atomic live region and extend tests to validate guidance, status semantics, and navigation behavior.
  • Introduce a SelectionMode Storybook story that programmatically enters select mode using accessible queries.
packages/web/src/components/ActivityList.tsx
packages/web/src/components/ActivityList.test.tsx
packages/web/src/components/ActivityList.stories.tsx
Aligned mobile Activities screen selection UX with web by clarifying deletion guidance, improving accessible naming, and making the selection count a polite live region, plus a Storybook interaction story.
  • Ensure the selection control’s accessibilityLabel and visible text consistently use the specific selection label and add an accessibilityHint describing the delete action.
  • Render guidance text under the controls header that explains the bulk delete behavior when selection is possible.
  • Change the selected count display to use plural-aware text and mark it as an accessibilityLiveRegion="polite" and update tests to assert on both guidance and live-region semantics.
  • Add a SelectionMode Storybook story that drives the screen into selection mode using role-based queries.
packages/mobile/app/(tabs)/activities.tsx
packages/mobile/app/(tabs)/activities.test.tsx
packages/mobile/app/(tabs)/activities.stories.tsx
Recorded a TDD-oriented implementation plan for the activity bulk selection improvements.
  • Add a markdown doc describing the goal, behavior, scope, test strategy, file structure, and concrete task checklist for clarifying bulk selection and accessible counts.
  • Document the linkage to the tracking issue and the verification steps run (lint, type checks, tests).
docs/superpowers/plans/2026-07-30-activity-bulk-selection.md

Assessment against linked issues

Issue Objective Addressed Explanation
#2122 Rename the ambiguous 'Select' control to 'Select activities' across activity selection entry points on web and mobile.
#2122 Explain the resulting bulk action for activity selection (delete on normal surfaces; delete/restore on hidden-activity surfaces) in the UI.
#2122 Expose the current selection count as an accessible, live-updating status (with correct singular/plural) on web and mobile.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Clarify activity bulk selection labels and accessible counts

🐞 Bug fix ✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Standardize bulk selection entry points to “Select activities” across web and mobile.
• Add action-specific guidance text and live, pluralized selection count announcements for
 accessibility.
• Add focused tests, selection-mode Storybook stories, and a TDD plan for bulk selection behavior.
Diagram

graph TD
  U["User"] --> W["Web ActivitiesPage"] --> SG["Selection guidance"] --> SC["Live count status"] --> BA["Bulk actions"]
  U --> M["Mobile ActivitiesScreen"] --> SG --> SC --> BA
  BA --> D["Delete selected"]
  BA --> R["Restore hidden (web)"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Extract shared selection copy/count helper
  • ➕ Reduces drift between ActivitiesPage, ActivityList, and mobile screen
  • ➕ Keeps pluralization and guidance wording consistent across surfaces
  • ➖ Adds indirection for a small, mostly-copy change
  • ➖ May be awkward to share between web and React Native without a shared UI layer
2. Adopt an i18n pluralization solution (ICU/messageformat)
  • ➕ Correct pluralization in all locales
  • ➕ Scales better if selection UI becomes more complex
  • ➖ Heavier dependency/infra for a single English string today
  • ➖ Requires broader product decision on localization strategy

Recommendation: The PR’s inline approach is appropriate given the constrained scope (no new selection model, no new actions). If additional bulk actions or localization are planned, consider extracting a shared helper (or adopting i18n pluralization) to prevent wording and accessibility semantics from diverging across web/mobile.

Files changed (9) +205 / -33

Bug fix (3) +57 / -8
activities.tsxClarify mobile selection UI and announce pluralized selection counts +16/-2

Clarify mobile selection UI and announce pluralized selection counts

• Renames the visible selection entry label to “Select activities” and adds an accessibility hint explaining the reachable delete action. Adds a visible guidance line and changes the selection count display to a polite live region with correct singular/plural grammar.

packages/mobile/app/(tabs)/activities.tsx

ActivityList.tsxClarify ActivityList selection entry point and live selection count +17/-3

Clarify ActivityList selection entry point and live selection count

• Renames the selection button to “Select activities” and adds guidance copy describing the delete action. Exposes the selected count via an aria-live, aria-atomic output and wires the button to that guidance via aria-describedby.

packages/web/src/components/ActivityList.tsx

ActivitiesPage.tsxClarify page-level selection guidance and accessible count announcements +24/-3

Clarify page-level selection guidance and accessible count announcements

• Adds contextual guidance copy that differs for normal vs hidden-activities views (delete-only vs delete/restore). Renames the selection entry button to “Select activities” and converts the selected count to an aria-live, aria-atomic output for accessible announcements.

packages/web/src/pages/ActivitiesPage.tsx

Tests (5) +61 / -25
activities.stories.tsxAdd mobile Storybook story that enters selection mode +9/-0

Add mobile Storybook story that enters selection mode

• Adds a SelectionMode story that programmatically clicks the “Select activities” control via a play function. Helps demonstrate and verify the real interaction path for selection mode.

packages/mobile/app/(tabs)/activities.stories.tsx

activities.test.tsxUpdate mobile tests for selection guidance and live count announcements +15/-9

Update mobile tests for selection guidance and live count announcements

• Switches selection entry interactions to target the accessible button name “Select activities.” Adds assertions for guidance copy and verifies the live-region behavior with singular/plural count text.

packages/mobile/app/(tabs)/activities.test.tsx

ActivityList.stories.tsxAdd web ActivityList selection-mode Storybook story +10/-0

Add web ActivityList selection-mode Storybook story

• Adds a SelectionMode story that enters selection mode by clicking the “Select activities” button. Provides a quick way to validate the clarified selection controls in the reusable list.

packages/web/src/components/ActivityList.stories.tsx

ActivityList.test.tsxAdd/adjust ActivityList tests for guidance copy and status semantics +8/-4

Add/adjust ActivityList tests for guidance copy and status semantics

• Updates tests to assert pre-selection guidance copy and verifies the selection count is exposed via an ARIA status with polite, atomic announcements. Ensures singular/plural count wording is correct when toggling selections.

packages/web/src/components/ActivityList.test.tsx

ActivitiesPage.test.tsxUpdate ActivitiesPage tests for selection guidance, hidden restore copy, and status +19/-12

Update ActivitiesPage tests for selection guidance, hidden restore copy, and status

• Adjusts tests to use the “Select activities” button role/name and asserts new guidance copy appears before selection mode. Adds coverage for ARIA status semantics on the count and for the hidden-activities guidance that explains delete vs restore.

packages/web/src/pages/ActivitiesPage.test.tsx

Documentation (1) +87 / -0
2026-07-30-activity-bulk-selection.mdAdd TDD plan for activity bulk selection clarity and accessibility +87/-0

Add TDD plan for activity bulk selection clarity and accessibility

• Introduces a scoped plan documenting the intended bulk selection behavior, parity requirements across web/mobile, and a focused test + Storybook strategy. Explicitly constrains implementation to copy and accessibility semantics without changing mutations or state modeling.

docs/superpowers/plans/2026-07-30-activity-bulk-selection.md

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The update clarifies bulk activity selection on web and mobile by renaming controls, adding bulk-action guidance, announcing singular/plural selection counts, and covering the behavior with tests and Storybook stories.

Changes

Activity bulk selection

Layer / File(s) Summary
Selection behavior plan
docs/superpowers/plans/2026-07-30-activity-bulk-selection.md
Documents the scope, test strategy, implementation tasks, paired stories, and verification checklist.
Web selection controls and coverage
packages/web/src/components/ActivityList.tsx, packages/web/src/pages/ActivitiesPage.tsx, packages/web/src/components/ActivityList.test.tsx, packages/web/src/pages/ActivitiesPage.test.tsx, packages/web/src/components/ActivityList.stories.tsx
Web selection controls now use “Select activities,” provide bulk-action guidance, and expose polite atomic singular/plural count announcements with updated tests and Storybook coverage.
Mobile selection controls and coverage
packages/mobile/app/(tabs)/activities.tsx, packages/mobile/app/(tabs)/activities.test.tsx, packages/mobile/app/(tabs)/activities.stories.tsx
Mobile selection mode now provides guidance, explicit labeling, pluralized live count announcements, and updated tests and Storybook coverage.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
Use “Select activities” instead of ambiguous “Select” [#2122]
Explain the resulting bulk action [#2122]
Expose the current selection count [#2122]

Possibly related PRs

  • Asherlc/dofek#1878: Modifies the mobile Activities selection-mode accessibility metadata and selection announcements.

Suggested labels: area/web, area/mobile, type/bug

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 1 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title is relevant, but it does not use the required area prefix format like [web] or [mobile]. Change it to an imperative title prefixed by the relevant area, for example: [web] clarify bulk selection or [mobile] clarify bulk selection.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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.

@qodo-code-review

qodo-code-review Bot commented Jul 30, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 186 rules

Grey Divider


Remediation recommended

1. Duplicate guidance element id ✓ Resolved 🐞 Bug ≡ Correctness
Description
ActivitiesPage ActivityControls hard-codes id="activity-selection-guidance" and references it via
aria-describedby; if multiple ActivitiesPage/ActivityControls instances are mounted in the same
document, duplicate IDs make the described-by reference ambiguous for assistive tech. This was
introduced by this PR when adding the new guidance paragraph + aria-describedby wiring.
Code

packages/web/src/pages/ActivitiesPage.tsx[R365-375]

+            <p id="activity-selection-guidance" className="mt-0.5 text-xs text-muted">
+              {selectionGuidance}
+            </p>
+          ) : null}
+        </div>
        {canSelect && !selectMode ? (
          <button
            type="button"
            onClick={onSelect}
+            aria-describedby="activity-selection-guidance"
            className="px-3 py-1.5 text-xs rounded bg-accent/10 text-foreground hover:bg-surface-hover transition-colors cursor-pointer"
Relevance

●●● Strong

Team previously accepted replacing hardcoded ARIA-linked ids with per-instance useId() to avoid
duplicate DOM ids.

PR-#2204
PR-#2150

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR adds a fixed id and uses it for aria-describedby in ActivitiesPage. Elsewhere (ActivityList)
the codebase uses useId() for the same described-by pattern, which avoids duplicate-id collisions
when multiple instances render.

packages/web/src/pages/ActivitiesPage.tsx[352-379]
packages/web/src/components/ActivityList.tsx[76-82]
packages/web/src/components/ActivityList.tsx[258-316]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`ActivityControls` in `ActivitiesPage.tsx` uses a fixed DOM id (`activity-selection-guidance`) for the guidance paragraph and references it from `aria-describedby`. If multiple instances render in the same document (e.g., Storybook compositions, embedded previews, certain tests), duplicate IDs can cause assistive tech to read the wrong description or none at all.

### Issue Context
A similar pattern in `ActivityList` already uses `useId()` to generate a per-instance id.

### Fix Focus Areas
- packages/web/src/pages/ActivitiesPage.tsx[352-379]

### Implementation notes
- Import and use `useId()` (or equivalent) inside `ActivityControls`.
- Replace the hard-coded string id with the generated id.
- Keep `aria-describedby` pointing at the generated id only when the guidance element is rendered.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread packages/web/src/pages/ActivitiesPage.tsx Outdated
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Storybook previews for 54ca9e42 are ready:

This comment updates automatically on each PR push.

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Mobile Preview

Scan to open on device:

QR code for dofek://preview/pr-2344

Channel pr-2344
Deep Link dofek://preview/pr-2344
Commit 54ca9e4

To test on device:

  1. Build and install the preview client: PREVIEW_CHANNEL=pr-2344 pnpm expo prebuild --clean -p ios
  2. Or tap deep link on an existing preview build: dofek://preview/pr-2344

Each PR gets its own channel. Build a preview client with PREVIEW_CHANNEL=pr-{N} to test.

Prevent duplicate aria-describedby targets when multiple activity controls mount.\n\nRefs #2122
@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@docs/superpowers/plans/2026-07-30-activity-bulk-selection.md`:
- Around line 3-4: Remove the agent-only “REQUIRED SUB-SKILL” instruction from
the plan document while preserving the checkbox step guidance. If this
instruction must remain available to agents, relocate it to the applicable
AGENTS.md rather than keeping it under docs/**.

In `@packages/mobile/app/`(tabs)/activities.tsx:
- Around line 455-456: Update the selected-count announcement flow around
selectedCountLabel to call
AccessibilityInfo.announceForAccessibility(selectedCountLabel) on iOS, while
preserving the existing accessibilityLiveRegion behavior for Android.
🪄 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: ASSERTIVE

Plan: Pro Plus

Run ID: 0cc08faa-bf58-47e7-a914-2b03c6648d51

📥 Commits

Reviewing files that changed from the base of the PR and between ff0e1eb and c72f3f2.

📒 Files selected for processing (9)
  • docs/superpowers/plans/2026-07-30-activity-bulk-selection.md
  • packages/mobile/app/(tabs)/activities.stories.tsx
  • packages/mobile/app/(tabs)/activities.test.tsx
  • packages/mobile/app/(tabs)/activities.tsx
  • packages/web/src/components/ActivityList.stories.tsx
  • packages/web/src/components/ActivityList.test.tsx
  • packages/web/src/components/ActivityList.tsx
  • packages/web/src/pages/ActivitiesPage.test.tsx
  • packages/web/src/pages/ActivitiesPage.tsx

Comment thread docs/superpowers/plans/2026-07-30-activity-bulk-selection.md Outdated
Comment thread packages/mobile/app/(tabs)/activities.tsx
Keep Android live-region behavior while explicitly announcing selection count changes to VoiceOver, and remove agent-only instructions from the human plan.\n\nRefs #2122
@codereviewbot-ai

Copy link
Copy Markdown

🤖 Review skipped: Repository rate limit exceeded. Free accounts are limited to 2 reviews per 4 hours per repository. Upgrade to a paid plan for unlimited reviews.

@Asherlc
Asherlc merged commit a5a5808 into main Jul 30, 2026
103 checks passed
@Asherlc
Asherlc deleted the Asherlc/issue-2122-activity-bulk-selection branch July 30, 2026 08:13
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.

[ACT-04] Select control is ambiguous about bulk action

2 participants