@rancher/shell 3.0.2-rc.6 → 3.0.3

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 (57) hide show
  1. package/assets/styles/global/_layout.scss +3 -1
  2. package/assets/styles/themes/_light.scss +1 -2
  3. package/assets/styles/themes/_suse.scss +1 -0
  4. package/assets/translations/en-us.yaml +18 -3
  5. package/chart/monitoring/prometheus/index.vue +13 -10
  6. package/components/ButtonGroup.vue +4 -0
  7. package/components/FixedBanner.vue +19 -12
  8. package/components/LocaleSelector.vue +2 -0
  9. package/components/SortableTable/THead.vue +2 -0
  10. package/components/SortableTable/index.vue +35 -5
  11. package/components/StatusBadge.vue +71 -0
  12. package/components/__tests__/FixedBanner.test.ts +3 -3
  13. package/components/form/MatchExpressions.vue +4 -0
  14. package/components/form/Select.vue +11 -2
  15. package/components/form/UnitInput.vue +2 -2
  16. package/components/form/__tests__/UnitInput.test.ts +4 -5
  17. package/components/nav/Favorite.vue +5 -1
  18. package/components/nav/Group.vue +4 -0
  19. package/components/nav/Jump.vue +7 -0
  20. package/components/nav/Pinned.vue +1 -1
  21. package/components/nav/TopLevelMenu.vue +1 -12
  22. package/components/nav/Type.vue +1 -0
  23. package/components/nav/__tests__/TopLevelMenu.test.ts +0 -40
  24. package/config/router/routes.js +1 -0
  25. package/core/plugin-routes.ts +5 -115
  26. package/core/plugins.js +1 -1
  27. package/core/types.ts +18 -2
  28. package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +84 -23
  29. package/detail/autoscaling.horizontalpodautoscaler/index.vue +13 -3
  30. package/edit/auth/__tests__/oidc.test.ts +34 -3
  31. package/edit/auth/ldap/__tests__/config.test.ts +0 -14
  32. package/edit/auth/ldap/config.vue +0 -24
  33. package/edit/auth/oidc.vue +1 -1
  34. package/edit/autoscaling.horizontalpodautoscaler/metric-identifier.vue +5 -2
  35. package/edit/fleet.cattle.io.clustergroup.vue +5 -3
  36. package/edit/fleet.cattle.io.gitrepo.vue +1 -0
  37. package/edit/logging-flow/Match.vue +1 -1
  38. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +0 -2
  39. package/edit/provisioning.cattle.io.cluster/rke2.vue +1 -1
  40. package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +5 -2
  41. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +1 -1
  42. package/edit/service.vue +0 -3
  43. package/edit/workload/Job.vue +6 -6
  44. package/edit/workload/__tests__/Job.test.ts +0 -1
  45. package/models/__tests__/logging.banzaicloud.io.flow.test.ts +88 -0
  46. package/models/logging.banzaicloud.io.flow.js +2 -1
  47. package/package.json +2 -2
  48. package/pages/auth/login.vue +1 -9
  49. package/rancher-components/Form/Checkbox/Checkbox.vue +9 -1
  50. package/rancher-components/Form/LabeledInput/LabeledInput.vue +7 -2
  51. package/scripts/extension/helm/charts/ui-plugin-server/templates/_helpers.tpl +2 -2
  52. package/scripts/test-plugins-build.sh +4 -6
  53. package/store/aws.js +9 -2
  54. package/types/shell/index.d.ts +0 -10
  55. package/utils/banners.js +0 -45
  56. package/utils/color.js +9 -8
  57. package/utils/object.js +0 -3
@@ -61,6 +61,8 @@ HEADER {
61
61
  display: flex;
62
62
  flex-direction: column;
63
63
  height: 100vh;
64
+ width: 100vw;
65
+ position: absolute;
64
66
  }
65
67
 
66
68
  .dashboard-content {
@@ -162,4 +164,4 @@ HEADER {
162
164
  opacity: 1;
163
165
  }
164
166
 
165
- // !END
167
+ // !END
@@ -26,7 +26,6 @@ $disabled : $medium;
26
26
  $primary : #3D98D3;
27
27
  $secondary : $darker;
28
28
  $link : #3D98D3;
29
- $keyboard-focus : #{darken($primary, 10%)};
30
29
 
31
30
  // Status colors
32
31
  $success : #5D995D;
@@ -54,7 +53,7 @@ BODY, .theme-light {
54
53
  --primary-border : #{$primary};
55
54
  --primary-banner-bg : #{rgba($primary, 0.15)};
56
55
  --primary-light-bg : #{rgba($primary, 0.05)};
57
- --primary-keyboard-focus : #{$keyboard-focus};
56
+ --primary-keyboard-focus : hsl(from var(--primary) h s calc(l - 10));
58
57
 
59
58
 
60
59
  .text-primary {
@@ -12,6 +12,7 @@
12
12
  --primary-border : #{$primary};
13
13
  --primary-banner-bg : #{rgba($primary, 0.15)};
14
14
  --primary-light-bg : #{rgba($primary, 0.05)};
15
+ --primary-keyboard-focus : hsl(from var(--primary) h s calc(l - 10));
15
16
 
16
17
  --info : #{$info};
17
18
  --info-text : #{contrast-color($info)};
@@ -239,6 +239,7 @@ nav:
239
239
  label: Resource Search
240
240
  toolTip: Resource Search {key}
241
241
  placeholder: Type to search for a resource...
242
+ filteringDescription: Using this input will immediately filter the results in the list below
242
243
  header:
243
244
  setLoginPage: Set as login page
244
245
  restoreCards: Restore hidden cards
@@ -545,9 +546,6 @@ authConfig:
545
546
  starttls:
546
547
  label: Start TLS
547
548
  tip: Upgrades non-encrypted connections by wrapping with TLS during the connection process. Can not be used in conjunction with TLS.
548
- searchUsingServiceAccount:
549
- label: Enable Service Account Search
550
- tip: When enabled, Rancher will use the service account instead of the user account to search for users and groups.
551
549
  tls: TLS
552
550
  userEnabledAttribute: User Enabled Attribute
553
551
  userMemberAttribute: User Member Attribute
@@ -2779,6 +2777,7 @@ hpa:
2779
2777
  label: Metric Name
2780
2778
  placeholder: e.g. packets-per-second
2781
2779
  selector:
2780
+ header: Metric Selector
2782
2781
  label: Add Selector
2783
2782
  metricTarget:
2784
2783
  averageVal:
@@ -5138,6 +5137,9 @@ resourceDetail:
5138
5137
  stage: "Stage from {subtype} {name}"
5139
5138
  view: "{subtype} {name}"
5140
5139
  masthead:
5140
+ ariaLabel:
5141
+ favoriteAction: Add {resource} to your starred/favorites list
5142
+ unfavoriteAction: Remove {resource} from your starred/favorites list
5141
5143
  age: Age
5142
5144
  createdBy: Created by
5143
5145
  restartCount: Pod Restarts
@@ -5490,6 +5492,18 @@ setup:
5490
5492
  welcome: Welcome to {vendor}!
5491
5493
 
5492
5494
  sortableTable:
5495
+ ariaLabel:
5496
+ firstPageBtn: First page of results
5497
+ prevPageBtn: Previous page of results
5498
+ nextPageBtn: Next page of results
5499
+ lastPageBtn: Last page of results
5500
+ alt:
5501
+ firstPageBtn: First page of results icon
5502
+ prevPageBtn: Previous page of results icon
5503
+ nextPageBtn: Next page of results icon
5504
+ lastPageBtn: Last page of results icon
5505
+ sortingIconDesc: Table header descending sort icon
5506
+ sortingIconAsc: Table header ascending sort icon
5493
5507
  genericGroupCheckbox: Table group selection checkbox
5494
5508
  genericRowCheckbox: Table row selection checkbox for item {item}
5495
5509
  tableActionsLabel: More actions - { resource }
@@ -5518,6 +5532,7 @@ sortableTable:
5518
5532
  searchLabel: Filter table results
5519
5533
  in: in
5520
5534
  addFilter: Add Filter
5535
+ filteringDescription: Using this input will immediately filter the results in the table below
5521
5536
  filterFor: Filter for...
5522
5537
  selectCol: Select a column
5523
5538
  resetFilters: Reset
@@ -341,22 +341,25 @@ export default {
341
341
  </div>
342
342
  <div class="row">
343
343
  <div class="col span-12">
344
- <div class="mb-5 mt-5">
345
- <h4 class=" mb-10">
346
- {{ t('monitoring.prometheus.storage.selector') }}
347
- </h4>
348
- </div>
349
- <Banner
350
- color="warning"
351
- :label="t('monitoring.prometheus.storage.selectorWarning', {}, true)"
352
- />
353
344
  <MatchExpressions
354
345
  :initial-empty-row="false"
355
346
  :mode="mode"
356
347
  :value="matchExpressions"
357
348
  :show-remove="false"
358
349
  @update:value="matchChanged($event)"
359
- />
350
+ >
351
+ <template #header>
352
+ <div class="mb-5 mt-5">
353
+ <h4 class=" mb-10">
354
+ {{ t('monitoring.prometheus.storage.selector') }}
355
+ </h4>
356
+ </div>
357
+ <Banner
358
+ color="warning"
359
+ :label="t('monitoring.prometheus.storage.selectorWarning', {}, true)"
360
+ />
361
+ </template>
362
+ </MatchExpressions>
360
363
  </div>
361
364
  </div>
362
365
  </template>
@@ -77,6 +77,9 @@ export default {
77
77
  const tooltip = opt.tooltipKey ? this.t(opt.tooltipKey) : opt.tooltip;
78
78
 
79
79
  return ariaLabel || tooltip || label || undefined;
80
+ },
81
+ isPressed(opt) {
82
+ return this.value === opt.value;
80
83
  }
81
84
  }
82
85
  };
@@ -97,6 +100,7 @@ export default {
97
100
  :disabled="disabled || opt.disabled"
98
101
  role="button"
99
102
  :aria-label="actionAriaLabel(opt)"
103
+ :aria-pressed="isPressed(opt)"
100
104
  @click="change(opt.value)"
101
105
  >
102
106
  <slot
@@ -37,7 +37,7 @@ export default {
37
37
  handleLineBreaksConsentText(banner) {
38
38
  if (banner.text?.length) {
39
39
  // split text by newline char
40
- const textArray = banner.text.split(/\\n/).filter((element) => element);
40
+ const textArray = banner.text.split('\n').filter((element) => element);
41
41
 
42
42
  if (textArray.length > 1) {
43
43
  textArray.forEach((str, i) => {
@@ -130,11 +130,11 @@ export default {
130
130
 
131
131
  if (isEmpty(banner)) {
132
132
  if (showHeader && this.header) {
133
- bannerContent = bannerHeader || {};
133
+ bannerContent = this.handleLineBreaksConsentText(bannerHeader) || {};
134
134
  } else if (showConsent && this.consent) {
135
135
  bannerContent = this.handleLineBreaksConsentText(bannerConsent) || {};
136
136
  } else if (showFooter && this.footer) {
137
- bannerContent = bannerFooter || {};
137
+ bannerContent = this.handleLineBreaksConsentText(bannerFooter) || {};
138
138
  } else {
139
139
  bannerContent = {};
140
140
  }
@@ -168,16 +168,20 @@ export default {
168
168
  >
169
169
  <!-- text as array to support line breaks programmatically rather than just exposing HTML -->
170
170
  <div v-if="isTextAnArray">
171
- <p
171
+ <div
172
172
  v-for="(text, index) in banner.text"
173
173
  :key="index"
174
+ class="array-row"
174
175
  >
175
176
  {{ text }}
176
- </p>
177
+ </div>
177
178
  </div>
178
- <p v-else>
179
+ <div
180
+ v-else
181
+ class="single-row"
182
+ >
179
183
  {{ banner.text }}
180
- </p>
184
+ </div>
181
185
  </div>
182
186
  <div v-else-if="showDialog">
183
187
  <div class="banner-dialog-glass" />
@@ -192,16 +196,20 @@ export default {
192
196
  >
193
197
  <!-- text as array to support line breaks programmatically rather than just exposing HTML -->
194
198
  <div v-if="isTextAnArray">
195
- <p
199
+ <div
196
200
  v-for="(text, index) in banner.text"
197
201
  :key="index"
202
+ class="array-row"
198
203
  >
199
204
  {{ text }}
200
- </p>
205
+ </div>
201
206
  </div>
202
- <p v-else>
207
+ <div
208
+ v-else
209
+ class="single-row"
210
+ >
203
211
  {{ banner.text }}
204
- </p>
212
+ </div>
205
213
  </div>
206
214
  <button
207
215
  class="btn role-primary"
@@ -223,7 +231,6 @@ export default {
223
231
  padding: 0 20px;
224
232
 
225
233
  &.banner-consent {
226
- position: absolute;
227
234
  height: unset;
228
235
  min-height: 2em;
229
236
  overflow: hidden;
@@ -119,6 +119,7 @@ export default {
119
119
  tabindex="0"
120
120
  role="menuitem"
121
121
  class="hand"
122
+ :lang="name"
122
123
  @click.stop="switchLocale(name)"
123
124
  @keyup.enter.stop="switchLocale(name)"
124
125
  @keyup.space.stop="switchLocale(name)"
@@ -134,6 +135,7 @@ export default {
134
135
  <Select
135
136
  :value="selectedOption"
136
137
  :options="localesOptions"
138
+ :is-lang-select="true"
137
139
  @update:value="switchLocale($event)"
138
140
  />
139
141
  </div>
@@ -282,10 +282,12 @@ export default {
282
282
  <i
283
283
  v-if="isCurrent(col) && !descending"
284
284
  class="icon icon-sort-down icon-stack-1x"
285
+ :alt="t('sortableTable.alt.sortingIconDesc')"
285
286
  />
286
287
  <i
287
288
  v-if="isCurrent(col) && descending"
288
289
  class="icon icon-sort-up icon-stack-1x"
290
+ :alt="t('sortableTable.alt.sortingIconAsc')"
289
291
  />
290
292
  </span>
291
293
  </div>
@@ -1081,6 +1081,8 @@ export default {
1081
1081
  :class="{[bulkActionClass]:true}"
1082
1082
  :disabled="!act.enabled"
1083
1083
  :data-testid="componentTestid + '-' + act.action"
1084
+ role="button"
1085
+ :aria-label="act.label"
1084
1086
  @click="applyTableAction(act, null, $event)"
1085
1087
  @keydown.enter.stop
1086
1088
  @mouseover="setBulkActionOfInterest(act)"
@@ -1234,13 +1236,21 @@ export default {
1234
1236
  </div>
1235
1237
  </div>
1236
1238
  </div>
1237
- <input
1239
+ <p
1238
1240
  v-else-if="search"
1241
+ id="describe-filter-sortable-table"
1242
+ hidden
1243
+ >
1244
+ {{ t('sortableTable.filteringDescription') }}
1245
+ </p>
1246
+ <input
1247
+ v-if="search"
1239
1248
  ref="searchQuery"
1240
1249
  v-model="eventualSearchQuery"
1241
1250
  type="search"
1242
1251
  class="input-sm search-box"
1243
1252
  :aria-label="t('sortableTable.searchLabel')"
1253
+ aria-describedby="describe-filter-sortable-table"
1244
1254
  :placeholder="t('sortableTable.search')"
1245
1255
  >
1246
1256
  <slot name="header-button" />
@@ -1532,18 +1542,28 @@ export default {
1532
1542
  class="btn btn-sm role-multi-action"
1533
1543
  data-testid="pagination-first"
1534
1544
  :disabled="page == 1 || loading"
1545
+ role="button"
1546
+ :aria-label="t('sortableTable.ariaLabel.firstPageBtn')"
1535
1547
  @click="goToPage('first')"
1536
1548
  >
1537
- <i class="icon icon-chevron-beginning" />
1549
+ <i
1550
+ class="icon icon-chevron-beginning"
1551
+ :alt="t('sortableTable.alt.firstPageBtn')"
1552
+ />
1538
1553
  </button>
1539
1554
  <button
1540
1555
  type="button"
1541
1556
  class="btn btn-sm role-multi-action"
1542
1557
  data-testid="pagination-prev"
1543
1558
  :disabled="page == 1 || loading"
1559
+ role="button"
1560
+ :aria-label="t('sortableTable.ariaLabel.prevPageBtn')"
1544
1561
  @click="goToPage('prev')"
1545
1562
  >
1546
- <i class="icon icon-chevron-left" />
1563
+ <i
1564
+ class="icon icon-chevron-left"
1565
+ :alt="t('sortableTable.alt.prevPageBtn')"
1566
+ />
1547
1567
  </button>
1548
1568
  <span>
1549
1569
  {{ pagingDisplay }}
@@ -1553,18 +1573,28 @@ export default {
1553
1573
  class="btn btn-sm role-multi-action"
1554
1574
  data-testid="pagination-next"
1555
1575
  :disabled="page == totalPages || loading"
1576
+ role="button"
1577
+ :aria-label="t('sortableTable.ariaLabel.nextPageBtn')"
1556
1578
  @click="goToPage('next')"
1557
1579
  >
1558
- <i class="icon icon-chevron-right" />
1580
+ <i
1581
+ class="icon icon-chevron-right"
1582
+ :alt="t('sortableTable.alt.nextPageBtn')"
1583
+ />
1559
1584
  </button>
1560
1585
  <button
1561
1586
  type="button"
1562
1587
  class="btn btn-sm role-multi-action"
1563
1588
  data-testid="pagination-last"
1564
1589
  :disabled="page == totalPages || loading"
1590
+ role="button"
1591
+ :aria-label="t('sortableTable.ariaLabel.lastPageBtn')"
1565
1592
  @click="goToPage('last')"
1566
1593
  >
1567
- <i class="icon icon-chevron-end" />
1594
+ <i
1595
+ class="icon icon-chevron-end"
1596
+ :alt="t('sortableTable.alt.lastPageBtn')"
1597
+ />
1568
1598
  </button>
1569
1599
  </div>
1570
1600
  <button
@@ -0,0 +1,71 @@
1
+ <script setup lang="ts">
2
+
3
+ const STATUS = {
4
+ success: {
5
+ color: 'text-success',
6
+ icon: 'icon-checkmark'
7
+ },
8
+ warning: {
9
+ color: 'text-warning',
10
+ icon: 'icon-warning'
11
+ },
12
+ info: {
13
+ color: 'text-info',
14
+ icon: 'icon-info'
15
+ },
16
+ error: {
17
+ color: 'text-error',
18
+ icon: 'icon-error'
19
+ }
20
+ };
21
+
22
+ const { status = 'success', label } = defineProps<{
23
+ status?: 'success' | 'warning' | 'info' | 'error',
24
+ label?: string
25
+ }>();
26
+
27
+ </script>
28
+ <template>
29
+ <div
30
+ class="status-badge"
31
+ >
32
+ <i
33
+ class="status-badge__icon icon"
34
+ :class="{
35
+ [STATUS[status].icon]: true,
36
+ [STATUS[status].color]: true
37
+ }"
38
+ />
39
+ <div
40
+ v-if="label"
41
+ class="status-badge__label"
42
+ >
43
+ {{ label }}
44
+ </div>
45
+ </div>
46
+ </template>
47
+
48
+ <style lang="scss" scoped>
49
+ .status-badge {
50
+ align-items: center;
51
+ display: inline-flex;
52
+ border: 1px solid;
53
+ border-color: var(--border);
54
+ margin-top: 20px;
55
+
56
+ & + & {
57
+ margin-left: 20px;
58
+ }
59
+
60
+ &__label {
61
+ border-left: 1px solid var(--border);
62
+ padding: 5px 20px;
63
+ color: var(--body-text);
64
+ }
65
+
66
+ &__icon {
67
+ text-align: center;
68
+ padding: 5px 10px;
69
+ }
70
+ }
71
+ </style>
@@ -40,7 +40,7 @@ describe('component: FixedBanner', () => {
40
40
  expect(wrapper.vm.showHeader).toStrictEqual(true);
41
41
 
42
42
  const bannerElem = wrapper.find('.banner');
43
- const noArrayTextElem = wrapper.find('.banner > p');
43
+ const noArrayTextElem = wrapper.find('.banner .single-row');
44
44
 
45
45
  expect(bannerElem.exists()).toBe(true);
46
46
  expect(bannerElem.classes()).not.toContain('banner-consent');
@@ -60,7 +60,7 @@ describe('component: FixedBanner', () => {
60
60
  expect(wrapper.vm.showFooter).toStrictEqual(true);
61
61
 
62
62
  const bannerElem = wrapper.find('.banner');
63
- const noArrayTextElem = wrapper.find('.banner > p');
63
+ const noArrayTextElem = wrapper.find('.banner .single-row');
64
64
 
65
65
  expect(bannerElem.exists()).toBe(true);
66
66
  expect(bannerElem.classes()).not.toContain('banner-consent');
@@ -84,7 +84,7 @@ describe('component: FixedBanner', () => {
84
84
  const bannerDialogElem = wrapper.find('.banner-dialog');
85
85
  const bannerDialogFrameElem = wrapper.find('.banner-dialog-frame');
86
86
  const buttonDialog = wrapper.find('.banner-dialog button');
87
- const noArrayTextElem = wrapper.find('.banner > p');
87
+ const noArrayTextElem = wrapper.find('.banner .single-row');
88
88
 
89
89
  expect(bannerElem.exists()).toBe(true);
90
90
  expect(bannerDialogGlassElem.exists()).toBe(true);
@@ -242,6 +242,10 @@ export default {
242
242
 
243
243
  <template>
244
244
  <div>
245
+ <slot
246
+ v-if="rules.length"
247
+ name="header"
248
+ />
245
249
  <button
246
250
  v-if="showRemove && !isView"
247
251
  type="button"
@@ -87,6 +87,10 @@ export default {
87
87
  type: Boolean,
88
88
  default: null
89
89
  },
90
+ isLangSelect: {
91
+ type: Boolean,
92
+ default: false
93
+ },
90
94
  },
91
95
 
92
96
  methods: {
@@ -289,8 +293,13 @@ export default {
289
293
  @open="resizeHandler"
290
294
  @option:created="(e) => $emit('createdListItem', e)"
291
295
  >
292
- <template #option="option">
293
- <div @mousedown="(e) => onClickOption(option, e)">
296
+ <template
297
+ #option="option"
298
+ >
299
+ <div
300
+ :lang="isLangSelect ? option.value : undefined"
301
+ @mousedown="(e) => onClickOption(option, e)"
302
+ >
294
303
  {{ getOptionLabel(option.label) }}
295
304
  </div>
296
305
  </template>
@@ -206,7 +206,7 @@ export default {
206
206
  }
207
207
 
208
208
  if (this.outputModifier) {
209
- out = out === null ? null : `${ inputValue }${ this.unit }`;
209
+ out = out === null ? null : `${ parseInt(inputValue) }${ this.unit }`;
210
210
  } else if ( this.outputAs === 'string' ) {
211
211
  out = out === null ? '' : `${ inputValue }`;
212
212
  } else if (out) {
@@ -235,7 +235,7 @@ export default {
235
235
  :required="required"
236
236
  :placeholder="placeholder"
237
237
  :hide-arrows="hideArrows"
238
- @change="update($event.target.value)"
238
+ @update:value="update"
239
239
  @blur="update($event.target.value)"
240
240
  >
241
241
  <template #suffix>
@@ -11,7 +11,7 @@ describe('component: UnitInput', () => {
11
11
  expect(wrapper.isVisible()).toBe(true);
12
12
  });
13
13
 
14
- it.each(['blur', 'change'])('should emit input event when "%p" is fired', async(event) => {
14
+ it.each(['blur', 'update:value'])('should emit input event when "%p" is fired', async(event) => {
15
15
  const wrapper = mount(UnitInput, { props: { value: 1, delay: 0 } });
16
16
  const input = wrapper.find('input');
17
17
 
@@ -20,7 +20,7 @@ describe('component: UnitInput', () => {
20
20
  input.trigger(event);
21
21
 
22
22
  expect(wrapper.emitted('update:value')).toBeTruthy();
23
- expect(wrapper.emitted('update:value')[2]).toStrictEqual([4]);
23
+ expect(wrapper.emitted('update:value')[1]).toStrictEqual([4]);
24
24
  });
25
25
 
26
26
  it.each([
@@ -184,7 +184,7 @@ describe('component: UnitInput', () => {
184
184
  input.trigger('blur');
185
185
 
186
186
  expect(wrapper.emitted('update:value')).toBeTruthy();
187
- expect(wrapper.emitted('update:value')[3][0]).toBe(value);
187
+ expect(wrapper.emitted('update:value')[0][0]).toBe(value);
188
188
  });
189
189
 
190
190
  describe.each([
@@ -207,7 +207,7 @@ describe('component: UnitInput', () => {
207
207
  expect(inputElement.value).toBe('123');
208
208
  });
209
209
 
210
- it.each(['input', 'blur'])('on %p 123 should display input value 123', async(trigger) => {
210
+ it.each(['update:value', 'blur'])('on %p 123 should display input value 123', async(trigger) => {
211
211
  const wrapper = mount(UnitInput, {
212
212
  props: {
213
213
  value: '0',
@@ -248,7 +248,6 @@ describe('component: UnitInput', () => {
248
248
  const input = wrapper.find('input');
249
249
 
250
250
  await input.trigger('update:value');
251
- await input.trigger('input');
252
251
 
253
252
  expect(input.element.value).toBe('123');
254
253
  });
@@ -10,6 +10,9 @@ export default {
10
10
  computed: {
11
11
  isFavorite() {
12
12
  return this.$store.getters['type-map/isFavorite'](this.resource);
13
+ },
14
+ ariaLabel() {
15
+ return this.t(`resourceDetail.masthead.ariaLabel.${ this.isFavorite ? 'unfavoriteAction' : 'favoriteAction' }`, { resource: this.resource });
13
16
  }
14
17
  },
15
18
 
@@ -28,10 +31,11 @@ export default {
28
31
  <template>
29
32
  <i
30
33
  :tabindex="0"
31
- :aria-checked="!!isFavorite"
34
+ :aria-pressed="!!isFavorite"
32
35
  class="favorite icon"
33
36
  :class="{'icon-star-open': !isFavorite, 'icon-star': isFavorite}"
34
37
  aria-role="button"
38
+ :aria-label="ariaLabel"
35
39
  @click.stop.prevent="toggle"
36
40
  @keydown.enter.prevent="toggle"
37
41
  @keydown.space.prevent="toggle"
@@ -403,6 +403,10 @@ export default {
403
403
  padding: 10px 7px 9px 7px !important;
404
404
  }
405
405
  }
406
+
407
+ &:deep() .type-link > .label {
408
+ padding-left: 10px;
409
+ }
406
410
  }
407
411
 
408
412
  &:not(.depth-0) {
@@ -71,6 +71,12 @@ export default {
71
71
 
72
72
  <template>
73
73
  <div>
74
+ <p
75
+ id="describe-filter-resource-search"
76
+ hidden
77
+ >
78
+ {{ t('nav.resourceSearch.filteringDescription') }}
79
+ </p>
74
80
  <input
75
81
  ref="input"
76
82
  v-model="value"
@@ -78,6 +84,7 @@ export default {
78
84
  class="search"
79
85
  role="textbox"
80
86
  :aria-label="t('nav.resourceSearch.label')"
87
+ aria-describedby="describe-filter-resource-search"
81
88
  @keyup.esc="$emit('closeSearch')"
82
89
  >
83
90
  <div class="results">
@@ -36,7 +36,7 @@ export default {
36
36
  :aria-checked="!!pinned"
37
37
  class="pin icon"
38
38
  :class="{'icon-pin-outlined': !pinned, 'icon-pin': pinned}"
39
- aria-role="button"
39
+ role="button"
40
40
  :aria-label="t('nav.ariaLabel.pinCluster', { cluster: cluster.label })"
41
41
  @click.stop.prevent="toggle"
42
42
  @keydown.enter.prevent="toggle"
@@ -14,7 +14,6 @@ import { SETTING } from '@shell/config/settings';
14
14
  import { getProductFromRoute } from '@shell/utils/router';
15
15
  import { isRancherPrime } from '@shell/config/version';
16
16
  import Pinned from '@shell/components/nav/Pinned';
17
- import { getGlobalBannerFontSizes } from '@shell/utils/banners';
18
17
  import { TopLevelMenuHelperPagination, TopLevelMenuHelperLegacy } from '@shell/components/nav/TopLevelMenu.helper';
19
18
  import { debounce } from 'lodash';
20
19
  import { sameContents } from '@shell/utils/array';
@@ -82,15 +81,6 @@ export default {
82
81
  return this.$store.getters['prefs/get'](PINNED_CLUSTERS);
83
82
  },
84
83
 
85
- sideMenuStyle() {
86
- const globalBannerSettings = getGlobalBannerFontSizes(this.$store);
87
-
88
- return {
89
- marginBottom: globalBannerSettings?.footerFont,
90
- marginTop: globalBannerSettings?.headerFont
91
- };
92
- },
93
-
94
84
  showClusterSearch() {
95
85
  return this.allClustersCount > this.maxClustersToShow;
96
86
  },
@@ -483,7 +473,6 @@ export default {
483
473
  data-testid="side-menu"
484
474
  class="side-menu"
485
475
  :class="{'menu-open': shown, 'menu-close':!shown}"
486
- :style="sideMenuStyle"
487
476
  tabindex="-1"
488
477
  role="navigation"
489
478
  :aria-label="t('nav.ariaLabel.topLevelMenu')"
@@ -1002,7 +991,7 @@ export default {
1002
991
  }
1003
992
  }
1004
993
 
1005
- position: fixed;
994
+ position: absolute;
1006
995
  top: 0;
1007
996
  left: 0px;
1008
997
  bottom: 0;