diff options
Diffstat (limited to 'packages/frontend/src/components/MkChannelFollowButton.vue')
| -rw-r--r-- | packages/frontend/src/components/MkChannelFollowButton.vue | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/packages/frontend/src/components/MkChannelFollowButton.vue b/packages/frontend/src/components/MkChannelFollowButton.vue new file mode 100644 index 0000000000..9e275d6172 --- /dev/null +++ b/packages/frontend/src/components/MkChannelFollowButton.vue @@ -0,0 +1,129 @@ +<template> +<button + class="hdcaacmi _button" + :class="{ wait, active: isFollowing, full }" + :disabled="wait" + @click="onClick" +> + <template v-if="!wait"> + <template v-if="isFollowing"> + <span v-if="full">{{ i18n.ts.unfollow }}</span><i class="ti ti-minus"></i> + </template> + <template v-else> + <span v-if="full">{{ i18n.ts.follow }}</span><i class="ti ti-plus"></i> + </template> + </template> + <template v-else> + <span v-if="full">{{ i18n.ts.processing }}</span><MkLoading :em="true"/> + </template> +</button> +</template> + +<script lang="ts" setup> +import { ref } from 'vue'; +import * as os from '@/os'; +import { i18n } from '@/i18n'; + +const props = withDefaults(defineProps<{ + channel: Record<string, any>; + full?: boolean; +}>(), { + full: false, +}); + +const isFollowing = ref<boolean>(props.channel.isFollowing); +const wait = ref(false); + +async function onClick() { + wait.value = true; + + try { + if (isFollowing.value) { + await os.api('channels/unfollow', { + channelId: props.channel.id, + }); + isFollowing.value = false; + } else { + await os.api('channels/follow', { + channelId: props.channel.id, + }); + isFollowing.value = true; + } + } catch (err) { + console.error(err); + } finally { + wait.value = false; + } +} +</script> + +<style lang="scss" scoped> +.hdcaacmi { + position: relative; + display: inline-block; + font-weight: bold; + color: var(--accent); + background: transparent; + border: solid 1px var(--accent); + padding: 0; + height: 31px; + font-size: 16px; + border-radius: 32px; + background: #fff; + + &.full { + padding: 0 8px 0 12px; + font-size: 14px; + } + + &:not(.full) { + width: 31px; + } + + &:focus-visible { + &:after { + content: ""; + pointer-events: none; + position: absolute; + top: -5px; + right: -5px; + bottom: -5px; + left: -5px; + border: 2px solid var(--focus); + border-radius: 32px; + } + } + + &:hover { + //background: mix($primary, #fff, 20); + } + + &:active { + //background: mix($primary, #fff, 40); + } + + &.active { + color: #fff; + background: var(--accent); + + &:hover { + background: var(--accentLighten); + border-color: var(--accentLighten); + } + + &:active { + background: var(--accentDarken); + border-color: var(--accentDarken); + } + } + + &.wait { + cursor: wait !important; + opacity: 0.7; + } + + > span { + margin-right: 6px; + } +} +</style> |