Sidebar: narrower layout, shows message counts, header no longer displays a stream name, and text items truncate sooner
Stream view now initializes to player mode by default with unchanged toggle between player and list
Style
Refined profile avatar sizing and fallback text sizing on Settings
Adjusted camera icon dimensions for clearer visual hierarchy
Ensured scroll area renders full-width content
Closes #283
Closes #282
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
* **Improvements**
* Sidebar: narrower layout, shows message counts, header no longer displays a stream name, and text items truncate sooner
* Stream view now initializes to player mode by default with unchanged toggle between player and list
* **Style**
* Refined profile avatar sizing and fallback text sizing on Settings
* Adjusted camera icon dimensions for clearer visual hierarchy
* Ensured scroll area renders full-width content
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
No actionable comments were generated in the recent review. 🎉
ℹ️ Recent review info⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: b6125fe9-d4e6-43b8-99f0-fa4a3b077ef4
📥 Commits
Reviewing files that changed from the base of the PR and between 3175b04d3c and ba0fbcb4ba.
📒 Files selected for processing (1)
js/desktop/src/features/particles/stream-view.tsx
💤 Files with no reviewable changes (1)
js/desktop/src/features/particles/stream-view.tsx
📝 Walkthrough
Walkthrough
Removes streamName prop from StreamListSidebar and its callsites; tightens text clamp; defaults useStreamViewMode to 'player'; enforces ScrollArea child full width; and adjusts HumanAvatar sizing and camera overlay icon.
StreamListSidebarProps removes streamName; component props destructuring drops streamName; header no longer displays streamName and shows "{items.length} messages"; text particle clamp reduced from line-clamp-3 to line-clamp-2.
HumanAvatarclassName changed to size-16 and fallbackClassName updated with text-xl; camera overlay icon size reduced to size-2.5.
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
flowy-live/llink#279: Related refactors to StreamListSidebar and view-mode wiring.
Poem
I hop along the sidebar's edge,
I clip the lines and trim the ledge.
Avatars snug, the camera small,
View starts as player — ready for all. 🐇
🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (2 warnings)
Check name
Status
Explanation
Resolution
Out of Scope Changes check
⚠️ Warning
The hook simplification in useStreamViewMode appears to go beyond proportions/affordance requirements and may represent scope creep.
Clarify whether removing stream-id-driven mode re-evaluation logic from useStreamViewMode was intentional or represents unintended scope expansion beyond the stated UI improvements.
Docstring Coverage
⚠️ Warning
Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%.
Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name
Status
Explanation
Description Check
✅ Passed
Check skipped - CodeRabbit’s high-level summary is enabled.
Title check
✅ Passed
The title accurately summarizes the main changes: improving the stream sidebar experience through UI adjustments and improving avatar affordance via styling updates.
Linked Issues check
✅ Passed
Changes address both linked issues: #283 sidebar proportions improved via scroll-area styling and streamName removal for narrower sidebar; #282 avatar affordance enhanced through HumanAvatar styling adjustments.
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches📝 Generate docstrings
Create stacked PR
Commit on current branch
🧪 Generate unit tests (beta)
Create PR with unit tests
Commit unit tests in branch experience-nits
Comment @coderabbitai help to get the list of available commands and usage tips.
<!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/flowy-live/llink/pull/284?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
No actionable comments were generated in the recent review. 🎉
<details>
<summary>ℹ️ Recent review info</summary>
<details>
<summary>⚙️ Run configuration</summary>
**Configuration used**: defaults
**Review profile**: CHILL
**Plan**: Pro Plus
**Run ID**: `b6125fe9-d4e6-43b8-99f0-fa4a3b077ef4`
</details>
<details>
<summary>📥 Commits</summary>
Reviewing files that changed from the base of the PR and between 3175b04d3c666d7bc1715b349fa141d55fa462f2 and ba0fbcb4bab9103444fe2414ff84d1bce2d516c0.
</details>
<details>
<summary>📒 Files selected for processing (1)</summary>
* `js/desktop/src/features/particles/stream-view.tsx`
</details>
<details>
<summary>💤 Files with no reviewable changes (1)</summary>
* js/desktop/src/features/particles/stream-view.tsx
</details>
</details>
---
<!-- walkthrough_start -->
<details>
<summary>📝 Walkthrough</summary>
## Walkthrough
Removes `streamName` prop from StreamListSidebar and its callsites; tightens text clamp; defaults useStreamViewMode to 'player'; enforces ScrollArea child full width; and adjusts HumanAvatar sizing and camera overlay icon.
## Changes
**Stream Sidebar and Layout Refinements**
|Layer / File(s)|Summary|
|---|---|
|**Stream sidebar component refactoring** <br> `js/desktop/src/features/particles/stream-list-sidebar.tsx`|`StreamListSidebarProps` removes `streamName`; component props destructuring drops `streamName`; header no longer displays streamName and shows "{items.length} messages"; text particle clamp reduced from `line-clamp-3` to `line-clamp-2`.|
|**Stream view integration** <br> `js/desktop/src/features/particles/stream-view.tsx`|`useStreamViewMode` is now called without arguments; StreamView no longer passes `streamName={streamParticle.properties.name}` to StreamListSidebar.|
|**View mode initial state** <br> `js/desktop/src/hooks/use-stream-view-mode.ts`|`useStreamViewMode` becomes parameterless and initializes `mode` to `'player'`, removing prior stream-id-based decide logic.|
|**ScrollArea child width enforcement** <br> `js/desktop/src/components/ui/scroll-area.tsx`|`ScrollArea` root `className` adds `[&>div]:!w-full` to force child div full width.|
|**Avatar styling enhancements** <br> `js/desktop/src/features/settings-page.tsx`|`HumanAvatar` `className` changed to `size-16` and `fallbackClassName` updated with `text-xl`; camera overlay icon size reduced to `size-2.5`.|
## Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~20 minutes
## Possibly related PRs
- [flowy-live/llink#279](https://github.com/flowy-live/llink/pull/279): Related refactors to StreamListSidebar and view-mode wiring.
## Poem
> I hop along the sidebar's edge,
> I clip the lines and trim the ledge.
> Avatars snug, the camera small,
> View starts as player — ready for all. 🐇
</details>
<!-- walkthrough_end -->
<!-- pre_merge_checks_walkthrough_start -->
<details>
<summary>🚥 Pre-merge checks | ✅ 3 | ❌ 2</summary>
### ❌ Failed checks (2 warnings)
| Check name | Status | Explanation | Resolution |
| :------------------------: | :--------- | :----------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Out of Scope Changes check | ⚠️ Warning | The hook simplification in useStreamViewMode appears to go beyond proportions/affordance requirements and may represent scope creep. | Clarify whether removing stream-id-driven mode re-evaluation logic from useStreamViewMode was intentional or represents unintended scope expansion beyond the stated UI improvements. |
| Docstring Coverage | ⚠️ Warning | Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |
<details>
<summary>✅ Passed checks (3 passed)</summary>
| Check name | Status | Explanation |
| :-----------------: | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title accurately summarizes the main changes: improving the stream sidebar experience through UI adjustments and improving avatar affordance via styling updates. |
| Linked Issues check | ✅ Passed | Changes address both linked issues: `#283` sidebar proportions improved via scroll-area styling and streamName removal for narrower sidebar; `#282` avatar affordance enhanced through HumanAvatar styling adjustments. |
</details>
<sub>✏️ Tip: You can configure your own custom pre-merge checks in the settings.</sub>
</details>
<!-- pre_merge_checks_walkthrough_end -->
<!-- finishing_touch_checkbox_start -->
<details>
<summary>✨ Finishing Touches</summary>
<details>
<summary>📝 Generate docstrings</summary>
- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> Create stacked PR
- [ ] <!-- {"checkboxId": "3e1879ae-f29b-4d0d-8e06-d12b7ba33d98"} --> Commit on current branch
</details>
<details>
<summary>🧪 Generate unit tests (beta)</summary>
- [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Create PR with unit tests
- [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Commit unit tests in branch `experience-nits`
</details>
</details>
<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->
---
<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>
<!-- tips_end -->
<!-- internal state start -->
<!-- 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 -->
<!-- internal state end -->
coderabbitai[bot]
(Migrated from github.com)
reviewed 2026-06-13 18:29:32 +00:00
coderabbitai[bot]
(Migrated from github.com)
left a comment
Copy Link
Copy Source
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 `@js/desktop/src/components/ui/scroll-area.tsx`:
- Line 19: The Tailwind important modifier is placed before the utility in the
className string inside the ScrollArea component; change the arbitrary variant
"[&>div]:!w-full" to place the ! after the utility like "[&>div]:w-full!" so it
conforms to Tailwind v4 syntax; update the className assignment used in the
component (the string containing "focus-visible:ring-ring/50 size-full
rounded-[inherit] transition-[color,box-shadow] outline-none
focus-visible:ring-[3px] focus-visible:outline-1 [&>div]:!w-full") to use the
corrected "[&>div]:w-full!" token.
In `@js/desktop/src/hooks/use-stream-view-mode.ts`:
- Line 21: The initial state for mode was changed to a constant 'player',
causing inconsistent behavior; restore the lazy initializer so the state is
computed via decideMode(streamParticle, userId) on first mount (i.e., change the
useState in use-stream-view-mode.ts back to useState<StreamViewMode>(() =>
decideMode(streamParticle, userId))). Ensure this makes the initial mount match
the navigation recomputation that already calls decideMode; alternatively, if
starting always in 'player' was intentional, document that rationale and remove
the navigation re-computation and the now-unused decideMode function to keep
behavior consistent.
🪄 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 Plus
Run ID: 05fb4bae-9ed4-4693-a929-ca4778cf53bf
📥 Commits
Reviewing files that changed from the base of the PR and between 9249cb4107 and 3381ff0b02.
**Actionable comments posted: 2**
<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>
```
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 `@js/desktop/src/components/ui/scroll-area.tsx`:
- Line 19: The Tailwind important modifier is placed before the utility in the
className string inside the ScrollArea component; change the arbitrary variant
"[&>div]:!w-full" to place the ! after the utility like "[&>div]:w-full!" so it
conforms to Tailwind v4 syntax; update the className assignment used in the
component (the string containing "focus-visible:ring-ring/50 size-full
rounded-[inherit] transition-[color,box-shadow] outline-none
focus-visible:ring-[3px] focus-visible:outline-1 [&>div]:!w-full") to use the
corrected "[&>div]:w-full!" token.
In `@js/desktop/src/hooks/use-stream-view-mode.ts`:
- Line 21: The initial state for mode was changed to a constant 'player',
causing inconsistent behavior; restore the lazy initializer so the state is
computed via decideMode(streamParticle, userId) on first mount (i.e., change the
useState in use-stream-view-mode.ts back to useState<StreamViewMode>(() =>
decideMode(streamParticle, userId))). Ensure this makes the initial mount match
the navigation recomputation that already calls decideMode; alternatively, if
starting always in 'player' was intentional, document that rationale and remove
the navigation re-computation and the now-unused decideMode function to keep
behavior consistent.
```
</details>
<details>
<summary>🪄 Autofix (Beta)</summary>
Fix all unresolved CodeRabbit comments on this PR:
- [ ] <!-- {"checkboxId": "4b0d0e0a-96d7-4f10-b296-3a18ea78f0b9"} --> Push a commit to this branch (recommended)
- [ ] <!-- {"checkboxId": "ff5b1114-7d8c-49e6-8ac1-43f82af23a33"} --> Create a new PR with the fixes
</details>
---
<details>
<summary>ℹ️ Review info</summary>
<details>
<summary>⚙️ Run configuration</summary>
**Configuration used**: defaults
**Review profile**: CHILL
**Plan**: Pro Plus
**Run ID**: `05fb4bae-9ed4-4693-a929-ca4778cf53bf`
</details>
<details>
<summary>📥 Commits</summary>
Reviewing files that changed from the base of the PR and between 9249cb4107fc1f5bcc4516740f1e793c0f4da778 and 3381ff0b025daf6df02ab10680e869b1ba4313c4.
</details>
<details>
<summary>📒 Files selected for processing (5)</summary>
* `js/desktop/src/components/ui/scroll-area.tsx`
* `js/desktop/src/features/particles/stream-list-sidebar.tsx`
* `js/desktop/src/features/particles/stream-view.tsx`
* `js/desktop/src/features/settings-page.tsx`
* `js/desktop/src/hooks/use-stream-view-mode.ts`
</details>
<details>
<summary>💤 Files with no reviewable changes (1)</summary>
* js/desktop/src/features/particles/stream-view.tsx
</details>
</details>
<!-- This is an auto-generated comment by CodeRabbit for review status -->
Tailwind CSS v4 important modifier syntax arbitrary variants
💡 Result:
In Tailwind CSS v4, the syntax and handling for important modifiers and arbitrary variants have been updated to align with standard CSS conventions and a CSS-first configuration approach. Important Modifier Syntax In Tailwind v4, the important modifier (!) is placed at the end of the utility class, mirroring native CSS where!important follows the declaration [1][2][3]. - Example: Instead of!text-blue-500 (v3 style), use text-blue-500! [4][2][3]. - This applies to utilities in HTML as well as those used within @apply directives in CSS [5][3]. - Global important: To apply!important to all utility classes globally, add the important keyword to the Tailwind import statement in your CSS: @import "tailwindcss" important; [6][7]. You can also wrap all utilities in a custom selector by specifying it, for example: @import "tailwindcss" important(#app); [6]. Arbitrary Variants Arbitrary variants allow for on-the-fly selector modification directly in your HTML using square bracket notation, similar to arbitrary values [8][9]. - Syntax: They are written as [selector], where the ampersand (&) represents the current element [10]. - Example: [
...
] applies styles to child list items [10]. - If a selector contains spaces, use an underscore (e.g., [&_p]:text-blue-500) [8]. - For frequently used variants, Tailwind v4 introduces the @custom-variant directive in CSS, which allows you to define reusable variant selectors without requiring JavaScript plugins [11][12]. Top Results: [4][6][2][8][3]
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@js/desktop/src/components/ui/scroll-area.tsx` at line 19, The Tailwind
important modifier is placed before the utility in the className string inside
the ScrollArea component; change the arbitrary variant "[&>div]:!w-full" to
place the ! after the utility like "[&>div]:w-full!" so it conforms to Tailwind
v4 syntax; update the className assignment used in the component (the string
containing "focus-visible:ring-ring/50 size-full rounded-[inherit]
transition-[color,box-shadow] outline-none focus-visible:ring-[3px]
focus-visible:outline-1 [&>div]:!w-full") to use the corrected "[&>div]:w-full!"
token.
_⚠️ Potential issue_ | _🔴 Critical_
<details>
<summary>🧩 Analysis chain</summary>
🌐 Web query:
`Tailwind CSS v4 important modifier syntax arbitrary variants`
💡 Result:
In Tailwind CSS v4, the syntax and handling for important modifiers and arbitrary variants have been updated to align with standard CSS conventions and a CSS-first configuration approach. Important Modifier Syntax In Tailwind v4, the important modifier (!) is placed at the end of the utility class, mirroring native CSS where!important follows the declaration [1][2][3]. - Example: Instead of!text-blue-500 (v3 style), use text-blue-500! [4][2][3]. - This applies to utilities in HTML as well as those used within `@apply` directives in CSS [5][3]. - Global important: To apply!important to all utility classes globally, add the important keyword to the Tailwind import statement in your CSS: `@import` "tailwindcss" important; [6][7]. You can also wrap all utilities in a custom selector by specifying it, for example: `@import` "tailwindcss" important(`#app`); [6]. Arbitrary Variants Arbitrary variants allow for on-the-fly selector modification directly in your HTML using square bracket notation, similar to arbitrary values [8][9]. - Syntax: They are written as [selector], where the ampersand (&) represents the current element [10]. - Example: [<div class="[&>li]:py-2">...</div>] applies styles to child list items [10]. - If a selector contains spaces, use an underscore (e.g., [&_p]:text-blue-500) [8]. - For frequently used variants, Tailwind v4 introduces the `@custom-variant` directive in CSS, which allows you to define reusable variant selectors without requiring JavaScript plugins [11][12]. Top Results: [4][6][2][8][3]
Citations:
- 1: https://stackoverflow.com/questions/75664539/tailwind-css-class-precedence-is-not-respected
- 2: https://playbooks.com/skills/fusengine/agents/tailwindcss-v4
- 3: https://tailwindcss.com/docs/upgrade-guide
- 4: https://tailwindlabs-tailwindcss.mintlify.app/advanced/important-modifier
- 5: https://github.com/tailwindlabs/tailwindcss/pull/14434
- 6: https://github.com/tailwindlabs/tailwindcss/pull/14448
- 7: https://github.com/tailwindlabs/tailwindcss/discussions/17994
- 8: https://tailwindcss.com/docs/hover-focus-and-other-states
- 9: https://tailwindcss.com/docs/adding-custom-styles
- 10: https://llmbestpractices.com/frontend/tailwind-arbitrary-values
- 11: https://tailwindcss.com/docs/functions-and-directives
- 12: https://deepwiki.com/tlq5l/tailwindcss-v4-skill/2.4-the-@variant-and-@custom-variant-directives
---
</details>
**Fix Tailwind v4 important modifier placement in `scroll-area.tsx`.**
In Tailwind v4, `!` must come **after** the utility (even inside arbitrary variants), so `[&>div]:w-full!` instead of `[&>div]:!w-full`.
<details>
<summary>🔧 Proposed fix</summary>
```diff
- className="focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1 [&>div]:!w-full"
+ className="focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1 [&>div]:w-full!"
```
</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
```
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@js/desktop/src/components/ui/scroll-area.tsx` at line 19, The Tailwind
important modifier is placed before the utility in the className string inside
the ScrollArea component; change the arbitrary variant "[&>div]:!w-full" to
place the ! after the utility like "[&>div]:w-full!" so it conforms to Tailwind
v4 syntax; update the className assignment used in the component (the string
containing "focus-visible:ring-ring/50 size-full rounded-[inherit]
transition-[color,box-shadow] outline-none focus-visible:ring-[3px]
focus-visible:outline-1 [&>div]:!w-full") to use the corrected "[&>div]:w-full!"
token.
```
</details>
<!-- fingerprinting:phantom:poseidon:puma -->
<!-- cr-comment:v1:4dccc68c6d825f79f4034232 -->
<!-- This is an auto-generated comment by CodeRabbit -->
Inconsistent initial mode behavior degrades UX for caught-up users.
Removing the lazy initializer that computed the initial mode via decideMode(streamParticle, userId) creates a behavioral inconsistency:
First mount: Mode is always 'player', regardless of whether the user is caught up with the stream.
Navigation (lines 25-27): Mode is correctly computed via decideMode, so subsequent streams show the appropriate view.
This means users who are caught up with a stream will initially see the player view when they should see the list view, but navigating to another stream and back will show the correct mode. The inconsistency is confusing and degrades the user experience.
Recommended fix: Restore the lazy initializer to ensure consistent behavior on both initial mount and navigation.
If this change was intentional (e.g., to always start in player mode for layout reasons), please document the rationale and consider removing the navigation re-computation logic (lines 23-28) and the now-mostly-unused decideMode function for consistency.
📝 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.
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@js/desktop/src/hooks/use-stream-view-mode.ts` at line 21, The initial state
for mode was changed to a constant 'player', causing inconsistent behavior;
restore the lazy initializer so the state is computed via
decideMode(streamParticle, userId) on first mount (i.e., change the useState in
use-stream-view-mode.ts back to useState<StreamViewMode>(() =>
decideMode(streamParticle, userId))). Ensure this makes the initial mount match
the navigation recomputation that already calls decideMode; alternatively, if
starting always in 'player' was intentional, document that rationale and remove
the navigation re-computation and the now-unused decideMode function to keep
behavior consistent.
_⚠️ Potential issue_ | _🟠 Major_ | _⚡ Quick win_
**Inconsistent initial mode behavior degrades UX for caught-up users.**
Removing the lazy initializer that computed the initial mode via `decideMode(streamParticle, userId)` creates a behavioral inconsistency:
- **First mount**: Mode is always `'player'`, regardless of whether the user is caught up with the stream.
- **Navigation** (lines 25-27): Mode is correctly computed via `decideMode`, so subsequent streams show the appropriate view.
This means users who are caught up with a stream will initially see the player view when they should see the list view, but navigating to another stream and back will show the correct mode. The inconsistency is confusing and degrades the user experience.
**Recommended fix**: Restore the lazy initializer to ensure consistent behavior on both initial mount and navigation.
<details>
<summary>🔄 Proposed fix to restore consistent initial mode</summary>
```diff
- const [mode, setMode] = useState<StreamViewMode>('player');
+ const [mode, setMode] = useState<StreamViewMode>(() =>
+ decideMode(streamParticle, userId)
+ );
```
</details>
If this change was intentional (e.g., to always start in player mode for layout reasons), please document the rationale and consider removing the navigation re-computation logic (lines 23-28) and the now-mostly-unused `decideMode` function for consistency.
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **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.
```suggestion
const [mode, setMode] = useState<StreamViewMode>(() =>
decideMode(streamParticle, userId)
);
```
</details>
<!-- suggestion_end -->
<details>
<summary>🤖 Prompt for AI Agents</summary>
```
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@js/desktop/src/hooks/use-stream-view-mode.ts` at line 21, The initial state
for mode was changed to a constant 'player', causing inconsistent behavior;
restore the lazy initializer so the state is computed via
decideMode(streamParticle, userId) on first mount (i.e., change the useState in
use-stream-view-mode.ts back to useState<StreamViewMode>(() =>
decideMode(streamParticle, userId))). Ensure this makes the initial mount match
the navigation recomputation that already calls decideMode; alternatively, if
starting always in 'player' was intentional, document that rationale and remove
the navigation re-computation and the now-unused decideMode function to keep
behavior consistent.
```
</details>
<!-- fingerprinting:phantom:poseidon:puma -->
<!-- cr-comment:v1:9d61156f6b3488286272070e -->
<!-- This is an auto-generated comment by CodeRabbit -->
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #283
Closes #282
Summary by CodeRabbit
Improvements
Style
No actionable comments were generated in the recent review. 🎉
ℹ️ Recent review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID:
b6125fe9-d4e6-43b8-99f0-fa4a3b077ef4📥 Commits
Reviewing files that changed from the base of the PR and between
3175b04d3candba0fbcb4ba.📒 Files selected for processing (1)
js/desktop/src/features/particles/stream-view.tsx💤 Files with no reviewable changes (1)
📝 Walkthrough
Walkthrough
Removes
streamNameprop from StreamListSidebar and its callsites; tightens text clamp; defaults useStreamViewMode to 'player'; enforces ScrollArea child full width; and adjusts HumanAvatar sizing and camera overlay icon.Changes
Stream Sidebar and Layout Refinements
js/desktop/src/features/particles/stream-list-sidebar.tsxStreamListSidebarPropsremovesstreamName; component props destructuring dropsstreamName; header no longer displays streamName and shows "{items.length} messages"; text particle clamp reduced fromline-clamp-3toline-clamp-2.js/desktop/src/features/particles/stream-view.tsxuseStreamViewModeis now called without arguments; StreamView no longer passesstreamName={streamParticle.properties.name}to StreamListSidebar.js/desktop/src/hooks/use-stream-view-mode.tsuseStreamViewModebecomes parameterless and initializesmodeto'player', removing prior stream-id-based decide logic.js/desktop/src/components/ui/scroll-area.tsxScrollArearootclassNameadds[&>div]:!w-fullto force child div full width.js/desktop/src/features/settings-page.tsxHumanAvatarclassNamechanged tosize-16andfallbackClassNameupdated withtext-xl; camera overlay icon size reduced tosize-2.5.Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
#283sidebar proportions improved via scroll-area styling and streamName removal for narrower sidebar;#282avatar affordance enhanced through HumanAvatar styling adjustments.✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
📝 Generate docstrings
🧪 Generate unit tests (beta)
experience-nitsComment
@coderabbitai helpto get the list of available commands and usage tips.Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID:
05fb4bae-9ed4-4693-a929-ca4778cf53bf📥 Commits
Reviewing files that changed from the base of the PR and between
9249cb4107and3381ff0b02.📒 Files selected for processing (5)
js/desktop/src/components/ui/scroll-area.tsxjs/desktop/src/features/particles/stream-list-sidebar.tsxjs/desktop/src/features/particles/stream-view.tsxjs/desktop/src/features/settings-page.tsxjs/desktop/src/hooks/use-stream-view-mode.ts💤 Files with no reviewable changes (1)
@@ -18,3 +18,3 @@data-slot="scroll-area-viewport"className="focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1"className="focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1 [&>div]:!w-full">⚠️ Potential issue | 🔴 Critical
🧩 Analysis chain
🌐 Web query:
Tailwind CSS v4 important modifier syntax arbitrary variants💡 Result:
In Tailwind CSS v4, the syntax and handling for important modifiers and arbitrary variants have been updated to align with standard CSS conventions and a CSS-first configuration approach. Important Modifier Syntax In Tailwind v4, the important modifier (!) is placed at the end of the utility class, mirroring native CSS where!important follows the declaration [1][2][3]. - Example: Instead of!text-blue-500 (v3 style), use text-blue-500! [4][2][3]. - This applies to utilities in HTML as well as those used within
@applydirectives in CSS [5][3]. - Global important: To apply!important to all utility classes globally, add the important keyword to the Tailwind import statement in your CSS:@import"tailwindcss" important; [6][7]. You can also wrap all utilities in a custom selector by specifying it, for example:@import"tailwindcss" important(#app); [6]. Arbitrary Variants Arbitrary variants allow for on-the-fly selector modification directly in your HTML using square bracket notation, similar to arbitrary values [8][9]. - Syntax: They are written as [selector], where the ampersand (&) represents the current element [10]. - Example: [@custom-variantdirective in CSS, which allows you to define reusable variant selectors without requiring JavaScript plugins [11][12]. Top Results: [4][6][2][8][3]Citations:
Fix Tailwind v4 important modifier placement in
scroll-area.tsx.In Tailwind v4,
!must come after the utility (even inside arbitrary variants), so[&>div]:w-full!instead of[&>div]:!w-full.🔧 Proposed fix
🤖 Prompt for AI Agents
⚠️ Potential issue | 🟠 Major | ⚡ Quick win
Inconsistent initial mode behavior degrades UX for caught-up users.
Removing the lazy initializer that computed the initial mode via
decideMode(streamParticle, userId)creates a behavioral inconsistency:'player', regardless of whether the user is caught up with the stream.decideMode, so subsequent streams show the appropriate view.This means users who are caught up with a stream will initially see the player view when they should see the list view, but navigating to another stream and back will show the correct mode. The inconsistency is confusing and degrades the user experience.
Recommended fix: Restore the lazy initializer to ensure consistent behavior on both initial mount and navigation.
🔄 Proposed fix to restore consistent initial mode
If this change was intentional (e.g., to always start in player mode for layout reasons), please document the rationale and consider removing the navigation re-computation logic (lines 23-28) and the now-mostly-unused
decideModefunction for consistency.📝 Committable suggestion
🤖 Prompt for AI Agents