Add popovers to sheet column headers, improve mouse UX

This commit is contained in:
Andrew Kingston 2023-03-06 15:09:42 +00:00
parent 36e8664605
commit b93f575bca
8 changed files with 90 additions and 62 deletions

View File

@ -19,6 +19,7 @@
export let dismissible = true
export let offset = 5
export let customHeight
export let animate = true
$: target = portalTarget || getContext(Context.PopoverRoot) || ".spectrum"
@ -76,7 +77,7 @@
class="spectrum-Popover is-open"
role="presentation"
style="height: {customHeight}"
transition:fly|local={{ y: -20, duration: 200 }}
transition:fly|local={{ y: -20, duration: animate ? 200 : 0 }}
>
<slot />
</div>

View File

@ -228,5 +228,6 @@
display: flex;
flex-direction: column;
background: var(--background);
overflow: hidden;
}
</style>

View File

@ -1,15 +1,8 @@
<script>
import { getContext } from "svelte"
const {
visibleRows,
columns,
rand,
scroll,
visibleColumns,
cellHeight,
stickyColumn,
} = getContext("sheet")
const { columns, rand, scroll, visibleColumns, stickyColumn } =
getContext("sheet")
const MinColumnWidth = 100
let initialMouseX = null
@ -22,8 +15,6 @@
$: scrollLeft = $scroll.left
$: cutoff = scrollLeft + 40 + ($columns[0]?.width || 0)
$: offset = 40 + ($stickyColumn?.width || 0)
$: rowCount = $visibleRows.length
$: contentHeight = (rowCount + 2) * cellHeight
const startResizing = (idx, e) => {
// Prevent propagation to stop reordering triggering
@ -78,9 +69,9 @@
document.getElementById(`sheet-${rand}`).classList.remove("is-resizing")
}
const getStyle = (col, offset, scrollLeft, contentHeight) => {
const getStyle = (col, offset, scrollLeft) => {
const left = offset + col.left + col.width - scrollLeft
return `--left:${left}px; --content-height:${contentHeight}px;`
return `--left:${left}px;`
}
</script>
@ -89,8 +80,7 @@
class="resize-slider sticky"
class:visible={columnIdx === "sticky"}
on:mousedown={e => startResizing("sticky", e)}
style="--left:{40 +
$stickyColumn.width}px; --content-height:{contentHeight}px;"
style="--left:{40 + $stickyColumn.width}px;"
>
<div class="resize-indicator" />
</div>
@ -100,7 +90,7 @@
class="resize-slider"
class:visible={columnIdx === col.idx}
on:mousedown={e => startResizing(col.idx, e)}
style={getStyle(col, offset, scrollLeft, contentHeight)}
style={getStyle(col, offset, scrollLeft)}
>
<div class="resize-indicator" />
</div>
@ -114,7 +104,7 @@
height: var(--cell-height);
left: var(--left);
opacity: 0;
padding: 0 16px;
padding: 0 8px;
transform: translateX(-50%);
user-select: none;
}
@ -122,7 +112,6 @@
.resize-slider.visible {
cursor: col-resize;
opacity: 1;
height: min(var(--content-height), 100%);
}
.resize-slider.sticky {
z-index: 2;

View File

@ -5,6 +5,7 @@
import SheetCell from "./cells/SheetCell.svelte"
import { getCellRenderer } from "./renderers"
import SheetScrollWrapper from "./SheetScrollWrapper.svelte"
import HeaderCell from "./cells/HeaderCell.svelte"
const {
rows,
@ -67,6 +68,7 @@
<!-- Field headers -->
<SheetCell
header
foo
label
width="40"
on:click={$config.allowSelectRows && selectAll}
@ -77,21 +79,7 @@
</SheetCell>
{#if $stickyColumn}
<SheetCell
header
sticky
width={$stickyColumn.width}
reorderTarget={$reorder.targetColumn === $stickyColumn.name}
>
<Icon
size="S"
name={getIconForField($stickyColumn)}
color="var(--spectrum-global-color-gray-600)"
/>
<span>
{$stickyColumn.name}
</span>
</SheetCell>
<HeaderCell column={$stickyColumn} />
{/if}
</div>

View File

@ -1,56 +1,92 @@
<script>
import { getContext } from "svelte"
import SheetCell from "./SheetCell.svelte"
import { Icon, Popover } from "@budibase/bbui"
import { Icon, Popover, Menu, MenuItem } from "@budibase/bbui"
import { getIconForField } from "../utils"
export let column
const { reorder } = getContext("sheet")
const { reorder, isReordering, rand } = getContext("sheet")
let popover
let timeout
let anchor
let open = false
let isClick = true
const openPopover = () => {
console.log("open")
popover.show()
const startReordering = e => {
isClick = true
timeout = setTimeout(() => {
isClick = false
reorder.actions.startReordering(column.name, e)
}, 250)
}
const stopReordering = () => {
clearTimeout(timeout)
}
const onClick = () => {
if (isClick) {
stopReordering()
open = true
}
}
</script>
<div class="header-cell" bind:this={anchor}>
<div
class="header-cell"
class:open
style="flex: 0 0 {column.width}px;"
bind:this={anchor}
class:disabled={$isReordering}
>
<SheetCell
reorderSource={$reorder.sourceColumn === column.name}
reorderTarget={$reorder.targetColumn === column.name}
on:mousedown={e => reorder.actions.startReordering(column.name, e)}
on:click={openPopover}
on:mousedown={startReordering}
on:mouseup={stopReordering}
on:click={onClick}
width={column.width}
left={column.left}
>
<div class="content">
<Icon
size="S"
name={getIconForField(column)}
color="var(--spectrum-global-color-gray-600)"
/>
<div class="name">
{column.name} asdasdasd asdasdas asdasdasd
</div>
<div class="more">
<Icon size="S" name="MoreVertical" />
</div>
<Icon
size="S"
name={getIconForField(column)}
color="var(--spectrum-global-color-gray-600)"
/>
<div class="name">
{column.name}
</div>
<div class="more">
<Icon size="S" name="MoreVertical" />
</div>
</SheetCell>
</div>
<Popover bind:this={popover} {anchor} align="left"
>asdsad asdasd asdasd asasa</Popover
<Popover
bind:open
{anchor}
align="left"
offset={0}
popoverTarget={document.getElementById(`sheet-${rand}`)}
animate={false}
>
<Menu>
<MenuItem icon="Edit">Edit column</MenuItem>
<MenuItem icon="SortOrderUp">Sort ascending</MenuItem>
<MenuItem icon="SortOrderDown">Sort descending</MenuItem>
<MenuItem icon="ArrowLeft">Move left</MenuItem>
<MenuItem icon="ArrowRight">Move right</MenuItem>
<MenuItem icon="Delete">Delete</MenuItem>
</Menu>
</Popover>
<style>
.header-cell {
display: contents;
display: flex;
}
.header-cell:hover :global(.cell) {
.header-cell:not(.disabled):hover :global(.cell),
.header-cell:not(.disabled).open :global(.cell) {
cursor: pointer;
background: var(--spectrum-global-color-gray-200);
}
@ -72,7 +108,8 @@
.more {
display: none;
}
.header-cell:hover .more {
.header-cell:not(.disabled):hover .more,
.header-cell:not(.disabled).open .more {
display: block;
}
</style>

View File

@ -10,6 +10,7 @@
export let center = false
export let selectedUser = null
export let rowIdx
export let foo
$: style = getStyle(width, selectedUser)
@ -24,6 +25,7 @@
<div
class="cell"
class:foo
class:label
class:row-selected={rowSelected}
class:row-hovered={rowHovered}
@ -34,8 +36,9 @@
class:reorder-target={reorderTarget}
class:center
on:focus
on:click
on:mousedown
on:mouseup
on:click
{style}
data-row={rowIdx}
>
@ -113,6 +116,9 @@
justify-content: center;
align-items: center;
}
.cell.foo {
background: var(--spectrum-global-color-gray-100);
}
/* Other user email */
.user {

View File

@ -1,4 +1,4 @@
import { get, writable } from "svelte/store"
import { get, writable, derived } from "svelte/store"
export const createReorderStores = context => {
const { columns, rand, scroll, bounds, stickyColumn } = context
@ -7,8 +7,11 @@ export const createReorderStores = context => {
targetColumn: null,
breakpoints: [],
initialMouseX: null,
scrollLeft: 0,
sheetLeft: 0,
}
const reorder = writable(reorderInitialState)
const isReordering = derived(reorder, $reorder => !!$reorder.sourceColumn)
// Callback when dragging on a colum header and starting reordering
const startReordering = (column, e) => {
@ -115,5 +118,6 @@ export const createReorderStores = context => {
stopReordering,
},
},
isReordering,
}
}

View File

@ -4,6 +4,7 @@ import Koa from "koa"
import Cookies from "cookies"
import { userAgent } from "koa-useragent"
import { auth } from "@budibase/backend-core"
import currentApp from "../middleware/currentapp"
export default class Socket {
io: Server
@ -25,6 +26,7 @@ export default class Socket {
const middlewares = [
userAgent,
authenticate,
// currentApp,
...(additionalMiddlewares || []),
]