diff options
| author | かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> | 2024-03-30 16:02:03 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-30 16:02:03 +0900 |
| commit | b96d9c6973b1c861306fdb9f51256cee5325a2b1 (patch) | |
| tree | b6aba03fba4f018e35213da755d4064a602bb1d6 /packages/frontend/src/components/MkMenu.vue | |
| parent | enhance(frontend): 2要素認証セットアップウィザードにアプリ... (diff) | |
| download | sharkey-b96d9c6973b1c861306fdb9f51256cee5325a2b1.tar.gz sharkey-b96d9c6973b1c861306fdb9f51256cee5325a2b1.tar.bz2 sharkey-b96d9c6973b1c861306fdb9f51256cee5325a2b1.zip | |
fix/enhance(frontend): 映像・音声周りの改修 (#13206)
* enhance(frontend): 映像・音声周りの改修
* fix
* fix design
* fix lint
* キーボードショートカットを整備
* Update Changelog
* fix
* feat: ループ再生
* ネイティブの動作と同期されるように
* Update Changelog
* key指定を消す
Diffstat (limited to 'packages/frontend/src/components/MkMenu.vue')
| -rw-r--r-- | packages/frontend/src/components/MkMenu.vue | 91 |
1 files changed, 86 insertions, 5 deletions
diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue index faed6416d0..d91239b9e2 100644 --- a/packages/frontend/src/components/MkMenu.vue +++ b/packages/frontend/src/components/MkMenu.vue @@ -42,9 +42,26 @@ SPDX-License-Identifier: AGPL-3.0-only </div> </button> <button v-else-if="item.type === 'switch'" role="menuitemcheckbox" :tabindex="i" class="_button" :class="[$style.item, $style.switch, { [$style.switchDisabled]: item.disabled } ]" @click="switchItem(item)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> - <MkSwitchButton :class="$style.switchButton" :checked="item.ref" :disabled="item.disabled" @toggle="switchItem(item)"/> + <i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i> + <MkSwitchButton v-else :class="$style.switchButton" :checked="item.ref" :disabled="item.disabled" @toggle="switchItem(item)"/> + <div :class="$style.item_content"> + <span :class="[$style.item_content_text, { [$style.switchText]: !item.icon }]">{{ item.text }}</span> + <MkSwitchButton v-if="item.icon" :class="[$style.switchButton, $style.caret]" :checked="item.ref" :disabled="item.disabled" @toggle="switchItem(item)"/> + </div> + </button> + <button v-else-if="item.type === 'radio'" class="_button" role="menuitem" :tabindex="i" :class="[$style.item, $style.parent, { [$style.childShowing]: childShowingItem === item }]" @mouseenter="preferClick ? null : showRadioOptions(item, $event)" @click="!preferClick ? null : showRadioOptions(item, $event)"> + <i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]" style="pointer-events: none;"></i> + <div :class="$style.item_content"> + <span :class="$style.item_content_text" style="pointer-events: none;">{{ item.text }}</span> + <span :class="$style.caret" style="pointer-events: none;"><i class="ti ti-chevron-right ti-fw"></i></span> + </div> + </button> + <button v-else-if="item.type === 'radioOption'" :tabindex="i" class="_button" role="menuitem" :class="[$style.item, { [$style.radioActive]: item.active }]" @click="clicked(item.action, $event, false)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> + <div :class="$style.icon"> + <span :class="[$style.radio, { [$style.radioChecked]: item.active }]"></span> + </div> <div :class="$style.item_content"> - <span :class="[$style.item_content_text, $style.switchText]">{{ item.text }}</span> + <span :class="$style.item_content_text">{{ item.text }}</span> </div> </button> <button v-else-if="item.type === 'parent'" class="_button" role="menuitem" :tabindex="i" :class="[$style.item, $style.parent, { [$style.childShowing]: childShowingItem === item }]" @mouseenter="preferClick ? null : showChildren(item, $event)" @click="!preferClick ? null : showChildren(item, $event)"> @@ -77,7 +94,7 @@ SPDX-License-Identifier: AGPL-3.0-only import { ComputedRef, computed, defineAsyncComponent, isRef, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue'; import { focusPrev, focusNext } from '@/scripts/focus.js'; import MkSwitchButton from '@/components/MkSwitch.button.vue'; -import { MenuItem, InnerMenuItem, MenuPending, MenuAction, MenuSwitch, MenuParent } from '@/types/menu.js'; +import { MenuItem, InnerMenuItem, MenuPending, MenuAction, MenuSwitch, MenuRadio, MenuRadioOption, MenuParent } from '@/types/menu.js'; import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; import { isTouchUsing } from '@/scripts/touch.js'; @@ -168,6 +185,31 @@ function onItemMouseLeave(item) { if (childCloseTimer) window.clearTimeout(childCloseTimer); } +async function showRadioOptions(item: MenuRadio, ev: MouseEvent) { + const children: MenuItem[] = Object.keys(item.options).map<MenuRadioOption>(key => { + const value = item.options[key]; + return { + type: 'radioOption', + text: key, + action: () => { + item.ref = value; + }, + active: computed(() => item.ref === value), + }; + }); + + if (props.asDrawer) { + os.popupMenu(children, ev.currentTarget ?? ev.target).finally(() => { + emit('close'); + }); + emit('hide'); + } else { + childTarget.value = (ev.currentTarget ?? ev.target) as HTMLElement; + childMenu.value = children; + childShowingItem.value = item; + } +} + async function showChildren(item: MenuParent, ev: MouseEvent) { const children: MenuItem[] = await (async () => { if (childrenCache.has(item)) { @@ -196,8 +238,10 @@ async function showChildren(item: MenuParent, ev: MouseEvent) { } } -function clicked(fn: MenuAction, ev: MouseEvent) { +function clicked(fn: MenuAction, ev: MouseEvent, doClose = true) { fn(ev); + + if (!doClose) return; close(true); } @@ -350,6 +394,15 @@ onBeforeUnmount(() => { } } + &.radioActive { + color: var(--accent) !important; + opacity: 1; + + &:before { + background-color: var(--accentedBg) !important; + } + } + &:not(:active):focus-visible { box-shadow: 0 0 0 2px var(--focus) inset; } @@ -417,11 +470,11 @@ onBeforeUnmount(() => { .switchButton { margin-left: -2px; + --height: 1.35em; } .switchText { margin-left: 8px; - margin-top: 2px; overflow: hidden; text-overflow: ellipsis; } @@ -461,4 +514,32 @@ onBeforeUnmount(() => { margin: 8px 0; border-top: solid 0.5px var(--divider); } + +.radio { + display: inline-block; + position: relative; + width: 1em; + height: 1em; + vertical-align: -.125em; + border-radius: 50%; + border: solid 2px var(--divider); + background-color: var(--panel); + + &.radioChecked { + border-color: var(--accent); + + &::after { + content: ""; + display: block; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 50%; + height: 50%; + border-radius: 50%; + background-color: var(--accent); + } + } +} </style> |