Skip to content

Commit d72651f

Browse files
committed
✨ new flag for MucButton: Spinning Icon on click (for e.g. copy-link actions)
1 parent 2844412 commit d72651f

File tree

2 files changed

+37
-27
lines changed

2 files changed

+37
-27
lines changed

src/components/Button/MucButton.stories.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ export const IconOnly = {
5454
},
5555
};
5656

57+
export const CopyButton = {
58+
args: {
59+
default: "Copy",
60+
icon: "copy-link",
61+
variant: "secondary",
62+
spinIconOnClick: true,
63+
},
64+
};
65+
5766
export const IconAnimated = {
5867
args: {
5968
default: "With Icon",

src/components/Button/MucButton.vue

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,15 @@
33
@click="handleClick"
44
:aria-disabled="disabled"
55
class="m-button"
6-
:class="[buttonVariantClass, iconAnimatedClass, disabledClass]"
6+
:class="{
7+
'm-button--secondary': variant === 'secondary',
8+
'm-button--ghost': variant === 'ghost',
9+
'm-button--primary': variant !== 'secondary' && variant !== 'ghost',
10+
'm-button--animated-right': iconAnimated,
11+
'm-button--animated-left': iconAnimated && iconShownLeft,
12+
disabled: disabled,
13+
copied: spinIconOnClick && animateIconSpin,
14+
}"
715
>
816
<span>
917
<slot v-if="!iconShownLeft" />
@@ -22,7 +30,7 @@
2230
</template>
2331

2432
<script setup lang="ts">
25-
import { computed } from "vue";
33+
import { ref } from "vue";
2634
2735
import { MucIcon } from "../Icon";
2836
@@ -33,6 +41,7 @@ const {
3341
disabled = false,
3442
iconAnimated = false,
3543
iconShownLeft = false,
44+
spinIconOnClick = false,
3645
} = defineProps<{
3746
/**
3847
* The variant prop gives you easy access to several different button styles.
@@ -54,6 +63,12 @@ const {
5463
* Default is `false`
5564
*/
5665
iconAnimated?: boolean;
66+
/**
67+
* Wether the Icon should spin when the button is clicked (used e.g. when building a "copy"-Button)
68+
*
69+
* Default is 'false';
70+
*/
71+
spinIconOnClick?: boolean;
5772
/**
5873
* Whether the Icon should be shown on the left side of the button (slide-right) or not.
5974
*
@@ -77,38 +92,20 @@ const emit = defineEmits<
7792
(e: "click") => void
7893
>();
7994
80-
const buttonVariantClass = computed(() => {
81-
switch (variant) {
82-
case "secondary":
83-
return "m-button--secondary";
84-
case "ghost":
85-
return "m-button--ghost";
86-
default:
87-
return "m-button--primary";
88-
}
89-
});
90-
91-
const iconAnimatedClass = computed(() => {
92-
if (iconAnimated && iconShownLeft) {
93-
return "m-button--animated-left";
94-
} else if (iconAnimated) {
95-
return "m-button--animated-right";
96-
} else {
97-
return "";
98-
}
99-
});
95+
const animateIconSpin = ref(false);
10096
10197
/**
10298
* Emit a click event if not in disabled state.
10399
*/
104100
const handleClick = () => {
101+
animateIconSpin.value = true;
102+
105103
if (!disabled) emit("click");
106-
};
107104
108-
/**
109-
* Ensure that the disabled button style is applied when it is in the 'disabled' state.
110-
*/
111-
const disabledClass = computed(() => (disabled ? "disabled" : ""));
105+
setTimeout(() => {
106+
animateIconSpin.value = false;
107+
}, 1000);
108+
};
112109
</script>
113110

114111
<style scoped>
@@ -124,6 +121,10 @@ const disabledClass = computed(() => (disabled ? "disabled" : ""));
124121
margin-left: 0.75rem;
125122
}
126123
124+
.copied .m-button__icon {
125+
animation: rotate 1s ease-in-out;
126+
}
127+
127128
.m-button--ghost {
128129
padding-right: 0;
129130
}

0 commit comments

Comments
 (0)