Improve new row top component and fix style issues with z-index with validation labels

This commit is contained in:
Andrew Kingston 2023-04-21 15:16:11 +01:00
parent ea78f7fede
commit 77406ac183
5 changed files with 111 additions and 154 deletions

View File

@ -9,7 +9,7 @@
icon="TableRowAddBottom" icon="TableRowAddBottom"
quiet quiet
size="M" size="M"
on:click={() => dispatch("add-row")} on:click={() => dispatch("add-row-inline")}
disabled={!loaded || disabled={!loaded ||
!$config.allowAddRows || !$config.allowAddRows ||
(!$columns.length && !$stickyColumn)} (!$columns.length && !$stickyColumn)}

View File

@ -1,28 +0,0 @@
<script>
import { Icon } from "@budibase/bbui"
import { getContext } from "svelte"
const { dispatch } = getContext("grid")
</script>
<div class="floating-add-row" on:click={() => dispatch("add-row-inline")}>
<Icon name="Add" size="L" color="white" />
</div>
<style>
.floating-add-row {
position: absolute;
bottom: 32px;
left: 32px;
height: 50px;
width: 50px;
border-radius: 50%;
background: var(--spectrum-global-color-blue-400);
display: grid;
place-items: center;
}
.floating-add-row:hover {
background: var(--spectrum-global-color-blue-500);
cursor: pointer;
}
</style>

View File

@ -23,7 +23,6 @@
import AddRowButton from "../controls/AddRowButton.svelte" import AddRowButton from "../controls/AddRowButton.svelte"
import RowHeightButton from "../controls/RowHeightButton.svelte" import RowHeightButton from "../controls/RowHeightButton.svelte"
import NewRowTop from "./NewRowTop.svelte" import NewRowTop from "./NewRowTop.svelte"
import FloatingAddRowButton from "../controls/FloatingAddRowButton.svelte"
import { import {
MaxCellRenderHeight, MaxCellRenderHeight,
MaxCellRenderWidthOverflow, MaxCellRenderWidthOverflow,
@ -129,14 +128,11 @@
<HeaderRow /> <HeaderRow />
<GridBody /> <GridBody />
</div> </div>
<NewRowTop />
<div class="overlays"> <div class="overlays">
<NewRowTop />
<ResizeOverlay /> <ResizeOverlay />
<ReorderOverlay /> <ReorderOverlay />
<BetaButton /> <BetaButton />
{#if allowAddRows}
<FloatingAddRowButton />
{/if}
<ScrollOverlay /> <ScrollOverlay />
<MenuOverlay /> <MenuOverlay />
</div> </div>

View File

@ -4,7 +4,7 @@
import { Icon, Button } from "@budibase/bbui" import { Icon, Button } from "@budibase/bbui"
import GridScrollWrapper from "./GridScrollWrapper.svelte" import GridScrollWrapper from "./GridScrollWrapper.svelte"
import DataCell from "../cells/DataCell.svelte" import DataCell from "../cells/DataCell.svelte"
import { fly } from "svelte/transition" import { fade } from "svelte/transition"
import { GutterWidth } from "../lib/constants" import { GutterWidth } from "../lib/constants"
const { const {
@ -14,11 +14,11 @@
scroll, scroll,
config, config,
dispatch, dispatch,
visibleColumns,
rows, rows,
showHScrollbar, showHScrollbar,
tableId, tableId,
subscribe, subscribe,
renderedColumns,
scrollLeft, scrollLeft,
} = getContext("grid") } = getContext("grid")
@ -26,7 +26,7 @@
let newRow = {} let newRow = {}
let touched = false let touched = false
$: firstColumn = $stickyColumn || $visibleColumns[0] $: firstColumn = $stickyColumn || $renderedColumns[0]
$: rowHovered = $hoveredRowId === "new" $: rowHovered = $hoveredRowId === "new"
$: rowFocused = $focusedCellId?.startsWith("new-") $: rowFocused = $focusedCellId?.startsWith("new-")
$: width = GutterWidth + ($stickyColumn?.width || 0) $: width = GutterWidth + ($stickyColumn?.width || 0)
@ -52,11 +52,14 @@
const cancel = () => { const cancel = () => {
isAdding = false isAdding = false
$focusedCellId = null
$hoveredRowId = null
} }
const startAdding = () => { const startAdding = () => {
newRow = {} newRow = {}
isAdding = true isAdding = true
$hoveredRowId = "new"
if (firstColumn) { if (firstColumn) {
$focusedCellId = `new-${firstColumn.name}` $focusedCellId = `new-${firstColumn.name}`
} }
@ -72,74 +75,78 @@
dispatch("add-row") dispatch("add-row")
} }
const handleKeyPress = e => {
if (!isAdding) {
return
}
if (e.key === "Escape") {
cancel()
}
}
onMount(() => subscribe("add-row-inline", startAdding)) onMount(() => subscribe("add-row-inline", startAdding))
onMount(() => {
document.addEventListener("keydown", handleKeyPress)
return () => {
document.removeEventListener("keydown", handleKeyPress)
}
})
</script> </script>
<!-- Only show new row functionality if we have any columns --> <!-- Only show new row functionality if we have any columns -->
{#if isAdding} {#if isAdding}
<div class="container" transition:fly={{ y: 20, duration: 130 }}> <div class="container">
<div class="content" class:above-scrollbar={$showHScrollbar}> <div
<div class="sticky-column"
class="new-row" transition:fade={{ duration: 130 }}
on:mouseenter={() => ($hoveredRowId = "new")} style="flex: 0 0 {width}px"
on:mouseleave={() => ($hoveredRowId = null)} class:scrolled={$scrollLeft > 0}
> >
<div <GridCell width={GutterWidth} {rowHovered} rowFocused>
class="sticky-column" <div class="gutter">
style="flex: 0 0 {width}px" <div class="number">1</div>
class:scrolled={$scrollLeft > 0} {#if $config.allowExpandRows}
> <Icon name="Maximize" size="S" hoverable on:click={addViaModal} />
<GridCell width={GutterWidth} {rowHovered} rowFocused>
<div class="gutter">
<div class="number">1</div>
{#if $config.allowExpandRows}
<Icon
name="Maximize"
size="S"
hoverable
on:click={addViaModal}
/>
{/if}
</div>
</GridCell>
{#if $stickyColumn}
{@const cellId = `new-${$stickyColumn.name}`}
<DataCell
{cellId}
rowFocused
column={$stickyColumn}
row={newRow}
focused={$focusedCellId === cellId}
width={$stickyColumn.width}
{updateValue}
rowIdx={0}
/>
{/if} {/if}
</div> </div>
</GridCell>
<GridScrollWrapper scrollHorizontally wheelInteractive> {#if $stickyColumn}
<div class="row"> {@const cellId = `new-${$stickyColumn.name}`}
{#each $visibleColumns as column} <DataCell
{@const cellId = `new-${column.name}`} {cellId}
{#key cellId} rowFocused
<DataCell column={$stickyColumn}
{cellId} row={newRow}
{column} focused={$focusedCellId === cellId}
row={newRow} width={$stickyColumn.width}
{rowHovered} {updateValue}
focused={$focusedCellId === cellId} rowIdx={0}
{rowFocused} />
width={column.width} {/if}
{updateValue}
rowIdx={0}
/>
{/key}
{/each}
</div>
</GridScrollWrapper>
</div>
</div> </div>
<div class="buttons"> <div class="normal-columns" transition:fade={{ duration: 130 }}>
<GridScrollWrapper scrollHorizontally wheelInteractive>
<div class="row">
{#each $renderedColumns as column}
{@const cellId = `new-${column.name}`}
{#key cellId}
<DataCell
{cellId}
{column}
{rowFocused}
{rowHovered}
{updateValue}
row={newRow}
focused={$focusedCellId === cellId}
width={column.width}
rowIdx={0}
/>
{/key}
{/each}
</div>
</GridScrollWrapper>
</div>
<div class="buttons" transition:fade={{ duration: 130 }}>
<Button size="M" cta on:click={addRow}>Save</Button> <Button size="M" cta on:click={addRow}>Save</Button>
<Button size="M" secondary newStyles on:click={cancel}>Cancel</Button> <Button size="M" secondary newStyles on:click={cancel}>Cancel</Button>
</div> </div>
@ -148,17 +155,22 @@
<style> <style>
.container { .container {
pointer-events: none;
position: absolute; position: absolute;
top: var(--row-height); top: var(--default-row-height);
left: 0; left: 0;
width: 100%; width: 100%;
padding-bottom: 800px; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: row;
align-items: stretch; align-items: stretch;
} }
.container:before { .container :global(.cell) {
--cell-background: var(--spectrum-global-color-gray-100);
}
/* Add overlays independently behind both separate z-indexed column containers */
.sticky-column:before,
.normal-columns:before {
position: absolute; position: absolute;
content: ""; content: "";
left: 0; left: 0;
@ -167,56 +179,17 @@
width: 100%; width: 100%;
background: var(--cell-background); background: var(--cell-background);
opacity: 0.8; opacity: 0.8;
z-index: -1;
}
.content {
pointer-events: all;
background: var(--background);
border-bottom: var(--cell-border);
}
.new-row {
display: flex;
bottom: 0;
left: 0;
width: 100%;
transition: margin-bottom 130ms ease-out;
}
.new-row :global(.cell) {
--cell-background: var(--background) !important;
border-bottom: none;
} }
/* Sticky column styles */
.sticky-column { .sticky-column {
display: flex; display: flex;
z-index: 1; z-index: 2;
position: relative; position: relative;
} }
/* Don't show borders between cells in the sticky column */
.sticky-column :global(.cell:not(:last-child)) { .sticky-column :global(.cell:not(:last-child)) {
border-right: none; border-right: none;
} }
.row {
width: 0;
display: flex;
}
/* Add shadow when scrolled */
.sticky-column.scrolled {
/*box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.1);*/
}
.sticky-column.scrolled:after {
content: "";
width: 10px;
height: 100%;
background: linear-gradient(to right, rgba(0, 0, 0, 0.05), transparent);
left: 100%;
top: 0;
position: absolute;
}
/* Styles for gutter */
.gutter { .gutter {
flex: 1 1 auto; flex: 1 1 auto;
display: grid; display: grid;
@ -225,17 +198,6 @@
grid-template-columns: 1fr auto; grid-template-columns: 1fr auto;
gap: var(--cell-spacing); gap: var(--cell-spacing);
} }
/* Floating buttons */
.buttons {
display: flex;
flex-direction: row;
gap: 8px;
margin: 24px 0 0 var(--gutter-width);
pointer-events: all;
align-self: flex-start;
}
.number { .number {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -243,4 +205,25 @@
align-items: center; align-items: center;
color: var(--spectrum-global-color-gray-500); color: var(--spectrum-global-color-gray-500);
} }
/* Normal column styles */
.normal-columns {
flex: 1 1 auto;
}
.row {
width: 0;
display: flex;
}
/* Floating buttons */
.buttons {
display: flex;
flex-direction: row;
gap: 8px;
pointer-events: all;
z-index: 2;
position: absolute;
top: calc(var(--row-height) + 24px);
left: var(--gutter-width);
}
</style> </style>

View File

@ -10,6 +10,7 @@
stickyColumn, stickyColumn,
focusedCellAPI, focusedCellAPI,
clipboard, clipboard,
dispatch,
} = getContext("grid") } = getContext("grid")
// Global key listener which intercepts all key events // Global key listener which intercepts all key events
@ -19,6 +20,9 @@
if (e.key === "Tab") { if (e.key === "Tab") {
e.preventDefault() e.preventDefault()
focusFirstCell() focusFirstCell()
} else if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
e.preventDefault()
dispatch("add-row-inline")
} }
return return
} }
@ -58,6 +62,8 @@
clipboard.actions.paste() clipboard.actions.paste()
} }
break break
case "Enter":
dispatch("add-row-inline")
} }
} else { } else {
switch (e.key) { switch (e.key) {