Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
2f6f6cd
refactor: Use customization to get api base urls (#10871)
mfortman11 Dec 4, 2025
e948d5d
fix: Clean up the default startup logging (#10842)
erichare Dec 4, 2025
b4a54d8
refactor: add code sample customizations (#10884)
mfortman11 Dec 4, 2025
8aec1f3
Fix: lfx serve asyncio event loop error (#10887)
HzaRashid Dec 4, 2025
6cedc28
fix: Update LangflowCounts component to format star and Discord count…
viktoravelino Dec 4, 2025
d5a3124
Add test
jordanrfrazier Dec 5, 2025
e77d924
Revert "Add test"
jordanrfrazier Dec 5, 2025
7a053bd
Fix: update lfx serve tests to mock the .serve() to prevent hanging (…
HzaRashid Dec 5, 2025
7fc4208
fix: correctly raise file not found errors in File GET endpoints (#10…
jordanrfrazier Dec 8, 2025
c0d33c3
fix: image pathing to operate with s3 storage (#10919)
jordanrfrazier Dec 8, 2025
9a7ce34
fix: Add empty input check in ALTKAgent for Anthropic (#10913)
jsntsay Dec 8, 2025
9ed8321
fix: Composio's Freshdesk description error (#10760)
Uday-sidagana Dec 8, 2025
101cbd0
feat: updated Composio Github icon (#10764)
Uday-sidagana Dec 8, 2025
b0bae86
Feat: migrate MCP transport from SSE to streamable http (#10727)
HzaRashid Dec 8, 2025
a209acd
feat: Add a Unified Model Providers configuration (#10565)
HimavarshaVS Dec 9, 2025
12d17dc
fix(ci): Allow prerelease packages and fix runtime type imports (#10945)
Cristhianzl Dec 10, 2025
34216b2
fix: update sidebar icon styles to maintain backward compatibility (#…
viktoravelino Dec 10, 2025
840ec0f
feat: add tenacity retry in openserach (#10917)
edwinjosechittilappilly Dec 10, 2025
f3c08db
fix: Properly set a default Ollama base url (#10940)
erichare Dec 10, 2025
63141c1
feat: Ability to add custom colors for sticky notes. (#10961)
deon-sanchez Dec 10, 2025
2f9136c
fix: Support tool mode in components without inputs (#10959)
erichare Dec 11, 2025
397deff
fix: Proper MCP / Oauth support (#10965)
erichare Dec 11, 2025
70432fe
fix: prevent UI from getting stuck when switching to cURL mode after …
andifilhohub Dec 11, 2025
9463c4a
fix: Ensure dict return for MCP component (#10960)
erichare Dec 11, 2025
bce16ca
feat: Add Correlation ID for CHAIN & LLM Traces in ArizePhoenixTracer…
ialisaleh Dec 11, 2025
9d57aa8
bug: Fix watsonX embedding model selection (#10980)
deon-sanchez Dec 11, 2025
3fed9fe
fix: Add authentication to various endpoints (#10977)
erichare Dec 12, 2025
e9a537b
Fix: cuga integration (#10976)
sami-marreed Dec 12, 2025
24dbc60
Fix: ensure streamable-http session manager is entered and exited fro…
HzaRashid Dec 12, 2025
7ebccb8
Fix: Flowing edge for Boilerplate nodes with default width and height…
olayinkaadelakun Dec 12, 2025
3a41259
feat: Handle error events in OpenAI response streaming (#10844)
edwinjosechittilappilly Dec 12, 2025
f5e68c2
fix: Add graceful subprocess cleanup during shutdown (#10909)
Cristhianzl Dec 12, 2025
a54e508
fix: ruff errors in test openai respons api tests (#11005)
edwinjosechittilappilly Dec 12, 2025
d4ada6b
fix: mcp-proxy process leak (#10988)
phact Dec 12, 2025
757ef6c
feat: Add Hook for Auto Refresh of Model Provider Input (#10996)
deon-sanchez Dec 12, 2025
07a01ad
fix: Disable Local storage option in Write File component for cloud e…
HimavarshaVS Dec 12, 2025
7627660
Fix: disable mcp sse endpoints astra (#11006)
HzaRashid Dec 13, 2025
909bdb1
refactor: Improve image path extraction and validation (#11001)
Cristhianzl Dec 14, 2025
2a5ed55
Fix: Remove hidden from LCAgentComponent (#10984)
olayinkaadelakun Dec 15, 2025
53015c1
fix: cuga update (#11019)
sami-marreed Dec 15, 2025
056a76a
Fix: improve exception handling and status code for disabled endpoint…
HzaRashid Dec 15, 2025
c1c930b
fix: langwatch traces all api endpoints (#11013)
HzaRashid Dec 15, 2025
c970f99
docs: OpenAPI spec content updated without version change (#11032)
github-actions[bot] Dec 16, 2025
ae70c61
fix: Make sure loop inputs are properly handled in research (#11029)
erichare Dec 16, 2025
5ba7fe9
feat: add sliding container infrastructure to playgroundComponent
Nov 30, 2025
2191047
style: add border-radius to flow canvas and update Share button styling
Nov 30, 2025
7766290
fix: add sessionStorage fallback and update types (any -> unknown)
Nov 30, 2025
d4a3b30
feat: add chat-header feature to sliding container
Nov 30, 2025
b192fee
refactor: simplify FlowPageSlidingContainerContent by extracting sess…
Nov 30, 2025
b0b1bed
fix: restore session rename persistence logic from slide-chat-header …
Nov 30, 2025
0c96bbf
chore: revert formatting-only files to main (moved to infrastructure …
Nov 30, 2025
e108cc5
chore: sync formatting files with infrastructure branch
Nov 30, 2025
f956db3
rebase conflicts
Nov 30, 2025
524c54a
removed unecessary comment
Dec 1, 2025
279645b
fix: update messages store when renaming session to prevent content s…
Dec 1, 2025
d6a576f
refactor(ui): remove Sessions icon and adjust padding when playground…
Dec 3, 2025
db147e2
test: add ChatSidebar component tests
Dec 3, 2025
1c56d42
Add animated sidebar transition in playground chat
Dec 9, 2025
7db3329
Revert "Add animated sidebar transition in playground chat"
Dec 9, 2025
72216b2
Restore animated-close and align chat header with mini
Dec 15, 2025
9dd56dd
changes to fix animation using AnimatedConditional
Dec 16, 2025
05fb733
replace hooks
Dec 16, 2025
0704419
remove redundant hook and use use-add-session etc intead
Dec 16, 2025
6989beb
fix(auth): Disallow refresh token access to API endpoints (#10840)
mpawlow Dec 3, 2025
1a66d8a
changes to fix animation using AnimatedConditional
Dec 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: add sliding container infrastructure to playgroundComponent
- Move sliding container components to core/playgroundComponent/sliding-container
- Add sliding container store for state management
- Add playground button integration
- Add basic FlowPage integration with placeholder content
- Sliding panel is testable: opens/closes, resizes, fullscreen works
  • Loading branch information
Olfa Maslah authored and Olfa Maslah committed Dec 16, 2025
commit 5ba7fe9a9b3ade33bcda86821293a4d39aadf347
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import ShadTooltip from "@/components/common/shadTooltipComponent";
import { PlaygroundButtonSliding } from "@/components/core/playgroundComponent/sliding-container/components";
import { PLAYGROUND_BUTTON_NAME } from "@/constants/constants";
import { CustomIOModal } from "@/customization/components/custom-new-modal";
// Will be reverted before merging this PR - IOModal commented out to test sliding container
// import { CustomIOModal } from "@/customization/components/custom-new-modal";
import { ENABLE_PUBLISH } from "@/customization/feature-flags";

interface PlaygroundButtonProps {
Expand Down Expand Up @@ -49,22 +51,26 @@ const PlaygroundButton = ({
setOpen,
canvasOpen,
}: PlaygroundButtonProps) => {
return hasIO ? (
<CustomIOModal
open={open}
setOpen={setOpen}
disable={!hasIO}
canvasOpen={canvasOpen}
>
<ActiveButton />
</CustomIOModal>
) : (
<ShadTooltip content="Add a Chat Input or Chat Output to use the playground">
<div>
<DisabledButton />
</div>
</ShadTooltip>
);
// Will be reverted before merging this PR - IOModal commented out to test sliding container
// return hasIO ? (
// <CustomIOModal
// open={open}
// setOpen={setOpen}
// disable={!hasIO}
// canvasOpen={canvasOpen}
// >
// <ActiveButton />
// </CustomIOModal>
// ) : (
// <ShadTooltip content="Add a Chat Input or Chat Output to use the playground">
// <div>
// <DisabledButton />
// </div>
// </ShadTooltip>
// );

// New sliding container implementation for testing
return <PlaygroundButtonSliding hasIO={hasIO} />;
};

export default PlaygroundButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useSlidingContainerStore } from "../stores/sliding-container-store";

// Placeholder content for sliding container
// This will be replaced with ChatHeader in the next PR
function SlidingContainerPlaceholder() {
return (
<div className="h-full w-full bg-background border-l border-transparent shadow-lg flex items-center justify-center">
<p className="text-muted-foreground">
Sliding container - content coming soon
</p>
</div>
);
}

export function FlowPageSlidingContainerContent() {
return <SlidingContainerPlaceholder />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { FlowPageSlidingContainerContent } from "./flow-page-sliding-container";
export { PlaygroundButtonSliding } from "./playground-button-sliding";
export { SlidingContainer } from "./sliding-container";
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import ShadTooltip from "@/components/common/shadTooltipComponent";
import { PLAYGROUND_BUTTON_NAME } from "@/constants/constants";
import { ENABLE_PUBLISH } from "@/customization/feature-flags";
import { useSlidingContainerStore } from "../stores/sliding-container-store";

interface PlaygroundButtonSlidingProps {
hasIO: boolean;
}

const STROKE_WIDTH = ENABLE_PUBLISH ? 2 : 1.5;
const ICON_CLASS = "h-4 w-4 transition-all flex-shrink-0";

export function PlaygroundButtonSliding({
hasIO,
}: PlaygroundButtonSlidingProps) {
const toggle = useSlidingContainerStore((state) => state.toggle);
const isOpen = useSlidingContainerStore((state) => state.isOpen);
const width = useSlidingContainerStore((state) => state.width);
const iconName = isOpen ? "PanelRightClose" : "Play";

// Show label when slide container is closed (width === 0px or not open)
const showLabel = !isOpen || width === 0;

if (!hasIO) {
// For disabled state, always show label since container can't be opened
return (
<ShadTooltip content="Add a Chat Input or Chat Output to use the playground">
<div
className="playground-btn-flow-toolbar cursor-not-allowed text-muted-foreground duration-150"
data-testid="playground-btn-flow-sliding"
>
<ForwardedIconComponent
name="Play"
className={ICON_CLASS}
strokeWidth={STROKE_WIDTH}
/>
<span className="hidden md:block">{PLAYGROUND_BUTTON_NAME}</span>
</div>
</ShadTooltip>
);
}

return (
<div
onClick={toggle}
data-testid="playground-btn-flow-io-sliding"
className="playground-btn-flow-toolbar hover:bg-accent cursor-pointer"
>
<ForwardedIconComponent
name={iconName}
className={ICON_CLASS}
strokeWidth={STROKE_WIDTH}
/>
{showLabel && (
<span className="hidden md:block">{PLAYGROUND_BUTTON_NAME}</span>
)}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { cn } from "@/utils/utils";

const DEFAULT_WIDTH = 400;
const DEFAULT_DURATION = 300;

interface SlidingContainerProps {
isOpen: boolean;
children: React.ReactNode;
className?: string;
width?: number;
onWidthChange?: (width: number) => void;
resizable?: boolean;
duration?: number;
isFullscreen?: boolean;
}

export function SlidingContainer({
isOpen,
children,
className,
width = DEFAULT_WIDTH,
onWidthChange,
resizable = false,
duration = DEFAULT_DURATION,
isFullscreen = false,
}: SlidingContainerProps) {
const [isResizing, setIsResizing] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);

const handleMouseDown = useCallback(
(e: React.MouseEvent) => {
if (!resizable || !isOpen) return;
e.preventDefault();
setIsResizing(true);
},
[resizable, isOpen],
);

useEffect(() => {
if (!isResizing) return;

const handleMouseMove = (e: MouseEvent) => {
if (!onWidthChange) return;
const newWidth = window.innerWidth - e.clientX;
onWidthChange(newWidth);
};

const handleMouseUp = () => {
setIsResizing(false);
};

document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);

return () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
};
}, [isResizing, onWidthChange]);

const actualWidth = isFullscreen ? "100%" : isOpen ? `${width}px` : "0px";

return (
<div
ref={containerRef}
className={cn(
"relative h-full overflow-hidden transition-all ease-in-out",
isResizing && "select-none",
className,
)}
style={{
width: actualWidth,
minWidth: actualWidth,
transitionDuration: isResizing ? "0ms" : `${duration}ms`,
}}
>
{resizable && isOpen && !isFullscreen && (
<div
onMouseDown={handleMouseDown}
className={cn(
"absolute left-0 top-0 z-10 h-full w-1 cursor-col-resize bg-transparent hover:bg-primary/20 transition-colors",
isResizing && "bg-primary/30",
)}
style={{ touchAction: "none" }}
aria-label="Resize panel"
/>
)}
<div className="h-full w-full">{children}</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type { SlidingContainerStoreType } from "./sliding-container-store";
export { useSlidingContainerStore } from "./sliding-container-store";
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { create } from "zustand";

const MIN_WIDTH = 300;
const MAX_WIDTH_RATIO = 0.8;
const DEFAULT_WIDTH = 400;

export interface SlidingContainerStoreType {
isOpen: boolean;
setIsOpen: (isOpen: boolean) => void;
toggle: () => void;
width: number;
setWidth: (width: number) => void;
isFullscreen: boolean;
setIsFullscreen: (isFullscreen: boolean) => void;
toggleFullscreen: () => void;
}

export const useSlidingContainerStore = create<SlidingContainerStoreType>(
(set) => ({
isOpen: false,
setIsOpen: (isOpen: boolean) => set({ isOpen }),
toggle: () => set((state) => ({ isOpen: !state.isOpen })),
width: DEFAULT_WIDTH,
setWidth: (width: number) => {
const maxWidth = window.innerWidth * MAX_WIDTH_RATIO;
set({ width: Math.max(MIN_WIDTH, Math.min(maxWidth, width)) });
},
isFullscreen: false,
setIsFullscreen: (isFullscreen: boolean) => set({ isFullscreen }),
toggleFullscreen: () =>
set((state) => ({ isFullscreen: !state.isFullscreen })),
}),
);
79 changes: 75 additions & 4 deletions src/frontend/src/pages/FlowPage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { useEffect, useState } from "react";
import { useBlocker, useParams } from "react-router-dom";
import { SlidingContainer } from "@/components/core/playgroundComponent/sliding-container/components";
import { FlowPageSlidingContainerContent } from "@/components/core/playgroundComponent/sliding-container/components/flow-page-sliding-container";
import { useSlidingContainerStore } from "@/components/core/playgroundComponent/sliding-container/stores";
import { SidebarProvider } from "@/components/ui/sidebar";
import { useGetFlow } from "@/controllers/API/queries/flows/use-get-flow";
import { useGetTypes } from "@/controllers/API/queries/flows/use-get-types";
Expand Down Expand Up @@ -162,6 +165,19 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {

const isMobile = useIsMobile();

// Sliding container state - Will be reverted before merging this PR
const isSlidingContainerOpen = useSlidingContainerStore(
(state) => state.isOpen,
);
const slidingContainerWidth = useSlidingContainerStore(
(state) => state.width,
);
const setSlidingContainerWidth = useSlidingContainerStore(
(state) => state.setWidth,
);
const isFullscreen = useSlidingContainerStore((state) => state.isFullscreen);
const hasIO = useFlowStore((state) => state.hasIO);

return (
<>
<div className="flow-page-positioning">
Expand All @@ -173,11 +189,66 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
segmentedSidebar={ENABLE_NEW_SIDEBAR}
>
<FlowSearchProvider>
{!view && <FlowSidebarComponent isLoading={isLoading} />}
{!view && !isFullscreen && (
<FlowSidebarComponent isLoading={isLoading} />
)}
{/* Will be reverted before merging this PR - Original main layout */}
{/* <main className="flex w-full overflow-hidden relative">
{!isFullscreen && (
<div className="h-full w-full">
<Page setIsLoading={setIsLoading} />
</div>
)}
{hasIO && (
<SlidingContainer
isOpen={isSlidingContainerOpen}
width={slidingContainerWidth}
onWidthChange={setSlidingContainerWidth}
resizable={!isFullscreen}
isFullscreen={isFullscreen}
className={
!isFullscreen
? "absolute right-0 top-0 bottom-0 z-40"
: ""
}
>
<FlowPageSlidingContainerContent />
</SlidingContainer>
)}
</main> */}
{/* Will be reverted before merging this PR - New side-by-side layout */}
<main className="flex w-full overflow-hidden">
<div className="h-full w-full">
<Page setIsLoading={setIsLoading} />
</div>
{!isFullscreen && (
<div
className="h-full overflow-hidden"
style={{
width:
hasIO && isSlidingContainerOpen
? `calc(100% - ${slidingContainerWidth}px)`
: "100%",
minWidth: 0,
padding: "0.5rem",
}}
>
<Page setIsLoading={setIsLoading} />
</div>
)}
{hasIO && (
<SlidingContainer
isOpen={isSlidingContainerOpen}
width={slidingContainerWidth}
onWidthChange={setSlidingContainerWidth}
resizable={!isFullscreen}
isFullscreen={isFullscreen}
className={
isFullscreen
? "fixed top-[48px] left-0 right-0 bottom-0 z-50 bg-background"
: ""
}
>
<FlowPageSlidingContainerContent />
</SlidingContainer>
)}
</main>
</FlowSearchProvider>
</SidebarProvider>
Expand Down