Skip to content

Commit c818fb1

Browse files
authored
Merge pull request #5769 from nextcloud-libraries/backport/5767/next
[next] feat(NcButton): Add `size` prop to allow setting the button size to `small`, `normal`, `large`
2 parents a7a1c02 + 71c3a1e commit c818fb1

File tree

2 files changed

+71
-24
lines changed

2 files changed

+71
-24
lines changed

src/components/NcButton/NcButton.vue

+68-24
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ It can be used with one or multiple actions.
2222
<NcCheckboxRadioSwitch v-model="style" value="icon" name="style" type="radio">Icon only</NcCheckboxRadioSwitch>
2323
<NcCheckboxRadioSwitch v-model="style" value="icontext" name="style" type="radio">Icon and text</NcCheckboxRadioSwitch>
2424
<NcCheckboxRadioSwitch v-model="disabled" type="checkbox">Disabled</NcCheckboxRadioSwitch>
25-
<!--<NcCheckboxRadioSwitch v-model="readonly" type="checkbox">Read-only</NcCheckboxRadioSwitch>-->
25+
<NcCheckboxRadioSwitch v-model="size" value="small" name="size" type="radio">Small</NcCheckboxRadioSwitch>
26+
<NcCheckboxRadioSwitch v-model="size" value="normal" name="size" type="radio">Normal (default)</NcCheckboxRadioSwitch>
27+
<NcCheckboxRadioSwitch v-model="size" value="large" name="size" type="radio">Large</NcCheckboxRadioSwitch>
2628
</div>
2729

2830
<h5>Standard buttons</h5>
@@ -34,7 +36,7 @@ It can be used with one or multiple actions.
3436
<NcButton
3537
aria-label="Example text"
3638
:disabled="disabled"
37-
:readonly="readonly"
39+
:size="size"
3840
type="tertiary-no-background">
3941
<template v-if="style.indexOf('icon') !== -1" #icon>
4042
<Video
@@ -45,7 +47,7 @@ It can be used with one or multiple actions.
4547
<NcButton
4648
aria-label="Example text"
4749
:disabled="disabled"
48-
:readonly="readonly"
50+
:size="size"
4951
type="tertiary">
5052
<template v-if="style.indexOf('icon') !== -1" #icon>
5153
<Video
@@ -56,7 +58,7 @@ It can be used with one or multiple actions.
5658
<NcButton
5759
aria-label="Example text"
5860
:disabled="disabled"
59-
:readonly="readonly">
61+
:size="size">
6062
<template v-if="style.indexOf('icon') !== -1" #icon>
6163
<Video
6264
:size="20" />
@@ -66,7 +68,7 @@ It can be used with one or multiple actions.
6668
<NcButton
6769
aria-label="Example text"
6870
:disabled="disabled"
69-
:readonly="readonly"
71+
:size="size"
7072
type="primary">
7173
<template v-if="style.indexOf('icon') !== -1" #icon>
7274
<Video
@@ -80,7 +82,7 @@ It can be used with one or multiple actions.
8082
<h5>Wide button</h5>
8183
<NcButton
8284
:disabled="disabled"
83-
:readonly="readonly"
85+
:size="size"
8486
:wide="true"
8587
text="Example text">
8688
<template #icon>
@@ -99,7 +101,7 @@ It can be used with one or multiple actions.
99101
<p> - </p>
100102
<NcButton
101103
:disabled="disabled"
102-
:readonly="readonly"
104+
:size="size"
103105
type="success">
104106
<template #icon>
105107
<Video
@@ -109,7 +111,7 @@ It can be used with one or multiple actions.
109111
</NcButton>
110112
<NcButton
111113
:disabled="disabled"
112-
:readonly="readonly"
114+
:size="size"
113115
type="warning">
114116
<template #icon>
115117
<Video
@@ -119,7 +121,7 @@ It can be used with one or multiple actions.
119121
</NcButton>
120122
<NcButton
121123
:disabled="disabled"
122-
:readonly="readonly"
124+
:size="size"
123125
type="error">
124126
<template #icon>
125127
<Video
@@ -143,7 +145,7 @@ export default {
143145
return {
144146
toggled: false,
145147
disabled: false,
146-
readonly: false,
148+
size: 'normal',
147149
style: 'icontext',
148150
}
149151
}
@@ -157,6 +159,7 @@ export default {
157159

158160
.grid {
159161
display: grid;
162+
gap: 12px;
160163
grid-template-columns: 1fr 1fr 1fr 1fr;
161164
grid-template-rows: repeat(auto-fill, auto);
162165
position: relative;
@@ -459,6 +462,18 @@ export default defineComponent({
459462
default: false,
460463
},
461464

465+
/**
466+
* Specify the button size
467+
* Accepted values: `'small'`, `'normal'` (default), `'large'`
468+
*/
469+
size: {
470+
type: String,
471+
default: 'normal',
472+
validator(value: string) {
473+
return ['small', 'normal', 'large'].includes(value)
474+
},
475+
},
476+
462477
/**
463478
* Specifies the button type
464479
* If left empty, the default button style will be applied.
@@ -468,8 +483,8 @@ export default defineComponent({
468483
*/
469484
type: {
470485
type: String as PropType<typeof BUTTON_TYPES[number]>,
471-
validator(value) {
472-
return typeof value === 'string' && (BUTTON_TYPES as readonly string[]).indexOf(value) !== -1
486+
validator(value: string) {
487+
return (BUTTON_TYPES as readonly string[]).includes(value)
473488
},
474489
default: 'secondary',
475490
},
@@ -622,6 +637,7 @@ export default defineComponent({
622637
{
623638
class: [
624639
'button-vue',
640+
`button-vue--size-${this.size}`,
625641
{
626642
'button-vue--icon-only': hasIcon && !hasText,
627643
'button-vue--text-only': hasText && !hasIcon,
@@ -692,17 +708,31 @@ export default defineComponent({
692708
</script>
693709

694710
<style lang="scss" scoped>
695-
696711
.button-vue {
712+
// Setup different button sizes
713+
--button-size: var(--default-clickable-area);
714+
--button-radius: var(--border-radius-element, calc(var(--button-size) / 2));
715+
--button-padding: clamp(var(--default-grid-baseline), var(--button-radius), calc(var(--default-grid-baseline) * 4));
716+
717+
&--size-small {
718+
--button-size: var(--clickable-area-small, 24px);
719+
--button-radius: var(--border-radius); // make the border radius even smaller for small buttons
720+
}
721+
722+
&--size-large {
723+
--button-size: var(--clickable-area-large, 48px);
724+
}
725+
726+
// General styles
697727
position: relative;
698728
width: fit-content;
699729
overflow: hidden;
700730
border: 0;
701731
padding: 0;
702732
font-size: var(--default-font-size);
703733
font-weight: bold;
704-
min-height: var(--default-clickable-area);
705-
min-width: var(--default-clickable-area);
734+
min-height: var(--button-size);
735+
min-width: var(--button-size);
706736
display: flex;
707737
align-items: center;
708738
justify-content: center;
@@ -713,7 +743,7 @@ export default defineComponent({
713743
span {
714744
cursor: pointer;
715745
}
716-
border-radius: var(--border-radius-element, calc(var(--default-clickable-area) / 2));
746+
border-radius: var(--button-radius);
717747
transition-property: color, border-color, background-color;
718748
transition-duration: 0.1s;
719749
transition-timing-function: linear;
@@ -764,18 +794,29 @@ export default defineComponent({
764794
}
765795

766796
&--reverse#{&}--icon-and-text {
767-
padding-inline: calc(var(--default-grid-baseline) * 4) var(--default-grid-baseline);
797+
padding-inline: var(--button-padding) var(--default-grid-baseline);
768798
}
769799

770800
&__icon {
771-
height: var(--default-clickable-area);
772-
width: var(--default-clickable-area);
773-
min-height: var(--default-clickable-area);
774-
min-width: var(--default-clickable-area);
801+
height: var(--button-size);
802+
width: var(--button-size);
803+
min-height: var(--button-size);
804+
min-width: var(--button-size);
775805
display: flex;
776806
justify-content: center;
777807
align-items: center;
778808
}
809+
// For small buttons we need to adjust the icon size
810+
&--size-small &__icon {
811+
:deep(> *) {
812+
max-height: 16px;
813+
max-width: 16px;
814+
}
815+
:deep(svg) {
816+
height: 16px;
817+
width: 16px;
818+
}
819+
}
779820

780821
&__text {
781822
font-weight: bold;
@@ -789,12 +830,12 @@ export default defineComponent({
789830
// Icon-only button
790831
&--icon-only {
791832
line-height: 1;
792-
width: var(--default-clickable-area) !important;
833+
width: var(--button-size) !important;
793834
}
794835

795836
// Text-only button
796837
&--text-only {
797-
padding: 0 12px;
838+
padding: 0 var(--button-padding);
798839
& .button-vue__text {
799840
margin-left: 4px;
800841
margin-right: 4px;
@@ -803,8 +844,11 @@ export default defineComponent({
803844

804845
// Icon and text button
805846
&--icon-and-text {
847+
// icon and text means the icon adds "visual" padding thus we need to adjust the text padding
848+
--button-padding: min(calc(var(--default-grid-baseline) + var(--button-radius)), calc(var(--default-grid-baseline) * 4));
849+
// Adjust padding as the icon already got some padding we need to reduce the padding on the icon side and only add larger padding to the text side
806850
padding-block: 0;
807-
padding-inline: var(--default-grid-baseline) calc(var(--default-grid-baseline) * 4);
851+
padding-inline: var(--default-grid-baseline) var(--button-padding);
808852
}
809853

810854
// Wide button spans the whole width of the container

src/components/NcHeaderMenu/NcHeaderMenu.vue

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ export default {
4141
display: flex;
4242
justify-content: right;
4343
background-color: var(--color-primary);
44+
height: var(--header-height, 50px);
45+
padding-right: 12px;
4446
}
4547
</style>
4648
```
@@ -64,6 +66,7 @@ export default {
6466
:aria-describedby="description ? descriptionId : null"
6567
:aria-controls="`header-menu-${id}`"
6668
:aria-expanded="opened.toString()"
69+
size="large"
6770
@click.prevent="toggleMenu">
6871
<template #icon>
6972
<!-- @slot Icon trigger slot. Make sure the svg path

0 commit comments

Comments
 (0)