fix(app): dismiss the composer track panel when a row is chosen

Track pills became menu surfaces when the trackers moved out of stacked
cards, but ComposerTrackRow kept the raw Pressable it had as an inline
card row. Nothing in that path reaches selectItem, so the popover or
sheet stayed parked over the transcript after opening a subagent, and on
iOS the action fired while UIKit was still tearing the sheet down. Rows
now hand the press to the engine and take closeOnSelect, as MenuItem
does; bulk archive opts out because its progress lands in the panel.

The running mark is the shared StatusRing rather than a still dot the
pill drew for itself, and the remaining dots read their colour from the
one bucket-to-colour map. The slot is sized for the ring in every state
so the label does not step sideways when the last child finishes.

Mounting the real menu engine in a test needed harness work: stubs for
two packages that ship untranspiled Flow, reanimated left out of Vite's
prebundle so its .web files win, and the gaps filled in the unistyles
test theme.
This commit is contained in:
Mohamed Boudra
2026-08-17 23:43:01 +02:00
parent 1cc6712e51
commit c859b59c99
13 changed files with 396 additions and 73 deletions
+35
View File
@@ -60,6 +60,20 @@ export default defineConfig({
},
},
},
// Reanimated ships one file per platform and picks between them by extension
// (`findHostInstance.web.js`). Vite's dependency optimizer does not apply `resolve.extensions`,
// so it scans the native files and dies on imports react-native-web has no answer for.
// Unbundled, the same imports go through the resolver below and land on the web files.
optimizeDeps: {
exclude: ["react-native-reanimated"],
},
// The globals a React Native bundler defines, which esbuild is no longer there to supply for
// the package excluded above.
define: {
"process.env.JEST_WORKER_ID": "undefined",
__DEV__: "false",
global: "globalThis",
},
resolve: {
extensions: [
".web.mjs",
@@ -86,6 +100,13 @@ export default defineConfig({
replacement: path.resolve(__dirname, "../relay/src/index.ts"),
},
{ find: "@", replacement: path.resolve(__dirname, "src") },
// Must precede the `react-native` alias: a string `find` matches by prefix, so this subpath
// would otherwise resolve inside a react-native-web *file* and break the dependency scan.
// Reanimated only imports it on the native path, which no test takes.
{
find: /^react-native\/Libraries\/Renderer\/shims\/ReactFabric$/,
replacement: path.resolve(__dirname, "test-stubs/react-native-fabric-shim.ts"),
},
// Point to the ESM build so Vite can transform its imports and apply the
// react alias below (the CJS build uses require('react') which bypasses
// Vite alias resolution).
@@ -114,6 +135,20 @@ export default defineConfig({
find: /^react-native-svg$/,
replacement: path.resolve(__dirname, "test-stubs/react-native-svg.ts"),
},
// Both ship untranspiled Flow and fail to parse on import, which takes out any test that
// mounts a menu surface.
{
find: /^react-native-safe-area-context$/,
replacement: path.resolve(__dirname, "test-stubs/react-native-safe-area-context.ts"),
},
{
find: /^@gorhom\/bottom-sheet$/,
replacement: path.resolve(__dirname, "test-stubs/gorhom-bottom-sheet.ts"),
},
{
find: /^react-native-reanimated\/scripts\/validate-worklets-version$/,
replacement: path.resolve(__dirname, "test-stubs/reanimated-validate-worklets-version.ts"),
},
{
find: /^expo-linking$/,
replacement: path.resolve(__dirname, "test-stubs/expo-linking.ts"),