@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.
- package/assets/styles/base/_color.scss +1 -0
- package/assets/styles/base/_typography.scss +14 -5
- package/assets/styles/themes/_light.scss +1 -1
- package/assets/styles/themes/_modern.scss +1 -1
- package/assets/translations/en-us.yaml +104 -33
- package/assets/translations/zh-hans.yaml +13 -2
- package/components/ActionMenu.vue +7 -8
- package/components/ActionMenuShell.vue +23 -24
- package/components/CodeMirror.vue +4 -3
- package/components/DetailText.vue +54 -7
- package/components/Drawer/Chrome.vue +11 -4
- package/components/Drawer/DrawerCard.vue +19 -0
- package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +3 -11
- package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +2 -2
- package/components/Drawer/ResourceDetailDrawer/index.vue +3 -20
- package/components/Drawer/types.ts +1 -0
- package/components/DynamicContent/DynamicContentCloseButton.vue +2 -2
- package/components/LocaleSelector.vue +1 -1
- package/components/Markdown.vue +1 -1
- package/components/PopoverCard.vue +3 -3
- package/components/Resource/Detail/Card/ExtrasCard.vue +39 -0
- package/components/Resource/Detail/Card/Scaler.vue +10 -2
- package/components/Resource/Detail/Card/StateCard/__tests__/composables.test.ts +142 -0
- package/components/Resource/Detail/Card/StateCard/composables.ts +41 -11
- package/components/Resource/Detail/Card/StateCard/index.vue +3 -9
- package/components/Resource/Detail/Card/StateCard/types.ts +6 -0
- package/components/Resource/Detail/Card/{PodsCard → StatusCard}/index.vue +14 -10
- package/components/Resource/Detail/Card/__tests__/PodsCard.test.ts +24 -25
- package/components/Resource/Detail/Cards.vue +27 -0
- package/components/Resource/Detail/Masthead/__tests__/index.test.ts +70 -0
- package/components/Resource/Detail/Masthead/index.vue +5 -0
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +4 -2
- package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +2 -2
- package/components/Resource/Detail/ResourceRow.types.ts +14 -0
- package/components/Resource/Detail/ResourceRow.vue +23 -35
- package/components/Resource/Detail/StatusRow.vue +5 -2
- package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +38 -7
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +106 -2
- package/components/Resource/Detail/TitleBar/composables.ts +2 -1
- package/components/Resource/Detail/TitleBar/index.vue +41 -6
- package/components/ResourceDetail/Masthead/__tests__/index.test.ts +49 -1
- package/components/ResourceDetail/Masthead/__tests__/latest.test.ts +85 -0
- package/components/ResourceDetail/Masthead/index.vue +1 -0
- package/components/ResourceDetail/Masthead/latest.vue +8 -1
- package/components/ResourceDetail/Masthead/legacy.vue +1 -1
- package/components/ResourceTable.vue +1 -1
- package/components/Setting.vue +1 -1
- package/components/SortableTable/index.vue +25 -0
- package/components/SortableTable/selection.js +25 -12
- package/components/SortableTable/sorting.js +1 -1
- package/components/Tabbed/Tab.vue +5 -0
- package/components/Tabbed/index.vue +40 -9
- package/components/Window/ContainerShell.vue +10 -13
- package/components/__tests__/ProjectRow.test.ts +102 -15
- package/components/fleet/FleetClusterTargets/TargetsList.vue +47 -29
- package/components/fleet/FleetClusterTargets/index.vue +82 -29
- package/components/fleet/FleetClusters.vue +26 -12
- package/components/fleet/FleetGitRepoPaths.vue +2 -2
- package/components/fleet/FleetResources.vue +14 -0
- package/components/fleet/FleetValuesFrom.vue +2 -2
- package/components/fleet/__tests__/FleetClusterTargets.test.ts +531 -0
- package/components/fleet/__tests__/FleetClusters.test.ts +576 -0
- package/components/fleet/dashboard/ResourceDetails.vue +96 -123
- package/components/form/Conditions.vue +1 -15
- package/components/form/HookOption.vue +5 -0
- package/components/form/LabeledSelect.vue +1 -1
- package/components/form/LifecycleHooks.vue +2 -6
- package/components/form/ResourceLabeledSelect.vue +12 -1
- package/components/form/ResourceQuota/Project.vue +59 -8
- package/components/form/ResourceQuota/ProjectRow.vue +116 -21
- package/components/form/ResourceQuota/shared.js +42 -18
- package/components/form/SeccompProfile.vue +113 -0
- package/components/form/Security.vue +244 -133
- package/components/form/__tests__/LabeledSelect.test.ts +1 -1
- package/components/form/__tests__/SeccompProfile.test.js +124 -0
- package/components/form/__tests__/Security.test.ts +125 -37
- package/components/formatter/Autoscaler.vue +2 -2
- package/components/formatter/FleetSummaryGraph.vue +4 -1
- package/components/formatter/LinkName.vue +3 -2
- package/components/nav/Group.vue +5 -0
- package/components/nav/Header.vue +3 -3
- package/components/nav/HeaderPageActionMenu.vue +1 -1
- package/components/nav/NamespaceFilter.vue +6 -6
- package/components/nav/NotificationCenter/index.vue +1 -1
- package/components/nav/TopLevelMenu.helper.ts +41 -16
- package/components/nav/TopLevelMenu.vue +45 -25
- package/components/nav/WorkspaceSwitcher.vue +1 -1
- package/components/nav/__tests__/TopLevelMenu.helper.test.ts +277 -0
- package/components/nav/__tests__/TopLevelMenu.test.ts +160 -4
- package/components/templates/default.vue +0 -3
- package/components/templates/home.vue +0 -3
- package/components/templates/plain.vue +0 -3
- package/composables/useClickOutside.ts +1 -1
- package/config/product/explorer.js +2 -3
- package/config/table-headers.js +9 -7
- package/config/types.js +45 -9
- package/detail/__tests__/workload.test.ts +8 -16
- package/detail/catalog.cattle.io.app.vue +5 -0
- package/detail/fleet.cattle.io.cluster.vue +6 -0
- package/detail/management.cattle.io.oidcclient.vue +15 -4
- package/detail/workload/index.vue +7 -109
- package/edit/__tests__/management.cattle.io.project.test.js +137 -0
- package/edit/__tests__/projectsecret.test.ts +42 -0
- package/edit/auth/__tests__/oidc.test.ts +50 -0
- package/edit/auth/oidc.vue +68 -44
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +140 -59
- package/edit/autoscaling.horizontalpodautoscaler/metrics-row.vue +41 -5
- package/edit/management.cattle.io.project.vue +36 -6
- package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +16 -3
- package/edit/projectsecret.vue +29 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +89 -200
- package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +58 -17
- package/edit/provisioning.cattle.io.cluster/rke2.vue +11 -0
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +3 -63
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +82 -14
- package/edit/workload/__tests__/index.test.ts +3 -4
- package/edit/workload/index.vue +47 -28
- package/edit/workload/mixins/workload.js +66 -31
- package/initialize/install-plugins.js +0 -2
- package/list/catalog.cattle.io.clusterrepo.vue +1 -1
- package/list/projectsecret.vue +2 -2
- package/machine-config/__tests__/vmwarevsphere.test.ts +64 -0
- package/machine-config/amazonec2.vue +2 -2
- package/machine-config/vmwarevsphere.vue +58 -4
- package/mixins/__tests__/chart.test.ts +63 -0
- package/mixins/chart.js +56 -51
- package/models/__tests__/catalog.cattle.io.app.test.ts +33 -0
- package/models/__tests__/workload.test.ts +333 -0
- package/models/catalog.cattle.io.app.js +8 -0
- package/models/management.cattle.io.cluster.js +22 -30
- package/models/pod.js +14 -0
- package/models/provisioning.cattle.io.cluster.js +2 -2
- package/models/secret.js +1 -1
- package/models/workload.js +93 -27
- package/package.json +4 -4
- package/pages/__tests__/diagnostic.test.ts +71 -0
- package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +91 -0
- package/pages/c/_cluster/apps/charts/install.vue +4 -4
- package/pages/c/_cluster/explorer/EventsTable.vue +2 -2
- package/pages/c/_cluster/explorer/tools/index.vue +23 -5
- package/pages/c/_cluster/fleet/index.vue +14 -8
- package/pages/c/_cluster/manager/hostedprovider/index.vue +1 -19
- package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +18 -5
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -1
- package/pages/c/_cluster/uiplugins/index.vue +41 -9
- package/pages/diagnostic.vue +17 -3
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +234 -0
- package/plugins/dashboard-store/actions.js +9 -8
- package/plugins/dashboard-store/resource-class.js +97 -1
- package/plugins/steve/__tests__/revision.test.ts +84 -0
- package/plugins/steve/__tests__/steve-pagination-utils.test.ts +30 -0
- package/plugins/steve/__tests__/subscribe.spec.ts +134 -0
- package/plugins/steve/revision.ts +26 -0
- package/plugins/steve/steve-pagination-utils.ts +6 -5
- package/plugins/steve/subscribe.js +188 -49
- package/plugins/subscribe-events.ts +2 -2
- package/rancher-components/Form/Checkbox/Checkbox.vue +13 -0
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -1
- package/rancher-components/Pill/RcCounterBadge/RcCounterBadge.vue +2 -1
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +3 -1
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +3 -1
- package/rancher-components/Pill/RcTag/RcTag.vue +1 -1
- package/rancher-components/Pill/index.ts +4 -0
- package/rancher-components/RcButton/RcButton.test.ts +53 -9
- package/rancher-components/RcButton/RcButton.vue +217 -25
- package/rancher-components/RcButton/types.ts +27 -1
- package/rancher-components/RcDropdown/RcDropdownMenu.vue +4 -4
- package/rancher-components/RcDropdown/types.ts +3 -3
- package/rancher-components/RcIcon/RcIcon.test.ts +42 -0
- package/rancher-components/RcIcon/RcIcon.vue +9 -6
- package/rancher-components/RcIcon/types.ts +13 -9
- package/rancher-components/RcItemCard/RcItemCard.test.ts +16 -6
- package/rancher-components/RcItemCard/RcItemCard.vue +13 -23
- package/rancher-components/utils/status.test.ts +10 -15
- package/rancher-components/utils/status.ts +5 -6
- package/store/__tests__/auth.test.ts +21 -5
- package/store/auth.js +6 -3
- package/store/aws.js +18 -12
- package/store/index.js +4 -8
- package/store/type-map.utils.ts +1 -1
- package/types/kube/kube-api.ts +29 -3
- package/types/rancher/steve.api.ts +40 -0
- package/types/shell/index.d.ts +262 -156
- package/types/store/pagination.types.ts +1 -0
- package/types/store/subscribe-events.types.ts +1 -0
- package/utils/__tests__/azure.test.ts +56 -0
- package/utils/__tests__/back-off.test.ts +364 -245
- package/utils/__tests__/error.test.ts +44 -0
- package/utils/__tests__/fleet.test.ts +8 -1
- package/utils/__tests__/pagination-wrapper.test.ts +167 -0
- package/utils/__tests__/version.test.ts +55 -1
- package/utils/azure.js +12 -0
- package/utils/back-off.ts +302 -69
- package/utils/dynamic-content/__tests__/index.test.ts +1 -1
- package/utils/dynamic-content/__tests__/new-release.test.ts +48 -7
- package/utils/dynamic-content/__tests__/support-notice.test.ts +1 -4
- package/utils/dynamic-content/index.ts +1 -6
- package/utils/dynamic-content/new-release.ts +5 -3
- package/utils/dynamic-content/types.d.ts +0 -1
- package/utils/error.js +9 -0
- package/utils/fleet.ts +2 -2
- package/utils/inactivity.ts +2 -3
- package/utils/pagination-wrapper.ts +99 -15
- package/utils/validators/formRules/index.ts +3 -0
- package/utils/version.js +38 -0
- package/components/auth/AzureWarning.vue +0 -77
- /package/components/Resource/Detail/{Card/PodsCard/Bubble.vue → Bubble.vue} +0 -0
- /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
|
|
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('
|
|
10
|
+
expect(button.classes()).toContain('variant-primary');
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
it('applies correct
|
|
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('
|
|
17
|
+
expect(button.classes()).toContain('variant-primary');
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
it('defaults to primary
|
|
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('
|
|
33
|
+
expect(button.classes()).toContain('variant-primary');
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
it('defaults to secondary
|
|
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('
|
|
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('
|
|
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 {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
{
|
|
19
|
-
{
|
|
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
|
|
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
|
|
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
|
-
|
|
33
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
57
|
-
|
|
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
|
|
63
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
&.
|
|
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
|
|
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
|
-
|
|
13
|
-
buttonSize:
|
|
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
|
-
:
|
|
30
|
-
:
|
|
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 {
|
|
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
|
-
|
|
45
|
-
buttonSize?:
|
|
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 {
|
|
2
|
+
import { RcIconSizeToCSS, RcIconTypeToClass, RcIconProps } from './types';
|
|
3
3
|
import { computed } from 'vue';
|
|
4
4
|
import { useStatusColors } from '@components/utils/status';
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<RcIconProps>(), {
|
|
7
|
+
size: 'small', ariaHidden: true, status: 'inherit'
|
|
8
|
+
});
|
|
6
9
|
const fontSize = computed(() => {
|
|
7
|
-
return
|
|
10
|
+
return RcIconSizeToCSS[props.size];
|
|
8
11
|
});
|
|
9
12
|
|
|
10
13
|
const iconClass = computed(() => {
|
|
11
|
-
return
|
|
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(
|
|
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 '
|
|
1
|
+
import { Status } from '@components/utils/status';
|
|
2
2
|
|
|
3
|
-
export const
|
|
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
|
|
149
|
-
large:
|
|
150
|
-
medium:
|
|
151
|
-
small:
|
|
152
|
-
|
|
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
|
-
|
|
157
|
-
|
|
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
|
|
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
|
-
|
|
201
|
+
// Simulate the action-invoked event being emitted from ActionMenu
|
|
202
|
+
const actionMenu = wrapper.findComponent({ name: 'ActionMenuShell' });
|
|
202
203
|
|
|
203
|
-
|
|
204
|
-
listeners.myActionB('payload-2');
|
|
204
|
+
expect(actionMenu.exists()).toBe(true);
|
|
205
205
|
|
|
206
|
-
|
|
207
|
-
|
|
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
|
});
|