summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/MkChannelFollowButton.vue
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src/components/MkChannelFollowButton.vue')
-rw-r--r--packages/frontend/src/components/MkChannelFollowButton.vue129
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>