diff options
| author | かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> | 2025-10-05 15:48:11 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-05 15:48:11 +0900 |
| commit | 720c6519cdca2b2c969cb5d8ce2de0145005b432 (patch) | |
| tree | 6a72acfb95453c5bc1e038aaac7da3ca53ce6878 | |
| parent | Update CHANGELOG with new features and enhancements (diff) | |
| download | misskey-720c6519cdca2b2c969cb5d8ce2de0145005b432.tar.gz misskey-720c6519cdca2b2c969cb5d8ce2de0145005b432.tar.bz2 misskey-720c6519cdca2b2c969cb5d8ce2de0145005b432.zip | |
refactor(frontend): MkTabの指定をpropsから行うように (#16596)
* refactor(frontend): MkTabの指定をpropsから行うように
* Update explore.featured.vue
| -rw-r--r-- | packages/frontend/src/components/MkTab.vue | 111 | ||||
| -rw-r--r-- | packages/frontend/src/pages/explore.featured.vue | 13 | ||||
| -rw-r--r-- | packages/frontend/src/pages/explore.users.vue | 14 | ||||
| -rw-r--r-- | packages/frontend/src/pages/qr.read.vue | 13 | ||||
| -rw-r--r-- | packages/frontend/src/pages/user/index.timeline.vue | 17 | ||||
| -rw-r--r-- | packages/frontend/src/pages/user/notes.vue | 17 |
6 files changed, 110 insertions, 75 deletions
diff --git a/packages/frontend/src/components/MkTab.vue b/packages/frontend/src/components/MkTab.vue index f557ffa5dc..d8ae52482e 100644 --- a/packages/frontend/src/components/MkTab.vue +++ b/packages/frontend/src/components/MkTab.vue @@ -3,76 +3,85 @@ SPDX-FileCopyrightText: syuilo and misskey-project SPDX-License-Identifier: AGPL-3.0-only --> +<template> + <div :class="$style.tabsRoot"> + <button + v-for="option in tabs" + :key="option.key" + :class="['_button', $style.tabButton, { [$style.active]: modelValue === option.key }]" + :disabled="modelValue === option.key" + @click="update(option.key)" + > + <i v-if="option.icon" :class="[option.icon, $style.icon]"></i> + {{ option.label }} + </button> + </div> +</template> + <script lang="ts"> -import { defineComponent, h, resolveDirective, withDirectives } from 'vue'; +export type Tab<T = string> = { + key: T; + icon?: string; + label?: string; +}; +</script> + +<script setup lang="ts" generic="const T extends Tab"> +import { defineProps, defineEmits } from 'vue'; -export default defineComponent({ - props: { - modelValue: { - required: true, - }, - }, - setup(props, { emit, slots }) { - const options = slots.default?.() ?? []; +defineProps<{ + tabs: T[]; +}>(); - return () => h('div', { - class: 'pxhvhrfw', - }, options.map(option => withDirectives(h('button', { - class: ['_button', { active: props.modelValue === option.props?.value }], - key: option.key as string, - disabled: props.modelValue === option.props?.value, - onClick: () => { - emit('update:modelValue', option.props?.value); - }, - }, option.children ?? []), [ - [resolveDirective('click-anime')], - ]))); - }, -}); +const model = defineModel<T['key']>(); + +function update(key: T['key']) { + model.value = key; +} </script> -<style lang="scss"> -.pxhvhrfw { +<style module lang="scss"> +.tabsRoot { display: flex; font-size: 90%; +} - > button { - flex: 1; - padding: 10px 8px; - border-radius: 999px; +.tabButton { + flex: 1; + padding: 10px 8px; + border-radius: 999px; - &:disabled { - opacity: 1 !important; - cursor: default; - } + &:disabled { + opacity: 1 !important; + cursor: default; + } - &.active { - color: var(--MI_THEME-accent); - background: var(--MI_THEME-accentedBg); - } + &.active { + color: var(--MI_THEME-accent); + background: var(--MI_THEME-accentedBg); + } - &:not(.active):hover { - color: var(--MI_THEME-fgHighlighted); - background: var(--MI_THEME-panelHighlight); - } + &:not(.active):hover { + color: var(--MI_THEME-fgHighlighted); + background: var(--MI_THEME-panelHighlight); + } - &:not(:first-child) { - margin-left: 8px; - } + &:not(:first-child) { + margin-left: 8px; + } - > .icon { - margin-right: 6px; - } + > .icon { + margin-right: 6px; } } @container (max-width: 500px) { - .pxhvhrfw { + .tabsRoot { font-size: 80%; + } - > button { - padding: 11px 8px; - } + .tabButton { + padding: 11px 8px; } } </style> diff --git a/packages/frontend/src/pages/explore.featured.vue b/packages/frontend/src/pages/explore.featured.vue index abb816a956..3158b384d2 100644 --- a/packages/frontend/src/pages/explore.featured.vue +++ b/packages/frontend/src/pages/explore.featured.vue @@ -5,9 +5,14 @@ SPDX-License-Identifier: AGPL-3.0-only <template> <div class="_spacer" style="--MI_SPACER-w: 800px;"> - <MkTab v-model="tab" style="margin-bottom: var(--MI-margin);"> - <option value="notes">{{ i18n.ts.notes }}</option> - <option value="polls">{{ i18n.ts.poll }}</option> + <MkTab + v-model="tab" + :tabs="[ + { key: 'notes', label: i18n.ts.notes }, + { key: 'polls', label: i18n.ts.poll }, + ]" + style="margin-bottom: var(--MI-margin);" + > </MkTab> <MkNotesTimeline v-if="tab === 'notes'" :paginator="paginatorForNotes"/> <MkNotesTimeline v-else-if="tab === 'polls'" :paginator="paginatorForPolls"/> @@ -33,5 +38,5 @@ const paginatorForPolls = markRaw(new Paginator('notes/polls/recommendation', { }, })); -const tab = ref('notes'); +const tab = ref<'notes' | 'polls'>('notes'); </script> diff --git a/packages/frontend/src/pages/explore.users.vue b/packages/frontend/src/pages/explore.users.vue index 08f9f5e582..4e3fb16b5a 100644 --- a/packages/frontend/src/pages/explore.users.vue +++ b/packages/frontend/src/pages/explore.users.vue @@ -5,9 +5,15 @@ SPDX-License-Identifier: AGPL-3.0-only <template> <div class="_spacer" style="--MI_SPACER-w: 1200px;"> - <MkTab v-if="instance.federation !== 'none'" v-model="origin" style="margin-bottom: var(--MI-margin);"> - <option value="local">{{ i18n.ts.local }}</option> - <option value="remote">{{ i18n.ts.remote }}</option> + <MkTab + v-if="instance.federation !== 'none'" + v-model="origin" + :tabs="[ + { key: 'local', label: i18n.ts.local }, + { key: 'remote', label: i18n.ts.remote }, + ]" + style="margin-bottom: var(--MI-margin);" + > </MkTab> <div v-if="origin === 'local'"> <template v-if="tag == null"> @@ -77,7 +83,7 @@ const props = defineProps<{ tag?: string; }>(); -const origin = ref('local'); +const origin = ref<'local' | 'remote'>('local'); const tagsLocal = ref<Misskey.entities.Hashtag[]>([]); const tagsRemote = ref<Misskey.entities.Hashtag[]>([]); diff --git a/packages/frontend/src/pages/qr.read.vue b/packages/frontend/src/pages/qr.read.vue index e4c475196a..251dccd0f0 100644 --- a/packages/frontend/src/pages/qr.read.vue +++ b/packages/frontend/src/pages/qr.read.vue @@ -39,10 +39,15 @@ SPDX-License-Identifier: AGPL-3.0-only > <MkStickyContainer> <template #header> - <MkTab v-model="tab" :class="$style.tab"> - <option value="users">{{ i18n.ts.users }}</option> - <option value="notes">{{ i18n.ts.notes }}</option> - <option value="all">{{ i18n.ts.all }}</option> + <MkTab + v-model="tab" + :tabs="[ + { key: 'users', label: i18n.ts.users }, + { key: 'notes', label: i18n.ts.notes }, + { key: 'all', label: i18n.ts.all }, + ]" + :class="$style.tab" + > </MkTab> </template> <div v-if="tab === 'users'" :class="[$style.users, '_margin']" style="padding-bottom: var(--MI-margin);"> diff --git a/packages/frontend/src/pages/user/index.timeline.vue b/packages/frontend/src/pages/user/index.timeline.vue index 5e9e671252..6d74de14a0 100644 --- a/packages/frontend/src/pages/user/index.timeline.vue +++ b/packages/frontend/src/pages/user/index.timeline.vue @@ -6,11 +6,16 @@ SPDX-License-Identifier: AGPL-3.0-only <template> <MkStickyContainer> <template #header> - <MkTab v-model="tab" :class="$style.tab"> - <option value="featured">{{ i18n.ts.featured }}</option> - <option value="notes">{{ i18n.ts.notes }}</option> - <option value="all">{{ i18n.ts.all }}</option> - <option value="files">{{ i18n.ts.withFiles }}</option> + <MkTab + v-model="tab" + :tabs="[ + { key: 'featured', label: i18n.ts.featured }, + { key: 'notes', label: i18n.ts.notes }, + { key: 'all', label: i18n.ts.all }, + { key: 'files', label: i18n.ts.withFiles }, + ]" + :class="$style.tab" + > </MkTab> </template> <MkNotesTimeline v-if="tab === 'featured'" :noGap="true" :paginator="featuredPaginator" :pullToRefresh="false" :class="$style.tl"/> @@ -30,7 +35,7 @@ const props = defineProps<{ user: Misskey.entities.UserDetailed; }>(); -const tab = ref<string>('all'); +const tab = ref<'featured' | 'notes' | 'all' | 'files'>('all'); const featuredPaginator = markRaw(new Paginator('users/featured-notes', { limit: 10, diff --git a/packages/frontend/src/pages/user/notes.vue b/packages/frontend/src/pages/user/notes.vue index b5e600da92..1e6dba73bd 100644 --- a/packages/frontend/src/pages/user/notes.vue +++ b/packages/frontend/src/pages/user/notes.vue @@ -8,11 +8,16 @@ SPDX-License-Identifier: AGPL-3.0-only <div :class="$style.root"> <MkStickyContainer> <template #header> - <MkTab v-model="tab" :class="$style.tab"> - <option value="featured">{{ i18n.ts.featured }}</option> - <option value="notes">{{ i18n.ts.notes }}</option> - <option value="all">{{ i18n.ts.all }}</option> - <option value="files">{{ i18n.ts.withFiles }}</option> + <MkTab + v-model="tab" + :tabs="[ + { key: 'featured', label: i18n.ts.featured }, + { key: 'notes', label: i18n.ts.notes }, + { key: 'all', label: i18n.ts.all }, + { key: 'files', label: i18n.ts.withFiles }, + ]" + :class="$style.tab" + > </MkTab> </template> <MkNotesTimeline v-if="tab === 'featured'" :noGap="true" :paginator="featuredPaginator" :class="$style.tl"/> @@ -34,7 +39,7 @@ const props = defineProps<{ user: Misskey.entities.UserDetailed; }>(); -const tab = ref<string>('all'); +const tab = ref<'featured' | 'notes' | 'all' | 'files'>('all'); const featuredPaginator = markRaw(new Paginator('users/featured-notes', { limit: 10, |