mirror of
https://github.com/paricafe/misskey.git
synced 2024-11-28 09:36:43 -06:00
refactor(frontend): getBgColorを共通化 (#14782)
* refactor: getBgColor関数の切り出し + fix types (taiyme#291) * move thing * revert unnecesary changes --------- Co-authored-by: taiy <53635909+taiyme@users.noreply.github.com>
This commit is contained in:
parent
a3a99467f0
commit
2250e521e4
9 changed files with 94 additions and 109 deletions
|
@ -64,26 +64,30 @@ const showBody = ref(props.expanded);
|
||||||
const ignoreOmit = ref(false);
|
const ignoreOmit = ref(false);
|
||||||
const omitted = ref(false);
|
const omitted = ref(false);
|
||||||
|
|
||||||
function enter(el) {
|
function enter(el: Element) {
|
||||||
|
if (!(el instanceof HTMLElement)) return;
|
||||||
const elementHeight = el.getBoundingClientRect().height;
|
const elementHeight = el.getBoundingClientRect().height;
|
||||||
el.style.height = 0;
|
el.style.height = '0';
|
||||||
el.offsetHeight; // reflow
|
el.offsetHeight; // reflow
|
||||||
el.style.height = Math.min(elementHeight, props.maxHeight ?? Infinity) + 'px';
|
el.style.height = `${Math.min(elementHeight, props.maxHeight ?? Infinity)}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function afterEnter(el) {
|
function afterEnter(el: Element) {
|
||||||
el.style.height = null;
|
if (!(el instanceof HTMLElement)) return;
|
||||||
|
el.style.height = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function leave(el) {
|
function leave(el: Element) {
|
||||||
|
if (!(el instanceof HTMLElement)) return;
|
||||||
const elementHeight = el.getBoundingClientRect().height;
|
const elementHeight = el.getBoundingClientRect().height;
|
||||||
el.style.height = elementHeight + 'px';
|
el.style.height = `${elementHeight}px`;
|
||||||
el.offsetHeight; // reflow
|
el.offsetHeight; // reflow
|
||||||
el.style.height = 0;
|
el.style.height = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
function afterLeave(el) {
|
function afterLeave(el: Element) {
|
||||||
el.style.height = null;
|
if (!(el instanceof HTMLElement)) return;
|
||||||
|
el.style.height = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const calcOmit = () => {
|
const calcOmit = () => {
|
||||||
|
|
|
@ -128,14 +128,14 @@ export default defineComponent({
|
||||||
return children;
|
return children;
|
||||||
};
|
};
|
||||||
|
|
||||||
function onBeforeLeave(element: Element) {
|
function onBeforeLeave(el: Element) {
|
||||||
const el = element as HTMLElement;
|
if (!(el instanceof HTMLElement)) return;
|
||||||
el.style.top = `${el.offsetTop}px`;
|
el.style.top = `${el.offsetTop}px`;
|
||||||
el.style.left = `${el.offsetLeft}px`;
|
el.style.left = `${el.offsetLeft}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLeaveCancelled(element: Element) {
|
function onLeaveCancelled(el: Element) {
|
||||||
const el = element as HTMLElement;
|
if (!(el instanceof HTMLElement)) return;
|
||||||
el.style.top = '';
|
el.style.top = '';
|
||||||
el.style.left = '';
|
el.style.left = '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div ref="rootEl" :class="$style.root">
|
<div ref="rootEl" :class="$style.root">
|
||||||
<header :class="$style.header" class="_button" :style="{ background: bg }" @click="showBody = !showBody">
|
<header :class="$style.header" class="_button" @click="showBody = !showBody">
|
||||||
<div :class="$style.title"><div><slot name="header"></slot></div></div>
|
<div :class="$style.title"><div><slot name="header"></slot></div></div>
|
||||||
<div :class="$style.divider"></div>
|
<div :class="$style.divider"></div>
|
||||||
<button class="_button" :class="$style.button">
|
<button class="_button" :class="$style.button">
|
||||||
|
@ -32,21 +32,23 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref, shallowRef, watch } from 'vue';
|
import { onMounted, ref, shallowRef, watch } from 'vue';
|
||||||
import tinycolor from 'tinycolor2';
|
|
||||||
import { miLocalStorage } from '@/local-storage.js';
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
|
import { getBgColor } from '@/scripts/get-bg-color.js';
|
||||||
|
|
||||||
const miLocalStoragePrefix = 'ui:folder:' as const;
|
const miLocalStoragePrefix = 'ui:folder:' as const;
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
expanded?: boolean;
|
expanded?: boolean;
|
||||||
persistKey?: string;
|
persistKey?: string | null;
|
||||||
}>(), {
|
}>(), {
|
||||||
expanded: true,
|
expanded: true,
|
||||||
|
persistKey: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const rootEl = shallowRef<HTMLDivElement>();
|
const rootEl = shallowRef<HTMLElement>();
|
||||||
const bg = ref<string>();
|
const parentBg = ref<string | null>(null);
|
||||||
|
// eslint-disable-next-line vue/no-setup-props-reactivity-loss
|
||||||
const showBody = ref((props.persistKey && miLocalStorage.getItem(`${miLocalStoragePrefix}${props.persistKey}`)) ? (miLocalStorage.getItem(`${miLocalStoragePrefix}${props.persistKey}`) === 't') : props.expanded);
|
const showBody = ref((props.persistKey && miLocalStorage.getItem(`${miLocalStoragePrefix}${props.persistKey}`)) ? (miLocalStorage.getItem(`${miLocalStoragePrefix}${props.persistKey}`) === 't') : props.expanded);
|
||||||
|
|
||||||
watch(showBody, () => {
|
watch(showBody, () => {
|
||||||
|
@ -55,47 +57,34 @@ watch(showBody, () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function enter(element: Element) {
|
function enter(el: Element) {
|
||||||
const el = element as HTMLElement;
|
if (!(el instanceof HTMLElement)) return;
|
||||||
const elementHeight = el.getBoundingClientRect().height;
|
const elementHeight = el.getBoundingClientRect().height;
|
||||||
el.style.height = '0';
|
el.style.height = '0';
|
||||||
el.offsetHeight; // reflow
|
el.offsetHeight; // reflow
|
||||||
el.style.height = elementHeight + 'px';
|
el.style.height = `${elementHeight}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function afterEnter(element: Element) {
|
function afterEnter(el: Element) {
|
||||||
const el = element as HTMLElement;
|
if (!(el instanceof HTMLElement)) return;
|
||||||
el.style.height = 'unset';
|
el.style.height = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function leave(element: Element) {
|
function leave(el: Element) {
|
||||||
const el = element as HTMLElement;
|
if (!(el instanceof HTMLElement)) return;
|
||||||
const elementHeight = el.getBoundingClientRect().height;
|
const elementHeight = el.getBoundingClientRect().height;
|
||||||
el.style.height = elementHeight + 'px';
|
el.style.height = `${elementHeight}px`;
|
||||||
el.offsetHeight; // reflow
|
el.offsetHeight; // reflow
|
||||||
el.style.height = '0';
|
el.style.height = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
function afterLeave(element: Element) {
|
function afterLeave(el: Element) {
|
||||||
const el = element as HTMLElement;
|
if (!(el instanceof HTMLElement)) return;
|
||||||
el.style.height = 'unset';
|
el.style.height = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
function getParentBg(el?: HTMLElement | null): string {
|
parentBg.value = getBgColor(rootEl.value?.parentElement);
|
||||||
if (el == null || el.tagName === 'BODY') return 'var(--MI_THEME-bg)';
|
|
||||||
const background = el.style.background || el.style.backgroundColor;
|
|
||||||
if (background) {
|
|
||||||
return background;
|
|
||||||
} else {
|
|
||||||
return getParentBg(el.parentElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const rawBg = getParentBg(rootEl.value);
|
|
||||||
const _bg = tinycolor(rawBg.startsWith('var(') ? getComputedStyle(document.documentElement).getPropertyValue(rawBg.slice(4, -1)) : rawBg);
|
|
||||||
_bg.setAlpha(0.85);
|
|
||||||
bg.value = _bg.toRgbString();
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -121,6 +110,7 @@ onMounted(() => {
|
||||||
top: var(--MI-stickyTop, 0px);
|
top: var(--MI-stickyTop, 0px);
|
||||||
-webkit-backdrop-filter: var(--MI-blur, blur(8px));
|
-webkit-backdrop-filter: var(--MI-blur, blur(8px));
|
||||||
backdrop-filter: var(--MI-blur, blur(20px));
|
backdrop-filter: var(--MI-blur, blur(20px));
|
||||||
|
background-color: color(from v-bind("parentBg ?? 'var(--bg)'") srgb r g b / 0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
|
|
@ -56,8 +56,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { nextTick, onMounted, shallowRef, ref } from 'vue';
|
import { nextTick, onMounted, ref, shallowRef } from 'vue';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
|
import { getBgColor } from '@/scripts/get-bg-color.js';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
defaultOpen?: boolean;
|
defaultOpen?: boolean;
|
||||||
|
@ -69,40 +70,35 @@ const props = withDefaults(defineProps<{
|
||||||
withSpacer: true,
|
withSpacer: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const getBgColor = (el: HTMLElement) => {
|
|
||||||
const style = window.getComputedStyle(el);
|
|
||||||
if (style.backgroundColor && !['rgba(0, 0, 0, 0)', 'rgba(0,0,0,0)', 'transparent'].includes(style.backgroundColor)) {
|
|
||||||
return style.backgroundColor;
|
|
||||||
} else {
|
|
||||||
return el.parentElement ? getBgColor(el.parentElement) : 'transparent';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const rootEl = shallowRef<HTMLElement>();
|
const rootEl = shallowRef<HTMLElement>();
|
||||||
const bgSame = ref(false);
|
const bgSame = ref(false);
|
||||||
const opened = ref(props.defaultOpen);
|
const opened = ref(props.defaultOpen);
|
||||||
const openedAtLeastOnce = ref(props.defaultOpen);
|
const openedAtLeastOnce = ref(props.defaultOpen);
|
||||||
|
|
||||||
function enter(el) {
|
function enter(el: Element) {
|
||||||
|
if (!(el instanceof HTMLElement)) return;
|
||||||
const elementHeight = el.getBoundingClientRect().height;
|
const elementHeight = el.getBoundingClientRect().height;
|
||||||
el.style.height = 0;
|
el.style.height = '0';
|
||||||
el.offsetHeight; // reflow
|
el.offsetHeight; // reflow
|
||||||
el.style.height = Math.min(elementHeight, props.maxHeight ?? Infinity) + 'px';
|
el.style.height = `${Math.min(elementHeight, props.maxHeight ?? Infinity)}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function afterEnter(el) {
|
function afterEnter(el: Element) {
|
||||||
el.style.height = null;
|
if (!(el instanceof HTMLElement)) return;
|
||||||
|
el.style.height = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function leave(el) {
|
function leave(el: Element) {
|
||||||
|
if (!(el instanceof HTMLElement)) return;
|
||||||
const elementHeight = el.getBoundingClientRect().height;
|
const elementHeight = el.getBoundingClientRect().height;
|
||||||
el.style.height = elementHeight + 'px';
|
el.style.height = `${elementHeight}px`;
|
||||||
el.offsetHeight; // reflow
|
el.offsetHeight; // reflow
|
||||||
el.style.height = 0;
|
el.style.height = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
function afterLeave(el) {
|
function afterLeave(el: Element) {
|
||||||
el.style.height = null;
|
if (!(el instanceof HTMLElement)) return;
|
||||||
|
el.style.height = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
|
@ -117,7 +113,7 @@ function toggle() {
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const computedStyle = getComputedStyle(document.documentElement);
|
const computedStyle = getComputedStyle(document.documentElement);
|
||||||
const parentBg = getBgColor(rootEl.value!.parentElement!);
|
const parentBg = getBgColor(rootEl.value?.parentElement) ?? 'transparent';
|
||||||
const myBg = computedStyle.getPropertyValue('--MI_THEME-panel');
|
const myBg = computedStyle.getPropertyValue('--MI_THEME-panel');
|
||||||
bgSame.value = parentBg === myBg;
|
bgSame.value = parentBg === myBg;
|
||||||
});
|
});
|
||||||
|
|
|
@ -53,7 +53,7 @@ export type Tab = {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, onUnmounted, watch, nextTick, shallowRef } from 'vue';
|
import { nextTick, onMounted, onUnmounted, shallowRef, watch } from 'vue';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
|
@ -120,14 +120,14 @@ function onTabWheel(ev: WheelEvent) {
|
||||||
|
|
||||||
let entering = false;
|
let entering = false;
|
||||||
|
|
||||||
async function enter(element: Element) {
|
async function enter(el: Element) {
|
||||||
|
if (!(el instanceof HTMLElement)) return;
|
||||||
entering = true;
|
entering = true;
|
||||||
const el = element as HTMLElement;
|
|
||||||
const elementWidth = el.getBoundingClientRect().width;
|
const elementWidth = el.getBoundingClientRect().width;
|
||||||
el.style.width = '0';
|
el.style.width = '0';
|
||||||
el.style.paddingLeft = '0';
|
el.style.paddingLeft = '0';
|
||||||
el.offsetWidth; // force reflow
|
el.offsetWidth; // reflow
|
||||||
el.style.width = elementWidth + 'px';
|
el.style.width = `${elementWidth}px`;
|
||||||
el.style.paddingLeft = '';
|
el.style.paddingLeft = '';
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
entering = false;
|
entering = false;
|
||||||
|
@ -136,22 +136,23 @@ async function enter(element: Element) {
|
||||||
setTimeout(renderTab, 170);
|
setTimeout(renderTab, 170);
|
||||||
}
|
}
|
||||||
|
|
||||||
function afterEnter(element: Element) {
|
function afterEnter(el: Element) {
|
||||||
//el.style.width = '';
|
if (!(el instanceof HTMLElement)) return;
|
||||||
|
// element.style.width = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function leave(element: Element) {
|
async function leave(el: Element) {
|
||||||
const el = element as HTMLElement;
|
if (!(el instanceof HTMLElement)) return;
|
||||||
const elementWidth = el.getBoundingClientRect().width;
|
const elementWidth = el.getBoundingClientRect().width;
|
||||||
el.style.width = elementWidth + 'px';
|
el.style.width = `${elementWidth}px`;
|
||||||
el.style.paddingLeft = '';
|
el.style.paddingLeft = '';
|
||||||
el.offsetWidth; // force reflow
|
el.offsetWidth; // reflow
|
||||||
el.style.width = '0';
|
el.style.width = '0';
|
||||||
el.style.paddingLeft = '0';
|
el.style.paddingLeft = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
function afterLeave(element: Element) {
|
function afterLeave(el: Element) {
|
||||||
const el = element as HTMLElement;
|
if (!(el instanceof HTMLElement)) return;
|
||||||
el.style.width = '';
|
el.style.width = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,19 +4,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Directive } from 'vue';
|
import { Directive } from 'vue';
|
||||||
|
import { getBgColor } from '@/scripts/get-bg-color.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mounted(src, binding, vn) {
|
mounted(src, binding, vn) {
|
||||||
const getBgColor = (el: HTMLElement) => {
|
const parentBg = getBgColor(src.parentElement) ?? 'transparent';
|
||||||
const style = window.getComputedStyle(el);
|
|
||||||
if (style.backgroundColor && !['rgba(0, 0, 0, 0)', 'rgba(0,0,0,0)', 'transparent'].includes(style.backgroundColor)) {
|
|
||||||
return style.backgroundColor;
|
|
||||||
} else {
|
|
||||||
return el.parentElement ? getBgColor(el.parentElement) : 'transparent';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const parentBg = getBgColor(src.parentElement);
|
|
||||||
|
|
||||||
const myBg = window.getComputedStyle(src).backgroundColor;
|
const myBg = window.getComputedStyle(src).backgroundColor;
|
||||||
|
|
||||||
|
|
|
@ -4,19 +4,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Directive } from 'vue';
|
import { Directive } from 'vue';
|
||||||
|
import { getBgColor } from '@/scripts/get-bg-color.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mounted(src, binding, vn) {
|
mounted(src, binding, vn) {
|
||||||
const getBgColor = (el: HTMLElement) => {
|
const parentBg = getBgColor(src.parentElement) ?? 'transparent';
|
||||||
const style = window.getComputedStyle(el);
|
|
||||||
if (style.backgroundColor && !['rgba(0, 0, 0, 0)', 'rgba(0,0,0,0)', 'transparent'].includes(style.backgroundColor)) {
|
|
||||||
return style.backgroundColor;
|
|
||||||
} else {
|
|
||||||
return el.parentElement ? getBgColor(el.parentElement) : 'transparent';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const parentBg = getBgColor(src.parentElement);
|
|
||||||
|
|
||||||
const myBg = window.getComputedStyle(src).backgroundColor;
|
const myBg = window.getComputedStyle(src).backgroundColor;
|
||||||
|
|
||||||
|
|
|
@ -4,19 +4,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Directive } from 'vue';
|
import { Directive } from 'vue';
|
||||||
|
import { getBgColor } from '@/scripts/get-bg-color.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mounted(src, binding, vn) {
|
mounted(src, binding, vn) {
|
||||||
const getBgColor = (el: HTMLElement) => {
|
const parentBg = getBgColor(src.parentElement) ?? 'transparent';
|
||||||
const style = window.getComputedStyle(el);
|
|
||||||
if (style.backgroundColor && !['rgba(0, 0, 0, 0)', 'rgba(0,0,0,0)', 'transparent'].includes(style.backgroundColor)) {
|
|
||||||
return style.backgroundColor;
|
|
||||||
} else {
|
|
||||||
return el.parentElement ? getBgColor(el.parentElement) : 'transparent';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const parentBg = getBgColor(src.parentElement);
|
|
||||||
|
|
||||||
const myBg = getComputedStyle(document.documentElement).getPropertyValue('--MI_THEME-panel');
|
const myBg = getComputedStyle(document.documentElement).getPropertyValue('--MI_THEME-panel');
|
||||||
|
|
||||||
|
|
18
packages/frontend/src/scripts/get-bg-color.ts
Normal file
18
packages/frontend/src/scripts/get-bg-color.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import tinycolor from 'tinycolor2';
|
||||||
|
|
||||||
|
export const getBgColor = (elem?: Element | null | undefined): string | null => {
|
||||||
|
if (elem == null) return null;
|
||||||
|
|
||||||
|
const { backgroundColor: bg } = window.getComputedStyle(elem);
|
||||||
|
|
||||||
|
if (bg && tinycolor(bg).getAlpha() !== 0) {
|
||||||
|
return bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getBgColor(elem.parentElement);
|
||||||
|
};
|
Loading…
Reference in a new issue