Configuring a SheetFrameHeader

The sheet frame header is especially intended to use in multi-document editors.

The sheet frame header is especially intended to use in multi-document editors. It provides an area in the top of a sheet frame(see figure 1), in which users can see and manipulate the current state of a document. Examples of these actions are saving, acquiring/releasing a lock or updating a document to its latest version. 

Figure 1: An example of the sheet frame header in a specific document state.

The new sheet frame header is a replacement of the following widget areas:

  • blockBanner
  • blockHeader
  • blockHeaderLeft
  • blockHeaderRight

This does not apply for node/document previews. In that case the original widgets and widget areas are still used. The document/node previews do NOT use the new sheet frame header. If you want to see any widgets in areas from the list above during a preview (such as a markup label in blockHeaderLeft), make sure you still configure it for the blockHeaderLeft area even if you use the new [default] sheet frame header (which also uses a markup label widget).

Default or custom 

There are two ways to configure a sheet frame header. You can choose to use the default sheet frame header we provide in order to quickly get up and running. If this does not fulfil the needs of the people who use your editor, it is also possible to configure a custom sheet frame header where you can use custom components and the components from the default sheet frame header as you like. 

Using the default sheet frame header

The DefaultSheetFrameHeader consists of the following components:

  • DocumentLockStateWidget: A widget indicating the lock status, allowing the user to release/acquire the lock by clicking the widget.
  • DocumentMarkupLabel: The markup label of the configured sheet frame node.
  • SheetFrameHeaderDocumentStateLabel: A label indicating the current state of the document (document saving state, document out of sync state, further clarification of the lock status).
  • DocumentStateSyncButton: When the document is out of sync, a button is shown allowing the user to refresh the document.
  • DocumentSaveWidget: A widget indicating the save status, allowing the user to save the document by clicking the widget.
  • DocumentContextualOperationsWidget: A contextual operations widget, showing all available contextual operations in a menu which can be opened by clicking the widget.

These components are laid out in three sub-areas of the sheet frame header(see figure 2).

  1. The lock area (FxSheetFrameHeaderLockArea) has the same width as the left padding of a sheet frame. As the name suggests, this area is designed to contain the DocumentLockStateWidget.
  2. The Info area (FxSheetFrameHeaderLockArea) is an area with flexible width, and can be used to display state information, for example by using the SheetFrameHeaderDocumentStateLabel. 
  3. The action area (FxSheetFrameHeaderActionArea) is where buttons and other actions, like the DocumentSaveWidget or the DocumentContextualOperationsWidget should be. This area also grows- and shrinks based on the size of its content.

Figure 2: The different areas within the sheet frame header.


In order to configure this we can add the "sheetFrameHeaderComponentName" option to configureAsSheetFrame for the corresponding element like so:

configureSxModule.js
import configureAsSheetFrame from 'fontoxml-families/src/configureAsSheetFrame.js';

export default function configureSxModule(sxModule) {
	configureAsSheetFrame(sxModule, 'self::topic', 'topic', {
		sheetFrameHeaderComponentName: 'DefaultSheetFrameHeader'
	});
}


Caveats and known limitations

The sheet frame header may not be used in combination with the CVK visualisation option showWhen: 'has-focus'.


The default sheet frame header is designed for and is only supported for editors that use multiple documents: using separate files per document.

Using a custom sheet frame header

If the default sheet frame header does not work for your intended experience, you can set up a custom sheet frame header. All components of the default sheet frame header are available from the SDK, allowing you to pick and match the parts you need.

There is currently no overflow handling in the sheet frame header. When designing a custom sheet frame header, make sure that the components you use fit inside the header properly.


In order to configure a custom sheet frame header, it's required to register it as a custom React component. This can be done using uiManager.registerReactComponent, which should be done from the install.js of your package like so:

your-awesome-package/src/install.js
import uiManager from 'fontoxml-modular-ui/src/uiManager.js';
import MyAwesomeSheetFrameHeader from './ui/MyAwesomeSheetFrameHeader.jsx';

export default function install() {
	uiManager.registerReactComponent('MyAwesomeSheetFrameHeader', MyAwesomeSheetFrameHeader);
}

As a starting point, this is the actual implementation of the DefaultSheetFrameHeader, but implemented as the "MyAwesomeSheetFrameHeader" we just registered as a custom sheet frame header.

your-awesome-package/src/ui/MyAwesomeSheetFrameHeader.jsx
import PropTypes from 'prop-types';
import React from 'react';

import useRemoteDocumentState from 'fontoxml-remote-documents/src/useRemoteDocumentState.js';

import FxDocumentContextualOperationsWidget from 'fontoxml-fx/src/FxDocumentContextualOperationsWidget.jsx';
import FxDocumentLockStateWidget from 'fontoxml-fx/src/FxDocumentLockStateWidget.jsx';
import FxDocumentMarkupLabel from 'fontoxml-fx/src/FxDocumentMarkupLabel.jsx';
import FxDocumentSaveWidget from 'fontoxml-fx/src/FxDocumentSaveWidget.jsx';
import FxDocumentStateSyncButton from 'fontoxml-fx/src/FxDocumentStateSyncButton.jsx';
import FxSheetFrameHeaderActionArea from 'fontoxml-fx/src/FxSheetFrameHeaderActionArea.jsx';
import FxSheetFrameHeaderContainer from 'fontoxml-fx/src/FxSheetFrameHeaderContainer.jsx';
import FxSheetFrameHeaderDocumentStateLabel from 'fontoxml-fx/src/FxSheetFrameHeaderDocumentStateLabel.jsx';
import FxSheetFrameHeaderInfoArea from 'fontoxml-fx/src/FxSheetFrameHeaderInfoArea.jsx';
import FxSheetFrameHeaderLockArea from 'fontoxml-fx/src/FxSheetFrameHeaderLockArea.jsx';

/**
 * Note: all props are set automatically by the SDK, This component is usually not rendered
 * manually.
 */
function MyAwesomeSheetFrameHeader({
    contextNodeId,
    documentId,
    hierarchyNodeId,
    markupLabel,
    productContext
}) {
    const remoteDocumentState = useRemoteDocumentState(documentId);

    return (
        <FxSheetFrameHeaderContainer productContext={productContext}>
            <FxSheetFrameHeaderLockArea productContext={productContext}>
                {productContext === 'editor' && (
                    <FxDocumentLockStateWidget
                        documentId={documentId}
                        remoteDocumentState={remoteDocumentState}
                    />
                )}
            </FxSheetFrameHeaderLockArea>

            <FxSheetFrameHeaderInfoArea productContext={productContext}>
                <FxDocumentMarkupLabel>{markupLabel}</FxDocumentMarkupLabel>

                <FxSheetFrameHeaderDocumentStateLabel
                    documentId={documentId}
                    remoteDocumentState={remoteDocumentState}
                />
            </FxSheetFrameHeaderInfoArea>

            <FxSheetFrameHeaderActionArea productContext={productContext}>
                <FxDocumentStateSyncButton
                    documentId={documentId}
                    remoteDocumentState={remoteDocumentState}
                />

                {productContext === 'editor' && (
                    <FxDocumentSaveWidget
                        documentId={documentId}
						hierarchyNodeId={hierarchyNodeId}
                        remoteDocumentState={remoteDocumentState}
                    />
                )}

                {productContext === 'editor' && (
                    <FxDocumentContextualOperationsWidget contextNodeId={contextNodeId} hierarchyNodeId={hierarchyNodeId} />
                )}
            </FxSheetFrameHeaderActionArea>
        </FxSheetFrameHeaderContainer>
    );
}
MyAwesomeSheetFrameHeader.propTypes = {
    /**
     * The node id of the node that is configured as a sheet frame.
     * This is used to retrieve the contextual information such as operations for this node.
     */
    contextNodeId: PropTypes.string.isRequired,
    /**
     * The (local) document id of the document of the sheet frame node.
     * Used to determine contextual information for the document in which the sheet frame node occurs.
     */
    documentId: PropTypes.string.isRequired,
	/**
     * The id of the document's hierarchy node for which the sheet frame header is configured.
     */
    hierarchyNodeId: PropTypes.string.isRequired,
    /**
     * The markup label of the sheet frame node.
     */
    markupLabel: PropTypes.string.isRequired,
    /**
     * The system name of the product in which the sheet frame (header) is being rendered.
     * Used to alter the look'n'feel of certain parts and/or to disable certain parts in certain
     * contexts.
     * For example, in context of the review product the content is read-only. So the lock widget,
     * save widget and contextual operations are not used there.
     *
     * Can be one of either:
     * - "editor"
     * - "review"
     * - "history"
     */
    productContext: PropTypes.string.isRequired
};

export default MyAwesomeSheetFrameHeader;
Was this page helpful?