enhance(frontend): 絵文字管理画面β(ローカル)のUI・UX改善 (#15349)
* enhance(frontend): 絵文字管理画面β(ローカル)のUI・UX改善
* fix
* 🎨
* 表示件数をメニューから変更するように
* 確認ダイアログ
* fix i18n
* needWideArea: trueならwidgetの開閉ボタンを表示しないように
* fix: 検索ウィンドウは一つしか開けないように
This commit is contained in:
parent
791b4500ec
commit
297186e492
22 changed files with 659 additions and 416 deletions
|
|
@ -12,12 +12,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:iconClass="order.direction === '+' ? 'ti ti-arrow-up' : 'ti ti-arrow-down'"
|
||||
:exButtonIconClass="'ti ti-x'"
|
||||
:content="order.key"
|
||||
:class="$style.sortOrderTag"
|
||||
@click="onToggleSortOrderButtonClicked(order)"
|
||||
@exButtonClick="onRemoveSortOrderButtonClicked(order)"
|
||||
/>
|
||||
</div>
|
||||
<MkButton :class="$style.sortOrderAddButton" @click="onAddSortOrderButtonClicked">
|
||||
<span class="ti ti-plus"/>
|
||||
<span class="ti ti-plus"></span>
|
||||
</MkButton>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -109,4 +110,9 @@ function emitOrder(sortOrders: SortOrder<T>[]) {
|
|||
border-radius: 9999px;
|
||||
background-color: var(--MI_THEME-buttonBg);
|
||||
}
|
||||
|
||||
.sortOrderTag {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ export type SuperMenuDef = {
|
|||
active?: boolean;
|
||||
action: (ev: MouseEvent) => void;
|
||||
} | {
|
||||
type: 'link';
|
||||
type?: 'link';
|
||||
to: string;
|
||||
icon?: string;
|
||||
text: string;
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div :class="$style.root" @click="(ev) => emit('click', ev)">
|
||||
<span v-if="iconClass" :class="[$style.icon, iconClass]"/>
|
||||
<span v-if="iconClass" :class="[$style.icon, iconClass]"></span>
|
||||
<span :class="$style.content">{{ content }}</span>
|
||||
<MkButton v-if="exButtonIconClass" :class="$style.exButton" @click="(ev) => emit('exButtonClick', ev)">
|
||||
<span :class="[$style.exButtonIcon, exButtonIconClass]"/>
|
||||
<span :class="[$style.exButtonIcon, exButtonIconClass]"></span>
|
||||
</MkButton>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -48,13 +48,16 @@ import { scrollToTop } from '@@/js/scroll.js';
|
|||
import { globalEvents } from '@/events.js';
|
||||
import { injectReactiveMetadata } from '@/scripts/page-metadata.js';
|
||||
import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js';
|
||||
import { PageHeaderItem } from '@/types/page-header.js';
|
||||
import type { PageHeaderItem } from '@/types/page-header.js';
|
||||
import type { PageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
overridePageMetadata?: PageMetadata;
|
||||
tabs?: Tab[];
|
||||
tab?: string;
|
||||
actions?: PageHeaderItem[] | null;
|
||||
thin?: boolean;
|
||||
hideTitle?: boolean;
|
||||
displayMyAvatar?: boolean;
|
||||
}>(), {
|
||||
tabs: () => ([] as Tab[]),
|
||||
|
|
@ -64,9 +67,10 @@ const emit = defineEmits<{
|
|||
(ev: 'update:tab', key: string);
|
||||
}>();
|
||||
|
||||
const pageMetadata = injectReactiveMetadata();
|
||||
const injectedPageMetadata = injectReactiveMetadata();
|
||||
const pageMetadata = computed(() => props.overridePageMetadata ?? injectedPageMetadata.value);
|
||||
|
||||
const hideTitle = inject('shouldOmitHeaderTitle', false);
|
||||
const hideTitle = computed(() => inject('shouldOmitHeaderTitle', false) || props.hideTitle);
|
||||
const thin_ = props.thin || inject('shouldHeaderThin', false);
|
||||
|
||||
const el = shallowRef<HTMLElement | undefined>(undefined);
|
||||
|
|
@ -75,7 +79,7 @@ const narrow = ref(false);
|
|||
const hasTabs = computed(() => props.tabs.length > 0);
|
||||
const hasActions = computed(() => props.actions && props.actions.length > 0);
|
||||
const show = computed(() => {
|
||||
return !hideTitle || hasTabs.value || hasActions.value;
|
||||
return !hideTitle.value || hasTabs.value || hasActions.value;
|
||||
});
|
||||
|
||||
const preventDrag = (ev: TouchEvent) => {
|
||||
|
|
|
|||
|
|
@ -39,13 +39,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
{{ cell.value }}
|
||||
</div>
|
||||
<div v-else-if="cellType === 'boolean'">
|
||||
<span v-if="cell.value === true" class="ti ti-check"/>
|
||||
<span v-else class="ti"/>
|
||||
<div :class="[$style.bool, {
|
||||
[$style.boolTrue]: cell.value === true,
|
||||
'ti ti-check': cell.value === true,
|
||||
}]"></div>
|
||||
</div>
|
||||
<div v-else-if="cellType === 'image'">
|
||||
<img
|
||||
:src="cell.value as string"
|
||||
:alt="cell.value as string"
|
||||
:src="cell.value"
|
||||
:alt="cell.value"
|
||||
:class="$style.viewImage"
|
||||
@load="emitContentSizeChanged"
|
||||
/>
|
||||
|
|
@ -375,6 +377,31 @@ $cellHeight: 28px;
|
|||
object-fit: cover;
|
||||
}
|
||||
|
||||
.bool {
|
||||
position: relative;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background: var(--MI_THEME-panel);
|
||||
border: solid 2px var(--MI_THEME-divider);
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.boolTrue {
|
||||
border-color: var(--MI_THEME-accent);
|
||||
background: var(--MI_THEME-accent);
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: var(--MI_THEME-fgOnAccent);
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.editingInput {
|
||||
padding: 0 8px;
|
||||
width: 100%;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div
|
||||
ref="rootEl"
|
||||
class="mk_grid_border"
|
||||
:class="[$style.grid]"
|
||||
:class="[$style.grid, {
|
||||
[$style.noOverflowHandling]: rootSetting.noOverflowStyle,
|
||||
'mk_grid_root_rounded': rootSetting.rounded,
|
||||
'mk_grid_root_border': rootSetting.outerBorder,
|
||||
}]"
|
||||
@mousedown.prevent="onMouseDown"
|
||||
@keydown="onKeyDown"
|
||||
@contextmenu.prevent.stop="onContextMenu"
|
||||
|
|
@ -77,10 +81,17 @@ const emit = defineEmits<{
|
|||
}>();
|
||||
|
||||
const props = defineProps<{
|
||||
settings: GridSetting,
|
||||
data: DataSource[]
|
||||
settings: GridSetting;
|
||||
data: DataSource[];
|
||||
}>();
|
||||
|
||||
const rootSetting: Required<GridSetting['root']> = {
|
||||
noOverflowStyle: false,
|
||||
rounded: true,
|
||||
outerBorder: true,
|
||||
...props.settings.root,
|
||||
};
|
||||
|
||||
// non-reactive
|
||||
// eslint-disable-next-line vue/no-setup-props-reactivity-loss
|
||||
const rowSetting: Required<GridRowSetting> = {
|
||||
|
|
@ -1277,32 +1288,48 @@ onMounted(() => {
|
|||
overflow-x: scroll;
|
||||
// firefoxだとスクロールバーがセルに重なって見づらくなってしまうのでスペースを空けておく
|
||||
padding-bottom: 8px;
|
||||
|
||||
&.noOverflowHandling {
|
||||
overflow-x: revert;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
$borderSetting: solid 0.5px var(--MI_THEME-divider);
|
||||
$borderRadius: var(--MI-radius);
|
||||
|
||||
// 配下コンポーネントを含めて一括してコントロールするため、scopedもmoduleも使用できない
|
||||
.mk_grid_border {
|
||||
--rootBorderSetting: none;
|
||||
--borderRadius: 0;
|
||||
|
||||
border-spacing: 0;
|
||||
|
||||
&.mk_grid_root_border {
|
||||
--rootBorderSetting: #{$borderSetting};
|
||||
}
|
||||
|
||||
&.mk_grid_root_rounded {
|
||||
--borderRadius: var(--MI-radius);
|
||||
}
|
||||
|
||||
.mk_grid_thead {
|
||||
.mk_grid_tr {
|
||||
.mk_grid_th {
|
||||
border-left: $borderSetting;
|
||||
border-top: $borderSetting;
|
||||
border-top: var(--rootBorderSetting);
|
||||
|
||||
&:first-child {
|
||||
// 左上セル
|
||||
border-top-left-radius: $borderRadius;
|
||||
border-left: var(--rootBorderSetting);
|
||||
border-top-left-radius: var(--borderRadius);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
// 右上セル
|
||||
border-top-right-radius: $borderRadius;
|
||||
border-right: $borderSetting;
|
||||
border-top-right-radius: var(--borderRadius);
|
||||
border-right: var(--rootBorderSetting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1314,9 +1341,14 @@ $borderRadius: var(--MI-radius);
|
|||
border-left: $borderSetting;
|
||||
border-top: $borderSetting;
|
||||
|
||||
&:first-child {
|
||||
// 左端の列
|
||||
border-left: var(--rootBorderSetting);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
// 一番右端の列
|
||||
border-right: $borderSetting;
|
||||
border-right: var(--rootBorderSetting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1324,16 +1356,16 @@ $borderRadius: var(--MI-radius);
|
|||
.last_row {
|
||||
.mk_grid_td, .mk_grid_th {
|
||||
// 一番下の行
|
||||
border-bottom: $borderSetting;
|
||||
border-bottom: var(--rootBorderSetting);
|
||||
|
||||
&:first-child {
|
||||
// 左下セル
|
||||
border-bottom-left-radius: $borderRadius;
|
||||
border-bottom-left-radius: var(--borderRadius);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
// 右下セル
|
||||
border-bottom-right-radius: $borderRadius;
|
||||
border-bottom-right-radius: var(--borderRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:data-grid-cell-col="column.index"
|
||||
>
|
||||
<div :class="$style.root">
|
||||
<div :class="$style.left"/>
|
||||
<div :class="$style.left"></div>
|
||||
<div :class="$style.wrapper">
|
||||
<div ref="contentEl" :class="$style.contentArea">
|
||||
<span v-if="column.setting.icon" class="ti" :class="column.setting.icon" style="line-height: normal"/>
|
||||
<span v-if="column.setting.icon" class="ti" :class="column.setting.icon" style="line-height: normal"></span>
|
||||
<span v-else>{{ text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:class="$style.right"
|
||||
@mousedown="onHandleMouseDown"
|
||||
@dblclick="onHandleDoubleClick"
|
||||
/>
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,11 @@ import { GridColumnSetting } from '@/components/grid/column.js';
|
|||
import { GridRowSetting } from '@/components/grid/row.js';
|
||||
|
||||
export type GridSetting = {
|
||||
root?: {
|
||||
noOverflowStyle?: boolean;
|
||||
rounded?: boolean;
|
||||
outerBorder?: boolean;
|
||||
};
|
||||
row?: GridRowSetting;
|
||||
cols: GridColumnSetting[];
|
||||
cells?: GridCellSetting;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue