Skip to content

Comments

feat: add multi-step download app dropdown with platform-specific options#27211

Merged
PeerRich merged 29 commits intomainfrom
devin/1769278561-download-app-multi-step-dropdown
Jan 26, 2026
Merged

feat: add multi-step download app dropdown with platform-specific options#27211
PeerRich merged 29 commits intomainfrom
devin/1769278561-download-app-multi-step-dropdown

Conversation

@PeerRich
Copy link
Member

@PeerRich PeerRich commented Jan 24, 2026

What does this PR do?

Replaces the single "Download desktop app" link in the user dropdown with a platform-aware download menu that shows relevant options based on the user's device.

Download behavior:

  • On mobile (iOS): Single "Download app" menu item linking directly to iOS App Store
  • On mobile (Android): Single "Download app" menu item linking directly to Play Store
  • On desktop (macOS/Windows/Linux): Submenu with:
    1. Desktop app for current OS
    2. Browser extension for current browser (Chrome/Safari/Firefox/Edge)
    3. iOS app
    4. Android app

Changes:

  • Created useUserAgentData hook in packages/lib/hooks/ for detecting user's OS, browser, and mobile status
  • Migrated UserDropdown.tsx from Radix UI dropdown to @coss/ui Menu components
  • Added DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent components to UI library (for backwards compatibility)
  • Added i18n translations for all new download options
  • Created DownloadIcons.tsx with inline SVG components for all platform icons (Apple, Play Store, Chrome, Safari, Firefox, Edge, Windows, Linux)

Updates since last revision

  • Simplified mobile experience: no submenu on mobile, just a direct link to the relevant app store
  • Reordered desktop submenu: desktop app first, then browser extension, then mobile apps
  • Removed unused /icons/download/*.svg files (now inline in DownloadIcons.tsx)
  • Apple icon uses fill-foreground Tailwind class for dark/light mode adaptation
  • Other brand icons preserve their original colors/gradients
  • Added comprehensive tests for useUserAgentData hook (17 tests covering OS detection, browser detection, and SSR handling)

Visual Demo (For contributors especially)

Note: Visual testing was not performed locally. Please verify the dropdown behavior, icon rendering, and theme compatibility.

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. N/A - no documentation changes needed.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

  1. Log into the Cal.com web app on a desktop browser
  2. Click on the user dropdown in the sidebar
  3. Hover over "Download app" to open the submenu
  4. Verify on desktop:
    • Desktop OS option appears first (MacOS/Windows/Linux based on your OS)
    • Browser extension appears second (Chrome/Safari/Firefox/Edge based on your browser)
    • iOS and Android options appear at the bottom
  5. Test on mobile device or emulator:
    • On iOS: should see single "Download app" item (no submenu) linking to iOS App Store
    • On Android: should see single "Download app" item (no submenu) linking to Play Store
  6. Test dark/light mode: Toggle between themes and verify:
    • Apple icon adapts correctly (uses fill-foreground)
    • Other brand icons remain visible with their original colors
  7. Click each link and verify correct URLs:

Checklist for Human Review

  • Verify dropdown opens/closes correctly - previous coss-ui migration attempt caused 500 error
  • Verify submenu opens correctly on hover (desktop only)
  • Verify mobile shows direct link, not submenu - iOS shows iOS link, Android shows Android link
  • Verify user agent detection - test on different browsers/OS to confirm correct options appear
  • Verify Apple icon visibility in both light and dark modes - uses fill-foreground class
  • Verify brand icons render correctly - Chrome, Play Store, Firefox, Edge have complex gradients
  • Review useUserAgentData hook - new hook created for this PR, verify regex patterns handle edge cases

Link to Devin run: https://app.devin.ai/sessions/ff6f0652f3d84c53866902c820fef8c0
Requested by: @PeerRich

…ions

- Add DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent components to UI library
- Create useUserAgentData hook for detecting user's OS and browser
- Replace single download link with multi-step dropdown showing:
  - iOS and Android (always shown)
  - Browser extensions (Chrome, Safari, Firefox, Edge) based on detected browser
  - Desktop apps (MacOS, Windows, Linux) based on detected OS
- Add i18n translations for all new download options

Co-Authored-By: peer@cal.com <peer@cal.com>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

devin-ai-integration bot and others added 2 commits January 24, 2026 18:28
…ata hook

Co-Authored-By: peer@cal.com <peer@cal.com>
@PeerRich PeerRich marked this pull request as ready for review January 24, 2026 19:03
@PeerRich PeerRich requested review from a team as code owners January 24, 2026 19:03
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 6 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/web/modules/shell/user-dropdown/UserDropdown.tsx">

<violation number="1" location="apps/web/modules/shell/user-dropdown/UserDropdown.tsx:154">
P3: Localize these UI strings via `t()`; avoid hardcoded text in the dropdown. Use the existing `loading` key for the loading state and add a new translation key for the “Nameless User” fallback so lingo.dev can propagate it.

(Based on your team's feedback about verifying localization keys with lingo.dev.) [FEEDBACK_USED]</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

<span className="w-24 shrink-0 text-sm leading-none">
<span className="text-emphasis block truncate py-0.5 font-medium leading-normal">
{isPending ? "Loading..." : user?.name ?? "Nameless User"}
{isPending ? "Loading..." : (user?.name ?? "Nameless User")}
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 24, 2026

Choose a reason for hiding this comment

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

P3: Localize these UI strings via t(); avoid hardcoded text in the dropdown. Use the existing loading key for the loading state and add a new translation key for the “Nameless User” fallback so lingo.dev can propagate it.

(Based on your team's feedback about verifying localization keys with lingo.dev.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/web/modules/shell/user-dropdown/UserDropdown.tsx, line 154:

<comment>Localize these UI strings via `t()`; avoid hardcoded text in the dropdown. Use the existing `loading` key for the loading state and add a new translation key for the “Nameless User” fallback so lingo.dev can propagate it.

(Based on your team's feedback about verifying localization keys with lingo.dev.) </comment>

<file context>
@@ -135,7 +151,7 @@ export function UserDropdown({ small }: UserDropdownProps) {
               <span className="w-24 shrink-0 text-sm leading-none">
                 <span className="text-emphasis block truncate py-0.5 font-medium leading-normal">
-                  {isPending ? "Loading..." : user?.name ?? "Nameless User"}
+                  {isPending ? "Loading..." : (user?.name ?? "Nameless User")}
                 </span>
               </span>
</file context>
Fix with Cubic

@github-actions
Copy link
Contributor

Devin AI is addressing Cubic AI's review feedback

A Devin session has been created to address the issues identified by Cubic AI.

View Devin Session

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/web/modules/shell/user-dropdown/UserDropdown.tsx">

<violation number="1" location="apps/web/modules/shell/user-dropdown/UserDropdown.tsx:17">
P2: MenuSub/MenuSubTrigger/MenuSubPopup are Base UI menu primitives, but the dropdown root/content is still Radix. This context mismatch will prevent the submenu from opening. Use the Radix-based DropdownMenuSub* components or migrate the whole dropdown to the @coss/ui menu system.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 26, 2026

Devin AI is addressing Cubic AI's review feedback

New feedback has been sent to the existing Devin session.

View Devin Session


✅ No changes pushed

PeerRich and others added 4 commits January 26, 2026 13:22
The coss-ui Menu components (MenuSub, MenuSubTrigger, MenuSubPopup) require
a Base UI Menu.Root context, but they were being used inside a Radix UI
Dropdown which caused a context mismatch and 500 error.

Reverted to using the Radix-based DropdownMenuSub, DropdownMenuSubTrigger,
and DropdownMenuSubContent components which work correctly within the
existing Radix Dropdown context.

Co-Authored-By: peer@cal.com <peer@cal.com>
Replace Lucide icons with custom brand SVGs for each download option:
- Apple icon for iOS and macOS
- Play Store icon for Android
- Chrome, Safari, Firefox, Edge icons for browser extensions
- Windows and Linux icons for desktop apps

Co-Authored-By: peer@cal.com <peer@cal.com>
Replace Radix UI dropdown components with coss-ui Menu components:
- Menu, MenuTrigger, MenuPopup, MenuItem, MenuSeparator
- MenuSub, MenuSubTrigger, MenuSubPopup for submenu
- Use render prop pattern instead of asChild
- Update test mocks to use coss-ui components

Co-Authored-By: peer@cal.com <peer@cal.com>
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 2 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/web/modules/shell/user-dropdown/UserDropdown.tsx">

<violation number="1" location="apps/web/modules/shell/user-dropdown/UserDropdown.tsx:155">
P2: Replace the inline “Loading...”/“Nameless User” strings with localized `t()` keys to keep user-facing text translatable.</violation>

<violation number="2" location="apps/web/modules/shell/user-dropdown/UserDropdown.tsx:289">
P2: Use the existing `t("platform")` key instead of the hard-coded “Platform” label so it remains localized.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 26, 2026

Devin AI is addressing Cubic AI's review feedback

New feedback has been sent to the existing Devin session.

View Devin Session


✅ No changes pushed (confidence scores 8/10 are below the 9/10 threshold)

devin-ai-integration bot and others added 7 commits January 26, 2026 13:06
Replace img tags with inline SVG for Apple icons (iOS and macOS downloads)
to support dark/light mode color switching via Tailwind fill-foreground class.

Co-Authored-By: peer@cal.com <peer@cal.com>
Co-Authored-By: peer@cal.com <peer@cal.com>
…lti-step-dropdown' into devin/1769278561-download-app-multi-step-dropdown

Co-Authored-By: peer@cal.com <peer@cal.com>
@PeerRich PeerRich enabled auto-merge (squash) January 26, 2026 15:45
Co-Authored-By: peer@cal.com <peer@cal.com>
@PeerRich PeerRich merged commit 7dcc2fe into main Jan 26, 2026
51 checks passed
@PeerRich PeerRich deleted the devin/1769278561-download-app-multi-step-dropdown branch January 26, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants