Skip to content

Developers Guide ‐ Menu

Brad Simpson edited this page Feb 12, 2026 · 5 revisions

What is a Menu?

In Adapt Framework, a menu is a special type of ContentObject that displays navigation options to learners, allowing them to choose which pages or submenus to access. Menus serve as the primary navigation structure for courses.

Box Menu is the default menu plugin bundled with Adapt Framework. While other menu plugins can be installed and used, Box Menu provides the standard menu functionality for most courses.

Box Menu can be configured at two levels: course-level (global settings) and ContentObject-level (individual menu appearance). For complete configuration examples, see Box Menu's example.json.

Key Concepts

  • Menu - A ContentObject with "_type": "menu" that displays child items
  • Menu Items - ContentObjects (pages or nested menus) that appear as clickable tiles in the menu
  • Grouped Items - Multiple menu items visually grouped under a shared heading
  • Submenus - Nested menus that provide hierarchical navigation
  • Locking - Menu items can be locked to control access and enforce sequential progression. See Locking objects with '_isLocked' and '_lockType' for details.

Course-Level Settings

Course-level settings are defined in course.json and apply globally to all menus.

Global Text Labels

Attribute Type Description Default Framework Version
_globals._menu._boxMenu.itemCount String Label template for item count. Use {{_nthChild}} and {{_totalChild}} placeholders "Item {{_nthChild}} of {{_totalChild}}" v5.0+
_globals._menu._boxMenu.durationLabel String Label displayed before duration text "Duration:" v5.0+

Example:

{
  "_globals": {
    "_menu": {
      "_boxMenu": {
        "itemCount": "Item {{_nthChild}} of {{_totalChild}}",
        "durationLabel": "Duration:"
      }
    }
  }
}

Course Menu Header

Configure the appearance of the course-level menu (typically the home menu).

Attribute Type Description Framework Version
_boxMenu._graphic Object Logo image displayed above menu title v5.0+
_boxMenu._backgroundImage Object Background images for different screen sizes v5.0+
_boxMenu._backgroundStyles Object CSS background properties (size, repeat, position) v5.0+
_boxMenu._menuHeader Object Header configuration including text alignment, background, and minimum heights v5.0+

Graphic

Attribute Type Description Framework Version
_boxMenu._graphic._src String Path to logo image v5.0+
_boxMenu._graphic.alt String Alternative text for logo. Leave blank for decorative images v5.0+

Background Image

Attribute Type Description Framework Version
_boxMenu._backgroundImage._xlarge String Background image for extra large screens (HD laptop/desktop) v5.0+
_boxMenu._backgroundImage._large String Background image for large screens (laptop/desktop) v5.0+
_boxMenu._backgroundImage._medium String Background image for medium screens (tablet) v5.0+
_boxMenu._backgroundImage._small String Background image for small screens (mobile) v5.0+

Background Styles

Attribute Type Values Description Framework Version
_boxMenu._backgroundStyles._backgroundRepeat String "", "repeat", "repeat-x", "repeat-y", "no-repeat" Controls how background image repeats. Empty string uses browser default v5.0+
_boxMenu._backgroundStyles._backgroundSize String "", "auto", "cover", "contain" Resize behavior. cover: stretch/crop to fill container. contain: fit entire image visible v5.0+
_boxMenu._backgroundStyles._backgroundPosition String "", "left top", "left center", "left bottom", "center top", "center center", "center bottom", "right top", "right center", "right bottom" Position of background image. First value is horizontal, second is vertical v5.0+

Menu Header Configuration

The _menuHeader object controls the appearance of the menu header area.

Text Alignment

Attribute Type Values Description Framework Version
_boxMenu._menuHeader._textAlignment._title String "", "left", "center", "right" Alignment of menu title. Automatically reverses for RTL languages v5.0+
_boxMenu._menuHeader._textAlignment._subtitle String "", "left", "center", "right" Alignment of menu subtitle. Automatically reverses for RTL languages v5.0+
_boxMenu._menuHeader._textAlignment._body String "", "left", "center", "right" Alignment of menu body text. Automatically reverses for RTL languages v5.0+
_boxMenu._menuHeader._textAlignment._instruction String "", "left", "center", "right" Alignment of menu instruction text. Automatically reverses for RTL languages v5.0+

Header Background Image and Styles

The header supports its own background image and styling, separate from the main menu background. Uses the same structure as the main background:

  • _boxMenu._menuHeader._backgroundImage - Same properties as main background (_xlarge, _large, _medium, _small)
  • _boxMenu._menuHeader._backgroundStyles - Same properties as main background (_backgroundRepeat, _backgroundSize, _backgroundPosition)

Minimum Heights

Attribute Type Description Framework Version
_boxMenu._menuHeader._minimumHeights._xlarge Number Minimum height in pixels for extra large screens. Use to prevent background image cropping v5.0+
_boxMenu._menuHeader._minimumHeights._large Number Minimum height in pixels for large screens v5.0+
_boxMenu._menuHeader._minimumHeights._medium Number Minimum height in pixels for medium screens v5.0+
_boxMenu._menuHeader._minimumHeights._small Number Minimum height in pixels for small screens v5.0+

Example:

{
  "_boxMenu": {
    "_graphic": {
      "alt": "Course Logo",
      "_src": "course/en/images/logo.png"
    },
    "_backgroundImage": {
      "_xlarge": "course/en/images/menu-bg-xlarge.jpg",
      "_large": "course/en/images/menu-bg-large.jpg",
      "_medium": "course/en/images/menu-bg-medium.jpg",
      "_small": "course/en/images/menu-bg-small.jpg"
    },
    "_backgroundStyles": {
      "_backgroundSize": "cover",
      "_backgroundRepeat": "no-repeat",
      "_backgroundPosition": "center center"
    },
    "_menuHeader": {
      "_textAlignment": {
        "_title": "center",
        "_subtitle": "center",
        "_body": "left",
        "_instruction": "left"
      },
      "_backgroundImage": {
        "_xlarge": "course/en/images/header-bg.jpg",
        "_large": "course/en/images/header-bg.jpg",
        "_medium": "course/en/images/header-bg.jpg",
        "_small": "course/en/images/header-bg.jpg"
      },
      "_backgroundStyles": {
        "_backgroundSize": "cover",
        "_backgroundRepeat": "no-repeat",
        "_backgroundPosition": "center center"
      },
      "_minimumHeights": {
        "_xlarge": 500,
        "_large": 500,
        "_medium": 400,
        "_small": 200
      }
    }
  }
}

ContentObject Settings

Individual menus (ContentObjects with "_type": "menu") can override the course-level menu header settings.

Attribute Type Description Framework Version
_boxMenu._renderAsGroup Boolean When true, renders this menu as a grouped set of items on the parent menu instead of a navigable submenu v5.0+

Note: Submenu ContentObjects can use the same _boxMenu properties as the course-level menu (background images, styles, header configuration) to customize their appearance.

Menu Items

Menu items are ContentObjects (typically pages) that appear as tiles in the menu. Standard ContentObject properties control their display:

Attribute Type Description Framework Version
_id String Unique identifier for the ContentObject v5.0+
_parentId String ID of parent menu. Use "course" for top-level items v5.0+
_type String "page" for navigable pages, "menu" for submenus v5.0+
title String Item title (translatable) v5.0+
displayTitle String Title displayed in menu (translatable) v5.0+
body String Description text (translatable) v5.0+
_graphic Object Thumbnail image with src and alt properties v5.0+
linkText String Text for the navigation link (translatable) v5.0+
_linkIconClass String CSS class for link icon (e.g., "icon-controls-right") v5.0+
_linkIconPosition String Icon position: "left" or "right" v5.0+
duration String Estimated completion time (translatable) v5.0+
_isLocked Boolean When true, prevents navigation to this item. See locking documentation v5.0+

Example

{
  "_id": "co-05",
  "_parentId": "course",
  "_type": "page",
  "title": "Introduction",
  "displayTitle": "Introduction",
  "body": "Learn the basics in this introductory module",
  "_graphic": {
    "alt": "Introduction module",
    "src": "course/en/images/intro-thumb.jpg"
  },
  "linkText": "View",
  "_linkIconClass": "icon-controls-right",
  "_linkIconPosition": "right",
  "duration": "5 mins"
}

Grouped Items and Submenus

Box Menu supports two ways to organize menu items: grouped items and submenus. While they may appear similar, they serve different purposes.

Creating Grouped Items

Grouped items visually organize related menu items under a shared heading on the same menu screen. Groups display title, body, and instruction text above their items but do not create separate navigable screens.

When to Use Grouped Items

  • Organize related pages under thematic headings
  • Maintain all items on a single menu screen
  • Provide context for a set of menu items without additional navigation

Grouped Items Setup

  1. Create a ContentObject with "_type": "menu" as the group container
  2. Set "_boxMenu._renderAsGroup": true on this ContentObject
  3. Add child ContentObjects with _parentId matching the group's _id

Grouped Items Example

[
  {
    "_id": "module-1-group",
    "_parentId": "course",
    "_type": "menu",
    "title": "Module 1: Foundations",
    "displayTitle": "Module 1: Foundations",
    "body": "Complete these foundational lessons",
    "instruction": "Select a lesson to begin",
    "_boxMenu": {
      "_renderAsGroup": true
    }
  },
  {
    "_id": "co-10",
    "_parentId": "module-1-group",
    "_type": "page",
    "title": "Lesson 1",
    "displayTitle": "Getting Started",
    "body": "Learn the basics"
  },
  {
    "_id": "co-11",
    "_parentId": "module-1-group",
    "_type": "page",
    "title": "Lesson 2",
    "displayTitle": "Core Concepts",
    "body": "Understand key principles"
  }
]

Creating Submenus

Submenus are navigable menus nested within other menus, creating a hierarchical navigation structure. Clicking a submenu item navigates to a new menu screen.

When to Use Submenus

  • Create multi-level course structures
  • Organize large courses into sections
  • Provide separate navigation contexts for different course modules

Submenu Setup

  1. Create a ContentObject with "_type": "menu" as the submenu
  2. Do NOT set _renderAsGroup (or set it to false)
  3. Add child ContentObjects with _parentId matching the submenu's _id

Submenu Example

[
  {
    "_id": "advanced-module",
    "_parentId": "course",
    "_type": "menu",
    "title": "Advanced Topics",
    "displayTitle": "Advanced Topics",
    "body": "Explore advanced concepts",
    "_graphic": {
      "alt": "Advanced module",
      "src": "course/en/images/advanced-thumb.jpg"
    },
    "linkText": "Explore"
  },
  {
    "_id": "co-20",
    "_parentId": "advanced-module",
    "_type": "page",
    "title": "Advanced Lesson 1",
    "displayTitle": "Complex Systems",
    "body": "Deep dive into complex topics"
  }
]

Grouped Items vs. Submenus

Feature Grouped Items Submenus
Navigation No navigation - items stay on same menu Navigates to new menu screen
Visual Treatment Items grouped under heading on parent menu Appears as single clickable item on parent menu
Use _renderAsGroup true false or omitted
Displays group title/body Yes, above grouped items Yes, when navigated to submenu
Typical Use Case Thematic grouping on one screen Hierarchical navigation structure

Menu Architecture

Understanding the menu architecture helps when configuring courses or creating custom menu plugins.

Core Classes

Adapt Framework provides base classes in the core:

  • MenuModel (src/core/js/models/menuModel.js) - Extends ContentObjectModel. Handles menu-specific logic including locking behavior via _isLocked and _lockType
  • MenuView (src/core/js/views/menuView.js) - Extends ContentObjectView. Base class for rendering menu layouts
  • MenuItemView (src/core/js/views/menuItemView.js) - Base class for rendering individual menu items

Box Menu Classes

Box Menu extends these core classes:

  • BoxMenuModel - Extends MenuModel for Box Menu-specific model logic
  • BoxMenuView - Extends MenuView. Renders the menu container and determines whether items render as groups or standard items
  • BoxMenuItemView - Extends MenuItemView. Renders individual clickable menu items
  • BoxMenuGroupView - Extends MenuItemView. Renders grouped items with a heading

Registration

Menu plugins register with the framework's component system. Box Menu uses a dual registration to support both explicit and default usage:

// Default menu for "_type": "course" or "_type": "menu"
components.register('course menu', {
  view: BoxMenuView,
  model: BoxMenuModel
});

// Explicit usage with "_component": "boxMenu"
components.register('boxMenu', {
  view: BoxMenuView,
  model: BoxMenuModel
});

How Menus Are Rendered

  1. Framework encounters a ContentObject with "_type": "menu"
  2. Looks up registered menu view/model (defaults to Box Menu if installed)
  3. Creates menu view instance, which renders menu header and container
  4. For each child ContentObject:
    • If child has "_type": "menu" and "_renderAsGroup": true, renders as BoxMenuGroupView
    • Otherwise, renders as BoxMenuItemView
  5. Menu items become clickable and navigate via the router

Creating Custom Menu Plugins

While Box Menu handles most use cases, you may want to create a custom menu plugin for unique navigation requirements or visual designs.

Basic Structure

A menu plugin requires:

  1. Model class extending MenuModel
  2. View class extending MenuView
  3. Item view class extending MenuItemView (optional, can use core's MenuItemView)
  4. Registration via components.register()
  5. Templates (JSX or Handlebars)
  6. Schema files for configuration options

Minimal Example

js/myMenu.js

import components from 'core/js/components';
import MenuView from 'core/js/views/menuView';
import MenuModel from 'core/js/models/menuModel';

class MyMenuView extends MenuView {
  className() {
    return `${super.className()} mymenu`;
  }
}

MyMenuView.template = 'myMenu.jsx';

components.register('course menu', {
  view: MyMenuView,
  model: MenuModel
});

export default MyMenuView;

templates/myMenu.jsx

import React from 'react';
import { html, classes, compile } from 'core/js/reactHelpers';

export default function MyMenu(props) {
  const { displayTitle, body } = props;

  return (
    <div className="mymenu__inner">
      <div className="mymenu__header">
        {displayTitle && <h1 className="mymenu__title">{displayTitle}</h1>}
        {body && <div className="mymenu__body">{html(compile(body, props))}</div>}
      </div>
      <div className="mymenu__items js-children"></div>
    </div>
  );
}

Key Implementation Notes

  1. childContainer - Set static childContainer = '.js-children' to specify where child items render
  2. childView - Set static childView = MenuItemView or your custom item view class
  3. Templates - The js-children element is where framework injects menu items
  4. Styling - Add custom LESS files for visual design
  5. Schemas - Define configuration options in schema/*.schema.json files

Custom Item Views

If you need custom rendering for menu items, always check _isLocked before allowing navigation:

import MenuItemView from 'core/js/views/menuItemView';
import router from 'core/js/router';

class MyMenuItemView extends MenuItemView {

  events() {
    return {
      'click .js-item-click': 'onItemClick'
    };
  }

  onItemClick(event) {
    event?.preventDefault();
    // Always respect locking - see locking documentation for details
    if (this.model.get('_isLocked')) return;
    router.navigateToElement(this.model.get('_id'));
  }
}

MyMenuItemView.template = 'myMenuItem.jsx';

export default MyMenuItemView;

Adding Configuration Options

Define custom options in schema/course.schema.json and/or schema/contentobject.schema.json. See Box Menu's schema files for examples of property definitions.

Related Documentation

Note: For information about specific releases and features, see the Box Menu releases page.

Clone this wiki locally