+
+
+ {/* ── Curtain layer ─────────────────────────────────────
+ Renders ABOVE the header (z-index higher). `top` combines the
+ snap-derived resting position with the live finger drag — one
+ React-controlled inline style, no ref-based DOM writes. The
+ transition is disabled during the drag and restored on commit
+ so the snap commit animates smoothly without an intermediate
+ "snap back then animate forward" flash. */}
+
+ {children}
+ {/* `bottomPinned` (DirectSelfRow, ChannelCreateRow, etc.) is
+ kept mounted across snaps so the curtain reads as a self-
+ contained "screen" with its bottom row always pinned to
+ the stage bottom. While the on-screen keyboard is up the
+ slot collapses to `height: 0` so it neither paints nor
+ claims flex space above the keyboard (see the
+ `keyboardOpen` effect above for the rationale). */}
+ {bottomPinned && (
+
+ {bottomPinned}
+
+ )}
+
+
+ );
+}
+
+export { TABS_ROW_PX, CHIP_ROW_PX };
diff --git a/src/app/components/stream-header/forms/InlineNewChatForm.tsx b/src/app/components/stream-header/forms/InlineNewChatForm.tsx
new file mode 100644
index 00000000..80110f6c
--- /dev/null
+++ b/src/app/components/stream-header/forms/InlineNewChatForm.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+import { CreateChat } from '../../../features/create-chat';
+
+type Props = {
+ // Called after the form successfully creates or navigates to an
+ // existing DM. The StreamHeader uses this to close the curtain over
+ // the form.
+ onClose: () => void;
+};
+
+// Thin shell around the shared `CreateChat` form. The legacy
+// `/direct/_create` route renders the same component with a Page/
+// PageHero shell; here we only feed it the `onClose` callback and the
+// tighter `gap='400'` rhythm so the form fits comfortably under the
+// header.
+export function InlineNewChatForm({ onClose }: Props) {
+ return