client: refactor components/tab.vue to composition API

Refactoring this component could be done after changing its method of
receiving the list of available tabs by using slots to using an
ordinary parameter. This was possible because all uses of this
component just provided text as the tab labels.

Also removed unused imports of this component.

Also removed the use of the click-anime directive.

Reviewed-on: FoundKeyGang/FoundKey#184
This commit is contained in:
Johann150 2022-10-04 16:02:51 +02:00
parent c5f07ef66c
commit 6ef9069a2f
Signed by untrusted user: Johann150
GPG key ID: 9EE6577A2A06F8F1
7 changed files with 67 additions and 49 deletions

View file

@ -1,31 +1,29 @@
<script lang="ts">
import { defineComponent, h, resolveDirective, withDirectives } from 'vue';
<template>
<div class="pxhvhrfw" v-size="{ max: [500] }">
<button
v-for="option in options"
:key="option.value"
:class="{ '_button': true, active: modelValue === option.value }"
:disabled="modelValue === option.value"
@click.stop="emit('update:modelValue', option.value)"
>
{{ option.label }}
</button>
</div>
</template>
export default defineComponent({
props: {
modelValue: {
required: true,
},
},
render() {
const options = this.$slots.default();
<script lang="ts" setup>
const emit = defineEmits<{
(ev: 'update:modelValue', value: string): void;
}>();
return withDirectives(h('div', {
class: 'pxhvhrfw',
}, options.map(option => withDirectives(h('button', {
class: ['_button', { active: this.modelValue === option.props.value }],
key: option.key,
disabled: this.modelValue === option.props.value,
onClick: () => {
this.$emit('update:modelValue', option.props.value);
},
}, option.children), [
[resolveDirective('click-anime')],
]))), [
[resolveDirective('size'), { max: [500] }],
]);
},
});
const props = defineProps<{
modelValue: string;
options: {
value: string;
label: string;
};
}>();
</script>
<style lang="scss">

View file

@ -1,9 +1,6 @@
<template>
<MkSpacer :content-max="800">
<MkTab v-model="tab" style="margin-bottom: var(--margin);">
<option value="notes">{{ i18n.ts.notes }}</option>
<option value="polls">{{ i18n.ts.poll }}</option>
</MkTab>
<MkTab v-model="tab" :options="tabs" style="margin-bottom: var(--margin);"/>
<XNotes v-if="tab === 'notes'" :pagination="paginationForNotes"/>
<XNotes v-else-if="tab === 'polls'" :pagination="paginationForPolls"/>
</MkSpacer>
@ -14,6 +11,14 @@ import XNotes from '@/components/notes.vue';
import MkTab from '@/components/tab.vue';
import { i18n } from '@/i18n';
const tabs = [{
value: 'notes',
label: i18n.ts.notes,
}, {
value: 'polls',
label: i18n.ts.poll,
}];
const paginationForNotes = {
endpoint: 'notes/featured' as const,
limit: 10,

View file

@ -47,7 +47,6 @@ import XUserList from '@/components/user-list.vue';
import MkFolder from '@/components/ui/folder.vue';
import MkInput from '@/components/form/input.vue';
import MkButton from '@/components/ui/button.vue';
import MkTab from '@/components/tab.vue';
import MkPagination from '@/components/ui/pagination.vue';
import MkGalleryPostPreview from '@/components/gallery-post-preview.vue';
import number from '@/filters/number';

View file

@ -45,7 +45,6 @@ import MkPagination from '@/components/ui/pagination.vue';
import MkButton from '@/components/ui/button.vue';
import MkContainer from '@/components/ui/container.vue';
import MkAvatars from '@/components/avatars.vue';
import MkTab from '@/components/tab.vue';
import * as os from '@/os';
import { definePageMetadata } from '@/scripts/page-metadata';
import { i18n } from '@/i18n';

View file

@ -1,9 +1,6 @@
<template>
<div class="_formRoot">
<MkTab v-model="tab" style="margin-bottom: var(--margin);">
<option value="mute">{{ i18n.ts.mutedUsers }}</option>
<option value="block">{{ i18n.ts.blockedUsers }}</option>
</MkTab>
<MkTab v-model="tab" :options="tabs" style="margin-bottom: var(--margin);"/>
<div v-if="tab === 'mute'">
<MkPagination :pagination="mutingPagination" class="muting">
<template #empty><FormInfo>{{ i18n.ts.noUsers }}</FormInfo></template>
@ -39,6 +36,14 @@ import { definePageMetadata } from '@/scripts/page-metadata';
let tab = $ref('mute');
const tabs = [{
value: 'mute',
label: i18n.ts.mutedUsers,
}, {
value: 'block',
label: i18n.ts.blockedUsers,
}];
const mutingPagination = {
endpoint: 'mute/list' as const,
limit: 10,

View file

@ -1,9 +1,6 @@
<template>
<div class="_formRoot">
<MkTab v-model="tab" class="_formBlock">
<option value="soft">{{ i18n.ts._wordMute.soft }}</option>
<option value="hard">{{ i18n.ts._wordMute.hard }}</option>
</MkTab>
<MkTab v-model="tab" :options="tabs" class="_formBlock"/>
<div class="_formBlock">
<div v-show="tab === 'soft'">
<MkInfo class="_formBlock">{{ i18n.ts._wordMute.softDescription }}</MkInfo>
@ -50,6 +47,14 @@ const render = (mutedWords) => mutedWords.map(x => {
}
}).join('\n');
const tabs = [{
value: 'soft',
label: i18n.ts._wordMute.soft,
}, {
value: 'hard',
label: i18n.ts._wordMute.hard,
}];
const tab = ref('soft');
const softMutedWords = ref(render(defaultStore.state.mutedWords));
const hardMutedWords = ref(render($i!.mutedWords));

View file

@ -1,16 +1,12 @@
<template>
<div v-sticky-container class="yrzkoczt">
<MkTab v-model="include" class="tab">
<option :value="null">{{ i18n.ts.notes }}</option>
<option value="replies">{{ i18n.ts.notesAndReplies }}</option>
<option value="files">{{ i18n.ts.withFiles }}</option>
</MkTab>
<MkTab v-model="include" :options="tabs" class="tab"/>
<XNotes :no-gap="true" :pagination="pagination"/>
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { computed } from 'vue';
import * as foundkey from 'foundkey-js';
import XNotes from '@/components/notes.vue';
import MkTab from '@/components/tab.vue';
@ -21,15 +17,26 @@ const props = defineProps<{
user: foundkey.entities.UserDetailed;
}>();
const include = ref<string | null>(null);
const tabs = [{
value: 'notes',
label: i18n.ts.notes,
}, {
value: 'replies',
label: i18n.ts.notesAndReplies,
}, {
value: 'files',
label: i18n.ts.withFiles,
}];
let include: string = $ref('notes');
const pagination = {
endpoint: 'users/notes' as const,
limit: 10,
params: computed(() => ({
userId: props.user.id,
includeReplies: include.value === 'replies',
withFiles: include.value === 'files',
includeReplies: include === 'replies',
withFiles: include === 'files',
})),
};
</script>