Skip to content

feat(content-sidebar): focused state for threaded-replies in activity-feed-v2#4650

Open
mrscobbler wants to merge 1 commit into
box:masterfrom
mrscobbler:feature/threaded-replies-focus
Open

feat(content-sidebar): focused state for threaded-replies in activity-feed-v2#4650
mrscobbler wants to merge 1 commit into
box:masterfrom
mrscobbler:feature/threaded-replies-focus

Conversation

@mrscobbler

@mrscobbler mrscobbler commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a focused state to threaded-replies rows in the v2 activity-feed sidebar when activeFeedEntryId matches the row id.
  • Sidebar-scoped: no changes to @box/threaded-annotations or @box/activity-feed — overrides the vendor card's border + background only when the wrapper has .is-focused.
  • Wrapper uses display: contents by default so unfocused layout is byte-identical to today.

Test plan

  • Deep-link to a comment in the v2 sidebar — matching thread shows blue border + 4% blue tint, others unchanged
  • Switch between two deep-links — old highlight clears, new one applies
  • Confirm <li data-activity-id> is still emitted (scroll-to-id still works) — key now lives on the wrapper div
  • Verify legacy v1 activity feed and viewer-overlay surfaces are visually unchanged

Follow-up: scroll-block tuning ({ block: 'center' }) for deep-links depends on an @box/activity-feed API change tracked separately.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a focused state for the active activity feed entry, making the selected thread easier to spot.
    • Improved visual highlighting for threaded annotations in the activity feed.
  • Bug Fixes

    • Updated thread row styling so focused items display with clearer border and background emphasis.
    • Kept the active highlight consistent across feed comments and annotations.

…-feed-v2

When a comment or annotation is deep-linked via activeFeedEntryId, paint
a focused chrome on the matching thread by recoloring the vendor card's
existing border + background. The wrapper around ThreadedAnnotation is
display: contents by default so layout is untouched for unfocused rows
and the vendor's gap/padding contract is preserved.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@mrscobbler mrscobbler requested review from a team as code owners June 24, 2026 19:25
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

ActivityFeedV2 now forwards activeFeedEntryId into FeedItemRow. FeedItemRow marks the matching threaded entry as focused, wraps comment and annotation threads in keyed containers, and the stylesheet adds the corresponding focus border and background.

Changes

Activity feed focus state

Layer / File(s) Summary
Prop wiring and focus class
src/elements/content-sidebar/activity-feed-v2/ActivityFeedV2.tsx, src/elements/content-sidebar/activity-feed-v2/FeedItemRow.tsx
ActivityFeedV2 forwards activeFeedEntryId, and FeedItemRow accepts it, destructures it, and computes the focused wrapper class from the current item id.
Threaded row wrappers
src/elements/content-sidebar/activity-feed-v2/FeedItemRow.tsx
The comment and annotation render paths wrap ActivityFeed.List.ThreadedAnnotation in keyed divs that use the computed thread row class, and the key moves off ThreadedAnnotation.
Focused row styles
src/elements/content-sidebar/activity-feed-v2/ActivityFeedV2.scss
The stylesheet imports shared variables and adds the threaded row focus rule that sets border and background colors for focused annotation descendants.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • box/box-ui-elements#4533 — Introduced the threaded annotation rendering that this PR now wraps with active-row focus state.

Suggested reviewers

  • ahorowitz123
  • tjuanitas
  • reneshen0328

Poem

A bunny hopped through rows of light,
One thread glowed softly, focused right.
A blue-tinted nook, a border neat,
Made comment burrows feel complete.
🐰

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: adding a focused state to threaded replies in activity-feed-v2.
Description check ✅ Passed The description includes a clear summary, test plan, and follow-up notes, and it covers the change scope well.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

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

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.

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

🧹 Nitpick comments (1)
src/elements/content-sidebar/activity-feed-v2/FeedItemRow.tsx (1)

155-155: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

key on the single root wrapper <div> is redundant.

React only uses key to reconcile siblings in a list. Since this <div> is the sole element returned by FeedItemRow, and the list key is already applied where FeedItemRow is rendered (ActivityFeedV2.tsx Line 363), the key={item.id} here has no effect. Harmless, but can be dropped for clarity.

Also applies to: 220-220

🤖 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/elements/content-sidebar/activity-feed-v2/FeedItemRow.tsx` at line 155,
The single root wrapper div in FeedItemRow has a redundant key prop, since React
only uses keys among sibling list items and the parent render in ActivityFeedV2
already provides the list key. Remove key={item.id} from the root div in
FeedItemRow (and the similar duplicate occurrence in the same component) while
keeping the existing className and structure unchanged.
🤖 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.

Nitpick comments:
In `@src/elements/content-sidebar/activity-feed-v2/FeedItemRow.tsx`:
- Line 155: The single root wrapper div in FeedItemRow has a redundant key prop,
since React only uses keys among sibling list items and the parent render in
ActivityFeedV2 already provides the list key. Remove key={item.id} from the root
div in FeedItemRow (and the similar duplicate occurrence in the same component)
while keeping the existing className and structure unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 07e8e2aa-1785-4faf-afb0-08f7e8da4ce2

📥 Commits

Reviewing files that changed from the base of the PR and between c833428 and 07f50f4.

📒 Files selected for processing (3)
  • src/elements/content-sidebar/activity-feed-v2/ActivityFeedV2.scss
  • src/elements/content-sidebar/activity-feed-v2/ActivityFeedV2.tsx
  • src/elements/content-sidebar/activity-feed-v2/FeedItemRow.tsx

resolvedBy={item.resolvedBy}
userSelectorProps={userSelectorProps}
/>
<div key={item.id} className={threadRowClassName}>

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.

Do we have need any tests for these changes to make sure nothing breaks adding a non-semantic div around the activity item?

: item.annotationTarget;
return (
<ActivityFeed.List.ThreadedAnnotation
key={item.id}

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.

This doesn't affect rendering in any way downstream?

display: contents;

&.is-focused [class*='threadedAnnotations'] {
border-color: $bdl-box-blue-80;

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.

we should use bp tokens. for $bdl-box-blue-80, it should be "--bp-box-blue-80"


&.is-focused [class*='threadedAnnotations'] {
border-color: $bdl-box-blue-80;
background-color: rgba($bdl-box-blue, 0.04);

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.

we should use blueprint tokens

userSelectorProps,
}: FeedItemRowProps) => {
const threadRowClassName = classNames('bcs-NewActivityFeed-threadRow', {
'is-focused': item.id === activeFeedEntryId,

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.

would this be always active? when would the focus turn off? is the logic inside the consumer of buie then?

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.

3 participants