Skip to content

Commit fbb8398

Browse files
authored
Merge pull request #6595 from nextcloud-libraries/backport/6472/next
[next] feat: Add consistent `variant` prop for design variant of buttons / chips
2 parents 99d6fa6 + 47c8682 commit fbb8398

File tree

31 files changed

+265
-237
lines changed

31 files changed

+265
-237
lines changed

CHANGELOG.md

+14
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,20 @@ are now removed. Following components have been adjusted:
9696

9797
Additionally the default value `closeOnClickOutside` for `NcModal` was aligned with `NcDialog` and now defaults to `false`.
9898

99+
#### Removal of `type` and `nativeType` props
100+
101+
The `type` property for button components (`NcButton`, `NcActions`, `NcDialogButton`) was deprecated for the usage with color variants like `primary`.
102+
The fallback behavior was removed, `type` now only allows the native HTML button type like `button`, `reset` or `submit`.
103+
Instead use the `variant` property for the color variant.
104+
105+
The `nativeType` property was removed in favor of `type`.
106+
```vue
107+
<!-- Old: Nextcloud Vue v8 -->
108+
<NcButton type="primary" native-type="submit">Submit</NcButton>
109+
<!-- New: Nextcloud Vue v9 -->
110+
<NcButton type="submit" variant="primary">Submit</NcButton>
111+
```
112+
99113
#### Mixins are removed
100114
Mixins only work in Options API and are in general not recommended by Vue anymore:
101115

src/components/NcActions/NcActions.vue

+43-41
Original file line numberDiff line numberDiff line change
@@ -444,12 +444,12 @@ export default {
444444
</script>
445445
```
446446

447-
### Type variants
447+
### Design variants
448448

449449
```vue
450450
<template>
451451
<div>
452-
<NcActions :type="current">
452+
<NcActions :variant="current">
453453
<template #icon>
454454
<SelectColor :size="20" />
455455
</template>
@@ -461,7 +461,7 @@ export default {
461461
Remove
462462
</NcActionButton>
463463

464-
<NcActionButton v-for="row in types" close-after-click @click="define(row)" :key="`type-icon--${row}`">
464+
<NcActionButton v-for="row in variants" close-after-click @click="define(row)" :key="`type-icon--${row}`">
465465
<template #icon>
466466
<CheckboxMarkedCircleOutline v-if="row === current" :size="20" />
467467
<SelectColor v-else :size="20" />
@@ -470,15 +470,15 @@ export default {
470470
</NcActionButton>
471471
</NcActions>
472472

473-
<NcActions :type="current" menu-name="Choose a type">
473+
<NcActions :variant="current" menu-name="Choose a variant">
474474
<NcActionButton v-if="current" close-after-click @click="define()">
475475
<template #icon>
476476
<Delete :size="20" />
477477
</template>
478478
Remove
479479
</NcActionButton>
480480

481-
<NcActionButton v-for="row in types" close-after-click @click="define(row)" :key="`type-text--${row}`">
481+
<NcActionButton v-for="row in variants" close-after-click @click="define(row)" :key="`type-text--${row}`">
482482
<template #icon>
483483
<CheckboxMarkedCircleOutline v-if="row === current" :size="20" />
484484
<SelectColor v-else :size="20" />
@@ -487,7 +487,7 @@ export default {
487487
</NcActionButton>
488488
</NcActions>
489489

490-
<NcActions :type="current" menu-name="Choose a type">
490+
<NcActions :variant="current" menu-name="Choose a variant">
491491
<template #icon>
492492
<SelectColor :size="20" />
493493
</template>
@@ -499,7 +499,7 @@ export default {
499499
Remove
500500
</NcActionButton>
501501

502-
<NcActionButton v-for="row in types" close-after-click @click="define(row)" :key="`type-icon-text--${row}`">
502+
<NcActionButton v-for="row in variants" close-after-click @click="define(row)" :key="`type-icon-text--${row}`">
503503
<template #icon>
504504
<CheckboxMarkedCircleOutline v-if="row === current" :size="20" />
505505
<SelectColor v-else :size="20" />
@@ -526,7 +526,7 @@ export default {
526526
data() {
527527
return {
528528
current: 'primary',
529-
types: [
529+
variants: [
530530
'primary',
531531
'secondary',
532532
'tertiary',
@@ -554,7 +554,7 @@ export default {
554554
<p>Has buttons, button groups, links and router links, separators, texts. May have checkboxes and radio buttons. Separator can be used to make groups of radio buttons as well.</p>
555555
<p><kbd>Arrows</kbd> are used to navigate between items, <kbd>Tab</kbd> is used to navigate to the next UI element on the page.</p>
556556
<p>
557-
<NcActions aria-label="Email menu" type="tertiary">
557+
<NcActions aria-label="Email menu" variant="tertiary">
558558
<NcActionButtonGroup>
559559
<NcActionButton>
560560
<template #icon>
@@ -606,11 +606,11 @@ export default {
606606
</NcActions>
607607
</p>
608608
<p>
609-
<NcActions aria-label="Text settings" type="tertiary">
609+
<NcActions aria-label="Text settings" variant="tertiary">
610610
<template #icon>
611611
<FormatTitle :size="20" />
612612
</template>
613-
<NcActionButtonGroup name="Allignment">
613+
<NcActionButtonGroup name="Alignment">
614614
<NcActionButton aria-label="Left">
615615
<template #icon>
616616
<FormatAlignLeft :size="20" />
@@ -658,7 +658,7 @@ export default {
658658
<p>Has links or router links. May use text elements, captions and separators.</p>
659659
<p>Uses classic <kbd>Tab</kbd> navigation.</p>
660660
<p>
661-
<NcActions aria-label="Applications navigation" :inline="2" type="tertiary">
661+
<NcActions aria-label="Applications navigation" :inline="2" variant="tertiary">
662662
<NcActionLink href="/apps/dashboard" icon="icon-category-dashboard-white">
663663
Dashboard
664664
</NcActionLink>
@@ -697,7 +697,7 @@ export default {
697697
</p>
698698

699699
<h2>Tooltip</h2>
700-
Has only text and not interactive elements
700+
<p>Has only text and no interactive elements.</p>
701701
<p>
702702
<NcActions aria-label="Contact" :inline="1">
703703
<NcActionLink aria-label="View profile" href="/u/alice" icon="icon-user-white">
@@ -726,7 +726,7 @@ import CheckIcon from 'vue-material-design-icons/Check.vue'
726726
import OpenInNewIcon from 'vue-material-design-icons/OpenInNew.vue'
727727
import DownloadIcon from 'vue-material-design-icons/Download.vue'
728728

729-
// Formating icons
729+
// Formatting icons
730730
import FormatTitle from 'vue-material-design-icons/FormatTitle.vue'
731731
import FormatAlignLeft from 'vue-material-design-icons/FormatAlignLeft.vue'
732732
import FormatAlignCenter from 'vue-material-design-icons/FormatAlignCenter.vue'
@@ -751,7 +751,7 @@ export default {
751751
OpenInNewIcon,
752752
DownloadIcon,
753753

754-
// Formating icons
754+
// Formatting icons
755755
FormatTitle,
756756
FormatAlignLeft,
757757
FormatAlignCenter,
@@ -764,7 +764,7 @@ export default {
764764
data() {
765765
return {
766766
selected: false,
767-
// Formating
767+
// Formatting
768768
checked: {
769769
bold: true,
770770
italic: false,
@@ -934,7 +934,7 @@ const focusableSelector = '.focusable'
934934
/**
935935
* The Actions component can be used to display one ore more actions.
936936
* If only a single action is provided, it will be rendered as an inline icon.
937-
* For more, a menu indicator will be shown and a popovermenu containing the
937+
* For more, a menu indicator will be shown and a popover menu containing the
938938
* actions will be opened on click.
939939
*
940940
* @since 0.10.0
@@ -1014,19 +1014,6 @@ export default {
10141014
default: false,
10151015
},
10161016

1017-
/**
1018-
* Specifies the button type used for trigger and single actions buttons
1019-
* Accepted values: primary, secondary, tertiary, tertiary-no-background, tertiary-on-primary, error, warning, success. If left empty,
1020-
* the default button style will be applied.
1021-
*/
1022-
type: {
1023-
type: String,
1024-
validator(value) {
1025-
return ['primary', 'secondary', 'tertiary', 'tertiary-no-background', 'tertiary-on-primary', 'error', 'warning', 'success'].indexOf(value) !== -1
1026-
},
1027-
default: null,
1028-
},
1029-
10301017
/**
10311018
* Icon to show for the toggle menu button
10321019
* when more than one action is inside the actions component.
@@ -1099,6 +1086,22 @@ export default {
10991086
type: Number,
11001087
default: 0,
11011088
},
1089+
1090+
/**
1091+
* Specifies the button variant used for trigger and single actions buttons.
1092+
*
1093+
* Accepted values: primary, secondary, tertiary, tertiary-no-background, tertiary-on-primary, error, warning, success.
1094+
* If left empty, the default button style will be applied.
1095+
*
1096+
* @since 8.23.0
1097+
*/
1098+
variant: {
1099+
type: String,
1100+
validator(value) {
1101+
return ['primary', 'secondary', 'tertiary', 'tertiary-no-background', 'tertiary-on-primary', 'error', 'warning', 'success'].includes(value)
1102+
},
1103+
default: null,
1104+
},
11021105
},
11031106

11041107
emits: [
@@ -1157,9 +1160,9 @@ export default {
11571160
},
11581161

11591162
computed: {
1160-
triggerBtnType() {
1163+
triggerButtonVariant() {
11611164
// If requested, we use a primary button
1162-
return this.type || (this.primary
1165+
return this.variant || (this.primary
11631166
? 'primary'
11641167
// If it has a name, we use a secondary button
11651168
: this.menuName ? 'secondary' : 'tertiary')
@@ -1558,7 +1561,7 @@ export default {
15581561
this.$emit('blur', event)
15591562

15601563
// When there is no focusable elements to handle Tab press from actions menu
1561-
// It requries manual closing
1564+
// It requires manual closing
15621565
if (this.actionsMenuSemanticType === 'tooltip') {
15631566
// Tooltip is supposed to have no focusable element.
15641567
// However, if there is a custom focusable element, it will be auto-focused and cause the menu to be closed on open.
@@ -1688,7 +1691,7 @@ export default {
16881691
}
16891692

16901693
const propsToForward = { ...(action?.props ?? {}) }
1691-
const nativeType = ['submit', 'reset'].includes(propsToForward.type) ? propsToForward.modelValue : 'button'
1694+
const type = ['submit', 'reset'].includes(propsToForward.type) ? propsToForward.modelValue : 'button'
16921695
// not available on NcButton or with different meaning
16931696
delete propsToForward.modelValue
16941697
delete propsToForward.type
@@ -1700,11 +1703,11 @@ export default {
17001703
class: 'action-item action-item--single',
17011704
'aria-label': action?.props?.['aria-label'] || text,
17021705
title,
1703-
// If it has a menuName, we use a secondary button
1704-
type: this.type || (buttonText ? 'secondary' : 'tertiary'),
17051706
disabled: this.disabled || action?.props?.disabled,
17061707
pressed: action?.props?.modelValue,
1707-
nativeType,
1708+
type,
1709+
// If it has a menuName, we use a secondary button
1710+
variant: this.variant || (buttonText ? 'secondary' : 'tertiary'),
17081711
onFocus: this.onFocus,
17091712
onBlur: this.onBlur,
17101713
// forward any pressed state from NcButton just like NcActionButton does
@@ -1754,9 +1757,8 @@ export default {
17541757
trigger: () => h(NcButton, {
17551758
id: triggerRandomId,
17561759
class: 'action-item__menutoggle',
1757-
type: this.triggerBtnType,
17581760
disabled: this.disabled,
1759-
ariaHidden: this.ariaHidden,
1761+
variant: this.triggerButtonVariant,
17601762
ref: 'triggerButton',
17611763
'aria-label': this.menuName ? null : this.ariaLabel,
17621764
// 'aria-controls' should only present together with a valid aria-haspopup
@@ -1823,7 +1825,7 @@ export default {
18231825
{
18241826
class: [
18251827
'action-items',
1826-
`action-item--${this.triggerBtnType}`,
1828+
`action-item--${this.triggerButtonVariant}`,
18271829
],
18281830
},
18291831
[
@@ -1854,7 +1856,7 @@ export default {
18541856
{
18551857
class: [
18561858
'action-item action-item--default-popover',
1857-
`action-item--${this.triggerBtnType}`,
1859+
`action-item--${this.triggerButtonVariant}`,
18581860
{
18591861
'action-item--open': this.opened,
18601862
},

src/components/NcAppContent/NcAppDetailsToggle.vue

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55

66
<template>
77
<NcButton v-tooltip="title"
8-
type="tertiary"
9-
:aria-label="title"
108
class="app-details-toggle"
11-
:class="{ 'app-details-toggle--mobile': isMobile }">
9+
:class="{ 'app-details-toggle--mobile': isMobile }"
10+
:aria-label="title"
11+
variant="tertiary">
1212
<template #icon>
1313
<ArrowLeft v-if="isRtl" :size="20" />
1414
<ArrowRight v-else :size="20" />

src/components/NcAppNavigationItem/NcAppNavigationIconCollapsible.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
<!-- Button to expand or collapse children -->
88
<NcButton class="icon-collapse"
99
:class="{'icon-collapse--open':open}"
10-
type="tertiary"
1110
:aria-label="labelButton"
11+
variant="tertiary"
1212
@click="onClick">
1313
<template #icon>
1414
<ChevronUp v-if="open"

src/components/NcAppNavigationItem/NcAppNavigationItem.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,9 @@ Just set the `pinned` prop.
349349
:boundaries-element="actionsBoundariesElement"
350350
:placement="menuPlacement"
351351
:open="menuOpen"
352-
:type="(isActive && to) || active ? 'primary' : null"
353352
:force-menu="forceMenu"
354353
:default-icon="menuIcon"
354+
:variant="(isActive && to) || active ? 'primary' : null"
355355
@update:open="onMenuToggle">
356356
<template #icon>
357357
<!-- @slot Slot for the custom menu icon -->

src/components/NcAppNavigationItem/NcInputConfirmCancel.vue

+13-13
Original file line numberDiff line numberDiff line change
@@ -21,40 +21,40 @@
2121
class="app-navigation-input-confirm__input"
2222
:placeholder="placeholder">
2323

24-
<NcButton native-type="submit"
25-
type="primary"
26-
:aria-label="labelConfirm"
24+
<NcButton :aria-label="labelConfirm"
25+
type="submit"
26+
variant="primary"
2727
@click.stop.prevent="confirm">
2828
<template #icon>
29-
<ArrowRight :size="20" />
29+
<IconArrowRight :size="20" />
3030
</template>
3131
</NcButton>
3232

33-
<NcButton native-type="reset"
34-
:type="primary ? 'primary' : 'tertiary'"
35-
:aria-label="labelCancel"
33+
<NcButton :aria-label="labelCancel"
34+
type="reset"
35+
:variant="primary ? 'primary' : 'tertiary'"
3636
@click.stop.prevent="cancel">
3737
<template #icon>
38-
<Close :size="20" />
38+
<IconClose :size="20" />
3939
</template>
4040
</NcButton>
4141
</form>
4242
</div>
4343
</template>
4444
<script>
45-
import NcButton from '../NcButton/index.ts'
4645
import { t } from '../../l10n.js'
4746

48-
import ArrowRight from 'vue-material-design-icons/ArrowRight.vue'
49-
import Close from 'vue-material-design-icons/Close.vue'
47+
import IconArrowRight from 'vue-material-design-icons/ArrowRight.vue'
48+
import IconClose from 'vue-material-design-icons/Close.vue'
49+
import NcButton from '../NcButton/index.js'
5050

5151
export default {
5252
name: 'NcInputConfirmCancel',
5353

5454
components: {
55+
IconArrowRight,
56+
IconClose,
5557
NcButton,
56-
ArrowRight,
57-
Close,
5858
},
5959

6060
props: {

src/components/NcAppNavigationNew/NcAppNavigationNew.vue

+8-3
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
<template>
3030
<div class="app-navigation-new">
3131
<NcButton :id="buttonId"
32-
:disabled="disabled"
33-
:type="type"
32+
:disabled
33+
:variant
3434
@click="$emit('click')">
3535
<template #icon>
3636
<slot name="icon" />
@@ -62,7 +62,12 @@ export default {
6262
type: String,
6363
required: true,
6464
},
65-
type: {
65+
66+
/**
67+
* The color variant to use.
68+
* @default 'primary'
69+
*/
70+
variant: {
6671
type: String,
6772
default: 'primary',
6873
validator(value) {

0 commit comments

Comments
 (0)