Customize an Empty Workspace State with WorkspaceContents

You can replace the default empty workspace watermark with a custom React component by supplying your own WorkspaceContents implementation in the Workspaces UI. The key detail is to render the custom empty state only when the workspace has no windows and the user is not currently dragging a window.

This is a practical workaround for io.Connect Browser Workspaces UI and io.Connect Desktop Workspaces UI when you want a branded or more helpful empty-state experience.

When to use this approach

Use this customization when the default “empty box with a plus” watermark does not match your product UX, branding, or onboarding flow.

  • Show a branded empty state
  • Provide user guidance such as “Open app”, “Restore layout”, or “Drag apps here”
  • Display contextual actions for first-time users

Prerequisites

  • Access to the Workspaces UI source code or configuration
  • Working knowledge of React component development
  • Workspaces UI running in io.Connect Browser 4.5+ or io.Connect Desktop 9.x+

The customization applies at the Workspaces UI layer. It does not require changing the workspace engine behavior itself.

How it works

The WorkspaceContents component receives the current workspace windows as a prop. By checking windows.length, you can decide whether to render:

  • a custom empty-state component when there are no windows
  • the standard workspace contents when windows are present

This allows you to override only the empty-state experience while preserving the default rendering behavior for populated workspaces.

Implementation

1. Supply a custom WorkspaceContents component

In your Workspaces UI configuration, provide a custom component for the WorkspaceContents prop.

2. Render a custom component when the workspace is empty

The basic implementation checks whether the workspace contains any windows.

const CustomWorkspaceContents = ({ windows, ...props }) => {
  if (windows.length === 0) {
    return <MyCustomEmptyState />;
  }

  return <DefaultWorkspaceContents windows={windows} {...props} />;
};

This basic version is not sufficient on its own. During drag operations, the internal window list can temporarily appear empty, which may cause your custom UI to flash unexpectedly.

3. Add a drag-state guard to prevent flashing

When a user drags a window, the platform may temporarily report zero windows through its internal state. If your logic reacts immediately to that transient state, the empty component can appear briefly during the drag interaction.

To prevent this, check whether document.body contains the lm_dragging class and suppress the empty state while dragging is in progress.

const CustomWorkspaceContents = ({ windows, ...props }) => {
  const isDragging = document.body.classList.contains("lm_dragging");

  if (windows.length === 0 && !isDragging) {
    return <MyCustomEmptyState />;
  }

  return <DefaultWorkspaceContents windows={windows} {...props} />;
};

This guard ensures that the empty state appears only when the workspace is truly empty, not during a temporary drag transition.

Why the lm_dragging check matters

Without the drag guard, users may see a distracting flicker when moving the last window out of a workspace. That flicker happens because the drag lifecycle briefly creates a state in which no windows are reported, even though the user is still actively manipulating one.

If windows.length is used alone, the UI can misinterpret an in-progress drag as a genuinely empty workspace.

The lm_dragging class acts as a simple and effective signal that the layout is in a transient interaction state. Deferring the empty-state render until dragging finishes gives a smoother and more intentional user experience.

Expected result

  • When a workspace is genuinely empty, your custom React empty-state component is displayed.
  • When a user drags the last window out of the workspace, the empty state does not flash during the drag.
  • The custom empty state appears only after the drag completes and the workspace is truly empty.

Best practices

  • Keep the empty-state component lightweight so it renders quickly.
  • Include clear calls to action, such as opening an application or restoring a saved workspace.
  • Preserve the default workspace contents renderer for non-empty states instead of reimplementing standard behavior.
  • Treat lm_dragging as a UI-state guard, not a substitute for workspace state management.

Reference docs