Layouts in a web browser

The Web Layouts capability enables you to create flexible, interactive layouts for web applications that can contain multiple views (sometimes called a "platform").
This guide covers how to set up and use Web Layouts in your OpenFin web application.
The Web Layouts API is implemented in the @openfin/core-web npm package, which also supports web-based interoperability.
To fully leverage the power of the @openfin/core-web package, you can both lay out multiple views containing different content and enable the content of those views to interoperate.
This article focuses on the layout functionality.
See Web-based interoperability for details on supporting interoperability.

Layout concepts

Refer to Organize views with layouts for a basic introduction to layouts.
With Web Layouts, views are implemented as <iframe> elements within the parent browsing context (typically, a tab of a web browser).

Set up Web Layouts

The Web Layouts functionality of @openfin/core-web depends on its interoperability functionality.
Therefore, to use Web Layouts, you must set up a Web Broker for interoperability.

To use Web Layouts in your application, install it as described in Web-based interoperability:

  1. Install the package:

npm install @openfin/core-web -S

  1. Host the shared worker.
  2. Build a Web Broker.

Once you have installed the package, API references and developer guides are available from within your interactive development environment (IDE).

Set up imports

The @openfin/core-web library requires a peer dependency on @openfin/core for type definitions.


import type { OpenFin } from '@openfin/core'; // Get OpenFin types

import { connect, type WebLayoutSnapshot } from '@openfin/core-web';  

Initialize the window's layout

In order to use Layout API functionality, you must connect to the Web Broker and initialize the layout.
You can retrieve an existing layout, just as with the desktop Layouts API; refer to How to capture a layout.
Coding a layout structure "by hand" is not recommended.

const brokerUrl = 'http://example.com/web-broker';

// Populate this with a retrieved layout 
let layoutSnapshot:WebLayoutSnapshot; 
(async () => {
    // Connect to the OpenFin Web Broker. Pass in the `platform` key with a layoutSnapshot.
    const fin = await connect({
        connectionInheritance: 'enabled',
        options: { brokerUrl },
        platform: { layoutSnapshot }
    });
    const container = document.getElementById('layout-container');
    // You can now use the `fin` object. In this case, initialize and create layouts.
    await fin.Platform.Layout.init({ container });

Retrieve a layout

The call to retrieve a layout in Web Layouts is exactly the same as it is for desktop layouts.
The fin.Platform.Layout API is exactly the same as in the desktop library.

const layoutManager = fin.Platform.Layout.getCurrentLayoutManagerSync();

// returns an object like: { layouts: { ... } } where each key in layouts.&lt;key> is its own separate layout configuration

const layoutSnapshot = await layoutManager.getLayoutSnapshot();

Configure layout behavior

You can configure various aspects of the layout's behavior, such as whether users are allowed to reorder tabs, resize panes, and close views.

When drag-and-drop is enabled, users can:

  • Drag tab headers to reorder them within a tab strip
  • Drag tab headers to move views between different parts of the layout
  • Drag the splitter between views to resize them

The following Boolean options are available as LayoutOptions.settings to control aspects of drag-and-drop behavior:

  • hasHeaders (default true): Whether views (tabs) have tab headers. If false, the layout is displayed with splitters only.

  • preventSplitterResize (default false): Whether users can resize views by dragging the splitter between them. If true, splitters are not draggable, and the relative proportions of views cannot be changed.

  • reorderEnabled (default true): Whether users can reorder the view tabs in the tab strip by dragging them. Unlike a desktop OpenFin environment, dragging is limited to the current window.

The following option is available on views:

  • isClosable (default true): Whether the tab header has a close button to enable closing the tab.

The following code example shows setting these options to their non-default values.

fin.Platform.Layout.create({
  container,
  layoutName: 'main',
  layout: {
    settings: {
      hasHeaders: false,           // Suppress tab headers
      reorderEnabled: false,       // Prevent users from reordering tabs
      preventSplitterResize: false // Prevent users from resizing views
    },
    content: [
      {
        type: 'component',
        componentName: 'view',
        componentState: {
          url: 'https://example.com/view3'
        },
        title: 'View 3',
        isClosable: false    // Prevent users from closing this view
      }
    ]
  }
});

To enable views in a web-based layout to participate in interoperability, refer to Core Web interoperability for content developers.

Add and close views

To add a new view to an existing layout for which you have a LayoutIdentity object (as target):

// assume that `target` is a LayoutIdentity 

const layout = fin.Platform.Layout.wrapSync(target);
await layout.addView(
  { // View Configuration Options
    name: 'EXAMPLE_VIEW',
    url:'http://www.example.com'
  }
);

To close a view, for which you have its Identity as identity:

const layout = await fin.Platform.Layout.getLayoutByViewIdentity(identity);
await layout.closeView(viewIdentity)

Add and remove layouts

You can programmatically add or remove layouts.

To add a layout:

await fin.Platform.Layout.create({
  layoutName: 'newLayout',
  layout: {
    content: [
      {
        type: 'stack',
        content: [
          {
            type: 'component',
            componentName: 'view',
            componentState: {
              url: 'https://example.com/new-view'
            },
            title: 'New View'
          }
        ]
      }
    ]
  }
});

To remove a layout:

await fin.Platform.Layout.destroy('layoutIdentityToRemove');

Style the layout

Web Layouts uses predictable CSS class names, allowing you to easily style the layout components. For example:

/* Style the tab headers */
.lm_tab {
  background-color: #f0f0f0;
  border: 1px solid #ccc;
}

/* Style the content area */
.lm_content {
  padding: 10px;
}

Get a layout snapshot

To retrieve the current state of all layouts:


javascriptCopyconst layoutManager = fin.Platform.Layout.getCurrentLayoutManagerSync();

const layoutSnapshot = await layoutManager.getLayoutSnapshot();

This snapshot can be used to save the current state of layouts and restore them later.

Best practices

  • Use unique and descriptive identifiers for layout names. View names are optional; a name is generated for a view if not provided.

  • Consider user preferences when configuring layout behavior (for example, allowing or disabling drag-and-drop).

  • Test your layouts across different screen sizes to ensure responsiveness.

  • Use the styling capabilities to create a consistent look and feel with your application's branding.

Limitations

  • Web Layouts does not support dragging views between different browser windows.

  • The ability to "pop out" a tab into a new window is not supported.

  • While cross-origin views are allowed, they are restricted by normal content security policies (CSP) for <iframe> elements.