11import BaseContract from './base-contract' ;
22import ExtensionComponent from './extension-component' ;
33import { dasherize } from '@ember/string' ;
4+ import { isArray } from '@ember/array' ;
45import isObject from '../utils/is-object' ;
56
67/**
@@ -123,6 +124,11 @@ export default class MenuItem extends BaseContract {
123124 // plain object with at minimum { title, route } and optionally
124125 // { icon, iconPrefix, id }. Optional – defaults to null.
125126 this . shortcuts = definition . shortcuts || null ;
127+
128+ // An array of string tags used to improve search discoverability in
129+ // the overflow dropdown. e.g. ['logistics', 'tracking', 'fleet'].
130+ // Optional – defaults to null.
131+ this . tags = isArray ( definition . tags ) ? definition . tags : definition . tags ? [ definition . tags ] : null ;
126132 } else {
127133 // Handle string title with optional route (chaining pattern)
128134 this . title = titleOrDefinition ;
@@ -178,6 +184,7 @@ export default class MenuItem extends BaseContract {
178184 // ── Phase 2 additions ──────────────────────────────────────────
179185 this . description = null ;
180186 this . shortcuts = null ;
187+ this . tags = null ;
181188 }
182189
183190 // Call setup() to trigger validation after properties are set
@@ -388,14 +395,40 @@ export default class MenuItem extends BaseContract {
388395 }
389396
390397 /**
391- * Set an array of shortcut items displayed beneath the extension in the
392- * multi-column overflow dropdown. Each shortcut is a plain object:
398+ * Set an array of shortcut items displayed as independent sibling cards in
399+ * the multi-column overflow dropdown (AWS Console style). Each shortcut
400+ * supports the full MenuItem property surface:
401+ *
402+ * Required:
403+ * title {String} Display label
404+ *
405+ * Routing:
406+ * route {String} Ember route name
407+ * queryParams {Object}
408+ * routeParams {Array}
409+ *
410+ * Identity:
411+ * id {String} Explicit id (auto-dasherized from title if omitted)
412+ * slug {String} URL slug (falls back to id)
413+ *
414+ * Icons:
415+ * icon {String} FontAwesome icon name
416+ * iconPrefix {String} FA prefix (e.g. 'far', 'fab')
417+ * iconSize {String} FA size string
418+ * iconClass {String} Extra CSS class on the icon element
419+ * iconComponent {String} Lazy-loaded engine component path
420+ * iconComponentOptions {Object}
393421 *
394- * { title, route, icon?, iconPrefix?, id? }
422+ * Metadata:
423+ * description {String} Short description shown in the card
424+ * tags {String[]} Search tags
395425 *
396- * Shortcuts are purely navigational – they do not support onClick handlers.
397- * They are rendered as compact links inside the extension card in the
398- * dropdown and can be individually pinned to the navigation bar.
426+ * Behaviour:
427+ * onClick {Function} Click handler (receives the shortcut item)
428+ * disabled {Boolean}
429+ *
430+ * Shortcuts are registered as first-class header menu items at boot time
431+ * and can be individually pinned to the navigation bar.
399432 *
400433 * @method withShortcuts
401434 * @param {Array<Object> } shortcuts Array of shortcut definition objects
@@ -404,16 +437,47 @@ export default class MenuItem extends BaseContract {
404437 * @example
405438 * new MenuItem('Fleet-Ops', 'console.fleet-ops')
406439 * .withShortcuts([
407- * { title: 'Scheduler', route: 'console.fleet-ops.scheduler', icon: 'calendar' },
408- * { title: 'Order Config', route: 'console.fleet-ops.order-configs', icon: 'gear' },
440+ * {
441+ * title: 'Scheduler',
442+ * route: 'console.fleet-ops.scheduler',
443+ * icon: 'calendar',
444+ * description: 'Plan and visualise driver schedules',
445+ * tags: ['schedule', 'calendar'],
446+ * },
447+ * {
448+ * title: 'Live Map',
449+ * route: 'console.fleet-ops',
450+ * iconComponent: 'fleet-ops@components /live-map-icon',
451+ * description: 'Real-time vehicle tracking',
452+ * },
409453 * ])
410454 */
411455 withShortcuts ( shortcuts ) {
412- this . shortcuts = Array . isArray ( shortcuts ) ? shortcuts : null ;
456+ this . shortcuts = isArray ( shortcuts ) ? shortcuts : null ;
413457 this . _options . shortcuts = this . shortcuts ;
414458 return this ;
415459 }
416460
461+ /**
462+ * Set an array of string tags for this menu item.
463+ * Tags are matched against the search query in the overflow dropdown,
464+ * making items discoverable even when the query doesn't match the title
465+ * or description.
466+ *
467+ * @method withTags
468+ * @param {String|String[] } tags One tag string or an array of tag strings
469+ * @returns {MenuItem } This instance for chaining
470+ *
471+ * @example
472+ * new MenuItem('Fleet-Ops', 'console.fleet-ops')
473+ * .withTags(['logistics', 'tracking', 'fleet', 'drivers'])
474+ */
475+ withTags ( tags ) {
476+ this . tags = isArray ( tags ) ? tags : tags ? [ tags ] : null ;
477+ this . _options . tags = this . tags ;
478+ return this ;
479+ }
480+
417481 /**
418482 * Add a single shortcut to the existing shortcuts array.
419483 * Creates the array if it does not yet exist.
@@ -428,7 +492,7 @@ export default class MenuItem extends BaseContract {
428492 * .addShortcut({ title: 'Order Config', route: 'console.fleet-ops.order-configs' })
429493 */
430494 addShortcut ( shortcut ) {
431- if ( ! Array . isArray ( this . shortcuts ) ) {
495+ if ( ! isArray ( this . shortcuts ) ) {
432496 this . shortcuts = [ ] ;
433497 }
434498 this . shortcuts = [ ...this . shortcuts , shortcut ] ;
@@ -502,6 +566,9 @@ export default class MenuItem extends BaseContract {
502566 // Optional array of shortcut sub-links shown inside the extension card
503567 shortcuts : this . shortcuts ,
504568
569+ // Optional array of string tags for search discoverability
570+ tags : this . tags ,
571+
505572 // Indicator flag
506573 _isMenuItem : true ,
507574
0 commit comments