From fe4d90df2663bb7b83edae4da28b080a14068498 Mon Sep 17 00:00:00 2001 From: Fredrik Burmester Date: Sat, 30 May 2026 11:50:03 +0200 Subject: [PATCH] fix(dropdown): make all stacked dropdowns visible in download sheet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @expo/ui's (SDK 55) fills its parent and reports its own size via setStyleSize, so it can't size to content. With the Host's flex:1 height depending on a zero-size wrapper, a circular dependency collapsed every selector nested more than one level deep — only the first (Quality) stayed visible in the download sheet. Pin the wrapper View to the measured trigger size and let the Host fill it via absoluteFill, breaking the cycle so Video/Audio/Subtitle render too. --- components/PlatformDropdown.tsx | 36 ++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/components/PlatformDropdown.tsx b/components/PlatformDropdown.tsx index b9c006a6c..d7d02d274 100644 --- a/components/PlatformDropdown.tsx +++ b/components/PlatformDropdown.tsx @@ -262,24 +262,28 @@ const PlatformDropdownComponent = ({ }, [isVisible, controlledOpen, controlledOnOpenChange]); if (Platform.OS === "ios") { + // Pin the wrapper to the measured trigger size. @expo/ui's (SDK 55) + // fills its parent and reports its own size via setStyleSize, so it can't + // size itself to content. If the wrapper has no size, the Host's `flex: 1` + // height depends on the parent while the parent depends on the Host — a + // circular dependency that collapses to 0 for any selector nested more than + // one level deep (so only the first, shallowest dropdown stays visible). + // Giving the wrapper the measured size breaks the cycle; the Host then + // fills a concrete box. return ( - - {/* Hidden measurer: lays the trigger out normally to capture its - intrinsic size, which we then pin onto the Host below. */} - - - {trigger} - - - + {/* Hidden measurer: lays the trigger out off-flow to capture its + intrinsic size. Absolutely positioned WITHOUT right/bottom so it + sizes to the trigger's content rather than to its parent. */} + + {trigger} + + {groups.flatMap((group, groupIndex) => { // Check if this group has radio options