feat(ui): progressively shrink data grid toolbar
This commit is contained in:
15 files changed
+188
-67
No files matched your search
@@ -354,7 +354,9 @@ import { resolveGridFocusRestoreTarget } from "@/lib/dataGrid/dataGridFocusResto
|
||||
import { buildOrderedGridRows, type GridInsertRowPosition, type GridNewRowPlacement } from "@/lib/dataGrid/gridNewRowPlacement";
|
||||
import {
|
||||
DATA_GRID_CONDITION_TOOLBAR_MIN_WIDTH,
|
||||
DATA_GRID_TOOLBAR_ACTION_COLLAPSE_ORDER,
|
||||
dataGridDeleteRowToolbarState,
|
||||
dataGridToolbarActionCollapseCount,
|
||||
isDataGridToolbarCompact,
|
||||
type DataGridReloadIntent,
|
||||
type DataGridToolbarActionCapability,
|
||||
@@ -712,6 +714,7 @@ const columnCommentMap = computed(() => {
|
||||
const dataGridTopbarWidth = ref(0);
|
||||
const dataGridViewportWidth = ref(0);
|
||||
const dataGridTopbarOverflowCompact = ref(false);
|
||||
const dataGridTopbarOverflowActionCount = ref(0);
|
||||
const dataGridTopbarExpandedRequiredWidth = ref(0);
|
||||
const showColumnCommentsInHeader = computed(() => settingsStore.editorSettings.showColumnCommentsInHeader);
|
||||
const showColumnTypesInHeader = computed(() => settingsStore.editorSettings.showColumnTypesInHeader);
|
||||
@@ -733,6 +736,8 @@ const compactColumnHeaderActions = computed(() => settingsStore.editorSettings.c
|
||||
const dataGridRenderMode = computed(() => settingsStore.editorSettings.dataGridRenderMode);
|
||||
const dataGridSearchMode = computed(() => settingsStore.editorSettings.dataGridSearchMode);
|
||||
const compactDataGridToolbar = computed(() => dataGridTopbarOverflowCompact.value || isDataGridToolbarCompact(dataGridTopbarWidth.value, dataGridViewportWidth.value, DATA_GRID_CONDITION_TOOLBAR_MIN_WIDTH));
|
||||
const responsiveDataGridToolbarActionCount = computed(() => dataGridToolbarActionCollapseCount(dataGridTopbarWidth.value, dataGridViewportWidth.value, DATA_GRID_CONDITION_TOOLBAR_MIN_WIDTH));
|
||||
const compactDataGridToolbarActionCount = computed(() => Math.max(responsiveDataGridToolbarActionCount.value, dataGridTopbarOverflowActionCount.value));
|
||||
const infiniteScrollEnabled = computed(() => props.paginationEnabled && settingsStore.editorSettings.infiniteScroll);
|
||||
const queryResultMaxRows = computed(() => effectiveQueryResultMaxRows(settingsStore.editorSettings.queryResultMaxRowsEnabled, settingsStore.editorSettings.queryResultMaxRows));
|
||||
const paginationMaxRows = computed(() => (isResultsContext.value ? queryResultMaxRows.value : undefined));
|
||||
@@ -2561,6 +2566,8 @@ let gridScrollbarsRuntime: DataGridScrollbarsRuntime;
|
||||
let dataGridTopbarResizeObserver: ResizeObserver | null = null;
|
||||
let dataGridTopbarMutationObserver: MutationObserver | null = null;
|
||||
let dataGridTopbarRecheckTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
const DATA_GRID_TOPBAR_RECHECK_DELAY_MS = 360;
|
||||
const DATA_GRID_TOPBAR_EXPAND_HYSTERESIS_PX = 16;
|
||||
let cellEditResizeObserver: ResizeObserver | null = null;
|
||||
// vue-virtual-scroller's @resize only fires in pageMode (it observes window),
|
||||
// so in container-scroll mode (transpose uses RecycleScroller without pageMode)
|
||||
@@ -3210,43 +3217,57 @@ function observeGridHorizontalScrollbarScroller() {
|
||||
|
||||
function updateDataGridTopbarWidth() {
|
||||
const topbar = dataGridTopbarRef.value;
|
||||
const previousActionCount = compactDataGridToolbarActionCount.value;
|
||||
dataGridTopbarWidth.value = topbar?.clientWidth ?? 0;
|
||||
dataGridViewportWidth.value = typeof window === "undefined" ? 0 : window.innerWidth;
|
||||
|
||||
if (!topbar) return;
|
||||
|
||||
const fixedBreakpointCompact = isDataGridToolbarCompact(dataGridTopbarWidth.value, dataGridViewportWidth.value, DATA_GRID_CONDITION_TOOLBAR_MIN_WIDTH);
|
||||
if (fixedBreakpointCompact) return;
|
||||
|
||||
if (dataGridTopbarOverflowCompact.value) {
|
||||
if (dataGridTopbarWidth.value >= dataGridTopbarExpandedRequiredWidth.value) {
|
||||
dataGridTopbarOverflowCompact.value = false;
|
||||
dataGridTopbarExpandedRequiredWidth.value = 0;
|
||||
}
|
||||
if (compactDataGridToolbarActionCount.value !== previousActionCount) {
|
||||
scheduleDataGridTopbarRecheck();
|
||||
return;
|
||||
}
|
||||
|
||||
if (dataGridTopbarOverflowCompact.value || dataGridTopbarOverflowActionCount.value > 0) {
|
||||
if (dataGridTopbarWidth.value >= dataGridTopbarExpandedRequiredWidth.value) {
|
||||
dataGridTopbarOverflowCompact.value = false;
|
||||
dataGridTopbarOverflowActionCount.value = 0;
|
||||
dataGridTopbarExpandedRequiredWidth.value = 0;
|
||||
scheduleDataGridTopbarRecheck();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The action list gains preview/save/rollback controls in editable grids. The
|
||||
// fixed breakpoint cannot see that extra width, so capture the full layout
|
||||
// width before the overflow-clip wrapper can hide the trailing action.
|
||||
// responsive breakpoint cannot see that extra width, so progressively
|
||||
// compact the leftmost controls before overflow-clip hides a trailing action.
|
||||
if (topbar.scrollWidth > topbar.clientWidth + 1) {
|
||||
dataGridTopbarExpandedRequiredWidth.value = topbar.scrollWidth;
|
||||
dataGridTopbarOverflowCompact.value = true;
|
||||
dataGridTopbarExpandedRequiredWidth.value = Math.max(dataGridTopbarExpandedRequiredWidth.value, topbar.scrollWidth + DATA_GRID_TOPBAR_EXPAND_HYSTERESIS_PX);
|
||||
if (!compactDataGridToolbar.value) {
|
||||
dataGridTopbarOverflowCompact.value = true;
|
||||
} else if (compactDataGridToolbarActionCount.value < DATA_GRID_TOOLBAR_ACTION_COLLAPSE_ORDER.length) {
|
||||
dataGridTopbarOverflowActionCount.value = compactDataGridToolbarActionCount.value + 1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
scheduleDataGridTopbarRecheck();
|
||||
}
|
||||
}
|
||||
|
||||
function resetDataGridTopbarOverflowCompact() {
|
||||
if (!dataGridTopbarOverflowCompact.value) return;
|
||||
if (!dataGridTopbarOverflowCompact.value && dataGridTopbarOverflowActionCount.value === 0) return;
|
||||
dataGridTopbarOverflowCompact.value = false;
|
||||
dataGridTopbarOverflowActionCount.value = 0;
|
||||
dataGridTopbarExpandedRequiredWidth.value = 0;
|
||||
scheduleDataGridTopbarRecheck();
|
||||
}
|
||||
|
||||
function scheduleDataGridTopbarRecheck() {
|
||||
if (dataGridTopbarRecheckTimer) clearTimeout(dataGridTopbarRecheckTimer);
|
||||
// Wait for the label-width transition to finish before measuring the newly
|
||||
// shortened action list. If it still overflows, updateDataGridTopbarWidth
|
||||
// captures its new, smaller expanded width.
|
||||
dataGridTopbarRecheckTimer = setTimeout(() => {
|
||||
dataGridTopbarRecheckTimer = null;
|
||||
updateDataGridTopbarWidth();
|
||||
}, 360);
|
||||
}, DATA_GRID_TOPBAR_RECHECK_DELAY_MS);
|
||||
}
|
||||
|
||||
function clearDataGridTopbarRecheckTimer() {
|
||||
@@ -12676,7 +12697,8 @@ function openGridSnapshot() {
|
||||
|
||||
<DataGridToolbar
|
||||
class="ml-auto"
|
||||
:compact="compactDataGridToolbar"
|
||||
:compact-action-count="compactDataGridToolbarActionCount"
|
||||
:navigation-visible="props.result.columns.length > 0"
|
||||
:refresh="refreshToolbarCapability"
|
||||
:auto-refresh="autoRefreshToolbarCapability"
|
||||
:add-row="addRowToolbarCapability"
|
||||
@@ -12733,17 +12755,17 @@ function openGridSnapshot() {
|
||||
</Tooltip>
|
||||
</template>
|
||||
|
||||
<template #navigation>
|
||||
<template #navigation="{ compact }">
|
||||
<Tooltip v-if="props.result.columns.length">
|
||||
<TooltipTrigger as-child>
|
||||
<Popover v-model:open="goToColumnOpen">
|
||||
<PopoverTrigger as-child>
|
||||
<Button variant="ghost" size="sm" :class="['data-grid-topbar-action-button h-5 shrink-0 text-xs px-1.5', compactDataGridToolbar ? 'data-grid-topbar-action-button--compact' : '', goToColumnOpen ? 'text-primary bg-primary/10' : '']">
|
||||
<Button data-toolbar-action="navigation" variant="ghost" size="sm" :class="['data-grid-topbar-action-button h-5 shrink-0 text-xs px-1.5', compact ? 'data-grid-topbar-action-button--compact' : '', goToColumnOpen ? 'text-primary bg-primary/10' : '']">
|
||||
<Columns3 class="data-grid-topbar-action-icon w-3 h-3" />
|
||||
<span
|
||||
class="data-grid-topbar-action-label"
|
||||
:class="{
|
||||
'data-grid-topbar-action-label--compact': compactDataGridToolbar,
|
||||
'data-grid-topbar-action-label--compact': compact,
|
||||
}"
|
||||
>{{ t("grid.goToColumn") }}</span
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, onBeforeUnmount, ref, watch, type CSSProperties } from "vue";
|
||||
import { Check, Columns3, GripVertical, Search } from "@lucide/vue";
|
||||
import { Check, GripVertical, ListChecks, Search } from "@lucide/vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
@@ -306,7 +306,7 @@ onBeforeUnmount(resetColumnDragState);
|
||||
:title="t('grid.columnVisibility')"
|
||||
:aria-label="t('grid.columnVisibility')"
|
||||
>
|
||||
<Columns3 class="h-3.5 w-3.5" />
|
||||
<ListChecks class="h-3.5 w-3.5" />
|
||||
<span v-if="!compact">{{ t("grid.columnVisibility") }}</span>
|
||||
<span v-if="!compact && (grid?.hiddenColumnCount ?? 0) > 0" class="tabular-nums"> {{ grid?.visibleColumnCount }}/{{ grid?.displayableColumnCount }} </span>
|
||||
</Button>
|
||||
|
||||
@@ -5,7 +5,9 @@ import { Button } from "@/components/ui/button";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import {
|
||||
DATA_GRID_TOOLBAR_ACTION_COLLAPSE_ORDER,
|
||||
dataGridToolbarIntervalOptions,
|
||||
isDataGridToolbarActionCompact,
|
||||
isDataGridToolbarCapabilityDisabled,
|
||||
isDataGridToolbarCapabilityVisible,
|
||||
selectDataGridToolbarAddRowItem,
|
||||
@@ -16,6 +18,7 @@ import {
|
||||
triggerDataGridToolbarCopy,
|
||||
triggerDataGridToolbarAction,
|
||||
type DataGridToolbarActionCapability,
|
||||
type DataGridToolbarActionKey,
|
||||
type DataGridToolbarAddRowCapability,
|
||||
type DataGridToolbarAutoRefreshCapability,
|
||||
type DataGridToolbarCopyCapability,
|
||||
@@ -25,6 +28,8 @@ import {
|
||||
|
||||
const props = defineProps<{
|
||||
compact?: boolean;
|
||||
compactActionCount?: number;
|
||||
navigationVisible?: boolean;
|
||||
refresh: DataGridToolbarActionCapability;
|
||||
autoRefresh?: DataGridToolbarAutoRefreshCapability;
|
||||
addRow?: DataGridToolbarAddRowCapability;
|
||||
@@ -39,11 +44,36 @@ const props = defineProps<{
|
||||
rollback?: DataGridToolbarActionCapability;
|
||||
}>();
|
||||
|
||||
const actionButtonClass = computed(() => ["data-grid-topbar-action-button h-5 shrink-0 px-1.5 text-xs", props.compact ? "data-grid-topbar-action-button--compact" : ""]);
|
||||
const autoRefreshIntervals = computed(() => (props.autoRefresh ? dataGridToolbarIntervalOptions(props.autoRefresh.intervalOptions, props.autoRefresh.intervalSeconds) : []));
|
||||
const visibleActionOrder = computed<DataGridToolbarActionKey[]>(() => {
|
||||
const visibility: Record<DataGridToolbarActionKey, boolean> = {
|
||||
refresh: isDataGridToolbarCapabilityVisible(props.refresh),
|
||||
autoRefresh: isDataGridToolbarCapabilityVisible(props.autoRefresh),
|
||||
navigation: props.navigationVisible === true,
|
||||
copyData: isDataGridToolbarCapabilityVisible(props.copyData),
|
||||
addRow: isDataGridToolbarCapabilityVisible(props.addRow),
|
||||
deleteRow: isDataGridToolbarCapabilityVisible(props.deleteRow),
|
||||
exportData: isDataGridToolbarCapabilityVisible(props.exportData),
|
||||
transpose: isDataGridToolbarCapabilityVisible(props.transpose),
|
||||
tableInfo: isDataGridToolbarCapabilityVisible(props.tableInfo),
|
||||
layerPreview: isDataGridToolbarCapabilityVisible(props.layerPreview),
|
||||
preview: isDataGridToolbarCapabilityVisible(props.preview),
|
||||
save: isDataGridToolbarCapabilityVisible(props.save),
|
||||
rollback: isDataGridToolbarCapabilityVisible(props.rollback),
|
||||
};
|
||||
return DATA_GRID_TOOLBAR_ACTION_COLLAPSE_ORDER.filter((action) => visibility[action]);
|
||||
});
|
||||
|
||||
function actionLabelClass() {
|
||||
return { "data-grid-topbar-action-label--compact": props.compact };
|
||||
function actionIsCompact(action: DataGridToolbarActionKey): boolean {
|
||||
return isDataGridToolbarActionCompact(action, visibleActionOrder.value, props.compactActionCount ?? 0, props.compact === true);
|
||||
}
|
||||
|
||||
function actionButtonClass(action: DataGridToolbarActionKey) {
|
||||
return ["data-grid-topbar-action-button h-5 shrink-0 px-1.5 text-xs", actionIsCompact(action) ? "data-grid-topbar-action-button--compact" : ""];
|
||||
}
|
||||
|
||||
function actionLabelClass(action: DataGridToolbarActionKey) {
|
||||
return { "data-grid-topbar-action-label--compact": actionIsCompact(action) };
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -53,10 +83,10 @@ function actionLabelClass() {
|
||||
|
||||
<Tooltip v-if="isDataGridToolbarCapabilityVisible(refresh)">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="sm" :class="actionButtonClass" :disabled="isDataGridToolbarCapabilityDisabled(refresh)" @click="void triggerDataGridToolbarAction(refresh)">
|
||||
<Button data-toolbar-action="refresh" variant="ghost" size="sm" :class="actionButtonClass('refresh')" :disabled="isDataGridToolbarCapabilityDisabled(refresh)" @click="void triggerDataGridToolbarAction(refresh)">
|
||||
<Loader2 v-if="refresh.loading" class="data-grid-topbar-action-icon h-3 w-3 animate-spin" />
|
||||
<RefreshCcw v-else class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass()">{{ refresh.label }}</span>
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass('refresh')">{{ refresh.label }}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">{{ refresh.tooltip ?? refresh.label }}</TooltipContent>
|
||||
@@ -67,14 +97,15 @@ function actionLabelClass() {
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
:class="[...actionButtonClass, autoRefresh?.enabled ? 'bg-primary/10 text-primary hover:bg-primary/15' : 'text-muted-foreground hover:text-foreground']"
|
||||
data-toolbar-action="autoRefresh"
|
||||
:class="[...actionButtonClass('autoRefresh'), autoRefresh?.enabled ? 'bg-primary/10 text-primary hover:bg-primary/15' : 'text-muted-foreground hover:text-foreground']"
|
||||
:disabled="isDataGridToolbarCapabilityDisabled(autoRefresh)"
|
||||
:title="autoRefresh?.label"
|
||||
:aria-label="autoRefresh?.label"
|
||||
:aria-pressed="autoRefresh?.enabled"
|
||||
>
|
||||
<Timer class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass()">{{ autoRefresh?.enabled ? `${autoRefresh.intervalSeconds}s` : autoRefresh?.shortLabel }}</span>
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass('autoRefresh')">{{ autoRefresh?.enabled ? `${autoRefresh.intervalSeconds}s` : autoRefresh?.shortLabel }}</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" class="w-40">
|
||||
@@ -91,14 +122,14 @@ function actionLabelClass() {
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
<slot name="navigation" />
|
||||
<slot name="navigation" :compact="actionIsCompact('navigation')" />
|
||||
|
||||
<div v-if="isDataGridToolbarCapabilityVisible(copyData)" class="flex h-5 shrink-0 items-stretch overflow-hidden rounded-md border border-border">
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="sm" class="h-5 rounded-none border-0 px-1.5 text-xs" :disabled="copyData?.disabled" @click="void triggerDataGridToolbarCopy(copyData)">
|
||||
<Copy class="h-3 w-3" :class="compact ? '' : 'mr-1'" />
|
||||
<span v-if="!compact">{{ copyData?.label }}</span>
|
||||
<Button data-toolbar-action="copyData" variant="ghost" size="sm" :class="[...actionButtonClass('copyData'), 'rounded-none border-0']" :disabled="copyData?.disabled" @click="void triggerDataGridToolbarCopy(copyData)">
|
||||
<Copy class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass('copyData')">{{ copyData?.label }}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">{{ copyData?.tooltip ?? copyData?.label }}</TooltipContent>
|
||||
@@ -124,9 +155,9 @@ function actionLabelClass() {
|
||||
<div v-if="isDataGridToolbarCapabilityVisible(addRow)" class="flex h-5 shrink-0 items-stretch overflow-hidden rounded-md border border-border">
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="sm" class="h-5 rounded-none border-0 px-1.5 text-xs" :disabled="isDataGridToolbarCapabilityDisabled(addRow)" @click="void triggerDataGridToolbarAction(addRow)">
|
||||
<Plus class="h-3 w-3" :class="compact ? '' : 'mr-1'" />
|
||||
<span v-if="!compact">{{ addRow?.label }}</span>
|
||||
<Button data-toolbar-action="addRow" variant="ghost" size="sm" :class="[...actionButtonClass('addRow'), 'rounded-none border-0']" :disabled="isDataGridToolbarCapabilityDisabled(addRow)" @click="void triggerDataGridToolbarAction(addRow)">
|
||||
<Plus class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass('addRow')">{{ addRow?.label }}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">{{ addRow?.tooltip ?? addRow?.label }}</TooltipContent>
|
||||
@@ -152,9 +183,9 @@ function actionLabelClass() {
|
||||
|
||||
<Tooltip v-if="isDataGridToolbarCapabilityVisible(deleteRow)">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="sm" :class="actionButtonClass" :disabled="isDataGridToolbarCapabilityDisabled(deleteRow)" @click="void triggerDataGridToolbarAction(deleteRow)">
|
||||
<Button data-toolbar-action="deleteRow" variant="ghost" size="sm" :class="actionButtonClass('deleteRow')" :disabled="isDataGridToolbarCapabilityDisabled(deleteRow)" @click="void triggerDataGridToolbarAction(deleteRow)">
|
||||
<Trash2 class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass()">{{ deleteRow?.label }}</span>
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass('deleteRow')">{{ deleteRow?.label }}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">{{ deleteRow?.tooltip ?? deleteRow?.label }}</TooltipContent>
|
||||
@@ -164,9 +195,9 @@ function actionLabelClass() {
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button variant="ghost" size="sm" :class="actionButtonClass" :disabled="exportData?.disabled || !exportData?.items.length">
|
||||
<Button data-toolbar-action="exportData" variant="ghost" size="sm" :class="actionButtonClass('exportData')" :disabled="exportData?.disabled || !exportData?.items.length">
|
||||
<Download class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass()">{{ exportData?.label }}</span>
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass('exportData')">{{ exportData?.label }}</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
</TooltipTrigger>
|
||||
@@ -184,9 +215,17 @@ function actionLabelClass() {
|
||||
|
||||
<Tooltip v-if="isDataGridToolbarCapabilityVisible(transpose)">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="sm" :class="[...actionButtonClass, transpose?.active ? 'bg-primary/10 text-primary hover:bg-primary/15' : '']" :disabled="isDataGridToolbarCapabilityDisabled(transpose)" :aria-pressed="transpose?.active" @click="void triggerDataGridToolbarAction(transpose)">
|
||||
<Button
|
||||
data-toolbar-action="transpose"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
:class="[...actionButtonClass('transpose'), transpose?.active ? 'bg-primary/10 text-primary hover:bg-primary/15' : '']"
|
||||
:disabled="isDataGridToolbarCapabilityDisabled(transpose)"
|
||||
:aria-pressed="transpose?.active"
|
||||
@click="void triggerDataGridToolbarAction(transpose)"
|
||||
>
|
||||
<Rows3 class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass()">{{ transpose?.label }}</span>
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass('transpose')">{{ transpose?.label }}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">{{ transpose?.tooltip ?? transpose?.label }}</TooltipContent>
|
||||
@@ -194,9 +233,17 @@ function actionLabelClass() {
|
||||
|
||||
<Tooltip v-if="isDataGridToolbarCapabilityVisible(tableInfo)">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="sm" :class="[...actionButtonClass, tableInfo?.active ? 'bg-primary/10 text-primary hover:bg-primary/15' : '']" :disabled="isDataGridToolbarCapabilityDisabled(tableInfo)" :aria-pressed="tableInfo?.active" @click="void triggerDataGridToolbarAction(tableInfo)">
|
||||
<Button
|
||||
data-toolbar-action="tableInfo"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
:class="[...actionButtonClass('tableInfo'), tableInfo?.active ? 'bg-primary/10 text-primary hover:bg-primary/15' : '']"
|
||||
:disabled="isDataGridToolbarCapabilityDisabled(tableInfo)"
|
||||
:aria-pressed="tableInfo?.active"
|
||||
@click="void triggerDataGridToolbarAction(tableInfo)"
|
||||
>
|
||||
<TableProperties class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass()">{{ tableInfo?.label }}</span>
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass('tableInfo')">{{ tableInfo?.label }}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">{{ tableInfo?.tooltip ?? tableInfo?.label }}</TooltipContent>
|
||||
@@ -204,9 +251,9 @@ function actionLabelClass() {
|
||||
|
||||
<Tooltip v-if="isDataGridToolbarCapabilityVisible(layerPreview)">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="sm" :class="actionButtonClass" :disabled="isDataGridToolbarCapabilityDisabled(layerPreview)" @click="void triggerDataGridToolbarAction(layerPreview)">
|
||||
<Button data-toolbar-action="layerPreview" variant="ghost" size="sm" :class="actionButtonClass('layerPreview')" :disabled="isDataGridToolbarCapabilityDisabled(layerPreview)" @click="void triggerDataGridToolbarAction(layerPreview)">
|
||||
<Map class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass()">{{ layerPreview?.label }}</span>
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass('layerPreview')">{{ layerPreview?.label }}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">{{ layerPreview?.tooltip ?? layerPreview?.label }}</TooltipContent>
|
||||
@@ -214,10 +261,10 @@ function actionLabelClass() {
|
||||
|
||||
<Tooltip v-if="isDataGridToolbarCapabilityVisible(preview)">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="sm" :class="[...actionButtonClass, 'text-sky-600 hover:bg-sky-500/10 hover:text-sky-700']" :disabled="isDataGridToolbarCapabilityDisabled(preview)" @click="void triggerDataGridToolbarAction(preview)">
|
||||
<Button data-toolbar-action="preview" variant="ghost" size="sm" :class="[...actionButtonClass('preview'), 'text-sky-600 hover:bg-sky-500/10 hover:text-sky-700']" :disabled="isDataGridToolbarCapabilityDisabled(preview)" @click="void triggerDataGridToolbarAction(preview)">
|
||||
<Loader2 v-if="preview?.loading" class="data-grid-topbar-action-icon h-3 w-3 animate-spin" />
|
||||
<Eye v-else class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass()">{{ preview?.label }}</span>
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass('preview')">{{ preview?.label }}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom" class="max-w-sm">{{ preview?.tooltip ?? preview?.label }}</TooltipContent>
|
||||
@@ -225,20 +272,20 @@ function actionLabelClass() {
|
||||
|
||||
<Tooltip v-if="isDataGridToolbarCapabilityVisible(save)">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="default" size="sm" :class="[...actionButtonClass, 'data-grid-topbar-action-button--commit relative']" :disabled="isDataGridToolbarCapabilityDisabled(save)" @click="void triggerDataGridToolbarAction(save)">
|
||||
<Button data-toolbar-action="save" variant="default" size="sm" :class="[...actionButtonClass('save'), 'data-grid-topbar-action-button--commit relative']" :disabled="isDataGridToolbarCapabilityDisabled(save)" @click="void triggerDataGridToolbarAction(save)">
|
||||
<Loader2 v-if="save?.loading" class="data-grid-topbar-action-icon h-3 w-3 animate-spin" />
|
||||
<Save v-else-if="compact || !save?.pendingCount" class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<Save v-else-if="actionIsCompact('save') || !save?.pendingCount" class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span
|
||||
v-if="save && save.pendingCount > 0"
|
||||
:class="
|
||||
compact
|
||||
actionIsCompact('save')
|
||||
? 'absolute -right-1 -top-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-amber-300 px-1 text-[9px] font-semibold leading-none text-amber-950 shadow-[0_0_0_1px_rgba(120,53,15,0.16)] dark:bg-amber-400'
|
||||
: 'mr-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-amber-300 px-1 text-[9px] font-semibold leading-none text-amber-950 shadow-[0_0_0_1px_rgba(120,53,15,0.16)] dark:bg-amber-400'
|
||||
"
|
||||
>
|
||||
{{ save.pendingCount }}
|
||||
</span>
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass()">{{ save?.label }}</span>
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass('save')">{{ save?.label }}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom" class="max-w-sm"
|
||||
@@ -248,9 +295,9 @@ function actionLabelClass() {
|
||||
|
||||
<Tooltip v-if="isDataGridToolbarCapabilityVisible(rollback)">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="outline" size="sm" :class="actionButtonClass" :disabled="isDataGridToolbarCapabilityDisabled(rollback)" @click="void triggerDataGridToolbarAction(rollback)">
|
||||
<Button data-toolbar-action="rollback" variant="outline" size="sm" :class="actionButtonClass('rollback')" :disabled="isDataGridToolbarCapabilityDisabled(rollback)" @click="void triggerDataGridToolbarAction(rollback)">
|
||||
<RotateCcw class="data-grid-topbar-action-icon h-3 w-3" />
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass()">{{ rollback?.label }}</span>
|
||||
<span class="data-grid-topbar-action-label" :class="actionLabelClass('rollback')">{{ rollback?.label }}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">{{ rollback?.tooltip ?? rollback?.label }}</TooltipContent>
|
||||
|
||||
Reference in new issue
Block a user