Skip to content

Conversation

@bimakw
Copy link

@bimakw bimakw commented Dec 21, 2025

Summary

Fixes layout issues on mobile devices with narrow screens (<300px) where the vote selector button would get cut off when time slot options have long duration labels (e.g., "1h 30m").

Problem

On devices with low screen widths, the vote selector button becomes partially or fully hidden when polls display date options with extended duration text. Users cannot access the voting functionality on very narrow screens.

Solution

Instead of adding horizontal scrolling (which may not be intuitive for users), this fix uses CSS flexbox properties to ensure proper content sizing:

Changes in poll-option.tsx:

  • Add min-w-0 to flex containers to allow children to shrink below content size
  • Add shrink-0 to the vote selector container to prevent it from being cut off
  • Change children container from shrink-0 to shrink with min-w-0 to allow graceful shrinking

Changes in time-slot-option.tsx:

  • Add min-w-0 to allow the time slot content to shrink
  • Add shrink-0 to keep start time always visible
  • Add truncate to duration text for graceful text overflow
  • Reduce gaps on mobile (gap-x-2, gap-x-1) with larger gaps on sm+ screens (sm:gap-x-4, sm:gap-x-1.5)

Test Plan

  • Test on viewport width of 300px or less
  • Test with time slot options with extended durations (1h 30m, 2h 15m, etc.)
  • Verify vote selector button is always accessible
  • Test on both editable and view-only modes
  • Test on different mobile browsers (Safari, Chrome)

Screenshots

Testing should be done on narrow viewports - the vote button should remain visible and accessible.

Fixes #1437

Summary by CodeRabbit

  • Style
    • Enhanced mobile poll display with refined layout spacing and improved text handling to prevent overflow on poll options and time slot selections.

✏️ Tip: You can customize this high-level summary in your review settings.

Fixes layout issues on mobile devices with narrow screens (<300px)
where the vote selector button would get cut off when time slot
options have long duration labels (e.g., "1h 30m").

Changes:
- Add min-w-0 to flex containers to allow proper shrinking
- Add shrink-0 to vote selector to prevent it from being cut off
- Add truncate to duration text for graceful overflow handling
- Reduce gaps on mobile (gap-x-2) with larger gaps on sm+ screens

Fixes lukevella#1437
@vercel
Copy link

vercel bot commented Dec 21, 2025

@bimakw is attempting to deploy a commit to the rallly Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 21, 2025

Walkthrough

Two mobile poll components receive Tailwind layout refinements to prevent overflow on narrow screens. The poll-option and time-slot-option components gain min-w-0 and shrink-0 classes alongside adjusted gap spacing to maintain responsive behavior and ensure the vote selector button remains accessible on devices with constrained viewport widths.

Changes

Cohort / File(s) Summary
Mobile Poll Layout Adjustments
apps/web/src/components/poll/mobile-poll/poll-option.tsx
Added min-w-0 to outer container and adjusted shrink-0 positioning across child wrappers and action container to prevent flex item overflow.
Added shrink-0 to vote visibility container while maintaining size constraints.
Mobile Time Slot Responsive Layout
apps/web/src/components/poll/mobile-poll/time-slot-option.tsx
Replaced vertical spacing with constrained horizontal layout by adding min-w-0 to parent row.
Applied shrink-0 to start time and clock icon; wrapped duration text in span with truncate class to enable text overflow handling.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

  • Layout-only changes following consistent Tailwind patterns (min-w-0, shrink-0, truncate).
  • Minor structural wrapping in time-slot-option for text truncation behavior.
  • No logic or behavioral changes; verify visual alignment on narrow viewports during review.

Possibly related PRs

Poem

🐰 Flex shrinks, min-widths bloom,
No more buttons trapped in gloom!
Truncate dances, gaps align,
Mobile scrolls now work just fine!

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: fixing mobile poll layout issues on narrow screens through CSS flexbox adjustments.
Linked Issues check ✅ Passed Changes directly address issue #1437 by adding min-w-0 and shrink-0 to prevent vote selector button cutoff on narrow screens without horizontal scrolling.
Out of Scope Changes check ✅ Passed All changes are scoped to poll-option.tsx and time-slot-option.tsx layout adjustments directly addressing the narrow screen layout issue.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 708f797 and 5b5e106.

📒 Files selected for processing (2)
  • apps/web/src/components/poll/mobile-poll/poll-option.tsx (2 hunks)
  • apps/web/src/components/poll/mobile-poll/time-slot-option.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Use dayjs for date handling
Use react-query for data fetching
Prefer implicit return values over explicit return values
Use zod for form validation
Create separate import statements for types
Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
Prefer double quotes for strings over single quotes
Only add comments when it is necessary to explain code that isn't self-explanatory

**/*.{ts,tsx}: Only create named interfaces when they're reused or complex
When TypeScript errors occur for missing i18n keys, run pnpm i18n:scan instead of manually adding keys

Files:

  • apps/web/src/components/poll/mobile-poll/time-slot-option.tsx
  • apps/web/src/components/poll/mobile-poll/poll-option.tsx
**/*.{tsx,css,config.ts}

📄 CodeRabbit inference engine (.cursorrules)

Use tailwindcss for styling

Files:

  • apps/web/src/components/poll/mobile-poll/time-slot-option.tsx
  • apps/web/src/components/poll/mobile-poll/poll-option.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursorrules)

**/*.tsx: Use react-hook-form for form handling
All text in the UI should be translated using either the Trans component or the useTranslation hook
Prefer composable components in the style of shadcn UI over large monolithic components
DropdownMenuItem is a flex container with a preset gap so there is no need to add margins to the children
The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size
Keep the props of a component as minimal as possible. Pass only the bare minimum amount of information needed to it
All text in the UI should be translatable
Use the component in client components from @/components/trans with the defaults prop to provide the default text
Always use a composable patterns when building components
Use cn() from @rallly/ui to compose classes
Add the "use client" directive to the top of any .tsx file that requires client-side javascript

Files:

  • apps/web/src/components/poll/mobile-poll/time-slot-option.tsx
  • apps/web/src/components/poll/mobile-poll/poll-option.tsx
**/*.{ts,tsx,json}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,json}: i18n keys are in camelCase
i18nKeys should describe the message in camelCase. Ex. "lastUpdated": "Last Updated"
If the i18nKey is not intended to be reused, prefix it with the component name in camelCase

Files:

  • apps/web/src/components/poll/mobile-poll/time-slot-option.tsx
  • apps/web/src/components/poll/mobile-poll/poll-option.tsx
**/*

📄 CodeRabbit inference engine (.cursorrules)

Always use kebab-case for file names

Files:

  • apps/web/src/components/poll/mobile-poll/time-slot-option.tsx
  • apps/web/src/components/poll/mobile-poll/poll-option.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Biome for code formatting with indent of 2 spaces and double quotes

Files:

  • apps/web/src/components/poll/mobile-poll/time-slot-option.tsx
  • apps/web/src/components/poll/mobile-poll/poll-option.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{tsx,ts}: Prefer inline prop types over named interfaces for simple component props (e.g., function Component({ prop }: { prop: string }) instead of defining a separate interface)
Always use the useDialog hook from @rallly/ui/dialog for managing dialog state instead of manual useState for open/close state
Use TanStack Query with tRPC for server state management
Use React Context for client state (auth, preferences, etc.)
Use react-hook-form with Zod validation for form state management
Use TailwindCSS with custom design system for styling

Files:

  • apps/web/src/components/poll/mobile-poll/time-slot-option.tsx
  • apps/web/src/components/poll/mobile-poll/poll-option.tsx
apps/web/src/components/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place shared components in apps/web/src/components/

Files:

  • apps/web/src/components/poll/mobile-poll/time-slot-option.tsx
  • apps/web/src/components/poll/mobile-poll/poll-option.tsx
apps/web/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/better-auth.md)

apps/web/**/*.{ts,tsx,js,jsx}: When using the username plugin, require all sign up endpoints to accept a username (used for login, normalized) and an optional displayUsername (raw, for display purposes).
When using the username plugin, all username values must be normalized according to the configuration function before storage or comparison (default: lowercase).
Whenever updating a user's username, always check for uniqueness and apply the normalization procedure.
Login endpoints or forms supporting username authentication must allow signing in with username and password, not just email.

Files:

  • apps/web/src/components/poll/mobile-poll/time-slot-option.tsx
  • apps/web/src/components/poll/mobile-poll/poll-option.tsx
🧠 Learnings (1)
📚 Learning: 2025-11-25T11:03:55.173Z
Learnt from: CR
Repo: lukevella/rallly PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T11:03:55.173Z
Learning: Applies to **/*.tsx : DropdownMenuItem is a flex container with a preset gap so there is no need to add margins to the children

Applied to files:

  • apps/web/src/components/poll/mobile-poll/poll-option.tsx
🔇 Additional comments (3)
apps/web/src/components/poll/mobile-poll/time-slot-option.tsx (1)

20-26: LGTM! Well-executed flexbox shrinking strategy.

The changes effectively address the PR objectives by:

  • Using min-w-0 to allow the container to shrink below content minimum width
  • Applying shrink-0 to critical elements (startTime, clock icon) to keep them visible
  • Adding truncate to duration text for graceful overflow handling
  • Implementing responsive gaps (smaller on mobile: gap-x-2/gap-x-1, larger on sm+: sm:gap-x-4/sm:gap-x-1.5)

The shrinking priority is correct: duration text truncates first, while the start time and vote button remain fully accessible—exactly what's needed for narrow screens.

Minor note: Users may not see the full duration text when truncated (e.g., "1h 30m" → "1h 3..."), but this trade-off is acceptable to keep the vote button accessible.

apps/web/src/components/poll/mobile-poll/poll-option.tsx (2)

133-135: LGTM! Critical flexbox hierarchy established.

These changes work together to create the proper shrinking behavior:

  1. Line 133: min-w-0 on the outer container enables flex children to shrink below their minimum content width—essential for narrow screens.

  2. Line 134: Changing from shrink-0 to min-w-0 shrink is the key change that allows the time slot content (passed as children) to compress gracefully on narrow screens, preventing the vote button from being pushed off-screen.

  3. Line 135: shrink-0 on the action container ensures the vote selector and score summary buttons maintain their intended sizes and don't get squeezed.

This establishes the correct priority: content shrinks first, controls stay accessible—exactly what the PR objectives require.


155-155: LGTM! Preserves vote button dimensions.

Adding shrink-0 ensures the vote selector container maintains its size-7 (28×28px) dimensions even under space constraints. This keeps the touch target at a usable size for mobile interaction and directly addresses the PR objective of keeping the vote button accessible on narrow screens.


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.

@vercel
Copy link

vercel bot commented Dec 23, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
app Ready Ready Preview, Comment Dec 23, 2025 10:02am

@lukevella
Copy link
Owner

Closing because this conflicts with some changes we have in-progress to the polls page.

@lukevella lukevella closed this Dec 23, 2025
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.

Participants block not horizontally scrollable in mobile view

2 participants