refactor(client): use css modules
This commit is contained in:
		
							parent
							
								
									5e4e02235a
								
							
						
					
					
						commit
						ce528ff22e
					
				
					 4 changed files with 340 additions and 374 deletions
				
			
		|  | @ -1,17 +1,16 @@ | ||||||
| <template> | <template> | ||||||
| <div | <div :class="[$style.root, { [$style.rootIsMobile]: isMobile }]"> | ||||||
| 	class="mk-deck" :class="[{ isMobile }]" |  | ||||||
| > |  | ||||||
| 	<XSidebar v-if="!isMobile"/> | 	<XSidebar v-if="!isMobile"/> | ||||||
| 
 | 
 | ||||||
| 	<div class="main"> | 	<div :class="$style.main"> | ||||||
| 		<XStatusBars class="statusbars"/> | 		<XStatusBars/> | ||||||
| 		<div ref="columnsEl" class="columns" :class="deckStore.reactiveState.columnAlign.value" @contextmenu.self.prevent="onContextmenu"> | 		<div ref="columnsEl" :class="[$style.columns, deckStore.reactiveState.columnAlign.value]" @contextmenu.self.prevent="onContextmenu"> | ||||||
| 			<template v-for="ids in layout"> | 			<template v-for="ids in layout"> | ||||||
| 				<!-- sectionを利用しているのは、deck.vue側でcolumnに対してfirst-of-typeを効かせるため --> | 				<!-- sectionを利用しているのは、deck.vue側でcolumnに対してfirst-of-typeを効かせるため --> | ||||||
| 				<section | 				<section | ||||||
| 					v-if="ids.length > 1" | 					v-if="ids.length > 1" | ||||||
| 					class="folder column" | 					:class="$style.column" | ||||||
|  | 					class="folder" | ||||||
| 					:style="columns.filter(c => ids.includes(c.id)).some(c => c.flexible) ? { flex: 1, minWidth: '350px' } : { width: Math.max(...columns.filter(c => ids.includes(c.id)).map(c => c.width)) + 'px' }" | 					:style="columns.filter(c => ids.includes(c.id)).some(c => c.flexible) ? { flex: 1, minWidth: '350px' } : { width: Math.max(...columns.filter(c => ids.includes(c.id)).map(c => c.width)) + 'px' }" | ||||||
| 				> | 				> | ||||||
| 					<DeckColumnCore v-for="id in ids" :ref="id" :key="id" :column="columns.find(c => c.id === id)" :is-stacked="true" @parent-focus="moveFocus(id, $event)"/> | 					<DeckColumnCore v-for="id in ids" :ref="id" :key="id" :column="columns.find(c => c.id === id)" :is-stacked="true" @parent-focus="moveFocus(id, $event)"/> | ||||||
|  | @ -20,44 +19,45 @@ | ||||||
| 					v-else | 					v-else | ||||||
| 					:ref="ids[0]" | 					:ref="ids[0]" | ||||||
| 					:key="ids[0]" | 					:key="ids[0]" | ||||||
| 					class="column" | 					:class="$style.column" | ||||||
| 					:column="columns.find(c => c.id === ids[0])" | 					:column="columns.find(c => c.id === ids[0])" | ||||||
| 					:is-stacked="false" | 					:is-stacked="false" | ||||||
| 					:style="columns.find(c => c.id === ids[0])!.flexible ? { flex: 1, minWidth: '350px' } : { width: columns.find(c => c.id === ids[0])!.width + 'px' }" | 					:style="columns.find(c => c.id === ids[0])!.flexible ? { flex: 1, minWidth: '350px' } : { width: columns.find(c => c.id === ids[0])!.width + 'px' }" | ||||||
| 					@parent-focus="moveFocus(ids[0], $event)" | 					@parent-focus="moveFocus(ids[0], $event)" | ||||||
| 				/> | 				/> | ||||||
| 			</template> | 			</template> | ||||||
| 			<div v-if="layout.length === 0" class="intro _panel"> | 			<div v-if="layout.length === 0" class="_panel" :class="$style.onboarding"> | ||||||
| 				<div>{{ i18n.ts._deck.introduction }}</div> | 				<div>{{ i18n.ts._deck.introduction }}</div> | ||||||
| 				<MkButton primary class="add" @click="addColumn">{{ i18n.ts._deck.addColumn }}</MkButton> | 				<MkButton primary style="margin: 1em auto;" @click="addColumn">{{ i18n.ts._deck.addColumn }}</MkButton> | ||||||
| 				<div>{{ i18n.ts._deck.introduction2 }}</div> | 				<div>{{ i18n.ts._deck.introduction2 }}</div> | ||||||
| 			</div> | 			</div> | ||||||
| 			<div class="sideMenu"> | 			<div :class="$style.sideMenu"> | ||||||
| 				<div class="top"> | 				<div :class="$style.sideMenuTop"> | ||||||
| 					<button v-tooltip.noDelay.left="`${i18n.ts._deck.profile}: ${deckStore.state.profile}`" class="_button button" @click="changeProfile"><i class="ti ti-caret-down"></i></button> | 					<button v-tooltip.noDelay.left="`${i18n.ts._deck.profile}: ${deckStore.state.profile}`" :class="$style.sideMenuButton" class="_button" @click="changeProfile"><i class="ti ti-caret-down"></i></button> | ||||||
| 					<button v-tooltip.noDelay.left="i18n.ts._deck.deleteProfile" class="_button button" @click="deleteProfile"><i class="ti ti-trash"></i></button> | 					<button v-tooltip.noDelay.left="i18n.ts._deck.deleteProfile" :class="$style.sideMenuButton" class="_button" @click="deleteProfile"><i class="ti ti-trash"></i></button> | ||||||
| 				</div> | 				</div> | ||||||
| 				<div class="middle"> | 				<div :class="$style.sideMenuMiddle"> | ||||||
| 					<button v-tooltip.noDelay.left="i18n.ts._deck.addColumn" class="_button button" @click="addColumn"><i class="ti ti-plus"></i></button> | 					<button v-tooltip.noDelay.left="i18n.ts._deck.addColumn" :class="$style.sideMenuButton" class="_button" @click="addColumn"><i class="ti ti-plus"></i></button> | ||||||
| 				</div> | 				</div> | ||||||
| 				<div class="bottom"> | 				<div :class="$style.sideMenuBottom"> | ||||||
| 					<button v-tooltip.noDelay.left="i18n.ts.settings" class="_button button settings" @click="showSettings"><i class="ti ti-settings"></i></button> | 					<button v-tooltip.noDelay.left="i18n.ts.settings" :class="$style.sideMenuButton" class="_button" @click="showSettings"><i class="ti ti-settings"></i></button> | ||||||
| 				</div> | 				</div> | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| 
 | 
 | ||||||
| 	<div v-if="isMobile" class="buttons"> | 	<div v-if="isMobile" :class="$style.nav"> | ||||||
| 		<button class="button nav _button" @click="drawerMenuShowing = true"><i class="icon ti ti-menu-2"></i><span v-if="menuIndicated" class="indicator"><i class="_indicatorCircle"></i></span></button> | 		<button :class="$style.navButton" class="_button" @click="drawerMenuShowing = true"><i :class="$style.navButtonIcon" class="ti ti-menu-2"></i><span v-if="menuIndicated" :class="$style.navButtonIndicator"><i class="_indicatorCircle"></i></span></button> | ||||||
| 		<button class="button home _button" @click="mainRouter.push('/')"><i class="icon ti ti-home"></i></button> | 		<button :class="$style.navButton" class="_button" @click="mainRouter.push('/')"><i :class="$style.navButtonIcon" class="ti ti-home"></i></button> | ||||||
| 		<button class="button notifications _button" @click="mainRouter.push('/my/notifications')"><i class="icon ti ti-bell"></i><span v-if="$i?.hasUnreadNotification" class="indicator"><i class="_indicatorCircle"></i></span></button> | 		<button :class="$style.navButton" class="_button" @click="mainRouter.push('/my/notifications')"><i :class="$style.navButtonIcon" class="ti ti-bell"></i><span v-if="$i?.hasUnreadNotification" :class="$style.navButtonIndicator"><i class="_indicatorCircle"></i></span></button> | ||||||
| 		<button class="button post _button" @click="os.post()"><i class="icon ti ti-pencil"></i></button> | 		<button :class="$style.navButton" class="_button post" @click="os.post()"><i :class="$style.navButtonIcon" class="ti ti-pencil"></i></button> | ||||||
| 	</div> | 	</div> | ||||||
| 
 | 
 | ||||||
| 	<Transition :name="$store.state.animation ? 'menu-back' : ''"> | 	<Transition :name="$store.state.animation ? 'menu-back' : ''"> | ||||||
| 		<div | 		<div | ||||||
| 			v-if="drawerMenuShowing" | 			v-if="drawerMenuShowing" | ||||||
| 			class="menu-back _modalBg" | 			:class="$style.menuBg" | ||||||
|  | 			class="_modalBg" | ||||||
| 			@click="drawerMenuShowing = false" | 			@click="drawerMenuShowing = false" | ||||||
| 			@touchstart.passive="drawerMenuShowing = false" | 			@touchstart.passive="drawerMenuShowing = false" | ||||||
| 		></div> | 		></div> | ||||||
|  | @ -245,8 +245,10 @@ async function deleteProfile() { | ||||||
| .menu-back-leave-active { | .menu-back-leave-active { | ||||||
| 	opacity: 0; | 	opacity: 0; | ||||||
| } | } | ||||||
|  | </style> | ||||||
| 
 | 
 | ||||||
| .mk-deck { | <style lang="scss" module> | ||||||
|  | .root { | ||||||
| 	$nav-hide-threshold: 650px; // TODO: どこかに集約したい | 	$nav-hide-threshold: 650px; // TODO: どこかに集約したい | ||||||
| 
 | 
 | ||||||
| 	--margin: var(--marginHalf); | 	--margin: var(--marginHalf); | ||||||
|  | @ -257,170 +259,164 @@ async function deleteProfile() { | ||||||
| 	height: 100dvh; | 	height: 100dvh; | ||||||
| 	box-sizing: border-box; | 	box-sizing: border-box; | ||||||
| 	flex: 1; | 	flex: 1; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 	&.isMobile { | .rootIsMobile { | ||||||
| 		padding-bottom: 100px; | 	padding-bottom: 100px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .main { | ||||||
|  | 	flex: 1; | ||||||
|  | 	min-width: 0; | ||||||
|  | 	display: flex; | ||||||
|  | 	flex-direction: column; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .columns { | ||||||
|  | 	flex: 1; | ||||||
|  | 	display: flex; | ||||||
|  | 	overflow-x: auto; | ||||||
|  | 	overflow-y: clip; | ||||||
|  | 
 | ||||||
|  | 	&.center { | ||||||
|  | 		> .column:first-of-type { | ||||||
|  | 			margin-left: auto; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		> .column:last-of-type { | ||||||
|  | 			margin-right: auto; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .column { | ||||||
|  | 	flex-shrink: 0; | ||||||
|  | 	border-right: solid var(--deckDividerThickness) var(--deckDivider); | ||||||
|  | 
 | ||||||
|  | 	&:first-of-type { | ||||||
|  | 		border-left: solid var(--deckDividerThickness) var(--deckDivider); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	> .main { | 	&.folder { | ||||||
| 		flex: 1; |  | ||||||
| 		min-width: 0; |  | ||||||
| 		display: flex; | 		display: flex; | ||||||
| 		flex-direction: column; | 		flex-direction: column; | ||||||
| 
 | 
 | ||||||
| 		> .columns { | 		> *:not(:last-of-type) { | ||||||
| 			flex: 1; | 			border-bottom: solid var(--deckDividerThickness) var(--deckDivider); | ||||||
| 			display: flex; |  | ||||||
| 			overflow-x: auto; |  | ||||||
| 			overflow-y: clip; |  | ||||||
| 
 |  | ||||||
| 			&.center { |  | ||||||
| 				> .column:first-of-type { |  | ||||||
| 					margin-left: auto; |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				> .column:last-of-type { |  | ||||||
| 					margin-right: auto; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			> .column { |  | ||||||
| 				flex-shrink: 0; |  | ||||||
| 				border-right: solid var(--deckDividerThickness) var(--deckDivider); |  | ||||||
| 
 |  | ||||||
| 				&:first-of-type { |  | ||||||
| 					border-left: solid var(--deckDividerThickness) var(--deckDivider); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				&.folder { |  | ||||||
| 					display: flex; |  | ||||||
| 					flex-direction: column; |  | ||||||
| 
 |  | ||||||
| 					> *:not(:last-of-type) { |  | ||||||
| 						border-bottom: solid var(--deckDividerThickness) var(--deckDivider); |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			> .intro { |  | ||||||
| 				padding: 32px; |  | ||||||
| 				height: min-content; |  | ||||||
| 				text-align: center; |  | ||||||
| 				margin: auto; |  | ||||||
| 
 |  | ||||||
| 				> .add { |  | ||||||
| 					margin: 1em auto; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			> .sideMenu { |  | ||||||
| 				flex-shrink: 0; |  | ||||||
| 				margin-right: 0; |  | ||||||
| 				margin-left: auto; |  | ||||||
| 				display: flex; |  | ||||||
| 				flex-direction: column; |  | ||||||
| 				justify-content: center; |  | ||||||
| 				width: 32px; |  | ||||||
| 
 |  | ||||||
| 				> .top, > .middle, > .bottom { |  | ||||||
| 					> .button { |  | ||||||
| 						display: block; |  | ||||||
| 						width: 100%; |  | ||||||
| 						aspect-ratio: 1; |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				> .top { |  | ||||||
| 					margin-bottom: auto; |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				> .middle { |  | ||||||
| 					margin-top: auto; |  | ||||||
| 					margin-bottom: auto; |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				> .bottom { |  | ||||||
| 					margin-top: auto; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | } | ||||||
| 	> .buttons { | 
 | ||||||
| 		position: fixed; | .onboarding { | ||||||
| 		z-index: 1000; | 	padding: 32px; | ||||||
| 		bottom: 0; | 	height: min-content; | ||||||
| 		left: 0; | 	text-align: center; | ||||||
| 		padding: 12px 12px max(12px, env(safe-area-inset-bottom, 0px)) 12px; | 	margin: auto; | ||||||
| 		display: grid; | } | ||||||
| 		grid-template-columns: 1fr 1fr 1fr 1fr; | 
 | ||||||
| 		grid-gap: 8px; | .sideMenu { | ||||||
| 		width: 100%; | 	flex-shrink: 0; | ||||||
| 		box-sizing: border-box; | 	margin-right: 0; | ||||||
| 		-webkit-backdrop-filter: var(--blur, blur(32px)); | 	margin-left: auto; | ||||||
| 		backdrop-filter: var(--blur, blur(32px)); | 	display: flex; | ||||||
| 		background-color: var(--header); | 	flex-direction: column; | ||||||
| 		border-top: solid 0.5px var(--divider); | 	justify-content: center; | ||||||
| 
 | 	width: 32px; | ||||||
| 		> .button { | } | ||||||
| 			position: relative; | 
 | ||||||
| 			padding: 0; | .sideMenuButton { | ||||||
| 			aspect-ratio: 1; | 	display: block; | ||||||
| 			width: 100%; | 	width: 100%; | ||||||
| 			max-width: 60px; | 	aspect-ratio: 1; | ||||||
| 			margin: auto; | } | ||||||
| 			border-radius: 100%; | 
 | ||||||
| 			background: var(--panel); | .sideMenuTop { | ||||||
| 			color: var(--fg); | 	margin-bottom: auto; | ||||||
| 
 | } | ||||||
| 			&:hover { | 
 | ||||||
| 				background: var(--X2); | .sideMenuMiddle { | ||||||
| 			} | 	margin-top: auto; | ||||||
| 
 | 	margin-bottom: auto; | ||||||
| 			> .indicator { | } | ||||||
| 				position: absolute; | 
 | ||||||
| 				top: 0; | .sideMenuBottom { | ||||||
| 				left: 0; | 	margin-top: auto; | ||||||
| 				color: var(--indicator); | } | ||||||
| 				font-size: 16px; | 
 | ||||||
| 				animation: blink 1s infinite; | .menuBg { | ||||||
| 			} | 	z-index: 1001; | ||||||
| 
 | } | ||||||
| 			> .icon { | 
 | ||||||
| 				font-size: 18px; | .menu { | ||||||
| 			} | 	position: fixed; | ||||||
| 
 | 	top: 0; | ||||||
| 			&:disabled { | 	left: 0; | ||||||
| 				cursor: default; | 	z-index: 1001; | ||||||
| 
 | 	height: 100dvh; | ||||||
| 				> .icon { | 	width: 240px; | ||||||
| 					opacity: 0.5; | 	box-sizing: border-box; | ||||||
| 				} | 	contain: strict; | ||||||
| 			} | 	overflow: auto; | ||||||
| 
 | 	overscroll-behavior: contain; | ||||||
| 			&.post { | 	background: var(--navBg); | ||||||
| 				background: linear-gradient(90deg, var(--buttonGradateA), var(--buttonGradateB)); | } | ||||||
| 				color: var(--fgOnAccent); | 
 | ||||||
| 			} | .nav { | ||||||
| 		} | 	position: fixed; | ||||||
| 	} | 	z-index: 1000; | ||||||
| 
 | 	bottom: 0; | ||||||
| 	> .menu-back { | 	left: 0; | ||||||
| 		z-index: 1001; | 	padding: 12px 12px max(12px, env(safe-area-inset-bottom, 0px)) 12px; | ||||||
| 	} | 	display: grid; | ||||||
| 
 | 	grid-template-columns: 1fr 1fr 1fr 1fr; | ||||||
| 	> .menu { | 	grid-gap: 8px; | ||||||
| 		position: fixed; | 	width: 100%; | ||||||
| 		top: 0; | 	box-sizing: border-box; | ||||||
| 		left: 0; | 	-webkit-backdrop-filter: var(--blur, blur(32px)); | ||||||
| 		z-index: 1001; | 	backdrop-filter: var(--blur, blur(32px)); | ||||||
| 		height: 100dvh; | 	background-color: var(--header); | ||||||
| 		width: 240px; | 	border-top: solid 0.5px var(--divider); | ||||||
| 		box-sizing: border-box; | } | ||||||
| 		contain: strict; | 
 | ||||||
| 		overflow: auto; | .navButton { | ||||||
| 		overscroll-behavior: contain; | 	position: relative; | ||||||
| 		background: var(--navBg); | 	padding: 0; | ||||||
| 	} | 	aspect-ratio: 1; | ||||||
|  | 	width: 100%; | ||||||
|  | 	max-width: 60px; | ||||||
|  | 	margin: auto; | ||||||
|  | 	border-radius: 100%; | ||||||
|  | 	background: var(--panel); | ||||||
|  | 	color: var(--fg); | ||||||
|  | 
 | ||||||
|  | 	&:hover { | ||||||
|  | 		background: var(--X2); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	&:disabled { | ||||||
|  | 		cursor: default; | ||||||
|  | 
 | ||||||
|  | 		> .navButtonIcon { | ||||||
|  | 			opacity: 0.5; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	&.post { | ||||||
|  | 		background: linear-gradient(90deg, var(--buttonGradateA), var(--buttonGradateB)); | ||||||
|  | 		color: var(--fgOnAccent); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .navButtonIcon { | ||||||
|  | 	font-size: 18px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .navButtonIndicator { | ||||||
|  | 	position: absolute; | ||||||
|  | 	top: 0; | ||||||
|  | 	left: 0; | ||||||
|  | 	color: var(--indicator); | ||||||
|  | 	font-size: 16px; | ||||||
|  | 	animation: blink 1s infinite; | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ | ||||||
| 	@drop.prevent.stop="onDrop" | 	@drop.prevent.stop="onDrop" | ||||||
| > | > | ||||||
| 	<header | 	<header | ||||||
| 		:class="[$style.header, { [$style.indicated]: indicated }]" | 		:class="[$style.header]" | ||||||
| 		draggable="true" | 		draggable="true" | ||||||
| 		@click="goTop" | 		@click="goTop" | ||||||
| 		@dragstart="onDragstart" | 		@dragstart="onDragstart" | ||||||
|  | @ -43,12 +43,10 @@ const props = withDefaults(defineProps<{ | ||||||
| 	column: Column; | 	column: Column; | ||||||
| 	isStacked?: boolean; | 	isStacked?: boolean; | ||||||
| 	naked?: boolean; | 	naked?: boolean; | ||||||
| 	indicated?: boolean; |  | ||||||
| 	menu?: MenuItem[]; | 	menu?: MenuItem[]; | ||||||
| }>(), { | }>(), { | ||||||
| 	isStacked: false, | 	isStacked: false, | ||||||
| 	naked: false, | 	naked: false, | ||||||
| 	indicated: false, |  | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits<{ | const emit = defineEmits<{ | ||||||
|  | @ -289,10 +287,6 @@ function onDrop(ev) { | ||||||
| 	&:not(.active) { | 	&:not(.active) { | ||||||
| 		flex-basis: var(--deckColumnHeaderHeight); | 		flex-basis: var(--deckColumnHeaderHeight); | ||||||
| 		min-height: var(--deckColumnHeaderHeight); | 		min-height: var(--deckColumnHeaderHeight); | ||||||
| 
 |  | ||||||
| 		> .header.indicated { |  | ||||||
| 			box-shadow: 4px 0px var(--accent) inset; |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	&.naked { | 	&.naked { | ||||||
|  | @ -328,10 +322,6 @@ function onDrop(ev) { | ||||||
| 	&, * { | 	&, * { | ||||||
| 		user-select: none; | 		user-select: none; | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	&.indicated { |  | ||||||
| 		box-shadow: 0 3px 0 0 var(--accent); |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .title { | .title { | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| <template> | <template> | ||||||
| <XColumn :menu="menu" :column="column" :is-stacked="isStacked" :indicated="indicated" @change-active-state="onChangeActiveState" @parent-focus="$event => emit('parent-focus', $event)"> | <XColumn :menu="menu" :column="column" :is-stacked="isStacked" @parent-focus="$event => emit('parent-focus', $event)"> | ||||||
| 	<template #header> | 	<template #header> | ||||||
| 		<i v-if="column.tl === 'home'" class="ti ti-home"></i> | 		<i v-if="column.tl === 'home'" class="ti ti-home"></i> | ||||||
| 		<i v-else-if="column.tl === 'local'" class="ti ti-planet"></i> | 		<i v-else-if="column.tl === 'local'" class="ti ti-planet"></i> | ||||||
|  | @ -15,7 +15,7 @@ | ||||||
| 		</p> | 		</p> | ||||||
| 		<p class="desc">{{ $t('disabled-timeline.description') }}</p> | 		<p class="desc">{{ $t('disabled-timeline.description') }}</p> | ||||||
| 	</div> | 	</div> | ||||||
| 	<XTimeline v-else-if="column.tl" ref="timeline" :key="column.tl" :src="column.tl" @after="() => emit('loaded')" @queue="queueUpdated" @note="onNote"/> | 	<XTimeline v-else-if="column.tl" ref="timeline" :key="column.tl" :src="column.tl" @after="() => emit('loaded')"/> | ||||||
| </XColumn> | </XColumn> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
|  | @ -40,8 +40,6 @@ const emit = defineEmits<{ | ||||||
| }>(); | }>(); | ||||||
| 
 | 
 | ||||||
| let disabled = $ref(false); | let disabled = $ref(false); | ||||||
| let indicated = $ref(false); |  | ||||||
| let columnActive = $ref(true); |  | ||||||
| 
 | 
 | ||||||
| onMounted(() => { | onMounted(() => { | ||||||
| 	if (props.column.tl == null) { | 	if (props.column.tl == null) { | ||||||
|  | @ -77,26 +75,6 @@ async function setType() { | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function queueUpdated(q) { |  | ||||||
| 	if (columnActive) { |  | ||||||
| 		indicated = q !== 0; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function onNote() { |  | ||||||
| 	if (!columnActive) { |  | ||||||
| 		indicated = true; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function onChangeActiveState(state) { |  | ||||||
| 	columnActive = state; |  | ||||||
| 
 |  | ||||||
| 	if (columnActive) { |  | ||||||
| 		indicated = false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const menu = [{ | const menu = [{ | ||||||
| 	icon: 'ti ti-pencil', | 	icon: 'ti ti-pencil', | ||||||
| 	text: i18n.ts.timeline, | 	text: i18n.ts.timeline, | ||||||
|  |  | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <template> | <template> | ||||||
| <div class="dkgtipfy" :class="{ wallpaper }"> | <div :class="[$style.root, { [$style.withWallpaper]: wallpaper }]"> | ||||||
| 	<XSidebar v-if="!isMobile" class="sidebar"/> | 	<XSidebar v-if="!isMobile" :class="$style.sidebar"/> | ||||||
| 
 | 
 | ||||||
| 	<MkStickyContainer class="contents"> | 	<MkStickyContainer :class="$style.contents"> | ||||||
| 		<template #header><XStatusBars :class="$style.statusbars"/></template> | 		<template #header><XStatusBars :class="$style.statusbars"/></template> | ||||||
| 		<main style="min-width: 0;" :style="{ background: pageMetadata?.value?.bg }" @contextmenu.stop="onContextmenu"> | 		<main style="min-width: 0;" :style="{ background: pageMetadata?.value?.bg }" @contextmenu.stop="onContextmenu"> | ||||||
| 			<div :class="$style.content" style="container-type: inline-size;"> | 			<div :class="$style.content" style="container-type: inline-size;"> | ||||||
|  | @ -12,44 +12,46 @@ | ||||||
| 		</main> | 		</main> | ||||||
| 	</MkStickyContainer> | 	</MkStickyContainer> | ||||||
| 
 | 
 | ||||||
| 	<div v-if="isDesktop" ref="widgetsEl" class="widgets"> | 	<div v-if="isDesktop" ref="widgetsEl" :class="$style.widgets"> | ||||||
| 		<XWidgets @mounted="attachSticky"/> | 		<XWidgets @mounted="attachSticky"/> | ||||||
| 	</div> | 	</div> | ||||||
| 
 | 
 | ||||||
| 	<button v-if="!isDesktop && !isMobile" class="widgetButton _button" @click="widgetsShowing = true"><i class="ti ti-apps"></i></button> | 	<button v-if="!isDesktop && !isMobile" :class="$style.widgetButton" class="_button" @click="widgetsShowing = true"><i class="ti ti-apps"></i></button> | ||||||
| 
 | 
 | ||||||
| 	<div v-if="isMobile" class="buttons"> | 	<div v-if="isMobile" :class="$style.nav"> | ||||||
| 		<button class="button nav _button" @click="drawerMenuShowing = true"><i class="icon ti ti-menu-2"></i><span v-if="menuIndicated" class="indicator"><i class="_indicatorCircle"></i></span></button> | 		<button :class="$style.navButton" class="_button" @click="drawerMenuShowing = true"><i :class="$style.navButtonIcon" class="ti ti-menu-2"></i><span v-if="menuIndicated" :class="$style.navButtonIndicator"><i class="_indicatorCircle"></i></span></button> | ||||||
| 		<button class="button home _button" @click="mainRouter.currentRoute.value.name === 'index' ? top() : mainRouter.push('/')"><i class="icon ti ti-home"></i></button> | 		<button :class="$style.navButton" class="_button" @click="mainRouter.currentRoute.value.name === 'index' ? top() : mainRouter.push('/')"><i :class="$style.navButtonIcon" class="ti ti-home"></i></button> | ||||||
| 		<button class="button notifications _button" @click="mainRouter.push('/my/notifications')"><i class="icon ti ti-bell"></i><span v-if="$i?.hasUnreadNotification" class="indicator"><i class="_indicatorCircle"></i></span></button> | 		<button :class="$style.navButton" class="_button" @click="mainRouter.push('/my/notifications')"><i :class="$style.navButtonIcon" class="ti ti-bell"></i><span v-if="$i?.hasUnreadNotification" :class="$style.navButtonIndicator"><i class="_indicatorCircle"></i></span></button> | ||||||
| 		<button class="button widget _button" @click="widgetsShowing = true"><i class="icon ti ti-apps"></i></button> | 		<button :class="$style.navButton" class="_button" @click="widgetsShowing = true"><i :class="$style.navButtonIcon" class="ti ti-apps"></i></button> | ||||||
| 		<button class="button post _button" @click="os.post()"><i class="icon ti ti-pencil"></i></button> | 		<button :class="$style.navButton" class="_button post" @click="os.post()"><i :class="$style.navButtonIcon" class="ti ti-pencil"></i></button> | ||||||
| 	</div> | 	</div> | ||||||
| 
 | 
 | ||||||
| 	<Transition :name="$store.state.animation ? 'menuDrawer-back' : ''"> | 	<Transition :name="$store.state.animation ? 'menuDrawer-back' : ''"> | ||||||
| 		<div | 		<div | ||||||
| 			v-if="drawerMenuShowing" | 			v-if="drawerMenuShowing" | ||||||
| 			class="menuDrawer-back _modalBg" | 			:class="$style.menuDrawerBg" | ||||||
|  | 			class="_modalBg" | ||||||
| 			@click="drawerMenuShowing = false" | 			@click="drawerMenuShowing = false" | ||||||
| 			@touchstart.passive="drawerMenuShowing = false" | 			@touchstart.passive="drawerMenuShowing = false" | ||||||
| 		></div> | 		></div> | ||||||
| 	</Transition> | 	</Transition> | ||||||
| 
 | 
 | ||||||
| 	<Transition :name="$store.state.animation ? 'menuDrawer' : ''"> | 	<Transition :name="$store.state.animation ? 'menuDrawer' : ''"> | ||||||
| 		<XDrawerMenu v-if="drawerMenuShowing" class="menuDrawer"/> | 		<XDrawerMenu v-if="drawerMenuShowing" :class="$style.menuDrawer"/> | ||||||
| 	</Transition> | 	</Transition> | ||||||
| 
 | 
 | ||||||
| 	<Transition :name="$store.state.animation ? 'widgetsDrawer-back' : ''"> | 	<Transition :name="$store.state.animation ? 'widgetsDrawer-back' : ''"> | ||||||
| 		<div | 		<div | ||||||
| 			v-if="widgetsShowing" | 			v-if="widgetsShowing" | ||||||
| 			class="widgetsDrawer-back _modalBg" | 			:class="$style.widgetsDrawerBg" | ||||||
|  | 			class="_modalBg" | ||||||
| 			@click="widgetsShowing = false" | 			@click="widgetsShowing = false" | ||||||
| 			@touchstart.passive="widgetsShowing = false" | 			@touchstart.passive="widgetsShowing = false" | ||||||
| 		></div> | 		></div> | ||||||
| 	</Transition> | 	</Transition> | ||||||
| 
 | 
 | ||||||
| 	<Transition :name="$store.state.animation ? 'widgetsDrawer' : ''"> | 	<Transition :name="$store.state.animation ? 'widgetsDrawer' : ''"> | ||||||
| 		<XWidgets v-if="widgetsShowing" class="widgetsDrawer"/> | 		<XWidgets v-if="widgetsShowing" :class="$style.widgetsDrawer"/> | ||||||
| 	</Transition> | 	</Transition> | ||||||
| 
 | 
 | ||||||
| 	<XCommon/> | 	<XCommon/> | ||||||
|  | @ -218,151 +220,151 @@ const wallpaper = miLocalStorage.getItem('wallpaper') != null; | ||||||
| .menuDrawer-back-leave-active { | .menuDrawer-back-leave-active { | ||||||
| 	opacity: 0; | 	opacity: 0; | ||||||
| } | } | ||||||
| 
 |  | ||||||
| .dkgtipfy { |  | ||||||
| 	$ui-font-size: 1em; // TODO: どこかに集約したい |  | ||||||
| 	$widgets-hide-threshold: 1090px; |  | ||||||
| 
 |  | ||||||
| 	min-height: 100dvh; |  | ||||||
| 	box-sizing: border-box; |  | ||||||
| 	display: flex; |  | ||||||
| 
 |  | ||||||
| 	&.wallpaper { |  | ||||||
| 		background: var(--wallpaperOverlay); |  | ||||||
| 		//backdrop-filter: var(--blur, blur(4px)); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	> .sidebar { |  | ||||||
| 		border-right: solid 0.5px var(--divider); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	> .contents { |  | ||||||
| 		width: 100%; |  | ||||||
| 		min-width: 0; |  | ||||||
| 		background: var(--bg); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	> .widgets { |  | ||||||
| 		padding: 0 var(--margin); |  | ||||||
| 		border-left: solid 0.5px var(--divider); |  | ||||||
| 		background: var(--bg); |  | ||||||
| 
 |  | ||||||
| 		@media (max-width: $widgets-hide-threshold) { |  | ||||||
| 			display: none; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	> .widgetButton { |  | ||||||
| 		display: block; |  | ||||||
| 		position: fixed; |  | ||||||
| 		z-index: 1000; |  | ||||||
| 		bottom: 32px; |  | ||||||
| 		right: 32px; |  | ||||||
| 		width: 64px; |  | ||||||
| 		height: 64px; |  | ||||||
| 		border-radius: 100%; |  | ||||||
| 		box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12); |  | ||||||
| 		font-size: 22px; |  | ||||||
| 		background: var(--panel); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	> .widgetsDrawer-back { |  | ||||||
| 		z-index: 1001; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	> .widgetsDrawer { |  | ||||||
| 		position: fixed; |  | ||||||
| 		top: 0; |  | ||||||
| 		right: 0; |  | ||||||
| 		z-index: 1001; |  | ||||||
| 		height: 100dvh; |  | ||||||
| 		padding: var(--margin) !important; |  | ||||||
| 		box-sizing: border-box; |  | ||||||
| 		overflow: auto; |  | ||||||
| 		overscroll-behavior: contain; |  | ||||||
| 		background: var(--bg); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	> .buttons { |  | ||||||
| 		position: fixed; |  | ||||||
| 		z-index: 1000; |  | ||||||
| 		bottom: 0; |  | ||||||
| 		left: 0; |  | ||||||
| 		padding: 12px 12px max(12px, env(safe-area-inset-bottom, 0px)) 12px; |  | ||||||
| 		display: grid; |  | ||||||
| 		grid-template-columns: 1fr 1fr 1fr 1fr 1fr; |  | ||||||
| 		grid-gap: 8px; |  | ||||||
| 		width: 100%; |  | ||||||
| 		box-sizing: border-box; |  | ||||||
| 		-webkit-backdrop-filter: var(--blur, blur(32px)); |  | ||||||
| 		backdrop-filter: var(--blur, blur(32px)); |  | ||||||
| 		background-color: var(--header); |  | ||||||
| 		border-top: solid 0.5px var(--divider); |  | ||||||
| 
 |  | ||||||
| 		> .button { |  | ||||||
| 			position: relative; |  | ||||||
| 			padding: 0; |  | ||||||
| 			aspect-ratio: 1; |  | ||||||
| 			width: 100%; |  | ||||||
| 			max-width: 60px; |  | ||||||
| 			margin: auto; |  | ||||||
| 			border-radius: 100%; |  | ||||||
| 			background: var(--panel); |  | ||||||
| 			color: var(--fg); |  | ||||||
| 
 |  | ||||||
| 			&:hover { |  | ||||||
| 				background: var(--X2); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			> .indicator { |  | ||||||
| 				position: absolute; |  | ||||||
| 				top: 0; |  | ||||||
| 				left: 0; |  | ||||||
| 				color: var(--indicator); |  | ||||||
| 				font-size: 16px; |  | ||||||
| 				animation: blink 1s infinite; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			> .icon { |  | ||||||
| 				font-size: 18px; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			&:disabled { |  | ||||||
| 				cursor: default; |  | ||||||
| 
 |  | ||||||
| 				> .icon { |  | ||||||
| 					opacity: 0.5; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			&.post { |  | ||||||
| 				background: linear-gradient(90deg, var(--buttonGradateA), var(--buttonGradateB)); |  | ||||||
| 				color: var(--fgOnAccent); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	> .menuDrawer-back { |  | ||||||
| 		z-index: 1001; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	> .menuDrawer { |  | ||||||
| 		position: fixed; |  | ||||||
| 		top: 0; |  | ||||||
| 		left: 0; |  | ||||||
| 		z-index: 1001; |  | ||||||
| 		height: 100dvh; |  | ||||||
| 		width: 240px; |  | ||||||
| 		box-sizing: border-box; |  | ||||||
| 		contain: strict; |  | ||||||
| 		overflow: auto; |  | ||||||
| 		overscroll-behavior: contain; |  | ||||||
| 		background: var(--navBg); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| </style> | </style> | ||||||
| 
 | 
 | ||||||
| <style lang="scss" module> | <style lang="scss" module> | ||||||
|  | $ui-font-size: 1em; // TODO: どこかに集約したい | ||||||
|  | $widgets-hide-threshold: 1090px; | ||||||
|  | 
 | ||||||
|  | .root { | ||||||
|  | 	min-height: 100dvh; | ||||||
|  | 	box-sizing: border-box; | ||||||
|  | 	display: flex; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .withWallpaper { | ||||||
|  | 	background: var(--wallpaperOverlay); | ||||||
|  | 	//backdrop-filter: var(--blur, blur(4px)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .sidebar { | ||||||
|  | 	border-right: solid 0.5px var(--divider); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .contents { | ||||||
|  | 	width: 100%; | ||||||
|  | 	min-width: 0; | ||||||
|  | 	background: var(--bg); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .widgets { | ||||||
|  | 	padding: 0 var(--margin); | ||||||
|  | 	border-left: solid 0.5px var(--divider); | ||||||
|  | 	background: var(--bg); | ||||||
|  | 
 | ||||||
|  | 	@media (max-width: $widgets-hide-threshold) { | ||||||
|  | 		display: none; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .widgetButton { | ||||||
|  | 	display: block; | ||||||
|  | 	position: fixed; | ||||||
|  | 	z-index: 1000; | ||||||
|  | 	bottom: 32px; | ||||||
|  | 	right: 32px; | ||||||
|  | 	width: 64px; | ||||||
|  | 	height: 64px; | ||||||
|  | 	border-radius: 100%; | ||||||
|  | 	box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12); | ||||||
|  | 	font-size: 22px; | ||||||
|  | 	background: var(--panel); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .widgetsDrawerBg { | ||||||
|  | 	z-index: 1001; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .widgetsDrawer { | ||||||
|  | 	position: fixed; | ||||||
|  | 	top: 0; | ||||||
|  | 	right: 0; | ||||||
|  | 	z-index: 1001; | ||||||
|  | 	height: 100dvh; | ||||||
|  | 	padding: var(--margin) !important; | ||||||
|  | 	box-sizing: border-box; | ||||||
|  | 	overflow: auto; | ||||||
|  | 	overscroll-behavior: contain; | ||||||
|  | 	background: var(--bg); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .nav { | ||||||
|  | 	position: fixed; | ||||||
|  | 	z-index: 1000; | ||||||
|  | 	bottom: 0; | ||||||
|  | 	left: 0; | ||||||
|  | 	padding: 12px 12px max(12px, env(safe-area-inset-bottom, 0px)) 12px; | ||||||
|  | 	display: grid; | ||||||
|  | 	grid-template-columns: 1fr 1fr 1fr 1fr 1fr; | ||||||
|  | 	grid-gap: 8px; | ||||||
|  | 	width: 100%; | ||||||
|  | 	box-sizing: border-box; | ||||||
|  | 	-webkit-backdrop-filter: var(--blur, blur(32px)); | ||||||
|  | 	backdrop-filter: var(--blur, blur(32px)); | ||||||
|  | 	background-color: var(--header); | ||||||
|  | 	border-top: solid 0.5px var(--divider); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .navButton { | ||||||
|  | 	position: relative; | ||||||
|  | 	padding: 0; | ||||||
|  | 	aspect-ratio: 1; | ||||||
|  | 	width: 100%; | ||||||
|  | 	max-width: 60px; | ||||||
|  | 	margin: auto; | ||||||
|  | 	border-radius: 100%; | ||||||
|  | 	background: var(--panel); | ||||||
|  | 	color: var(--fg); | ||||||
|  | 
 | ||||||
|  | 	&:hover { | ||||||
|  | 		background: var(--X2); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	&:disabled { | ||||||
|  | 		cursor: default; | ||||||
|  | 
 | ||||||
|  | 		> .navButtonIcon { | ||||||
|  | 			opacity: 0.5; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	&.post { | ||||||
|  | 		background: linear-gradient(90deg, var(--buttonGradateA), var(--buttonGradateB)); | ||||||
|  | 		color: var(--fgOnAccent); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .navButtonIcon { | ||||||
|  | 	font-size: 18px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .navButtonIndicator { | ||||||
|  | 	position: absolute; | ||||||
|  | 	top: 0; | ||||||
|  | 	left: 0; | ||||||
|  | 	color: var(--indicator); | ||||||
|  | 	font-size: 16px; | ||||||
|  | 	animation: blink 1s infinite; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .menuDrawerBg { | ||||||
|  | 	z-index: 1001; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .menuDrawer { | ||||||
|  | 	position: fixed; | ||||||
|  | 	top: 0; | ||||||
|  | 	left: 0; | ||||||
|  | 	z-index: 1001; | ||||||
|  | 	height: 100dvh; | ||||||
|  | 	width: 240px; | ||||||
|  | 	box-sizing: border-box; | ||||||
|  | 	contain: strict; | ||||||
|  | 	overflow: auto; | ||||||
|  | 	overscroll-behavior: contain; | ||||||
|  | 	background: var(--navBg); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .statusbars { | .statusbars { | ||||||
| 	position: sticky; | 	position: sticky; | ||||||
| 	top: 0; | 	top: 0; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue