@rancher/shell 3.0.9-rc.1 → 3.0.9-rc.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 (208) hide show
  1. package/assets/styles/base/_color.scss +1 -0
  2. package/assets/styles/base/_typography.scss +14 -5
  3. package/assets/styles/themes/_light.scss +1 -1
  4. package/assets/styles/themes/_modern.scss +1 -1
  5. package/assets/translations/en-us.yaml +104 -33
  6. package/assets/translations/zh-hans.yaml +13 -2
  7. package/components/ActionMenu.vue +7 -8
  8. package/components/ActionMenuShell.vue +23 -24
  9. package/components/CodeMirror.vue +4 -3
  10. package/components/DetailText.vue +54 -7
  11. package/components/Drawer/Chrome.vue +11 -4
  12. package/components/Drawer/DrawerCard.vue +19 -0
  13. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +3 -11
  14. package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +2 -2
  15. package/components/Drawer/ResourceDetailDrawer/index.vue +3 -20
  16. package/components/Drawer/types.ts +1 -0
  17. package/components/DynamicContent/DynamicContentCloseButton.vue +2 -2
  18. package/components/LocaleSelector.vue +1 -1
  19. package/components/Markdown.vue +1 -1
  20. package/components/PopoverCard.vue +3 -3
  21. package/components/Resource/Detail/Card/ExtrasCard.vue +39 -0
  22. package/components/Resource/Detail/Card/Scaler.vue +10 -2
  23. package/components/Resource/Detail/Card/StateCard/__tests__/composables.test.ts +142 -0
  24. package/components/Resource/Detail/Card/StateCard/composables.ts +41 -11
  25. package/components/Resource/Detail/Card/StateCard/index.vue +3 -9
  26. package/components/Resource/Detail/Card/StateCard/types.ts +6 -0
  27. package/components/Resource/Detail/Card/{PodsCard → StatusCard}/index.vue +14 -10
  28. package/components/Resource/Detail/Card/__tests__/PodsCard.test.ts +24 -25
  29. package/components/Resource/Detail/Cards.vue +27 -0
  30. package/components/Resource/Detail/Masthead/__tests__/index.test.ts +70 -0
  31. package/components/Resource/Detail/Masthead/index.vue +5 -0
  32. package/components/Resource/Detail/Metadata/KeyValueRow.vue +4 -2
  33. package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +2 -2
  34. package/components/Resource/Detail/ResourceRow.types.ts +14 -0
  35. package/components/Resource/Detail/ResourceRow.vue +23 -35
  36. package/components/Resource/Detail/StatusRow.vue +5 -2
  37. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +38 -7
  38. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +106 -2
  39. package/components/Resource/Detail/TitleBar/composables.ts +2 -1
  40. package/components/Resource/Detail/TitleBar/index.vue +41 -6
  41. package/components/ResourceDetail/Masthead/__tests__/index.test.ts +49 -1
  42. package/components/ResourceDetail/Masthead/__tests__/latest.test.ts +85 -0
  43. package/components/ResourceDetail/Masthead/index.vue +1 -0
  44. package/components/ResourceDetail/Masthead/latest.vue +8 -1
  45. package/components/ResourceDetail/Masthead/legacy.vue +1 -1
  46. package/components/ResourceTable.vue +1 -1
  47. package/components/Setting.vue +1 -1
  48. package/components/SortableTable/index.vue +25 -0
  49. package/components/SortableTable/selection.js +25 -12
  50. package/components/SortableTable/sorting.js +1 -1
  51. package/components/Tabbed/Tab.vue +5 -0
  52. package/components/Tabbed/index.vue +40 -9
  53. package/components/Window/ContainerShell.vue +10 -13
  54. package/components/__tests__/ProjectRow.test.ts +102 -15
  55. package/components/fleet/FleetClusterTargets/TargetsList.vue +47 -29
  56. package/components/fleet/FleetClusterTargets/index.vue +82 -29
  57. package/components/fleet/FleetClusters.vue +26 -12
  58. package/components/fleet/FleetGitRepoPaths.vue +2 -2
  59. package/components/fleet/FleetResources.vue +14 -0
  60. package/components/fleet/FleetValuesFrom.vue +2 -2
  61. package/components/fleet/__tests__/FleetClusterTargets.test.ts +531 -0
  62. package/components/fleet/__tests__/FleetClusters.test.ts +576 -0
  63. package/components/fleet/dashboard/ResourceDetails.vue +96 -123
  64. package/components/form/Conditions.vue +1 -15
  65. package/components/form/HookOption.vue +5 -0
  66. package/components/form/LabeledSelect.vue +1 -1
  67. package/components/form/LifecycleHooks.vue +2 -6
  68. package/components/form/ResourceLabeledSelect.vue +12 -1
  69. package/components/form/ResourceQuota/Project.vue +59 -8
  70. package/components/form/ResourceQuota/ProjectRow.vue +116 -21
  71. package/components/form/ResourceQuota/shared.js +42 -18
  72. package/components/form/SeccompProfile.vue +113 -0
  73. package/components/form/Security.vue +244 -133
  74. package/components/form/__tests__/LabeledSelect.test.ts +1 -1
  75. package/components/form/__tests__/SeccompProfile.test.js +124 -0
  76. package/components/form/__tests__/Security.test.ts +125 -37
  77. package/components/formatter/Autoscaler.vue +2 -2
  78. package/components/formatter/FleetSummaryGraph.vue +4 -1
  79. package/components/formatter/LinkName.vue +3 -2
  80. package/components/nav/Group.vue +5 -0
  81. package/components/nav/Header.vue +3 -3
  82. package/components/nav/HeaderPageActionMenu.vue +1 -1
  83. package/components/nav/NamespaceFilter.vue +6 -6
  84. package/components/nav/NotificationCenter/index.vue +1 -1
  85. package/components/nav/TopLevelMenu.helper.ts +41 -16
  86. package/components/nav/TopLevelMenu.vue +45 -25
  87. package/components/nav/WorkspaceSwitcher.vue +1 -1
  88. package/components/nav/__tests__/TopLevelMenu.helper.test.ts +277 -0
  89. package/components/nav/__tests__/TopLevelMenu.test.ts +160 -4
  90. package/components/templates/default.vue +0 -3
  91. package/components/templates/home.vue +0 -3
  92. package/components/templates/plain.vue +0 -3
  93. package/composables/useClickOutside.ts +1 -1
  94. package/config/product/explorer.js +2 -3
  95. package/config/table-headers.js +9 -7
  96. package/config/types.js +45 -9
  97. package/detail/__tests__/workload.test.ts +8 -16
  98. package/detail/catalog.cattle.io.app.vue +5 -0
  99. package/detail/fleet.cattle.io.cluster.vue +6 -0
  100. package/detail/management.cattle.io.oidcclient.vue +15 -4
  101. package/detail/workload/index.vue +7 -109
  102. package/edit/__tests__/management.cattle.io.project.test.js +137 -0
  103. package/edit/__tests__/projectsecret.test.ts +42 -0
  104. package/edit/auth/__tests__/oidc.test.ts +50 -0
  105. package/edit/auth/oidc.vue +68 -44
  106. package/edit/autoscaling.horizontalpodautoscaler/index.vue +140 -59
  107. package/edit/autoscaling.horizontalpodautoscaler/metrics-row.vue +41 -5
  108. package/edit/management.cattle.io.project.vue +36 -6
  109. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +16 -3
  110. package/edit/projectsecret.vue +29 -0
  111. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +89 -200
  112. package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +58 -17
  113. package/edit/provisioning.cattle.io.cluster/rke2.vue +11 -0
  114. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +3 -63
  115. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +82 -14
  116. package/edit/workload/__tests__/index.test.ts +3 -4
  117. package/edit/workload/index.vue +47 -28
  118. package/edit/workload/mixins/workload.js +66 -31
  119. package/initialize/install-plugins.js +0 -2
  120. package/list/catalog.cattle.io.clusterrepo.vue +1 -1
  121. package/list/projectsecret.vue +2 -2
  122. package/machine-config/__tests__/vmwarevsphere.test.ts +64 -0
  123. package/machine-config/amazonec2.vue +2 -2
  124. package/machine-config/vmwarevsphere.vue +58 -4
  125. package/mixins/__tests__/chart.test.ts +63 -0
  126. package/mixins/chart.js +56 -51
  127. package/models/__tests__/catalog.cattle.io.app.test.ts +33 -0
  128. package/models/__tests__/workload.test.ts +333 -0
  129. package/models/catalog.cattle.io.app.js +8 -0
  130. package/models/management.cattle.io.cluster.js +22 -30
  131. package/models/pod.js +14 -0
  132. package/models/provisioning.cattle.io.cluster.js +2 -2
  133. package/models/secret.js +1 -1
  134. package/models/workload.js +93 -27
  135. package/package.json +4 -4
  136. package/pages/__tests__/diagnostic.test.ts +71 -0
  137. package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +91 -0
  138. package/pages/c/_cluster/apps/charts/install.vue +4 -4
  139. package/pages/c/_cluster/explorer/EventsTable.vue +2 -2
  140. package/pages/c/_cluster/explorer/tools/index.vue +23 -5
  141. package/pages/c/_cluster/fleet/index.vue +14 -8
  142. package/pages/c/_cluster/manager/hostedprovider/index.vue +1 -19
  143. package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +18 -5
  144. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -1
  145. package/pages/c/_cluster/uiplugins/index.vue +41 -9
  146. package/pages/diagnostic.vue +17 -3
  147. package/plugins/dashboard-store/__tests__/resource-class.test.ts +234 -0
  148. package/plugins/dashboard-store/actions.js +9 -8
  149. package/plugins/dashboard-store/resource-class.js +97 -1
  150. package/plugins/steve/__tests__/revision.test.ts +84 -0
  151. package/plugins/steve/__tests__/steve-pagination-utils.test.ts +30 -0
  152. package/plugins/steve/__tests__/subscribe.spec.ts +134 -0
  153. package/plugins/steve/revision.ts +26 -0
  154. package/plugins/steve/steve-pagination-utils.ts +6 -5
  155. package/plugins/steve/subscribe.js +188 -49
  156. package/plugins/subscribe-events.ts +2 -2
  157. package/rancher-components/Form/Checkbox/Checkbox.vue +13 -0
  158. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -1
  159. package/rancher-components/Pill/RcCounterBadge/RcCounterBadge.vue +2 -1
  160. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +3 -1
  161. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +3 -1
  162. package/rancher-components/Pill/RcTag/RcTag.vue +1 -1
  163. package/rancher-components/Pill/index.ts +4 -0
  164. package/rancher-components/RcButton/RcButton.test.ts +53 -9
  165. package/rancher-components/RcButton/RcButton.vue +217 -25
  166. package/rancher-components/RcButton/types.ts +27 -1
  167. package/rancher-components/RcDropdown/RcDropdownMenu.vue +4 -4
  168. package/rancher-components/RcDropdown/types.ts +3 -3
  169. package/rancher-components/RcIcon/RcIcon.test.ts +42 -0
  170. package/rancher-components/RcIcon/RcIcon.vue +9 -6
  171. package/rancher-components/RcIcon/types.ts +13 -9
  172. package/rancher-components/RcItemCard/RcItemCard.test.ts +16 -6
  173. package/rancher-components/RcItemCard/RcItemCard.vue +13 -23
  174. package/rancher-components/utils/status.test.ts +10 -15
  175. package/rancher-components/utils/status.ts +5 -6
  176. package/store/__tests__/auth.test.ts +21 -5
  177. package/store/auth.js +6 -3
  178. package/store/aws.js +18 -12
  179. package/store/index.js +4 -8
  180. package/store/type-map.utils.ts +1 -1
  181. package/types/kube/kube-api.ts +29 -3
  182. package/types/rancher/steve.api.ts +40 -0
  183. package/types/shell/index.d.ts +262 -156
  184. package/types/store/pagination.types.ts +1 -0
  185. package/types/store/subscribe-events.types.ts +1 -0
  186. package/utils/__tests__/azure.test.ts +56 -0
  187. package/utils/__tests__/back-off.test.ts +364 -245
  188. package/utils/__tests__/error.test.ts +44 -0
  189. package/utils/__tests__/fleet.test.ts +8 -1
  190. package/utils/__tests__/pagination-wrapper.test.ts +167 -0
  191. package/utils/__tests__/version.test.ts +55 -1
  192. package/utils/azure.js +12 -0
  193. package/utils/back-off.ts +302 -69
  194. package/utils/dynamic-content/__tests__/index.test.ts +1 -1
  195. package/utils/dynamic-content/__tests__/new-release.test.ts +48 -7
  196. package/utils/dynamic-content/__tests__/support-notice.test.ts +1 -4
  197. package/utils/dynamic-content/index.ts +1 -6
  198. package/utils/dynamic-content/new-release.ts +5 -3
  199. package/utils/dynamic-content/types.d.ts +0 -1
  200. package/utils/error.js +9 -0
  201. package/utils/fleet.ts +2 -2
  202. package/utils/inactivity.ts +2 -3
  203. package/utils/pagination-wrapper.ts +99 -15
  204. package/utils/validators/formRules/index.ts +3 -0
  205. package/utils/version.js +38 -0
  206. package/components/auth/AzureWarning.vue +0 -77
  207. /package/components/Resource/Detail/{Card/PodsCard/Bubble.vue → Bubble.vue} +0 -0
  208. /package/components/Resource/Detail/Card/{PodsCard → StatusCard}/composable.ts +0 -0
@@ -2,22 +2,22 @@ import { mount } from '@vue/test-utils';
2
2
  import RcButton from './RcButton.vue';
3
3
 
4
4
  describe('rcButton.vue', () => {
5
- it('renders with default role', () => {
5
+ it('renders with default variant', () => {
6
6
  const wrapper = mount(RcButton);
7
7
  const button = wrapper.find('button');
8
8
 
9
9
  expect(button.classes()).toContain('btn');
10
- expect(button.classes()).toContain('role-primary');
10
+ expect(button.classes()).toContain('variant-primary');
11
11
  });
12
12
 
13
- it('applies correct role', () => {
13
+ it('applies correct variant', () => {
14
14
  const wrapper = mount(RcButton, { props: { primary: true } });
15
15
  const button = wrapper.find('button');
16
16
 
17
- expect(button.classes()).toContain('role-primary');
17
+ expect(button.classes()).toContain('variant-primary');
18
18
  });
19
19
 
20
- it('defaults to primary role if multiple roles are provided', () => {
20
+ it('defaults to primary variant if multiple variants are provided', () => {
21
21
  const wrapper = mount(
22
22
  RcButton,
23
23
  {
@@ -30,10 +30,10 @@ describe('rcButton.vue', () => {
30
30
  );
31
31
  const button = wrapper.find('button');
32
32
 
33
- expect(button.classes()).toContain('role-primary');
33
+ expect(button.classes()).toContain('variant-primary');
34
34
  });
35
35
 
36
- it('defaults to secondary role if both secondary and tertiary roles are provided', () => {
36
+ it('defaults to secondary variant if both secondary and tertiary variants are provided', () => {
37
37
  const wrapper = mount(
38
38
  RcButton,
39
39
  {
@@ -45,7 +45,7 @@ describe('rcButton.vue', () => {
45
45
  );
46
46
  const button = wrapper.find('button');
47
47
 
48
- expect(button.classes()).toContain('role-secondary');
48
+ expect(button.classes()).toContain('variant-secondary');
49
49
  });
50
50
 
51
51
  it('applies correct size class', () => {
@@ -92,6 +92,50 @@ describe('rcButton.vue', () => {
92
92
  const wrapper = mount(RcButton, { props: { ghost: true } });
93
93
  const button = wrapper.find('button');
94
94
 
95
- expect(button.classes()).toContain('role-ghost');
95
+ expect(button.classes()).toContain('variant-ghost');
96
+ });
97
+
98
+ describe('variant prop', () => {
99
+ it('applies variant-primary class when variant="primary"', () => {
100
+ const wrapper = mount(RcButton, { props: { variant: 'primary' } });
101
+ const button = wrapper.find('button');
102
+
103
+ expect(button.classes()).toContain('variant-primary');
104
+ });
105
+
106
+ it('applies variant-secondary class when variant="secondary"', () => {
107
+ const wrapper = mount(RcButton, { props: { variant: 'secondary' } });
108
+ const button = wrapper.find('button');
109
+
110
+ expect(button.classes()).toContain('variant-secondary');
111
+ });
112
+
113
+ it('applies variant-tertiary class when variant="tertiary"', () => {
114
+ const wrapper = mount(RcButton, { props: { variant: 'tertiary' } });
115
+ const button = wrapper.find('button');
116
+
117
+ expect(button.classes()).toContain('variant-tertiary');
118
+ });
119
+
120
+ it('applies variant-link class when variant="link"', () => {
121
+ const wrapper = mount(RcButton, { props: { variant: 'link' } });
122
+ const button = wrapper.find('button');
123
+
124
+ expect(button.classes()).toContain('variant-link');
125
+ });
126
+
127
+ it('applies variant-multi-action class when variant="multiAction"', () => {
128
+ const wrapper = mount(RcButton, { props: { variant: 'multiAction' } });
129
+ const button = wrapper.find('button');
130
+
131
+ expect(button.classes()).toContain('variant-multi-action');
132
+ });
133
+
134
+ it('applies variant-ghost class when variant="ghost"', () => {
135
+ const wrapper = mount(RcButton, { props: { variant: 'ghost' } });
136
+ const button = wrapper.find('button');
137
+
138
+ expect(button.classes()).toContain('variant-ghost');
139
+ });
96
140
  });
97
141
  });
@@ -5,36 +5,82 @@
5
5
  *
6
6
  * Example:
7
7
  *
8
- * <rc-button primary @click="doAction">Perform an Action</rc-button>
8
+ * <rc-button variant="primary" @click="doAction">Perform an Action</rc-button>
9
9
  */
10
10
  import { computed, ref } from 'vue';
11
- import { ButtonRoleProps, ButtonSizeProps } from './types';
12
-
13
- const buttonRoles: { role: keyof ButtonRoleProps, className: string }[] = [
14
- { role: 'primary', className: 'role-primary' },
15
- { role: 'secondary', className: 'role-secondary' },
16
- { role: 'tertiary', className: 'role-tertiary' },
17
- { role: 'link', className: 'role-link' },
18
- { role: 'multiAction', className: 'role-multi-action' },
19
- { role: 'ghost', className: 'role-ghost' },
11
+ import {
12
+ ButtonVariantProps, ButtonSizeProps, ButtonVariantNewProps, ButtonSizeNewProps, ButtonSize,
13
+ IconProps
14
+ } from './types';
15
+ import RcIcon from '@components/RcIcon/RcIcon.vue';
16
+
17
+ const buttonVariants: { variant: keyof ButtonVariantProps, className: string }[] = [
18
+ { variant: 'primary', className: 'variant-primary' },
19
+ { variant: 'secondary', className: 'variant-secondary' },
20
+ { variant: 'tertiary', className: 'variant-tertiary' },
21
+ { variant: 'link', className: 'variant-link' },
22
+ { variant: 'multiAction', className: 'variant-multi-action' },
23
+ { variant: 'ghost', className: 'variant-ghost' },
20
24
  ];
21
25
 
22
26
  const buttonSizes: { size: keyof ButtonSizeProps, className: string }[] = [
23
27
  { size: 'small', className: 'btn-sm' },
24
28
  ];
25
29
 
26
- const props = defineProps<ButtonRoleProps & ButtonSizeProps>();
30
+ const buttonSizesNew: { size: ButtonSize, className: string }[] = [
31
+ { size: 'small', className: 'btn-small' },
32
+ { size: 'medium', className: 'btn-medium' },
33
+ { size: 'large', className: 'btn-large' },
34
+ ];
27
35
 
28
- const buttonClass = computed(() => {
29
- const activeRole = buttonRoles.find(({ role }) => props[role]);
30
- const isButtonSmall = buttonSizes.some(({ size }) => props[size]);
36
+ const props = withDefaults(defineProps<ButtonVariantProps & ButtonSizeProps & ButtonVariantNewProps & ButtonSizeNewProps & IconProps>(), { size: 'medium' });
31
37
 
32
- return {
33
- btn: true,
38
+ const activeVariantClassName = computed(() => {
39
+ if (props.variant === 'multiAction' || props.multiAction) {
40
+ console.warn('[RcButton] The "multiAction" variant is deprecated and will be removed in a future version.'); // eslint-disable-line no-console
41
+ }
42
+
43
+ const activeVariant = buttonVariants.find(({ variant }) => props[variant]);
44
+
45
+ if (activeVariant) {
46
+ console.warn( // eslint-disable-line no-console
47
+ `[RcButton] The "${ activeVariant.variant }" prop is deprecated and will be removed in a future version. ` +
48
+ `Please use variant="${ activeVariant.variant }" instead.`
49
+ );
50
+
51
+ return activeVariant.className;
52
+ } else {
53
+ const variantConfig = buttonVariants.find(({ variant }) => variant === props.variant);
54
+
55
+ return variantConfig?.className || 'variant-primary';
56
+ }
57
+ });
58
+
59
+ const activeSizeClassName = computed(() => {
60
+ const activeSize = buttonSizes.find(({ size }) => props[size]);
61
+
62
+ if (activeSize) {
63
+ /* eslint-disable no-console */
64
+ console.warn(
65
+ `[RcButton] The "${ activeSize.size }" prop is deprecated and will be removed in a future version. ` +
66
+ `Please use size="${ activeSize.size }" instead.`
67
+ );
68
+ /* eslint-enable no-console */
34
69
 
35
- [activeRole?.className || 'role-primary']: true,
70
+ return activeSize.className;
71
+ } else {
72
+ const sizeConfig = buttonSizesNew.find(({ size }) => size === props.size);
73
+
74
+ return sizeConfig?.className || '';
75
+ }
76
+ });
36
77
 
37
- 'btn-sm': isButtonSmall,
78
+ const buttonClass = computed(() => {
79
+ return {
80
+ 'rc-button': true,
81
+ btn: true,
82
+ [activeVariantClassName.value]: true,
83
+ [activeSizeClassName.value]: !!activeSizeClassName.value,
38
84
  };
39
85
  });
40
86
 
@@ -53,33 +99,142 @@ defineExpose({ focus });
53
99
  role="button"
54
100
  :class="{ ...buttonClass }"
55
101
  >
56
- <slot name="before">
57
- <!-- Empty Content -->
102
+ <slot
103
+ v-if="$slots.before || props.leftIcon"
104
+ name="before"
105
+ >
106
+ <RcIcon
107
+ v-if="props.leftIcon"
108
+ class="left-icon"
109
+ :type="props.leftIcon"
110
+ size="inherit"
111
+ />
58
112
  </slot>
59
113
  <slot>
60
114
  <!-- Empty Content -->
61
115
  </slot>
62
- <slot name="after">
63
- <!-- Empty Content -->
116
+ <slot
117
+ v-if="$slots.after || props.rightIcon"
118
+ name="after"
119
+ >
120
+ <RcIcon
121
+ v-if="props.rightIcon"
122
+ class="right-icon"
123
+ :type="props.rightIcon"
124
+ size="inherit"
125
+ />
64
126
  </slot>
65
127
  </button>
66
128
  </template>
67
129
 
68
130
  <style lang="scss" scoped>
69
131
  button {
70
- &.role-link {
132
+ display: inline-flex;
133
+ align-items: center;
134
+ justify-content: center;
135
+
136
+ // Much of the styling in here came from _button.scss. Because we're making changes from role to variant and we don't want to impact existing use cases we're pulling in some of these styles. We should in the long run deprecate that file.
137
+ // Variant styles
138
+ &.variant-primary {
139
+ background: var(--primary);
140
+ color: var(--primary-text);
141
+
142
+ &:hover, &._hover {
143
+ background-color: var(--primary-hover-bg);
144
+ color: var(--primary-text);
145
+ }
146
+
71
147
  &:focus, &.focused {
148
+ background-color: var(--primary-hover-bg);
149
+ color: var(--primary-text);
150
+ }
151
+
152
+ &:focus-visible {
72
153
  @include focus-outline;
73
- outline-offset: -2px;
154
+ outline-offset: 2px;
155
+ }
156
+
157
+ &:disabled {
158
+ background: var(--primary);
159
+ color: var(--primary-text);
160
+ opacity: 0.5;
161
+ }
162
+ }
163
+
164
+ &.variant-secondary {
165
+ background: var(--secondary, transparent);
166
+ color: var(--on-secondary, var(--primary));
167
+ border: solid 1px var(--secondary-border, var(--primary));
168
+
169
+ &:hover, &._hover {
170
+ background: var(--secondary-hover, transparent);
171
+ color: var(--on-secondary, var(--lightest));
172
+ }
173
+
174
+ &:focus, &.focused {
175
+ background-color: var(--secondary-hover, var(--primary-hover-bg));
176
+ color: var(--on-secondary, var(--primary-text));
177
+ }
178
+
179
+ &:focus-visible {
180
+ @include focus-outline;
181
+ outline-offset: 2px;
74
182
  }
183
+ }
184
+
185
+ &.variant-tertiary {
186
+ background: var(--tertiary, var(--accent-btn));
187
+ color: var(--on-tertiary, var(--primary));
188
+ border: solid 1px var(--tertiary-border, var(--primary));
75
189
 
76
190
  &:hover {
191
+ background: var(--tertiary-hover, var(--accent-btn));
192
+ color: var(--on-tertiary-hover, var(--lightest));
193
+ }
194
+
195
+ &:focus, &.focused {
196
+ background-color: var(--tertiary-hover, var(--primary-hover-bg));
197
+ color: var(--on-tertiary, var(--primary-text));
198
+ }
199
+
200
+ &:focus-visible {
201
+ @include focus-outline;
202
+ outline-offset: 2px;
203
+ }
204
+ }
205
+
206
+ &.variant-link {
207
+ background: transparent;
208
+ color: var(--link);
209
+
210
+ &:hover, &._hover {
211
+ color: var(--lightest);
77
212
  background-color: var(--accent-btn);
78
213
  box-shadow: none;
79
214
  }
215
+
216
+ &:focus, &.focused {
217
+ @include focus-outline;
218
+ outline-offset: -2px;
219
+ background: transparent;
220
+ color: var(--link);
221
+ box-shadow: none;
222
+ }
223
+
224
+ &:focus-visible {
225
+ @include focus-outline;
226
+ outline-offset: 2px;
227
+ }
80
228
  }
81
229
 
82
- &.role-ghost {
230
+ &.variant-multi-action {
231
+ background: var(--accent-btn);
232
+ border: solid thin var(--primary);
233
+ color: var(--primary);
234
+ border-radius: 2px;
235
+ }
236
+
237
+ &.variant-ghost {
83
238
  padding: 0;
84
239
  background-color: transparent;
85
240
 
@@ -93,4 +248,41 @@ button {
93
248
  outline-offset: 0;
94
249
  }
95
250
  }
251
+
252
+ // Size styles
253
+ &.btn-small {
254
+ //:not(.btn-sm) is being used to make the style more specific to override global styles. We may want to get rid of those styles at some point.
255
+ &, &:not(.btn-sm) {
256
+ line-height: 15px;
257
+ font-size: 12px;
258
+ min-height: 24px;
259
+
260
+ padding: 0 8px;
261
+ gap: 8px;
262
+ }
263
+ }
264
+
265
+ &.btn-medium {
266
+ //:not(.btn-sm) is being used to make the style more specific to override global styles. We may want to get rid of those styles at some point.
267
+ &, &:not(.btn-sm) {
268
+ line-height: 18px;
269
+ font-size: 14px;
270
+ min-height: 32px;
271
+
272
+ padding: 0 12px;
273
+ gap: 8px;
274
+ }
275
+ }
276
+
277
+ &.btn-large {
278
+ // This is the default size brought by the global button styling
279
+ &, &:not(.btn-sm) {
280
+ line-height: 20px;
281
+ font-size: 16px;
282
+ min-height: 40px;
283
+
284
+ padding: 0 16px;
285
+ gap: 12px;
286
+ }
287
+ }
96
288
  }</style>
@@ -1,18 +1,44 @@
1
+ import { RcIconType } from '@components/RcIcon/types';
2
+
1
3
  // TODO: 13211 Investigate why `InstanceType<typeof RcButton>` fails prod builds
2
4
  // export type RcButtonType = InstanceType<typeof RcButton>
3
5
  export type RcButtonType = {
4
6
  focus: () => void;
5
7
  }
6
8
 
7
- export type ButtonRoleProps = {
9
+ export type ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'link' | 'multiAction' | 'ghost';
10
+
11
+ export type ButtonVariantNewProps = {
12
+ variant?: ButtonVariant;
13
+ }
14
+
15
+ /**
16
+ * @deprecated Use the `variant` property instead. These boolean props will be removed in a future version.
17
+ */
18
+ export type ButtonVariantProps = {
8
19
  primary?: boolean;
9
20
  secondary?: boolean;
10
21
  tertiary?: boolean;
11
22
  link?: boolean;
12
23
  multiAction?: boolean;
13
24
  ghost?: boolean;
25
+
14
26
  }
15
27
 
28
+ export type ButtonSize = 'small' | 'medium' | 'large';
29
+
30
+ export type ButtonSizeNewProps = {
31
+ size?: ButtonSize;
32
+ }
33
+
34
+ /**
35
+ * @deprecated Use the `size` property instead. The `small` boolean prop will be removed in a future version.
36
+ */
16
37
  export type ButtonSizeProps = {
17
38
  small?: boolean;
18
39
  }
40
+
41
+ export type IconProps = {
42
+ leftIcon?: RcIconType;
43
+ rightIcon?: RcIconType;
44
+ }
@@ -9,8 +9,8 @@ import { RcDropdownMenuComponentProps, DropdownOption } from './types';
9
9
  import IconOrSvg from '@shell/components/IconOrSvg';
10
10
 
11
11
  withDefaults(defineProps<RcDropdownMenuComponentProps>(), {
12
- buttonRole: 'primary',
13
- buttonSize: undefined,
12
+ buttonVariant: 'primary',
13
+ buttonSize: undefined,
14
14
  });
15
15
 
16
16
  const emit = defineEmits(['update:open', 'select']);
@@ -26,8 +26,8 @@ const hasOptions = (options: DropdownOption[]) => {
26
26
  @update:open="(e: boolean) => emit('update:open', e)"
27
27
  >
28
28
  <rc-dropdown-trigger
29
- :[buttonRole]="true"
30
- :[buttonSize]="true"
29
+ :variant="buttonVariant"
30
+ :size="buttonSize"
31
31
  :data-testid="dataTestid"
32
32
  :aria-label="buttonAriaLabel"
33
33
  >
@@ -1,6 +1,6 @@
1
1
  import { Ref, ref } from 'vue';
2
2
  import type { RcButtonType } from '@components/RcButton';
3
- import { ButtonRoleProps, ButtonSizeProps } from '@components/RcButton/types';
3
+ import { ButtonVariant, ButtonSize } from '@components/RcButton/types';
4
4
 
5
5
  export type DropdownContext = {
6
6
  handleKeydown: () => void;
@@ -41,8 +41,8 @@ export type DropdownOption = {
41
41
 
42
42
  export type RcDropdownMenuComponentProps = {
43
43
  options: DropdownOption[];
44
- buttonRole?: keyof ButtonRoleProps;
45
- buttonSize?: keyof ButtonSizeProps;
44
+ buttonVariant?: ButtonVariant;
45
+ buttonSize?: ButtonSize;
46
46
  buttonAriaLabel?: string;
47
47
  dropdownAriaLabel?: string;
48
48
  dataTestid?: string;
@@ -48,4 +48,46 @@ describe('rcIcon.vue', () => {
48
48
 
49
49
  expect(wrapper.attributes('aria-hidden')).toBe('true');
50
50
  });
51
+
52
+ it('defaults the color to "inherit" when the status prop is omitted', () => {
53
+ const wrapper = shallowMount(RcIcon, {
54
+ props: {
55
+ size: 'medium',
56
+ type: 'search',
57
+ },
58
+ });
59
+
60
+ const vm = wrapper.vm as unknown as { color: string };
61
+
62
+ expect(vm.color).toBe('inherit');
63
+ });
64
+
65
+ it('uses "inherit" color when status is explicitly set to "inherit"', () => {
66
+ const wrapper = shallowMount(RcIcon, {
67
+ props: {
68
+ size: 'medium',
69
+ type: 'search',
70
+ status: 'inherit'
71
+ },
72
+ });
73
+
74
+ const vm = wrapper.vm as unknown as { color: string };
75
+
76
+ expect(vm.color).toBe('inherit');
77
+ });
78
+
79
+ it('uses appropriate color when status is provided with a specific value', () => {
80
+ const wrapper = shallowMount(RcIcon, {
81
+ props: {
82
+ size: 'medium',
83
+ type: 'search',
84
+ status: 'success'
85
+ },
86
+ });
87
+
88
+ const vm = wrapper.vm as unknown as { color: string };
89
+
90
+ expect(vm.color).not.toBe('inherit');
91
+ expect(vm.color).toContain('--rc-success');
92
+ });
51
93
  });
@@ -1,14 +1,17 @@
1
1
  <script setup lang="ts">
2
- import { RcIconProps, RcIconType, RcIconSize } from '@components/RcIcon/types';
2
+ import { RcIconSizeToCSS, RcIconTypeToClass, RcIconProps } from './types';
3
3
  import { computed } from 'vue';
4
4
  import { useStatusColors } from '@components/utils/status';
5
- const props = withDefaults(defineProps<RcIconProps>(), { size: 'small', ariaHidden: true });
5
+
6
+ const props = withDefaults(defineProps<RcIconProps>(), {
7
+ size: 'small', ariaHidden: true, status: 'inherit'
8
+ });
6
9
  const fontSize = computed(() => {
7
- return RcIconSize[props.size];
10
+ return RcIconSizeToCSS[props.size];
8
11
  });
9
12
 
10
13
  const iconClass = computed(() => {
11
- return RcIconType[props.type];
14
+ return RcIconTypeToClass[props.type];
12
15
  });
13
16
 
14
17
  const status = computed(() => {
@@ -19,10 +22,10 @@ const status = computed(() => {
19
22
  return 'none';
20
23
  });
21
24
 
22
- const { textColor } = useStatusColors({ status: status.value }, 'outlined');
25
+ const { textColor } = useStatusColors(status, 'outlined');
23
26
 
24
27
  const color = computed(() => {
25
- if (props.status === 'inherit') {
28
+ if (props.status === undefined || props.status === 'inherit') {
26
29
  return 'inherit';
27
30
  }
28
31
 
@@ -1,6 +1,6 @@
1
- import { Status } from '../utils/status';
1
+ import { Status } from '@components/utils/status';
2
2
 
3
- export const RcIconType = {
3
+ export const RcIconTypeToClass = {
4
4
  actions: 'icon-actions',
5
5
  ai: 'icon-ai',
6
6
  'alert-alt': 'icon-alert-alt',
@@ -145,16 +145,20 @@ export const RcIconType = {
145
145
  windows: 'icon-windows',
146
146
  };
147
147
 
148
- export const RcIconSize = {
149
- large: '25px',
150
- medium: '18px',
151
- small: '14px',
152
- none: undefined
148
+ export const RcIconSizeToCSS = {
149
+ large: '25px',
150
+ medium: '18px',
151
+ small: '14px',
152
+ inherit: 'inherit'
153
153
  };
154
154
 
155
+ export type RcIconSize = keyof typeof RcIconSizeToCSS;
156
+
157
+ export type RcIconType = keyof typeof RcIconTypeToClass;
158
+
155
159
  export interface RcIconProps {
156
- size: keyof typeof RcIconSize;
157
- type: keyof typeof RcIconType;
160
+ type: RcIconType;
161
+ size?: RcIconSize;
158
162
  ariaHidden?: boolean;
159
163
  status?: Status | 'inherit';
160
164
  }
@@ -187,7 +187,7 @@ describe('rcItemCard', () => {
187
187
  expect(icon.attributes('style')).toContain('color: red');
188
188
  });
189
189
 
190
- it('emits custom action events correctly', async() => {
190
+ it('emits action-invoked event when action is triggered', async() => {
191
191
  const wrapper = mount(RcItemCard, {
192
192
  props: {
193
193
  ...baseProps,
@@ -198,12 +198,22 @@ describe('rcItemCard', () => {
198
198
  }
199
199
  });
200
200
 
201
- const listeners = wrapper.vm.$.setupState.actionListeners;
201
+ // Simulate the action-invoked event being emitted from ActionMenu
202
+ const actionMenu = wrapper.findComponent({ name: 'ActionMenuShell' });
202
203
 
203
- listeners.myActionA('payload-1');
204
- listeners.myActionB('payload-2');
204
+ expect(actionMenu.exists()).toBe(true);
205
205
 
206
- expect(wrapper.emitted('myActionA')?.[0]).toStrictEqual(['payload-1']);
207
- expect(wrapper.emitted('myActionB')?.[0]).toStrictEqual(['payload-2']);
206
+ // Emit action-invoked event with payload
207
+ const payload = {
208
+ action: 'myActionA', actionData: { action: 'myActionA', label: 'Edit' }, event: new MouseEvent('click')
209
+ };
210
+
211
+ actionMenu.vm.$emit('action-invoked', payload);
212
+ await wrapper.vm.$nextTick();
213
+
214
+ const emitted = wrapper.emitted('action-invoked');
215
+
216
+ expect(emitted).toBeTruthy();
217
+ expect(emitted?.[0]).toStrictEqual([payload]);
208
218
  });
209
219
  });