mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-04 07:24:13 +00: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 omitted = ref(false);
 | 
			
		||||
 | 
			
		||||
function enter(el) {
 | 
			
		||||
function enter(el: Element) {
 | 
			
		||||
	if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
	const elementHeight = el.getBoundingClientRect().height;
 | 
			
		||||
	el.style.height = 0;
 | 
			
		||||
	el.style.height = '0';
 | 
			
		||||
	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) {
 | 
			
		||||
	el.style.height = null;
 | 
			
		||||
function afterEnter(el: Element) {
 | 
			
		||||
	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;
 | 
			
		||||
	el.style.height = elementHeight + 'px';
 | 
			
		||||
	el.style.height = `${elementHeight}px`;
 | 
			
		||||
	el.offsetHeight; // reflow
 | 
			
		||||
	el.style.height = 0;
 | 
			
		||||
	el.style.height = '0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function afterLeave(el) {
 | 
			
		||||
	el.style.height = null;
 | 
			
		||||
function afterLeave(el: Element) {
 | 
			
		||||
	if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
	el.style.height = '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const calcOmit = () => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,14 +128,14 @@ export default defineComponent({
 | 
			
		|||
			return children;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		function onBeforeLeave(element: Element) {
 | 
			
		||||
			const el = element as HTMLElement;
 | 
			
		||||
		function onBeforeLeave(el: Element) {
 | 
			
		||||
			if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
			el.style.top = `${el.offsetTop}px`;
 | 
			
		||||
			el.style.left = `${el.offsetLeft}px`;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		function onLeaveCancelled(element: Element) {
 | 
			
		||||
			const el = element as HTMLElement;
 | 
			
		||||
		function onLeaveCancelled(el: Element) {
 | 
			
		||||
			if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
			el.style.top = '';
 | 
			
		||||
			el.style.left = '';
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
 | 
			
		||||
<template>
 | 
			
		||||
<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.divider"></div>
 | 
			
		||||
		<button class="_button" :class="$style.button">
 | 
			
		||||
| 
						 | 
				
			
			@ -32,21 +32,23 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { onMounted, ref, shallowRef, watch } from 'vue';
 | 
			
		||||
import tinycolor from 'tinycolor2';
 | 
			
		||||
import { miLocalStorage } from '@/local-storage.js';
 | 
			
		||||
import { defaultStore } from '@/store.js';
 | 
			
		||||
import { getBgColor } from '@/scripts/get-bg-color.js';
 | 
			
		||||
 | 
			
		||||
const miLocalStoragePrefix = 'ui:folder:' as const;
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(defineProps<{
 | 
			
		||||
	expanded?: boolean;
 | 
			
		||||
	persistKey?: string;
 | 
			
		||||
	persistKey?: string | null;
 | 
			
		||||
}>(), {
 | 
			
		||||
	expanded: true,
 | 
			
		||||
	persistKey: null,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const rootEl = shallowRef<HTMLDivElement>();
 | 
			
		||||
const bg = ref<string>();
 | 
			
		||||
const rootEl = shallowRef<HTMLElement>();
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
watch(showBody, () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -55,47 +57,34 @@ watch(showBody, () => {
 | 
			
		|||
	}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function enter(element: Element) {
 | 
			
		||||
	const el = element as HTMLElement;
 | 
			
		||||
function enter(el: Element) {
 | 
			
		||||
	if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
	const elementHeight = el.getBoundingClientRect().height;
 | 
			
		||||
	el.style.height = '0';
 | 
			
		||||
	el.offsetHeight; // reflow
 | 
			
		||||
	el.style.height = elementHeight + 'px';
 | 
			
		||||
	el.style.height = `${elementHeight}px`;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function afterEnter(element: Element) {
 | 
			
		||||
	const el = element as HTMLElement;
 | 
			
		||||
	el.style.height = 'unset';
 | 
			
		||||
function afterEnter(el: Element) {
 | 
			
		||||
	if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
	el.style.height = '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function leave(element: Element) {
 | 
			
		||||
	const el = element as HTMLElement;
 | 
			
		||||
function leave(el: Element) {
 | 
			
		||||
	if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
	const elementHeight = el.getBoundingClientRect().height;
 | 
			
		||||
	el.style.height = elementHeight + 'px';
 | 
			
		||||
	el.style.height = `${elementHeight}px`;
 | 
			
		||||
	el.offsetHeight; // reflow
 | 
			
		||||
	el.style.height = '0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function afterLeave(element: Element) {
 | 
			
		||||
	const el = element as HTMLElement;
 | 
			
		||||
	el.style.height = 'unset';
 | 
			
		||||
function afterLeave(el: Element) {
 | 
			
		||||
	if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
	el.style.height = '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
	function getParentBg(el?: HTMLElement | null): string {
 | 
			
		||||
		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();
 | 
			
		||||
	parentBg.value = getBgColor(rootEl.value?.parentElement);
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +110,7 @@ onMounted(() => {
 | 
			
		|||
	top: var(--MI-stickyTop, 0px);
 | 
			
		||||
	-webkit-backdrop-filter: var(--MI-blur, blur(8px));
 | 
			
		||||
	backdrop-filter: var(--MI-blur, blur(20px));
 | 
			
		||||
	background-color: color(from v-bind("parentBg ?? 'var(--bg)'") srgb r g b / 0.85);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.title {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,8 +56,9 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { nextTick, onMounted, shallowRef, ref } from 'vue';
 | 
			
		||||
import { nextTick, onMounted, ref, shallowRef } from 'vue';
 | 
			
		||||
import { defaultStore } from '@/store.js';
 | 
			
		||||
import { getBgColor } from '@/scripts/get-bg-color.js';
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(defineProps<{
 | 
			
		||||
	defaultOpen?: boolean;
 | 
			
		||||
| 
						 | 
				
			
			@ -69,40 +70,35 @@ const props = withDefaults(defineProps<{
 | 
			
		|||
	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 bgSame = ref(false);
 | 
			
		||||
const opened = 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;
 | 
			
		||||
	el.style.height = 0;
 | 
			
		||||
	el.style.height = '0';
 | 
			
		||||
	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) {
 | 
			
		||||
	el.style.height = null;
 | 
			
		||||
function afterEnter(el: Element) {
 | 
			
		||||
	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;
 | 
			
		||||
	el.style.height = elementHeight + 'px';
 | 
			
		||||
	el.style.height = `${elementHeight}px`;
 | 
			
		||||
	el.offsetHeight; // reflow
 | 
			
		||||
	el.style.height = 0;
 | 
			
		||||
	el.style.height = '0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function afterLeave(el) {
 | 
			
		||||
	el.style.height = null;
 | 
			
		||||
function afterLeave(el: Element) {
 | 
			
		||||
	if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
	el.style.height = '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function toggle() {
 | 
			
		||||
| 
						 | 
				
			
			@ -117,7 +113,7 @@ function toggle() {
 | 
			
		|||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
	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');
 | 
			
		||||
	bgSame.value = parentBg === myBg;
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,7 +53,7 @@ export type Tab = {
 | 
			
		|||
</script>
 | 
			
		||||
 | 
			
		||||
<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';
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(defineProps<{
 | 
			
		||||
| 
						 | 
				
			
			@ -120,14 +120,14 @@ function onTabWheel(ev: WheelEvent) {
 | 
			
		|||
 | 
			
		||||
let entering = false;
 | 
			
		||||
 | 
			
		||||
async function enter(element: Element) {
 | 
			
		||||
async function enter(el: Element) {
 | 
			
		||||
	if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
	entering = true;
 | 
			
		||||
	const el = element as HTMLElement;
 | 
			
		||||
	const elementWidth = el.getBoundingClientRect().width;
 | 
			
		||||
	el.style.width = '0';
 | 
			
		||||
	el.style.paddingLeft = '0';
 | 
			
		||||
	el.offsetWidth; // force reflow
 | 
			
		||||
	el.style.width = elementWidth + 'px';
 | 
			
		||||
	el.offsetWidth; // reflow
 | 
			
		||||
	el.style.width = `${elementWidth}px`;
 | 
			
		||||
	el.style.paddingLeft = '';
 | 
			
		||||
	nextTick(() => {
 | 
			
		||||
		entering = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -136,22 +136,23 @@ async function enter(element: Element) {
 | 
			
		|||
	setTimeout(renderTab, 170);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function afterEnter(element: Element) {
 | 
			
		||||
	//el.style.width = '';
 | 
			
		||||
function afterEnter(el: Element) {
 | 
			
		||||
	if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
	// element.style.width = '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function leave(element: Element) {
 | 
			
		||||
	const el = element as HTMLElement;
 | 
			
		||||
async function leave(el: Element) {
 | 
			
		||||
	if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
	const elementWidth = el.getBoundingClientRect().width;
 | 
			
		||||
	el.style.width = elementWidth + 'px';
 | 
			
		||||
	el.style.width = `${elementWidth}px`;
 | 
			
		||||
	el.style.paddingLeft = '';
 | 
			
		||||
	el.offsetWidth; // force reflow
 | 
			
		||||
	el.offsetWidth; // reflow
 | 
			
		||||
	el.style.width = '0';
 | 
			
		||||
	el.style.paddingLeft = '0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function afterLeave(element: Element) {
 | 
			
		||||
	const el = element as HTMLElement;
 | 
			
		||||
function afterLeave(el: Element) {
 | 
			
		||||
	if (!(el instanceof HTMLElement)) return;
 | 
			
		||||
	el.style.width = '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,19 +4,11 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
import { Directive } from 'vue';
 | 
			
		||||
import { getBgColor } from '@/scripts/get-bg-color.js';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	mounted(src, binding, vn) {
 | 
			
		||||
		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 parentBg = getBgColor(src.parentElement);
 | 
			
		||||
		const parentBg = getBgColor(src.parentElement) ?? 'transparent';
 | 
			
		||||
 | 
			
		||||
		const myBg = window.getComputedStyle(src).backgroundColor;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,19 +4,11 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
import { Directive } from 'vue';
 | 
			
		||||
import { getBgColor } from '@/scripts/get-bg-color.js';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	mounted(src, binding, vn) {
 | 
			
		||||
		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 parentBg = getBgColor(src.parentElement);
 | 
			
		||||
		const parentBg = getBgColor(src.parentElement) ?? 'transparent';
 | 
			
		||||
 | 
			
		||||
		const myBg = window.getComputedStyle(src).backgroundColor;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,19 +4,11 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
import { Directive } from 'vue';
 | 
			
		||||
import { getBgColor } from '@/scripts/get-bg-color.js';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	mounted(src, binding, vn) {
 | 
			
		||||
		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 parentBg = getBgColor(src.parentElement);
 | 
			
		||||
		const parentBg = getBgColor(src.parentElement) ?? 'transparent';
 | 
			
		||||
 | 
			
		||||
		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…
	
	Add table
		
		Reference in a new issue