@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.63 → 2.0.0-next.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +392 -381
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +57 -199
  4. package/dist/alert-severity.d.ts.map +1 -1
  5. package/dist/alert-severity.js +37 -35
  6. package/dist/alert-severity.js.map +1 -1
  7. package/dist/ar/building-blocks/poi-header/poi-header.css.js +15 -15
  8. package/dist/ar/building-blocks/poi-header/poi-header.d.ts +6 -6
  9. package/dist/ar/building-blocks/poi-header/poi-header.d.ts.map +1 -1
  10. package/dist/ar/building-blocks/poi-header/poi-header.js +5 -5
  11. package/dist/ar/building-blocks/poi-header/poi-header.js.map +1 -1
  12. package/dist/ar/poi-button/poi-button.css.js +31 -30
  13. package/dist/ar/poi-button/poi-button.css.js.map +1 -1
  14. package/dist/ar/poi-button/poi-button.d.ts +6 -6
  15. package/dist/ar/poi-button/poi-button.d.ts.map +1 -1
  16. package/dist/ar/poi-button/poi-button.js +15 -15
  17. package/dist/ar/poi-button/poi-button.js.map +1 -1
  18. package/dist/ar/types.d.ts +5 -5
  19. package/dist/ar/types.d.ts.map +1 -1
  20. package/dist/ar/types.js +5 -5
  21. package/dist/ar/types.js.map +1 -1
  22. package/dist/automation/automation-badge/automation-badge.d.ts +7 -7
  23. package/dist/automation/automation-badge/automation-badge.d.ts.map +1 -1
  24. package/dist/automation/automation-badge/automation-badge.js +29 -29
  25. package/dist/automation/automation-badge/automation-badge.js.map +1 -1
  26. package/dist/automation/automation-button/abstract-automation-button.d.ts +5 -5
  27. package/dist/automation/automation-button/abstract-automation-button.d.ts.map +1 -1
  28. package/dist/automation/automation-button/abstract-automation-button.js +15 -15
  29. package/dist/automation/automation-button/abstract-automation-button.js.map +1 -1
  30. package/dist/automation/automation-tank/automation-tank.js +10 -10
  31. package/dist/automation/automation-tank/automation-tank.js.map +1 -1
  32. package/dist/components/accordion-card/accordion-card.css.js +5 -5
  33. package/dist/components/alert-button/alert-button.css.js +128 -128
  34. package/dist/components/alert-frame/alert-frame.css.js +6 -6
  35. package/dist/components/alert-frame/alert-frame.d.ts +4 -4
  36. package/dist/components/alert-frame/alert-frame.js.map +1 -1
  37. package/dist/components/alert-icon/alert-icon.js +4 -4
  38. package/dist/components/alert-icon/alert-icon.js.map +1 -1
  39. package/dist/components/badge/badge.css.js +10 -10
  40. package/dist/components/badge/badge.d.ts +13 -13
  41. package/dist/components/badge/badge.d.ts.map +1 -1
  42. package/dist/components/badge/badge.js +10 -10
  43. package/dist/components/badge/badge.js.map +1 -1
  44. package/dist/components/navigation-item/navigation-item.d.ts +7 -7
  45. package/dist/components/navigation-item/navigation-item.d.ts.map +1 -1
  46. package/dist/components/navigation-item/navigation-item.js +3 -15
  47. package/dist/components/navigation-item/navigation-item.js.map +1 -1
  48. package/dist/components/navigation-item-group/navigation-item-group.d.ts +8 -7
  49. package/dist/components/navigation-item-group/navigation-item-group.d.ts.map +1 -1
  50. package/dist/components/navigation-item-group/navigation-item-group.js +3 -15
  51. package/dist/components/navigation-item-group/navigation-item-group.js.map +1 -1
  52. package/dist/components/navigation-menu/navigation-menu.d.ts +2 -2
  53. package/dist/components/navigation-menu/navigation-menu.js.map +1 -1
  54. package/dist/components/tree-navigation-group/tree-navigation-group.d.ts +10 -10
  55. package/dist/components/tree-navigation-group/tree-navigation-group.d.ts.map +1 -1
  56. package/dist/components/tree-navigation-group/tree-navigation-group.js +3 -15
  57. package/dist/components/tree-navigation-group/tree-navigation-group.js.map +1 -1
  58. package/dist/components/tree-navigation-item/tree-navigation-item.css.js +13 -0
  59. package/dist/components/tree-navigation-item/tree-navigation-item.css.js.map +1 -1
  60. package/dist/components/tree-navigation-item/tree-navigation-item.d.ts +59 -8
  61. package/dist/components/tree-navigation-item/tree-navigation-item.d.ts.map +1 -1
  62. package/dist/components/tree-navigation-item/tree-navigation-item.js +46 -17
  63. package/dist/components/tree-navigation-item/tree-navigation-item.js.map +1 -1
  64. package/dist/manual-icon/icon-alerts-critical-twotone.d.ts +1 -1
  65. package/dist/manual-icon/icon-alerts-critical-twotone.js.map +1 -1
  66. package/dist/manual-icon/icon-alerts-diagnostic-twotone.d.ts +1 -1
  67. package/dist/manual-icon/icon-alerts-diagnostic-twotone.js.map +1 -1
  68. package/dist/types.d.ts +5 -5
  69. package/dist/types.d.ts.map +1 -1
  70. package/dist/types.js +11 -11
  71. package/dist/types.js.map +1 -1
  72. package/package.json +1 -1
  73. package/src/alert-severity.ts +43 -41
  74. package/src/ar/building-blocks/poi-header/poi-header.css +15 -15
  75. package/src/ar/building-blocks/poi-header/poi-header.ts +6 -6
  76. package/src/ar/poi-button/poi-button.css +31 -30
  77. package/src/ar/poi-button/poi-button.ts +16 -16
  78. package/src/ar/types.ts +5 -5
  79. package/src/automation/automation-badge/automation-badge.ts +22 -22
  80. package/src/automation/automation-button/abstract-automation-button.ts +15 -15
  81. package/src/automation/automation-tank/automation-tank.stories.ts +6 -6
  82. package/src/automation/automation-tank/automation-tank.ts +10 -10
  83. package/src/components/accordion-card/accordion-card.css +5 -5
  84. package/src/components/alert-button/alert-button.css +14 -14
  85. package/src/components/alert-button/alert-button.stories.ts +10 -10
  86. package/src/components/alert-frame/alert-frame.css +6 -6
  87. package/src/components/alert-frame/alert-frame.stories.ts +10 -10
  88. package/src/components/alert-frame/alert-frame.ts +4 -4
  89. package/src/components/alert-icon/alert-icon.stories.ts +10 -10
  90. package/src/components/alert-icon/alert-icon.ts +4 -4
  91. package/src/components/alert-list-details/alert-list-details.stories.ts +11 -11
  92. package/src/components/badge/badge.css +10 -10
  93. package/src/components/badge/badge.stories.ts +10 -10
  94. package/src/components/badge/badge.ts +18 -18
  95. package/src/components/navigation-item/navigation-item.ts +8 -12
  96. package/src/components/navigation-item-group/navigation-item-group.ts +9 -12
  97. package/src/components/navigation-menu/navigation-menu.stories.ts +34 -6
  98. package/src/components/navigation-menu/navigation-menu.ts +2 -2
  99. package/src/components/tree-navigation/tree-navigation.stories.ts +154 -9
  100. package/src/components/tree-navigation-group/tree-navigation-group.ts +11 -15
  101. package/src/components/tree-navigation-item/tree-navigation-item.css +12 -0
  102. package/src/components/tree-navigation-item/tree-navigation-item.stories.ts +38 -15
  103. package/src/components/tree-navigation-item/tree-navigation-item.ts +98 -17
  104. package/src/manual-icon/icon-alerts-critical-twotone.ts +1 -1
  105. package/src/manual-icon/icon-alerts-diagnostic-twotone.ts +1 -1
  106. package/src/navigation-instruments/readout/readout.stories.ts +2 -2
  107. package/src/navigation-instruments/readout-list-item/readout-list-item.stories.ts +4 -4
  108. package/src/types.ts +10 -10
@@ -188,57 +188,57 @@ export const OneItem: Story = {
188
188
  },
189
189
  };
190
190
 
191
- export const IsaCategories: Story = {
191
+ export const LevelCategories: Story = {
192
192
  args: {
193
193
  alerts: [
194
194
  {
195
- id: 'isa-1',
195
+ id: 'level-1',
196
196
  tagId: 'CRIT-01',
197
197
  source: 'PCS',
198
198
  text: 'Emergency shutdown condition detected',
199
199
  acknowledged: false,
200
200
  active: true,
201
- type: AlertType.IsaCritical,
201
+ type: AlertType.LevelCritical,
202
202
  time: new Date('2024-01-15T14:32:15Z'),
203
203
  },
204
204
  {
205
- id: 'isa-2',
205
+ id: 'level-2',
206
206
  tagId: 'HIGH-02',
207
207
  source: 'ME 1',
208
208
  text: 'Main engine overspeed',
209
209
  acknowledged: false,
210
210
  active: true,
211
- type: AlertType.IsaHigh,
211
+ type: AlertType.LevelHigh,
212
212
  time: new Date('2024-01-15T14:30:00Z'),
213
213
  },
214
214
  {
215
- id: 'isa-3',
215
+ id: 'level-3',
216
216
  tagId: 'MED-03',
217
217
  source: 'Tank 1',
218
218
  text: 'Tank level approaching high limit',
219
219
  acknowledged: false,
220
220
  active: true,
221
- type: AlertType.IsaMedium,
221
+ type: AlertType.LevelMedium,
222
222
  time: new Date('2024-01-15T14:28:00Z'),
223
223
  },
224
224
  {
225
- id: 'isa-4',
225
+ id: 'level-4',
226
226
  tagId: 'LOW-04',
227
227
  source: 'HVAC',
228
228
  text: 'Filter maintenance due',
229
229
  acknowledged: false,
230
230
  active: true,
231
- type: AlertType.IsaLow,
231
+ type: AlertType.LevelLow,
232
232
  time: new Date('2024-01-15T14:25:00Z'),
233
233
  },
234
234
  {
235
- id: 'isa-5',
235
+ id: 'level-5',
236
236
  tagId: 'DIAG-05',
237
237
  source: 'Network',
238
238
  text: 'Redundant link diagnostic message',
239
239
  acknowledged: false,
240
240
  active: true,
241
- type: AlertType.IsaDiagnostic,
241
+ type: AlertType.LevelDiagnostic,
242
242
  time: new Date('2024-01-15T14:20:00Z'),
243
243
  },
244
244
  ],
@@ -92,31 +92,31 @@
92
92
  }
93
93
 
94
94
  &.type-caution,
95
- &.type-isa-low {
95
+ &.type-level-low {
96
96
  background-color: var(--alert-caution-color);
97
97
  border-color: var(--alert-caution-outline-color);
98
98
  color: var(--on-caution-color);
99
99
  }
100
100
 
101
- &.type-isa-critical {
101
+ &.type-level-critical {
102
102
  background-color: var(--critical-enabled-background-color);
103
103
  border-color: var(--critical-enabled-border-color);
104
104
  color: var(--on-critical-color);
105
105
  }
106
106
 
107
- &.type-isa-high {
107
+ &.type-level-high {
108
108
  background-color: var(--alert-alarm-color);
109
109
  border-color: var(--alert-alarm-outline-color);
110
110
  color: var(--on-alarm-color);
111
111
  }
112
112
 
113
- &.type-isa-medium {
113
+ &.type-level-medium {
114
114
  background-color: var(--alert-warning-color);
115
115
  border-color: var(--alert-warning-outline-color);
116
116
  color: var(--on-warning-color);
117
117
  }
118
118
 
119
- &.type-isa-diagnostic {
119
+ &.type-level-diagnostic {
120
120
  background-color: var(--notification-enabled-background-color);
121
121
  border-color: var(--notification-enabled-border-color);
122
122
  color: var(--on-notification-active-color);
@@ -173,31 +173,31 @@
173
173
  background: none;
174
174
  }
175
175
  .icon.type-caution,
176
- .icon.type-isa-low {
176
+ .icon.type-level-low {
177
177
  color: unset;
178
178
  border-color: var(--alert-caution-outline-color);
179
179
  background: none;
180
180
  }
181
181
 
182
- .icon.type-isa-critical {
182
+ .icon.type-level-critical {
183
183
  color: unset;
184
184
  border-color: var(--critical-enabled-border-color);
185
185
  background: none;
186
186
  }
187
187
 
188
- .icon.type-isa-high {
188
+ .icon.type-level-high {
189
189
  color: unset;
190
190
  border-color: var(--alert-alarm-outline-color);
191
191
  background: none;
192
192
  }
193
193
 
194
- .icon.type-isa-medium {
194
+ .icon.type-level-medium {
195
195
  color: unset;
196
196
  border-color: var(--alert-warning-outline-color);
197
197
  background: none;
198
198
  }
199
199
 
200
- .icon.type-isa-diagnostic {
200
+ .icon.type-level-diagnostic {
201
201
  color: unset;
202
202
  border-color: var(--notification-enabled-border-color);
203
203
  background: none;
@@ -199,8 +199,8 @@ export const Caution: Story = {
199
199
  },
200
200
  };
201
201
 
202
- export const IsaCritical: Story = {
203
- args: {type: BadgeType.isaCritical, showIcon: true},
202
+ export const LevelCritical: Story = {
203
+ args: {type: BadgeType.levelCritical, showIcon: true},
204
204
  render(args) {
205
205
  return html`<obc-badge
206
206
  number=${args.number}
@@ -214,8 +214,8 @@ export const IsaCritical: Story = {
214
214
  },
215
215
  };
216
216
 
217
- export const IsaHigh: Story = {
218
- args: {type: BadgeType.isaHigh, showIcon: true},
217
+ export const LevelHigh: Story = {
218
+ args: {type: BadgeType.levelHigh, showIcon: true},
219
219
  render(args) {
220
220
  return html`<obc-badge
221
221
  number=${args.number}
@@ -229,8 +229,8 @@ export const IsaHigh: Story = {
229
229
  },
230
230
  };
231
231
 
232
- export const IsaMedium: Story = {
233
- args: {type: BadgeType.isaMedium, showIcon: true},
232
+ export const LevelMedium: Story = {
233
+ args: {type: BadgeType.levelMedium, showIcon: true},
234
234
  render(args) {
235
235
  return html`<obc-badge
236
236
  number=${args.number}
@@ -244,8 +244,8 @@ export const IsaMedium: Story = {
244
244
  },
245
245
  };
246
246
 
247
- export const IsaLow: Story = {
248
- args: {type: BadgeType.isaLow, showIcon: true},
247
+ export const LevelLow: Story = {
248
+ args: {type: BadgeType.levelLow, showIcon: true},
249
249
  render(args) {
250
250
  return html`<obc-badge
251
251
  number=${args.number}
@@ -259,8 +259,8 @@ export const IsaLow: Story = {
259
259
  },
260
260
  };
261
261
 
262
- export const IsaDiagnostic: Story = {
263
- args: {type: BadgeType.isaDiagnostic, showIcon: true},
262
+ export const LevelDiagnostic: Story = {
263
+ args: {type: BadgeType.levelDiagnostic, showIcon: true},
264
264
  render(args) {
265
265
  return html`<obc-badge
266
266
  number=${args.number}
@@ -25,11 +25,11 @@ export enum BadgeSize {
25
25
  * - `alarm`: Indicates a critical or urgent state.
26
26
  * - `warning`: Indicates a warning or cautionary state.
27
27
  * - `caution`: Indicates a less severe caution.
28
- * - `isa-critical`: ISA highest-severity state (critical).
29
- * - `isa-high`: ISA high-severity state (alarm-equivalent styling).
30
- * - `isa-medium`: ISA medium-severity state (warning-equivalent styling).
31
- * - `isa-low`: ISA low-severity state (caution-equivalent styling).
32
- * - `isa-diagnostic`: ISA diagnostic/notification state.
28
+ * - `level-critical`: level highest-severity state (critical).
29
+ * - `level-high`: level high-severity state (alarm-equivalent styling).
30
+ * - `level-medium`: level medium-severity state (warning-equivalent styling).
31
+ * - `level-low`: level low-severity state (caution-equivalent styling).
32
+ * - `level-diagnostic`: level diagnostic/notification state.
33
33
  * - `running`: Indicates an active or running state.
34
34
  * - `notification`: Used for general notifications.
35
35
  * - `enhance`: Used for enhanced or secondary notifications.
@@ -42,11 +42,11 @@ export enum BadgeType {
42
42
  alarm = 'alarm',
43
43
  warning = 'warning',
44
44
  caution = 'caution',
45
- isaCritical = 'isa-critical',
46
- isaHigh = 'isa-high',
47
- isaMedium = 'isa-medium',
48
- isaLow = 'isa-low',
49
- isaDiagnostic = 'isa-diagnostic',
45
+ levelCritical = 'level-critical',
46
+ levelHigh = 'level-high',
47
+ levelMedium = 'level-medium',
48
+ levelLow = 'level-low',
49
+ levelDiagnostic = 'level-diagnostic',
50
50
  running = 'running',
51
51
  notification = 'notification',
52
52
  enhance = 'enhance',
@@ -80,7 +80,7 @@ export enum BadgeVariant {
80
80
  * - `alarm`: Highlights critical or urgent states.
81
81
  * - `warning`: Indicates caution or warning.
82
82
  * - `caution`: Used for less severe caution.
83
- * - `isa-critical`, `isa-high`, `isa-medium`, `isa-low`, `isa-diagnostic`: ISA severity levels, styled to match their legacy equivalents (critical, alarm, warning, caution, notification).
83
+ * - `level-critical`, `level-high`, `level-medium`, `level-low`, `level-diagnostic`: level severity levels, styled to match their legacy equivalents (critical, alarm, warning, caution, notification).
84
84
  * - `running`: Represents active or running states.
85
85
  * - `notification`: For general notifications.
86
86
  * - `enhance`: For secondary notifications or emphasis.
@@ -170,7 +170,7 @@ export class ObcBadge extends LitElement {
170
170
  /**
171
171
  * Visual style/type of the badge.
172
172
  *
173
- * Possible values: `regular`, `alarm`, `warning`, `caution`, `isa-critical`, `isa-high`, `isa-medium`, `isa-low`, `isa-diagnostic`, `running`, `notification`, `enhance`, `automation`, `outline`, `empty`.
173
+ * Possible values: `regular`, `alarm`, `warning`, `caution`, `level-critical`, `level-high`, `level-medium`, `level-low`, `level-diagnostic`, `running`, `notification`, `enhance`, `automation`, `outline`, `empty`.
174
174
  *
175
175
  * Defaults to `regular`.
176
176
  */
@@ -194,7 +194,7 @@ export class ObcBadge extends LitElement {
194
194
  /**
195
195
  * Whether to show an icon in the badge.
196
196
  *
197
- * For built-in types (`alarm`, `warning`, `caution`, the `isa-*` severities, and `running`), a contextual icon is shown automatically.
197
+ * For built-in types (`alarm`, `warning`, `caution`, the `level-*` severities, and `running`), a contextual icon is shown automatically.
198
198
  * For other types, provide a custom icon in the `badge-icon` slot.
199
199
  */
200
200
  @property({type: Boolean}) showIcon = false;
@@ -244,7 +244,7 @@ export class ObcBadge extends LitElement {
244
244
  />
245
245
  </svg>
246
246
  `;
247
- case BadgeType.isaHigh:
247
+ case BadgeType.levelHigh:
248
248
  return html`
249
249
  <svg width="100%" height="100%" viewBox="0 0 12 12" fill="none">
250
250
  <path
@@ -253,7 +253,7 @@ export class ObcBadge extends LitElement {
253
253
  />
254
254
  </svg>
255
255
  `;
256
- case BadgeType.isaMedium:
256
+ case BadgeType.levelMedium:
257
257
  return html`
258
258
  <svg width="100%" height="100%" viewBox="0 0 12 12" fill="none">
259
259
  <circle
@@ -267,7 +267,7 @@ export class ObcBadge extends LitElement {
267
267
  />
268
268
  </svg>
269
269
  `;
270
- case BadgeType.isaLow:
270
+ case BadgeType.levelLow:
271
271
  return html`
272
272
  <svg width="100%" height="100%" viewBox="0 0 12 12" fill="none">
273
273
  <path
@@ -279,7 +279,7 @@ export class ObcBadge extends LitElement {
279
279
  />
280
280
  </svg>
281
281
  `;
282
- case BadgeType.isaCritical:
282
+ case BadgeType.levelCritical:
283
283
  return html`
284
284
  <svg width="100%" height="100%" viewBox="0 0 12 12" fill="none">
285
285
  <path
@@ -290,7 +290,7 @@ export class ObcBadge extends LitElement {
290
290
  />
291
291
  </svg>
292
292
  `;
293
- case BadgeType.isaDiagnostic:
293
+ case BadgeType.levelDiagnostic:
294
294
  return html`
295
295
  <svg width="100%" height="100%" viewBox="0 0 12 12" fill="none">
296
296
  <path
@@ -10,8 +10,8 @@ import '../tree-navigation-item/tree-navigation-item.js';
10
10
  import {
11
11
  TreeBranchType,
12
12
  TreeTerminalType,
13
+ type TreeNavigationItemAlerts,
13
14
  } from '../tree-navigation-item/tree-navigation-item.js';
14
- import {BadgeType} from '../badge/badge.js';
15
15
 
16
16
  enum NavigationItemRole {
17
17
  Button = 'button',
@@ -160,14 +160,12 @@ export class ObcNavigationItem extends LitElement {
160
160
  */
161
161
  @property({type: String}) terminalType: string = TreeTerminalType.regular;
162
162
 
163
- /** Whether a trailing alert counter badge is shown (Tree variant only). */
164
- @property({type: Boolean}) hasAlertBadge = false;
165
-
166
- /** The number shown in the alert badge when `hasAlertBadge` is true (Tree variant only). */
167
- @property({type: Number}) alertCount = 0;
168
-
169
- /** The severity/type of the alert badge — one of the `obc-badge` types (Tree variant only). */
170
- @property({type: String}) alertType: string = BadgeType.alarm;
163
+ /**
164
+ * Per-severity alert counts shown as trailing badge(s) (Tree variant only).
165
+ * Forwarded to the underlying `obc-tree-navigation-item`. See
166
+ * {@link TreeNavigationItemAlerts}.
167
+ */
168
+ @property({type: Object}) alerts?: TreeNavigationItemAlerts;
171
169
 
172
170
  @query('a') private anchorElement?: HTMLAnchorElement;
173
171
 
@@ -231,9 +229,7 @@ export class ObcNavigationItem extends LitElement {
231
229
  .hasLeadingIcon=${this.hasIcon}
232
230
  .href=${this.href}
233
231
  .terminalType=${this.terminalType}
234
- ?hasAlertBadge=${this.hasAlertBadge}
235
- .alertCount=${this.alertCount}
236
- .alertType=${this.alertType}
232
+ .alerts=${this.alerts}
237
233
  @click=${this.onClick}
238
234
  >
239
235
  ${this.hasIcon
@@ -8,8 +8,8 @@ import '../tree-navigation-item/tree-navigation-item.js';
8
8
  import {
9
9
  TreeBranchType,
10
10
  TreeTerminalType,
11
+ type TreeNavigationItemAlerts,
11
12
  } from '../tree-navigation-item/tree-navigation-item.js';
12
- import {BadgeType} from '../badge/badge.js';
13
13
 
14
14
  /**
15
15
  * `<obc-navigation-item-group>` – A collapsible navigation group component for organizing related navigation items under a single expandable label.
@@ -108,14 +108,13 @@ export class ObcNavigationItemGroup extends LitElement {
108
108
  */
109
109
  @property({type: String}) terminalType: string = TreeTerminalType.regular;
110
110
 
111
- /** Whether a trailing alert counter badge is shown on the header (Tree variant only). */
112
- @property({type: Boolean}) hasAlertBadge = false;
113
-
114
- /** The number shown in the header's alert badge when `hasAlertBadge` is true (Tree variant only). */
115
- @property({type: Number}) alertCount = 0;
116
-
117
- /** The severity/type of the header's alert badge — one of the `obc-badge` types (Tree variant only). */
118
- @property({type: String}) alertType: string = BadgeType.alarm;
111
+ /**
112
+ * Per-severity alert counts shown as trailing badge(s) on the group header
113
+ * (Tree variant only). Forwarded to the underlying `obc-tree-navigation-item`;
114
+ * typically `{aggregate: true, ...}` so the header totals the rows beneath it.
115
+ * See {@link TreeNavigationItemAlerts}.
116
+ */
117
+ @property({type: Object}) alerts?: TreeNavigationItemAlerts;
119
118
 
120
119
  /** Whether the group starts expanded. Useful for trees that open by default. */
121
120
  @property({type: Boolean}) defaultOpen = false;
@@ -178,9 +177,7 @@ export class ObcNavigationItemGroup extends LitElement {
178
177
  ?checked=${this.checked}
179
178
  .hasLeadingIcon=${this.hasIcon}
180
179
  .terminalType=${this.terminalType}
181
- ?hasAlertBadge=${this.hasAlertBadge}
182
- .alertCount=${this.alertCount}
183
- .alertType=${this.alertType}
180
+ .alerts=${this.expanded ? undefined : this.alerts}
184
181
  @expand-toggle=${this.onClickGroup}
185
182
  >
186
183
  ${this.hasIcon
@@ -268,6 +268,13 @@ export const Tree: Story = {
268
268
  label="Vessel"
269
269
  hasIcon
270
270
  defaultOpen
271
+ .alerts=${{
272
+ aggregate: true,
273
+ countLevelCritical: 1,
274
+ countLevelHigh: 1,
275
+ countLevelMedium: 2,
276
+ countLevelLow: 1,
277
+ }}
271
278
  >
272
279
  <obi-placeholder slot="icon"></obi-placeholder>
273
280
  <obc-navigation-item-group
@@ -275,26 +282,47 @@ export const Tree: Story = {
275
282
  hasIcon
276
283
  defaultOpen
277
284
  terminalType="aggregated-header"
285
+ .alerts=${{
286
+ aggregate: true,
287
+ countLevelCritical: 1,
288
+ countLevelHigh: 1,
289
+ }}
278
290
  >
279
291
  <obi-placeholder slot="icon"></obi-placeholder>
280
- <obc-navigation-item label="Main engine" hasIcon checked>
292
+ <obc-navigation-item
293
+ label="Main engine"
294
+ hasIcon
295
+ checked
296
+ .alerts=${{countLevelHigh: 1}}
297
+ >
281
298
  <obi-placeholder slot="icon"></obi-placeholder>
282
299
  </obc-navigation-item>
283
300
  <obc-navigation-item
284
301
  label="Cooling system"
285
302
  hasIcon
286
- hasAlertBadge
287
- .alertCount=${3}
303
+ .alerts=${{countLevelCritical: 1}}
288
304
  >
289
305
  <obi-placeholder slot="icon"></obi-placeholder>
290
306
  </obc-navigation-item>
291
307
  </obc-navigation-item-group>
292
- <obc-navigation-item-group label="Bridge" hasIcon>
308
+ <obc-navigation-item-group
309
+ label="Bridge"
310
+ hasIcon
311
+ .alerts=${{aggregate: true, countLevelMedium: 2, countLevelLow: 1}}
312
+ >
293
313
  <obi-placeholder slot="icon"></obi-placeholder>
294
- <obc-navigation-item label="Radar" hasIcon>
314
+ <obc-navigation-item
315
+ label="Radar"
316
+ hasIcon
317
+ .alerts=${{countLevelMedium: 2}}
318
+ >
295
319
  <obi-placeholder slot="icon"></obi-placeholder>
296
320
  </obc-navigation-item>
297
- <obc-navigation-item label="Autopilot" hasIcon>
321
+ <obc-navigation-item
322
+ label="Autopilot"
323
+ hasIcon
324
+ .alerts=${{countLevelLow: 1}}
325
+ >
298
326
  <obi-placeholder slot="icon"></obi-placeholder>
299
327
  </obc-navigation-item>
300
328
  </obc-navigation-item-group>
@@ -77,8 +77,8 @@ export enum ObcNavigationMenuFlyoutVariant {
77
77
  * - **Tree:** Renders the same `obc-navigation-item` / `obc-navigation-item-group`
78
78
  * markup as a hierarchical tree. Groups expand inline (instead of as flyouts),
79
79
  * rows are indented by depth, multiple branches can stay open at once, and the
80
- * tree-row presentation (alert badge, terminal marker) is available via the
81
- * items' `hasAlertBadge`/`alertCount`/`alertType`/`terminalType` properties.
80
+ * tree-row presentation (alert badges, terminal marker) is available via the
81
+ * items' `alerts`/`terminalType` properties.
82
82
  * - **Responsive Layout:**
83
83
  * - `smallScreen` property adapts the footer and logo layout for smaller viewports.
84
84
  * - **Slot-based Content:**
@@ -4,8 +4,9 @@ import './tree-navigation.js';
4
4
  import '../tree-navigation-group/tree-navigation-group.js';
5
5
  import '../tree-navigation-item/tree-navigation-item.js';
6
6
  import {TreeTerminalType} from '../tree-navigation-item/tree-navigation-item.js';
7
+ import type {TreeNavigationItemAlerts} from '../tree-navigation-item/tree-navigation-item.js';
7
8
  import {iconIdToIconHtml} from '../../storybook-util.js';
8
- import {LitElement, html} from 'lit';
9
+ import {LitElement, html, type TemplateResult} from 'lit';
9
10
  import {state} from 'lit/decorators.js';
10
11
  import {customElement} from '../../decorator.js';
11
12
 
@@ -21,22 +22,30 @@ const meta: Meta<typeof ObcTreeNavigation> = {
21
22
  component: 'obc-tree-navigation',
22
23
  render: () => html`
23
24
  <obc-tree-navigation>
24
- <obc-tree-navigation-group label="Vessel" expanded>
25
+ <obc-tree-navigation-group
26
+ label="Vessel"
27
+ .alerts=${{aggregate: true, countLevelHigh: 3}}
28
+ expanded
29
+ >
25
30
  ${iconIdToIconHtml('placeholder', {slot: 'icon'})}
26
31
  <obc-tree-navigation-group
27
32
  label="Engine room"
28
33
  expanded
34
+ .alerts=${{aggregate: true, countLevelHigh: 3}}
29
35
  .terminalType=${TreeTerminalType.aggregatedHeader}
30
36
  >
31
37
  ${iconIdToIconHtml('placeholder', {slot: 'icon'})}
32
- <obc-tree-navigation-item label="Main engine" checked>
38
+ <obc-tree-navigation-item
39
+ label="Main engine"
40
+ checked
41
+ .alerts=${{countLevelHigh: 1}}
42
+ >
33
43
  ${iconIdToIconHtml('placeholder', {slot: 'icon'})}
34
44
  </obc-tree-navigation-item>
35
45
  <obc-tree-navigation-group
36
46
  label="Auxiliary engine"
37
47
  expanded
38
- hasAlertBadge
39
- .alertCount=${3}
48
+ .alerts=${{aggregate: true, countLevelHigh: 1}}
40
49
  >
41
50
  ${iconIdToIconHtml('placeholder', {slot: 'icon'})}
42
51
  <obc-tree-navigation-item label="Fuel pump">
@@ -44,8 +53,7 @@ const meta: Meta<typeof ObcTreeNavigation> = {
44
53
  </obc-tree-navigation-item>
45
54
  <obc-tree-navigation-item
46
55
  label="Starter"
47
- hasAlertBadge
48
- .alertCount=${1}
56
+ .alerts=${{countLevelHigh: 1}}
49
57
  >
50
58
  ${iconIdToIconHtml('placeholder', {slot: 'icon'})}
51
59
  </obc-tree-navigation-item>
@@ -53,9 +61,16 @@ const meta: Meta<typeof ObcTreeNavigation> = {
53
61
  ${iconIdToIconHtml('placeholder', {slot: 'icon'})}
54
62
  </obc-tree-navigation-item>
55
63
  </obc-tree-navigation-group>
56
- <obc-tree-navigation-group label="Cooling system" expanded>
64
+ <obc-tree-navigation-group
65
+ label="Cooling system"
66
+ expanded
67
+ .alerts=${{aggregate: true, countLevelHigh: 1}}
68
+ >
57
69
  ${iconIdToIconHtml('placeholder', {slot: 'icon'})}
58
- <obc-tree-navigation-item label="Seawater pump">
70
+ <obc-tree-navigation-item
71
+ label="Seawater pump"
72
+ .alerts=${{countLevelHigh: 1}}
73
+ >
59
74
  ${iconIdToIconHtml('placeholder', {slot: 'icon'})}
60
75
  </obc-tree-navigation-item>
61
76
  </obc-tree-navigation-group>
@@ -160,3 +175,133 @@ export const Interactive: Story = {
160
175
  render: () =>
161
176
  html`<tree-navigation-selection-demo></tree-navigation-selection-demo>`,
162
177
  };
178
+
179
+ /** The `alerts` count fields summed across a subtree, most to least severe. */
180
+ const COUNT_KEYS = [
181
+ 'countLevelCritical',
182
+ 'countLevelHigh',
183
+ 'countLevelMedium',
184
+ 'countLevelLow',
185
+ 'countLevelDiagnostic',
186
+ ] as const satisfies ReadonlyArray<keyof TreeNavigationItemAlerts>;
187
+
188
+ /** A node in the alert-demo tree: a leaf carries its own counts; a group has children. */
189
+ interface AlertNode {
190
+ label: string;
191
+ /** Per-severity counts for a leaf row. */
192
+ alerts?: TreeNavigationItemAlerts;
193
+ /** Child rows; presence makes this node a group. */
194
+ children?: AlertNode[];
195
+ }
196
+
197
+ /**
198
+ * Level severities spread across leaves at several depths. The whole tree totals
199
+ * 1 critical, 3 high, 10 medium, 5 low, and 0 diagnostic, so the rolled-up group
200
+ * totals are easy to verify by eye.
201
+ */
202
+ const ALERT_TREE: AlertNode = {
203
+ label: 'Vessel',
204
+ children: [
205
+ {
206
+ label: 'Engine room',
207
+ children: [
208
+ {label: 'Main engine', alerts: {countLevelHigh: 1}},
209
+ {
210
+ label: 'Auxiliary engine',
211
+ children: [
212
+ {label: 'Fuel pump', alerts: {countLevelMedium: 4}},
213
+ {
214
+ label: 'Starter',
215
+ alerts: {countLevelCritical: 1, countLevelLow: 2},
216
+ },
217
+ {label: 'Oil filter', alerts: {countLevelMedium: 2}},
218
+ ],
219
+ },
220
+ {
221
+ label: 'Cooling system',
222
+ children: [
223
+ {
224
+ label: 'Seawater pump',
225
+ alerts: {countLevelHigh: 1, countLevelMedium: 3},
226
+ },
227
+ ],
228
+ },
229
+ ],
230
+ },
231
+ {
232
+ label: 'Bridge',
233
+ children: [
234
+ {label: 'Radar', alerts: {countLevelHigh: 1, countLevelLow: 3}},
235
+ {label: 'Autopilot'},
236
+ ],
237
+ },
238
+ {label: 'Deck', alerts: {countLevelMedium: 1}},
239
+ ],
240
+ };
241
+
242
+ /** Sum every descendant leaf's counts, per severity, for a group header. */
243
+ function sumAlerts(node: AlertNode): TreeNavigationItemAlerts {
244
+ if (!node.children) return node.alerts ?? {};
245
+ const total: TreeNavigationItemAlerts = {};
246
+ for (const child of node.children) {
247
+ const childTotal = sumAlerts(child);
248
+ for (const key of COUNT_KEYS) {
249
+ const value = childTotal[key];
250
+ if (value) total[key] = (total[key] ?? 0) + value;
251
+ }
252
+ }
253
+ return total;
254
+ }
255
+
256
+ /**
257
+ * Render a node with every row using the given `aggregate` setting. Group rows
258
+ * carry the summed counts of their whole subtree; leaf rows carry their own
259
+ * counts. With `aggregate` true each row collapses to a single total badge;
260
+ * with it false each row shows one badge per non-zero severity.
261
+ */
262
+ function renderAlertNode(node: AlertNode, aggregate: boolean): TemplateResult {
263
+ if (node.children) {
264
+ const alerts: TreeNavigationItemAlerts = {aggregate, ...sumAlerts(node)};
265
+ return html`<obc-tree-navigation-group
266
+ label=${node.label}
267
+ expanded
268
+ .alerts=${alerts}
269
+ >
270
+ ${iconIdToIconHtml('placeholder', {slot: 'icon'})}
271
+ ${node.children.map((child) => renderAlertNode(child, aggregate))}
272
+ </obc-tree-navigation-group>`;
273
+ }
274
+ const alerts = node.alerts ? {aggregate, ...node.alerts} : undefined;
275
+ return html`<obc-tree-navigation-item label=${node.label} .alerts=${alerts}>
276
+ ${iconIdToIconHtml('placeholder', {slot: 'icon'})}
277
+ </obc-tree-navigation-item>`;
278
+ }
279
+
280
+ /**
281
+ * Alerts spread across leaves at several depths, every row with
282
+ * `aggregate: true`. Each group header carries a single badge whose number is
283
+ * the sum of all alerts beneath it (child groups roll up into their parent in
284
+ * turn), styled as the most severe category present — e.g. "Auxiliary engine"
285
+ * totals 9 (1 critical + 6 medium + 2 low) and shows as critical, and "Vessel"
286
+ * totals 19 (1 critical + 3 high + 10 medium + 5 low) and also shows as critical.
287
+ */
288
+ export const AggregatedAlertCounts: Story = {
289
+ render: () =>
290
+ html`<obc-tree-navigation>
291
+ ${renderAlertNode(ALERT_TREE, true)}
292
+ </obc-tree-navigation>`,
293
+ };
294
+
295
+ /**
296
+ * The same tree and the same rolled-up totals, but every row with
297
+ * `aggregate: false`: each row renders one badge per non-zero severity instead
298
+ * of a single combined badge. Group headers still sum their whole subtree —
299
+ * e.g. "Auxiliary engine" shows separate critical (1), medium (6), and
300
+ * low (2) badges.
301
+ */
302
+ export const PerSeverityAlertCounts: Story = {
303
+ render: () =>
304
+ html`<obc-tree-navigation>
305
+ ${renderAlertNode(ALERT_TREE, false)}
306
+ </obc-tree-navigation>`,
307
+ };