feat(ui): add StreamReactions component and overflow emoji chip#67
feat(ui): add StreamReactions component and overflow emoji chip#67xsahil03x merged 12 commits intomain-design-systemfrom
StreamReactions component and overflow emoji chip#67Conversation
- Add `StreamReactions` component supporting segmented and clustered layouts. - Add `StreamEmojiChip.overflow` for displaying `+N` reaction counts with consistent numeric styling. - Implement `StreamReactionsTheme` and `StreamReactionsThemeData` for layout customization (spacing, gap, overlap, and indent). - Add support for positioning reactions as headers or footers relative to a child widget. - Update `StreamComponentFactory` to include a custom builder for reactions. - Add comprehensive playground and showcase examples for reactions in the design system gallery. - Refactor `StreamEmojiChip` internals to share a common `_RawEmojiChip` shell.
📝 WalkthroughWalkthroughThis pull request introduces StreamFlex, a new layout component with negative spacing support for overlapping elements, and StreamReactions, a new reactions component with segmented and clustered variants. It enhances StreamEmojiChip with multi-emoji and cluster/overflow support, integrates these into the theme system, and adds comprehensive gallery demonstrations. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 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 |
…ssage-reactions # Conflicts: # packages/stream_core_flutter/lib/src/factory/stream_component_factory.dart
- Rename `stream_reaction_theme.dart` and its generated file to plural `stream_reactions_theme.dart`. - Update all internal references and exports to match the new file name. - Improve documentation and comments within `StreamReactionsThemeData`.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
🧹 Nitpick comments (3)
packages/stream_core_flutter/lib/src/components/reaction/stream_reactions.dart (1)
129-144: Consider making the hardcoded chip theme overridable.The
StreamEmojiChipThemewrappingDefaultStreamReactions(lines 129-144) applies fixed styling that overrides the global emoji chip theme. This could prevent consumers from fully customizing reaction chip appearance viaStreamEmojiChipThemehigher in the tree.Consider allowing this to be influenced by a
StreamReactionsThemeDataproperty or making it opt-out.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/stream_core_flutter/lib/src/components/reaction/stream_reactions.dart` around lines 129 - 144, The current StreamEmojiChipTheme wrapping DefaultStreamReactions hardcodes chip styling (minimumSize, maximumSize, emojiSize, backgroundColor, textStyle, padding) which prevents consumer overrides; update the widget to derive these values from a higher-level theme or props: check for a provided StreamReactionsThemeData (or add one) and merge its StreamEmojiChipThemeData into the locally constructed StreamEmojiChipThemeData before applying it, and expose an opt-out flag (e.g., useDefaultChipTheme) on DefaultStreamReactions/props so callers can disable the local override; ensure to look for symbols StreamEmojiChipTheme, StreamEmojiChipThemeData, StreamReactionsThemeData, DefaultStreamReactions and props when making the change.apps/design_system_gallery/lib/components/reaction/stream_reactions.dart (1)
50-59: Keepmaxindependent fromoverlapin the playground.Overflow is orthogonal to overlap, but this hides the
+Npath wheneveroverlapis false. That makes detached layouts harder to exercise and lets large segmented sets get much wider than the available preview width.♻️ Suggested tweak
+ final limitVisible = context.knobs.boolean( + label: 'Limit Visible', + initialValue: true, + description: 'Collapse extra reactions into a +N chip.', + ); - final max = overlap + final max = limitVisible ? context.knobs.int.slider( label: 'Max Visible', initialValue: 4, min: 1, max: 6, divisions: 5, description: 'Reactions beyond this collapse into a +N chip.', ) : null;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/design_system_gallery/lib/components/reaction/stream_reactions.dart` around lines 50 - 59, The playground currently ties the max visible reactions knob to the overlap boolean so max is only configurable when overlap is true; make max independent by always exposing the context.knobs.int.slider for max (keep its label/limits) regardless of the overlap value and then use the resulting max where reactions collapse into a "+N" chip — update any conditional that creates max (refer to the max variable and overlap boolean and the context.knobs.int.slider call) so the slider is rendered/assigned unconditionally and the collapse behavior still respects overlap when determining layout.packages/stream_core_flutter/lib/src/components/avatar/stream_avatar_stack.dart (1)
192-205: Scope the no-scaling wrapper to the overflow badge.
MediaQuery.withNoTextScalingnow applies to every descendant inprops.children, so any custom avatar content also stops respecting the ambient text scale. If the goal is only to keep the+Nbadge stable, move the wrapper down toStreamBadgeCountand verify the stack at large text scales.♻️ Suggested change
- return MediaQuery.withNoTextScaling( - child: StreamAvatarTheme( - data: StreamAvatarThemeData(size: avatarSize), - child: StreamRow( - spacing: -diameter * props.overlap, - mainAxisSize: MainAxisSize.min, - children: [ - ...visible, - if (extraCount > 0) - StreamBadgeCount( - label: '+$extraCount', - size: extraBadgeSize, - ), - ], - ), - ), - ); + return StreamAvatarTheme( + data: StreamAvatarThemeData(size: avatarSize), + child: StreamRow( + spacing: -diameter * props.overlap, + mainAxisSize: MainAxisSize.min, + children: [ + ...visible, + if (extraCount > 0) + MediaQuery.withNoTextScaling( + child: StreamBadgeCount( + label: '+$extraCount', + size: extraBadgeSize, + ), + ), + ], + ), + );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/stream_core_flutter/lib/src/components/avatar/stream_avatar_stack.dart` around lines 192 - 205, The MediaQuery.withNoTextScaling wrapper is currently applied around the whole avatar stack causing all descendant avatar content to ignore textScaleFactor; restrict its scope to only the overflow badge by removing MediaQuery.withNoTextScaling from around StreamAvatarStack/props.children and instead wrapping only the StreamBadgeCount instantiation (the '+$extraCount' widget created when extraCount > 0) with MediaQuery.withNoTextScaling, preserving size inputs like extraBadgeSize and avatarSize and then run visual checks at large text scales to verify avatars still scale while the badge remains fixed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@apps/design_system_gallery/lib/components/reaction/stream_reactions.dart`:
- Around line 50-59: The playground currently ties the max visible reactions
knob to the overlap boolean so max is only configurable when overlap is true;
make max independent by always exposing the context.knobs.int.slider for max
(keep its label/limits) regardless of the overlap value and then use the
resulting max where reactions collapse into a "+N" chip — update any conditional
that creates max (refer to the max variable and overlap boolean and the
context.knobs.int.slider call) so the slider is rendered/assigned
unconditionally and the collapse behavior still respects overlap when
determining layout.
In
`@packages/stream_core_flutter/lib/src/components/avatar/stream_avatar_stack.dart`:
- Around line 192-205: The MediaQuery.withNoTextScaling wrapper is currently
applied around the whole avatar stack causing all descendant avatar content to
ignore textScaleFactor; restrict its scope to only the overflow badge by
removing MediaQuery.withNoTextScaling from around
StreamAvatarStack/props.children and instead wrapping only the StreamBadgeCount
instantiation (the '+$extraCount' widget created when extraCount > 0) with
MediaQuery.withNoTextScaling, preserving size inputs like extraBadgeSize and
avatarSize and then run visual checks at large text scales to verify avatars
still scale while the badge remains fixed.
In
`@packages/stream_core_flutter/lib/src/components/reaction/stream_reactions.dart`:
- Around line 129-144: The current StreamEmojiChipTheme wrapping
DefaultStreamReactions hardcodes chip styling (minimumSize, maximumSize,
emojiSize, backgroundColor, textStyle, padding) which prevents consumer
overrides; update the widget to derive these values from a higher-level theme or
props: check for a provided StreamReactionsThemeData (or add one) and merge its
StreamEmojiChipThemeData into the locally constructed StreamEmojiChipThemeData
before applying it, and expose an opt-out flag (e.g., useDefaultChipTheme) on
DefaultStreamReactions/props so callers can disable the local override; ensure
to look for symbols StreamEmojiChipTheme, StreamEmojiChipThemeData,
StreamReactionsThemeData, DefaultStreamReactions and props when making the
change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e4b6f9bb-7f5c-4549-b8b0-e15fd7a0a88f
📒 Files selected for processing (17)
apps/design_system_gallery/lib/app/gallery_app.directories.g.dartapps/design_system_gallery/lib/components/common/stream_flex.dartapps/design_system_gallery/lib/components/controls/stream_emoji_chip.dartapps/design_system_gallery/lib/components/reaction/stream_reactions.dartpackages/stream_core_flutter/lib/src/components.dartpackages/stream_core_flutter/lib/src/components/avatar/stream_avatar_stack.dartpackages/stream_core_flutter/lib/src/components/common/stream_flex.dartpackages/stream_core_flutter/lib/src/components/controls/stream_emoji_chip.dartpackages/stream_core_flutter/lib/src/components/reaction/stream_reactions.dartpackages/stream_core_flutter/lib/src/factory/stream_component_factory.dartpackages/stream_core_flutter/lib/src/factory/stream_component_factory.g.theme.dartpackages/stream_core_flutter/lib/src/theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_reactions_theme.dartpackages/stream_core_flutter/lib/src/theme/components/stream_reactions_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/stream_theme.dartpackages/stream_core_flutter/lib/src/theme/stream_theme.g.theme.dartpackages/stream_core_flutter/lib/src/theme/stream_theme_extensions.dart
Codecov Report❌ Patch coverage is ❌ Your patch status has failed because the patch coverage (1.21%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main-design-system #67 +/- ##
=====================================================
Coverage ? 33.30%
=====================================================
Files ? 115
Lines ? 3534
Branches ? 0
=====================================================
Hits ? 1177
Misses ? 2357
Partials ? 0 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Description of the pull request
StreamReactionscomponent supporting segmented and clustered layouts.StreamEmojiChip.overflowfor displaying+Nreaction counts with consistent numeric styling.StreamReactionsThemeandStreamReactionsThemeDatafor layout customization (spacing, gap, overlap, and indent).StreamComponentFactoryto include a custom builder for reactions.StreamEmojiChipinternals to share a common_RawEmojiChipshell.Screenshots / Videos
Summary by CodeRabbit
New Features
Documentation