From 0b08fcac4a966e0af347c80e96bdbdb059451a26 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Tue, 10 Jan 2023 06:02:46 +0900 Subject: [PATCH] refactor(client): use css modules --- packages/frontend/src/components/MkMenu.vue | 326 ++++++++++---------- 1 file changed, 163 insertions(+), 163 deletions(-) diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue index abae272e8f..a1020ef151 100644 --- a/packages/frontend/src/components/MkMenu.vue +++ b/packages/frontend/src/components/MkMenu.vue @@ -2,54 +2,54 @@ <div> <div ref="itemsEl" v-hotkey="keymap" - class="rrevdjwt _popup _shadow" - :class="{ center: align === 'center', asDrawer }" + class="_popup _shadow" + :class="[$style.root, { [$style.center]: align === 'center', [$style.asDrawer]: asDrawer }]" :style="{ width: (width && !asDrawer) ? width + 'px' : '', maxHeight: maxHeight ? maxHeight + 'px' : '' }" @contextmenu.self="e => e.preventDefault()" > <template v-for="(item, i) in items2"> - <div v-if="item === null" class="divider"></div> - <span v-else-if="item.type === 'label'" class="label item"> + <div v-if="item === null" :class="$style.divider"></div> + <span v-else-if="item.type === 'label'" :class="[$style.label, $style.item]"> <span>{{ item.text }}</span> </span> - <span v-else-if="item.type === 'pending'" :tabindex="i" class="pending item"> + <span v-else-if="item.type === 'pending'" :tabindex="i" :class="[$style.pending, $style.item]"> <span><MkEllipsis/></span> </span> - <MkA v-else-if="item.type === 'link'" :to="item.to" :tabindex="i" class="_button item" @click.passive="close(true)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> - <i v-if="item.icon" class="ti-fw" :class="item.icon"></i> - <MkAvatar v-if="item.avatar" :user="item.avatar" class="avatar"/> + <MkA v-else-if="item.type === 'link'" :to="item.to" :tabindex="i" class="_button" :class="$style.item" @click.passive="close(true)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> + <i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i> + <MkAvatar v-if="item.avatar" :user="item.avatar" :class="$style.avatar"/> <span>{{ item.text }}</span> - <span v-if="item.indicate" class="indicator"><i class="_indicatorCircle"></i></span> + <span v-if="item.indicate" :class="$style.indicator"><i class="_indicatorCircle"></i></span> </MkA> - <a v-else-if="item.type === 'a'" :href="item.href" :target="item.target" :download="item.download" :tabindex="i" class="_button item" @click="close(true)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> - <i v-if="item.icon" class="ti-fw" :class="item.icon"></i> + <a v-else-if="item.type === 'a'" :href="item.href" :target="item.target" :download="item.download" :tabindex="i" class="_button" :class="$style.item" @click="close(true)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> + <i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i> <span>{{ item.text }}</span> - <span v-if="item.indicate" class="indicator"><i class="_indicatorCircle"></i></span> + <span v-if="item.indicate" :class="$style.indicator"><i class="_indicatorCircle"></i></span> </a> - <button v-else-if="item.type === 'user'" :tabindex="i" class="_button item" :class="{ active: item.active }" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> - <MkAvatar :user="item.user" class="avatar"/><MkUserName :user="item.user"/> - <span v-if="item.indicate" class="indicator"><i class="_indicatorCircle"></i></span> + <button v-else-if="item.type === 'user'" :tabindex="i" class="_button" :class="[$style.item, { [$style.active]: item.active }]" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> + <MkAvatar :user="item.user" :class="$style.avatar"/><MkUserName :user="item.user"/> + <span v-if="item.indicate" :class="$style.indicator"><i class="_indicatorCircle"></i></span> </button> - <span v-else-if="item.type === 'switch'" :tabindex="i" class="item" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> + <span v-else-if="item.type === 'switch'" :tabindex="i" :class="$style.item" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> <MkSwitch v-model="item.ref" :disabled="item.disabled" class="form-switch">{{ item.text }}</MkSwitch> </span> - <button v-else-if="item.type === 'parent'" :tabindex="i" class="_button item parent" :class="{ childShowing: childShowingItem === item }" @mouseenter="showChildren(item, $event)"> - <i v-if="item.icon" class="ti-fw" :class="item.icon"></i> + <button v-else-if="item.type === 'parent'" :tabindex="i" class="_button" :class="[$style.item, $style.parent, { [$style.childShowing]: childShowingItem === item }]" @mouseenter="showChildren(item, $event)"> + <i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i> <span>{{ item.text }}</span> - <span class="caret"><i class="ti ti-caret-right ti-fw"></i></span> + <span :class="$style.caret"><i class="ti ti-caret-right ti-fw"></i></span> </button> - <button v-else :tabindex="i" class="_button item" :class="{ danger: item.danger, active: item.active }" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> - <i v-if="item.icon" class="ti-fw" :class="item.icon"></i> - <MkAvatar v-if="item.avatar" :user="item.avatar" class="avatar"/> + <button v-else :tabindex="i" class="_button" :class="[$style.item, { [$style.danger]: item.danger, [$style.active]: item.active }]" :disabled="item.active" @click="clicked(item.action, $event)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)"> + <i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i> + <MkAvatar v-if="item.avatar" :user="item.avatar" :class="$style.avatar"/> <span>{{ item.text }}</span> - <span v-if="item.indicate" class="indicator"><i class="_indicatorCircle"></i></span> + <span v-if="item.indicate" :class="$style.indicator"><i class="_indicatorCircle"></i></span> </button> </template> - <span v-if="items2.length === 0" class="none item"> + <span v-if="items2.length === 0" :class="[$style.none, $style.item]"> <span>{{ i18n.ts.none }}</span> </span> </div> - <div v-if="childMenu" class="child"> + <div v-if="childMenu" :class="$style.child"> <XChild ref="child" :items="childMenu" :target-element="childTarget" :root-element="itemsEl" showing @actioned="childActioned"/> </div> </div> @@ -186,8 +186,8 @@ onBeforeUnmount(() => { }); </script> -<style lang="scss" scoped> -.rrevdjwt { +<style lang="scss" module> +.root { padding: 8px 0; box-sizing: border-box; min-width: 200px; @@ -200,141 +200,6 @@ onBeforeUnmount(() => { } } - > .item { - display: block; - position: relative; - padding: 5px 16px; - width: 100%; - box-sizing: border-box; - white-space: nowrap; - font-size: 0.9em; - line-height: 20px; - text-align: left; - overflow: hidden; - text-overflow: ellipsis; - - &:before { - content: ""; - display: block; - position: absolute; - z-index: -1; - top: 0; - left: 0; - right: 0; - margin: auto; - width: calc(100% - 16px); - height: 100%; - border-radius: 6px; - } - - &:not(:disabled):hover { - color: var(--accent); - text-decoration: none; - - &:before { - background: var(--accentedBg); - } - } - - &.danger { - color: #ff2a2a; - - &:hover { - color: #fff; - - &:before { - background: #ff4242; - } - } - - &:active { - color: #fff; - - &:before { - background: #d42e2e !important; - } - } - } - - &:active, - &.active { - color: var(--fgOnAccent) !important; - opacity: 1; - - &:before { - background: var(--accent) !important; - } - } - - &:not(:active):focus-visible { - box-shadow: 0 0 0 2px var(--focus) inset; - } - - &.label { - pointer-events: none; - font-size: 0.7em; - padding-bottom: 4px; - - > span { - opacity: 0.7; - } - } - - &.pending { - pointer-events: none; - opacity: 0.7; - } - - &.none { - pointer-events: none; - opacity: 0.7; - } - - &.parent { - display: flex; - align-items: center; - cursor: default; - - > .caret { - margin-left: auto; - } - - &.childShowing { - color: var(--accent); - text-decoration: none; - - &:before { - background: var(--accentedBg); - } - } - } - - > i { - margin-right: 5px; - width: 20px; - } - - > .avatar { - margin-right: 5px; - width: 20px; - height: 20px; - } - - > .indicator { - position: absolute; - top: 5px; - left: 13px; - color: var(--indicator); - font-size: 12px; - animation: blink 1s infinite; - } - } - - > .divider { - margin: 8px 0; - border-top: solid 0.5px var(--divider); - } - &.asDrawer { padding: 12px 0 calc(env(safe-area-inset-bottom, 0px) + 12px) 0; width: 100%; @@ -351,7 +216,7 @@ onBeforeUnmount(() => { border-radius: 12px; } - > i { + > .icon { margin-right: 14px; width: 24px; } @@ -362,4 +227,139 @@ onBeforeUnmount(() => { } } } + +.item { + display: block; + position: relative; + padding: 5px 16px; + width: 100%; + box-sizing: border-box; + white-space: nowrap; + font-size: 0.9em; + line-height: 20px; + text-align: left; + overflow: hidden; + text-overflow: ellipsis; + + &:before { + content: ""; + display: block; + position: absolute; + z-index: -1; + top: 0; + left: 0; + right: 0; + margin: auto; + width: calc(100% - 16px); + height: 100%; + border-radius: 6px; + } + + &:not(:disabled):hover { + color: var(--accent); + text-decoration: none; + + &:before { + background: var(--accentedBg); + } + } + + &.danger { + color: #ff2a2a; + + &:hover { + color: #fff; + + &:before { + background: #ff4242; + } + } + + &:active { + color: #fff; + + &:before { + background: #d42e2e !important; + } + } + } + + &:active, + &.active { + color: var(--fgOnAccent) !important; + opacity: 1; + + &:before { + background: var(--accent) !important; + } + } + + &:not(:active):focus-visible { + box-shadow: 0 0 0 2px var(--focus) inset; + } + + &.label { + pointer-events: none; + font-size: 0.7em; + padding-bottom: 4px; + + > span { + opacity: 0.7; + } + } + + &.pending { + pointer-events: none; + opacity: 0.7; + } + + &.none { + pointer-events: none; + opacity: 0.7; + } + + &.parent { + display: flex; + align-items: center; + cursor: default; + + &.childShowing { + color: var(--accent); + text-decoration: none; + + &:before { + background: var(--accentedBg); + } + } + } +} + +.icon { + margin-right: 5px; + width: 20px; +} + +.caret { + margin-left: auto; +} + +.avatar { + margin-right: 5px; + width: 20px; + height: 20px; +} + +.indicator { + position: absolute; + top: 5px; + left: 13px; + color: var(--indicator); + font-size: 12px; + animation: blink 1s infinite; +} + +.divider { + margin: 8px 0; + border-top: solid 0.5px var(--divider); +} </style>