refactor: implement footer controls context for smooth transitions
Codex implemented a portal/context architecture to eliminate layout jank: - Created FooterControlsProvider context with register/unregister methods - GlobalFooter now reserves fixed height (88px + insets) for all modes - Both AgentInputArea and RealtimeControls stack absolutely in same space - Single shared Reanimated value drives cross-fade (250ms) - Agent screen registers controls via context instead of rendering inline - Content padding adjusted to account for footer height - Borders and safe area moved to shared container - AgentInputArea simplified to pure component (no internal animations) This guarantees: - No layout shifts during transitions - Smooth cross-fade between control modes - No gaps or double borders - Both controls never occupy layout space simultaneously Implementation by OpenAI Codex per architectural recommendation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import { createContext, useCallback, useContext, useMemo, useState } from "react";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
export const FOOTER_HEIGHT = 88;
|
||||
|
||||
interface FooterControlsContextValue {
|
||||
controls: ReactNode | null;
|
||||
registerFooterControls: (controls: ReactNode) => void;
|
||||
unregisterFooterControls: () => void;
|
||||
}
|
||||
|
||||
const FooterControlsContext = createContext<FooterControlsContextValue | undefined>(undefined);
|
||||
|
||||
export function FooterControlsProvider({ children }: { children: ReactNode }) {
|
||||
const [controls, setControls] = useState<ReactNode | null>(null);
|
||||
|
||||
const registerFooterControls = useCallback((nextControls: ReactNode) => {
|
||||
setControls(nextControls);
|
||||
}, []);
|
||||
|
||||
const unregisterFooterControls = useCallback(() => {
|
||||
setControls(null);
|
||||
}, []);
|
||||
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
controls,
|
||||
registerFooterControls,
|
||||
unregisterFooterControls,
|
||||
}),
|
||||
[controls, registerFooterControls, unregisterFooterControls],
|
||||
);
|
||||
|
||||
return (
|
||||
<FooterControlsContext.Provider value={value}>
|
||||
{children}
|
||||
</FooterControlsContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useFooterControls() {
|
||||
const context = useContext(FooterControlsContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error("useFooterControls must be used within a FooterControlsProvider");
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
Reference in New Issue
Block a user