diff --git a/src/components/nodes/InlineParameterPanel.tsx b/src/components/nodes/InlineParameterPanel.tsx
new file mode 100644
index 00000000..01e00269
--- /dev/null
+++ b/src/components/nodes/InlineParameterPanel.tsx
@@ -0,0 +1,62 @@
+"use client";
+
+import { ReactNode } from "react";
+
+interface InlineParameterPanelProps {
+ expanded: boolean;
+ onToggle: () => void;
+ children: ReactNode;
+ nodeId: string;
+}
+
+/**
+ * Collapsible parameter container for inline display within generation nodes.
+ * Provides a chevron toggle button and smooth expand/collapse transitions.
+ */
+export function InlineParameterPanel({
+ expanded,
+ onToggle,
+ children,
+ nodeId,
+}: InlineParameterPanelProps) {
+ return (
+
+ {/* Chevron toggle button - acts as visual boundary */}
+
+
+ {/* Collapsible content area */}
+
+
+ );
+}
diff --git a/src/hooks/useInlineParameters.ts b/src/hooks/useInlineParameters.ts
new file mode 100644
index 00000000..455742d4
--- /dev/null
+++ b/src/hooks/useInlineParameters.ts
@@ -0,0 +1,24 @@
+import { useState, useCallback } from "react";
+
+const INLINE_PARAMS_KEY = "node-banana-inline-parameters";
+
+export function useInlineParameters() {
+ const [enabled, setEnabled] = useState(() => {
+ try {
+ return localStorage.getItem(INLINE_PARAMS_KEY) === "true";
+ } catch {
+ return false;
+ }
+ });
+
+ const setInlineParameters = useCallback((value: boolean) => {
+ try {
+ localStorage.setItem(INLINE_PARAMS_KEY, String(value));
+ } catch {
+ // localStorage not available
+ }
+ setEnabled(value);
+ }, []);
+
+ return { inlineParametersEnabled: enabled, setInlineParameters };
+}
diff --git a/src/types/nodes.ts b/src/types/nodes.ts
index 65725dbd..963c41f7 100644
--- a/src/types/nodes.ts
+++ b/src/types/nodes.ts
@@ -177,6 +177,7 @@ export interface NanoBananaNodeData extends BaseNodeData {
useImageSearch: boolean; // Only available for Nano Banana 2
parameters?: Record; // Model-specific parameters for external providers
inputSchema?: ModelInputDef[]; // Model's input schema for dynamic handles
+ parametersExpanded?: boolean; // Collapse state for inline parameter display
status: NodeStatus;
error: string | null;
imageHistory: CarouselImageItem[]; // Carousel history (IDs only)
@@ -195,6 +196,7 @@ export interface GenerateVideoNodeData extends BaseNodeData {
selectedModel?: SelectedModel; // Required for video generation (no legacy fallback)
parameters?: Record; // Model-specific parameters
inputSchema?: ModelInputDef[]; // Model's input schema for dynamic handles
+ parametersExpanded?: boolean; // Collapse state for inline parameter display
status: NodeStatus;
error: string | null;
videoHistory: CarouselVideoItem[]; // Carousel history (IDs only)
@@ -214,6 +216,7 @@ export interface Generate3DNodeData extends BaseNodeData {
selectedModel?: SelectedModel;
parameters?: Record;
inputSchema?: ModelInputDef[];
+ parametersExpanded?: boolean; // Collapse state for inline parameter display
status: NodeStatus;
error: string | null;
}
@@ -238,6 +241,7 @@ export interface GenerateAudioNodeData extends BaseNodeData {
selectedModel?: SelectedModel; // Required for audio generation
parameters?: Record; // Model-specific parameters (voice, speed, etc.)
inputSchema?: ModelInputDef[]; // Model's input schema for dynamic handles
+ parametersExpanded?: boolean; // Collapse state for inline parameter display
status: NodeStatus;
error: string | null;
audioHistory: CarouselAudioItem[]; // Carousel history (IDs only)
@@ -258,6 +262,7 @@ export interface LLMGenerateNodeData extends BaseNodeData {
model: LLMModelType;
temperature: number;
maxTokens: number;
+ parametersExpanded?: boolean; // Collapse state for inline parameter display
status: NodeStatus;
error: string | null;
}