Skip to content

Update designs of the poll creation screen#6207

Merged
gpunto merged 2 commits intov7from
redesign/poll-creation
Mar 5, 2026
Merged

Update designs of the poll creation screen#6207
gpunto merged 2 commits intov7from
redesign/poll-creation

Conversation

@gpunto
Copy link
Contributor

@gpunto gpunto commented Mar 4, 2026

Goal

Update the poll creation screen to match the new Figma designs.

Note: the "Multiple votes" parent-child toggle (with stepper) is intentionally not included here. The current PollSwitchItem/PollSwitchItemFactory abstraction needs to be restructured first to remove unnecessary customization overhead (aligning with how the iOS SDKs handle this). That refactor will come in a follow-up PR.

Implementation

  • Replace LazyColumn with ReorderableColumn for options, to simplify the logic
  • Add per-option remove button
  • Add description field to PollSwitchItem, shown below each switch title
  • Simplify PollOptionInput API: remove shape/innerPadding params, make description required
  • Remove translatable="false" from strings

UI Changes

Before After
Screenshot_20260304_154225 Screenshot_20260304_155908

Testing

Check the poll creation flow in the sample app.

Summary by CodeRabbit

  • New Features

    • Added drag-and-drop reordering for poll options with visual handles.
  • Improvements

    • Redesigned poll creation screen with improved layout and spacing.
    • Enhanced visual styling for poll options and switches with better error state indicators.
    • Expanded descriptions and labels across poll creation UI for improved clarity.
    • Improved accessibility with updated translatable string resources.

@gpunto gpunto requested a review from a team as a code owner March 4, 2026 14:38
@github-actions
Copy link
Contributor

github-actions bot commented Mar 4, 2026

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled.

🎉 Great job! This PR is ready for review.

@gpunto gpunto added pr:breaking-change Breaking change pr:improvement Improvement labels Mar 4, 2026
@gpunto gpunto marked this pull request as draft March 4, 2026 14:41
@github-actions
Copy link
Contributor

github-actions bot commented Mar 4, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.25 MB 5.69 MB 0.44 MB 🟡
stream-chat-android-ui-components 10.60 MB 10.97 MB 0.38 MB 🟡
stream-chat-android-compose 12.81 MB 11.97 MB -0.84 MB 🚀

@coderabbitai
Copy link

coderabbitai bot commented Mar 4, 2026

Walkthrough

Poll-related Jetpack Compose UI components are restructured: public APIs simplified by removing layout control parameters (lazyListState, itemHeightSize, itemInnerPadding), description fields added to data classes, and list components refactored to manage layout internally. Screen layout updated to use Scaffold. Resources and test files updated accordingly.

Changes

Cohort / File(s) Summary
Poll Data Classes
PollSwitchItem.kt, PollOptionItem.kt, PollOptionSwitchItem.kt
Added description: String property to PollSwitchItem data class constructor; component methods adjusted accordingly. Related data classes extended with description-related accessors.
Poll Input Components
PollOptionInput.kt, PollQuestionInput.kt (in ui/components/poll/ and ui/messages/attachments/poll/)
PollOptionInput signature updated: added description: String parameter, replaced decorationBox signature, removed shape and innerPadding parameters. PollQuestionInput styling and layout reworked with border, padding, and typography adjustments.
Poll List Components Refactoring
PollOptionList.kt, PollSwitchList.kt
Removed public parameters (lazyListState, itemHeightSize, itemInnerPadding) from both; replaced LazyColumn with Column-based layouts. Introduced internal helper composables (PollOptionRow, PollSwitchListItem, PollSwitchHeader, PollSwitchInputField). Centralized state management and error handling.
Screen Layout Restructuring
CreatePollScreen.kt, PollCreationHeader.kt
CreatePollScreen refactored to use Scaffold layout instead of custom Column/scroll handling; header moved to topBar. Added internal CreatePollScreen() overload. PollCreationHeader padding modifier simplified on back button.
Resource Updates
stream_compose_ic_circle_minus.xml, stream_compose_ic_drag_handle.xml, strings.xml
New vector drawable added for circle-minus icon (20x20dp, stroke-based). Drag-handle icon updated: dimensions changed (24→20dp), path and stroke attributes added. Strings: removed translatable="false" flags, added poll-related description strings with standardized keys.
Factory and Utility Updates
PollSwitchItemFactory.kt, DefaultPollSwitchItemFactoryTest.kt
Updated four PollSwitchItem instantiations to include description parameter from resources. Test coverage extended to verify descriptions on all switch items.
Test Updates
AttachmentsPickerPollUtilsTest.kt, CreatePollViewModelTest.kt
Updated test constructors for PollSwitchItem to supply description = "" in multiple instantiations, reflecting new data class signature.
API Module Changes
stream-chat-android-compose.api
Public method signatures updated for poll components: parameter reordering, lambda arity changes (Function3→Function2 in several cases), removal of list-state and padding parameters from list composables, and synthetic constructor adjustments.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A hop through polls, descriptions bloom,
Simplify layouts, give them room,
Lambda arities dance and align,
Pull out the noise, keep the spine!
Icons drag and minus signs,
Translations ready—by design!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Update designs of the poll creation screen' clearly describes the main change—a design update to the poll creation screen—and aligns well with the PR objectives and implementation details.
Description check ✅ Passed The pull request description is comprehensive and follows the template structure with clear Goal, Implementation, UI Changes with before/after screenshots, and Testing sections.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch redesign/poll-creation

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollSwitchItem.kt (1)

23-41: ⚠️ Potential issue | 🟡 Minor

Add thread/state notes to this public API KDoc.

PollSwitchItem’s public contract changed (new required description), but the KDoc still omits thread expectations and state behavior notes required for public APIs.

As per coding guidelines, **/*.kt: "Document public APIs with KDoc, including thread expectations and state notes".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollSwitchItem.kt`
around lines 23 - 41, Update the KDoc for the public data class PollSwitchItem
to include thread and state notes: document that PollSwitchItem is immutable and
safe to read from any thread but must be created/updated from the UI/main thread
when used in Compose state, explain how its properties (title, description,
enabled, key, pollSwitchInput, pollOptionError) affect composition/recomposition
and that consumers should treat pollSwitchInput as optional UI-only state, and
note any lifecycle/ownership expectations (e.g., keys should be stable across
recompositions). Reference PollSwitchItem, its properties, and the immutability
contract in the KDoc so callers know thread-safety and state update rules.
🧹 Nitpick comments (1)
stream-chat-android-compose/api/stream-chat-android-compose.api (1)

1922-1922: Consider temporary compatibility overloads (or explicit migration notes) for these public API breaks.

Line 1922, Line 2378, Line 2421 through Line 2432, and Line 2443 change public signatures/constructor shape and will break existing SDK consumers (including destructuring of PollSwitchItem).
If v7 is intentionally breaking, please ensure migration guidance is shipped alongside; otherwise, a short deprecation window with bridging overloads would reduce upgrade friction.

Also applies to: 2378-2378, 2421-2432, 2443-2443

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@stream-chat-android-compose/api/stream-chat-android-compose.api` at line
1922, Public API signatures were changed for PollOptionInput and the
PollSwitchItem destructuring/constructors, breaking binary/source compatibility
for SDK consumers; restore temporary compatibility by adding overloads with the
previous parameter shapes (or companion factory functions) that forward to the
new implementations, and add explicit `@Deprecated` migration shims with clear
deprecation messages pointing to the new parameter order/types so consumers get
a compile-time hint; reference the public symbols PollOptionInput and
PollSwitchItem (and any constructors/factory methods) when adding these bridging
overloads or deprecation wrappers, and include a short migration note in the
library changelog/release notes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/CreatePollScreen.kt`:
- Around line 75-137: Add a Paparazzi snapshot test that covers the redesigned
CreatePollScreen Scaffold layout to prevent visual regressions: create a Compose
UI test (matching **/stream-chat-android-compose/**/*Test.kt) that composes
CreatePollScreen (or directly composes the Scaffold with PollCreationHeader,
PollQuestionInput, PollOptionList, PollSwitchList and the discard dialog state)
using Paparazzi, capture snapshots for default and scroll states, and include
assertions or snapshot dumps to verify header/content spacing and scroll
composition; run and include results of verifyPaparazziDebug in CI. Ensure the
test toggles isShowingDiscardDialog to cover PollCreationDiscardDialog and
exercises enabled/disabled states of PollCreationHeader (enabledCreation) to
cover variations.

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollOptionList.kt`:
- Around line 159-175: The decorationBox lambda in PollOptionList.kt fails to
call innerTextField() when item.pollOptionError != null and
item.title.isBlank(), causing the text field to not render; update the
decorationBox logic (the lambda that references item.pollOptionError, item.title
and innerTextField) so every conditional path calls innerTextField() — keep the
branch that shows the error message (Text with item.pollOptionError.message) for
non-blank titles, and for the case where pollOptionError exists but title is
blank, ensure innerTextField() is still invoked (e.g., show only
innerTextField() or show the error then innerTextField()) so the field always
renders.
- Around line 76-125: The AddPollOptionButton is currently placed after the
Column's closing brace, making it a sibling instead of a child; move the
AddPollOptionButton call inside the Column (e.g., just before the Column's
closing brace) so it becomes a child of the Column used in PollOptionList,
preserve its onClick logic that updates optionItemList and calls
onQuestionsChanged, and keep any Modifier/padding/spacing consistent with the
Column's layout (maintain or adjust Modifier and Arrangement to match
surrounding elements).

In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollSwitchList.kt`:
- Around line 74-80: The composable currently passes the mutable
SnapshotStateList (switchItemList) into the ViewModel via onSwitchesChanged
which causes state aliasing; change the call site in
PollSwitchList/PollSwitchListItem so you pass an immutable copy (e.g.,
switchItemList.toList()) instead of the raw switchItemList whenever calling
onSwitchesChanged, and ensure the CreatePollViewModel.updateSwitches continues
to accept an immutable List so it stores a copy rather than a mutable reference.

In `@stream-chat-android-compose/src/main/res/values/strings.xml`:
- Line 299: Fix the grammar in the user-facing string resource
stream_compose_poll_option_discard_dialog_description by replacing "Are you sure
want to discard your poll?" with the correct phrasing "Are you sure you want to
discard your poll?"; update this value in strings.xml (and any localized copies)
so the dialog reads correctly.

---

Outside diff comments:
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollSwitchItem.kt`:
- Around line 23-41: Update the KDoc for the public data class PollSwitchItem to
include thread and state notes: document that PollSwitchItem is immutable and
safe to read from any thread but must be created/updated from the UI/main thread
when used in Compose state, explain how its properties (title, description,
enabled, key, pollSwitchInput, pollOptionError) affect composition/recomposition
and that consumers should treat pollSwitchInput as optional UI-only state, and
note any lifecycle/ownership expectations (e.g., keys should be stable across
recompositions). Reference PollSwitchItem, its properties, and the immutability
contract in the KDoc so callers know thread-safety and state update rules.

---

Nitpick comments:
In `@stream-chat-android-compose/api/stream-chat-android-compose.api`:
- Line 1922: Public API signatures were changed for PollOptionInput and the
PollSwitchItem destructuring/constructors, breaking binary/source compatibility
for SDK consumers; restore temporary compatibility by adding overloads with the
previous parameter shapes (or companion factory functions) that forward to the
new implementations, and add explicit `@Deprecated` migration shims with clear
deprecation messages pointing to the new parameter order/types so consumers get
a compile-time hint; reference the public symbols PollOptionInput and
PollSwitchItem (and any constructors/factory methods) when adding these bridging
overloads or deprecation wrappers, and include a short migration note in the
library changelog/release notes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: dcd65a08-974e-44dc-a44e-4796befce340

📥 Commits

Reviewing files that changed from the base of the PR and between 3b5f6a2 and 68b4636.

⛔ Files ignored due to path filters (10)
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.poll_PollOptionInputTest_empty_input.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.poll_PollOptionInputTest_with_input.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages.attachments.poll_CreatePollScreenTest_dark_mode.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages.attachments.poll_CreatePollScreenTest_light_mode.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages.attachments.poll_PollCreationHeaderTest_disabled.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages.attachments.poll_PollCreationHeaderTest_enabled.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages.attachments.poll_PollOptionListTest_blank_items.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages.attachments.poll_PollOptionListTest_duplicated_error.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages.attachments.poll_PollOptionListTest_empty_list.png is excluded by !**/*.png
  • stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages.attachments.poll_PollSwitchListTest_list_items.png is excluded by !**/*.png
📒 Files selected for processing (15)
  • stream-chat-android-compose/api/stream-chat-android-compose.api
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/poll/PollOptionInput.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/CreatePollScreen.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollCreationHeader.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollOptionList.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollQuestionInput.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollSwitchItem.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollSwitchList.kt
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/util/PollSwitchItemFactory.kt
  • stream-chat-android-compose/src/main/res/drawable/stream_compose_ic_circle_minus.xml
  • stream-chat-android-compose/src/main/res/drawable/stream_compose_ic_drag_handle.xml
  • stream-chat-android-compose/src/main/res/values/strings.xml
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/messages/attachments/poll/AttachmentsPickerPollUtilsTest.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/messages/attachments/poll/CreatePollViewModelTest.kt
  • stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/util/DefaultPollSwitchItemFactoryTest.kt
💤 Files with no reviewable changes (1)
  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/attachments/poll/PollCreationHeader.kt

@gpunto gpunto force-pushed the redesign/poll-creation branch 5 times, most recently from b47e335 to 5122dd7 Compare March 4, 2026 16:52
@gpunto gpunto marked this pull request as ready for review March 5, 2026 10:25
Copy link
Contributor

@VelikovPetar VelikovPetar left a comment

Choose a reason for hiding this comment

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

One small comment about a snapshot test, otherwise looks pretty good!

@gpunto gpunto force-pushed the redesign/poll-creation branch from 5122dd7 to 7adaa8e Compare March 5, 2026 13:22
@gpunto gpunto enabled auto-merge (squash) March 5, 2026 13:23
@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 5, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
77.2% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@gpunto gpunto merged commit 7969679 into v7 Mar 5, 2026
17 of 21 checks passed
@gpunto gpunto deleted the redesign/poll-creation branch March 5, 2026 15:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:breaking-change Breaking change pr:improvement Improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants