fic: notification spacing on phone.

This commit is contained in:
Darshan
2025-09-24 18:39:40 +05:30
parent e62e58a149
commit 3e9480a3fa
4 changed files with 189 additions and 119 deletions
@@ -140,6 +140,11 @@
.layout-level-progress-bars {
width: 100%;
align-items: center;
box-sizing: border-box;
}
:global(main:has([data-side-sheet-visible='true']) .layout-level-progress-bars) {
visibility: hidden;
}
}
</style>
@@ -103,7 +103,6 @@
// hook the actual horizontal scroller once
if (!hScroller || !hScroller.isConnected) {
// TODO: @itznotabug, might not need this. check later.
const previousScrollLeft = hScroller?.scrollLeft || 0;
hScroller = findHorizontalScroller(headerElement);
if (hScroller) {
@@ -205,6 +204,32 @@
spreadsheetContainer.style.setProperty('--group-width', `${width + 2}px`);
};
// only for mobile, we can remove if not needed!
const scrollToFirstCustomColumn = () => {
if (!$isSmallViewport || customColumns.length === 0) return;
if (!headerElement || !headerElement.isConnected) {
headerElement = spreadsheetContainer.querySelector('[role="rowheader"]');
}
if (!headerElement) return;
const firstCustomColumnCell = headerElement.querySelector<HTMLElement>(
`[role="cell"][data-header="true"][data-column-id="${customColumns[0]?.key}"]`
);
if (firstCustomColumnCell && hScroller) {
const cellRect = firstCustomColumnCell.getBoundingClientRect();
const scrollerRect = hScroller.getBoundingClientRect();
const scrollLeft = hScroller.scrollLeft + cellRect.left - scrollerRect.left - 40;
hScroller.scrollTo({
left: Math.max(0, scrollLeft),
behavior: 'smooth'
});
}
};
const recalcAll = () => {
updateOverlayHeight();
updateOverlayBounds();
@@ -301,7 +326,7 @@
$tableColumnSuggestions.thinking = true;
try {
await sleep(5000);
await sleep(1250);
const suggestedColumns = isDev
? mockSuggestions
: ((await sdk
@@ -325,6 +350,8 @@
// Set hasTransitioned to disable future animations after initial state change
if (customColumns.length > 0) {
setTimeout(() => (hasTransitioned = true), 300); // After transition completes
setTimeout(() => scrollToFirstCustomColumn(), 100);
}
} catch (error) {
addNotification({
@@ -343,6 +370,10 @@
function onPopoverShowStateChanged(value: boolean) {
showFloatingBar = !value;
if ($isSmallViewport && rangeOverlayEl) {
rangeOverlayEl.style.opacity = value ? '0' : '1';
}
const currentScrollLeft = hScroller?.scrollLeft || 0;
tick().then(() => {
@@ -502,6 +533,10 @@
cancelAnimationFrame(scrollAnimationFrame);
}
});
function isCustomColumn(id: string) {
return !['$id', '$createdAt', '$updatedAt', 'actions'].includes(id);
}
</script>
<svelte:window on:resize={recalcAll} on:scroll={recalcAll} />
@@ -520,67 +555,6 @@
class:thinking={$tableColumnSuggestions.thinking}
class:no-transition={hasTransitioned && customColumns.length > 0}>
</div>
{#if $tableColumnSuggestions.thinking}
<div class="floating-action-wrapper thinking">
<FloatingActionBar>
<svelte:fragment slot="start">
<Layout.Stack direction="row" gap="xxs" alignItems="center">
<Spinner size="s" />
<Typography.Text style="white-space: nowrap">
Thinking of column suggestions
</Typography.Text>
</Layout.Stack>
</svelte:fragment>
<svelte:fragment slot="end">
<Button.Button
size="xs"
variant="secondary"
on:click={() => {
$tableColumnSuggestions.context = null;
$tableColumnSuggestions.enabled = false;
$tableColumnSuggestions.thinking = false;
}}
>Cancel
</Button.Button>
</svelte:fragment>
</FloatingActionBar>
</div>
{:else if customColumns.length > 0 && showFloatingBar}
<div class="floating-action-wrapper expanded">
<FloatingActionBar>
<svelte:fragment slot="start">
{#if creatingColumns}
<Spinner size="s" />
{/if}
<Typography.Text style="white-space: nowrap">
{creatingColumns
? 'Creating columns...'
: $isSmallViewport
? 'Review and edit columns'
: 'Review and edit suggested columns before applying'}
</Typography.Text>
</svelte:fragment>
<svelte:fragment slot="end">
{#if !creatingColumns}
<Layout.Stack direction="row" gap="xs" alignItems="center" inline>
<Button.Button
size="xs"
variant="text"
on:click={() => (confirmDismiss = true)}
>Dismiss
</Button.Button>
<Button.Button size="xs" variant="primary" on:click={createColumns}
>Apply
</Button.Button>
</Layout.Stack>
{/if}
</svelte:fragment>
</FloatingActionBar>
</div>
{/if}
</div>
<SpreadsheetContainer>
@@ -592,6 +566,7 @@
bottomActionClick={() => {}}>
<svelte:fragment slot="header" let:root>
{#each spreadsheetColumns as column, index (index)}
{@const isColumnInteractable = isCustomColumn(column.id)}
{#if column.isAction}
<Spreadsheet.Header.Cell column="actions" {root}>
<Button.Button icon variant="extra-compact">
@@ -607,12 +582,18 @@
? '--non-overlay-icon-color'
: '--overlay-icon-color'}
<Options onShowStateChanged={onPopoverShowStateChanged}>
<Options
enabled={isColumnInteractable}
onShowStateChanged={onPopoverShowStateChanged}>
{#snippet children(toggle)}
<Spreadsheet.Header.Cell
{root}
column={column.id}
on:contextmenu={toggle}>
on:contextmenu={(event) => {
if (isColumnInteractable) {
toggle(event);
}
}}>
<Layout.Stack
direction="row"
alignItems="center"
@@ -624,7 +605,12 @@
<Button.Button
size="xs"
variant="extra-compact"
on:click={toggle}>
disabled={!isColumnInteractable}
on:click={(event) => {
if (isColumnInteractable) {
toggle(event);
}
}}>
<Icon
size="s"
color={columnIconColor}
@@ -697,42 +683,42 @@
)}
{@const ColumnComponent = selectedOption?.component}
<Layout.Stack gap="xl">
<Layout.Stack gap="xl">
<Layout.Stack direction="row">
<InputText
id="key"
label="Key"
placeholder="Enter key"
bind:value={columnObj.key}
autofocus
required
pattern="^[A-Za-z0-9][A-Za-z0-9._\-]*$" />
<Layout.Stack
direction={$isSmallViewport ? 'column' : 'row'}>
<InputText
id="key"
label="Key"
placeholder="Enter key"
bind:value={columnObj.key}
autofocus
required
pattern="^[A-Za-z0-9][A-Za-z0-9._\-]*$" />
<InputSelect
id="type"
required
label="Type"
value={selectedOption?.name || 'String'}
on:change={(e) => {
const newOption = columnOptions.find(
(opt) => opt.name === e.detail
);
if (newOption) {
updateColumn(column.id, {
type: newOption.type,
format: newOption.format || null
});
}
}}
options={basicColumnOptions.map((col) => {
return {
label: col.name,
value: col.name,
leadingIcon: col.icon
};
})} />
</Layout.Stack>
<InputSelect
id="type"
required
label="Type"
value={selectedOption?.name || 'String'}
on:change={(e) => {
const newOption = columnOptions.find(
(opt) => opt.name === e.detail
);
if (newOption) {
updateColumn(column.id, {
type: newOption.type,
format: newOption.format || null
});
}
}}
options={basicColumnOptions.map((col) => {
return {
label: col.name,
value: col.name,
leadingIcon: col.icon
};
})} />
</Layout.Stack>
{#if ColumnComponent}
<ColumnComponent data={columnObj} />
{/if}
@@ -749,8 +735,70 @@
<div
class="spreadsheet-fade-bottom"
data-collapsed-tabs={!$expandTabs}
style="height: var(--overlay-height);">
style="height: var(--overlay-height);"
style:opacity={showFloatingBar ? '1' : '0'}>
</div>
{#if $tableColumnSuggestions.thinking}
<div class="floating-action-wrapper thinking">
<FloatingActionBar>
<svelte:fragment slot="start">
<Layout.Stack direction="row" gap="xxs" alignItems="center">
<Spinner size="s" />
<Typography.Text style="white-space: nowrap">
Thinking of column suggestions
</Typography.Text>
</Layout.Stack>
</svelte:fragment>
<svelte:fragment slot="end">
<Button.Button
size="xs"
variant="secondary"
on:click={() => {
$tableColumnSuggestions.context = null;
$tableColumnSuggestions.enabled = false;
$tableColumnSuggestions.thinking = false;
}}
>Cancel
</Button.Button>
</svelte:fragment>
</FloatingActionBar>
</div>
{:else if customColumns.length > 0 && showFloatingBar}
<div class="floating-action-wrapper expanded">
<FloatingActionBar>
<svelte:fragment slot="start">
{#if creatingColumns}
<Spinner size="s" />
{/if}
<Typography.Text style="white-space: nowrap">
{creatingColumns
? 'Creating columns...'
: $isSmallViewport
? 'Review and edit columns'
: 'Review and edit suggested columns before applying'}
</Typography.Text>
</svelte:fragment>
<svelte:fragment slot="end">
{#if !creatingColumns}
<Layout.Stack direction="row" gap="xs" alignItems="center" inline>
<Button.Button
size="xs"
variant="text"
on:click={() => (confirmDismiss = true)}
>Dismiss
</Button.Button>
<Button.Button size="xs" variant="primary" on:click={createColumns}
>Apply
</Button.Button>
</Layout.Stack>
{/if}
</svelte:fragment>
</FloatingActionBar>
</div>
{/if}
</div>
<Confirm
@@ -837,20 +885,10 @@
& .floating-action-wrapper {
& :global(:first-child) {
z-index: 21;
left: calc(50% - 40px);
@media (max-width: 768px) {
left: 0;
}
}
&.expanded :global(:first-child) {
left: calc(50% - 40px);
max-width: 525px !important;
@media (max-width: 768px) {
left: 0;
}
}
}
@@ -2,32 +2,59 @@
import type { Snippet } from 'svelte';
import { Popover } from '@appwrite.io/pink-svelte';
import { isSmallViewport } from '$lib/stores/viewport';
import SideSheet from '../table-[table]/layout/sidesheet.svelte';
let {
children,
tooltipChildren,
toggleOnTapClick = true,
onShowStateChanged = null
onShowStateChanged = null,
enabled = true
}: {
children: Snippet<[toggle: (event: Event) => void]>;
tooltipChildren: Snippet<[toggle: (event: Event) => void]>;
toggleOnTapClick: boolean;
toggleOnTapClick?: boolean;
onShowStateChanged?: (showing: boolean) => void;
enabled?: boolean;
} = $props();
let showSheet = $state(false);
$effect(() => {
if (!$isSmallViewport) {
showSheet = false;
}
});
</script>
<Popover let:toggle let:showing placement="bottom-start" portal>
{onShowStateChanged?.(showing)}
<Popover let:toggle let:showing portal padding="none" placement="bottom-start">
{onShowStateChanged?.(showing || showSheet)}
{#if toggleOnTapClick && $isSmallViewport}
<button onclick={toggle} aria-label="Open column review modal">
<button onclick={() => enabled && (showSheet = true)} aria-label="Open column review modal">
{@render children(toggle)}
</button>
{:else}
{@render children(toggle)}
<button style:cursor={enabled ? 'pointer' : undefined}>
{@render children(toggle)}
</button>
{/if}
<div slot="tooltip" let:toggle style:width="480px" style:padding="16px">
<div let:toggle slot="tooltip" style:width="480px" style:padding="16px">
{@render tooltipChildren(toggle)}
</div>
</Popover>
{#if $isSmallViewport}
<SideSheet
bind:show={showSheet}
title="Edit suggested column"
submit={{
text: 'Update',
onClick: () => {
showSheet = false;
}
}}>
{@render tooltipChildren(() => (showSheet = false))}
</SideSheet>
{/if}
@@ -46,7 +46,7 @@
let copyText = $state(undefined);
</script>
<div class="sheet-container">
<div class="sheet-container" data-side-sheet-visible={show}>
<Sheet bind:open={show} {closeOnBlur}>
<div slot="header" style:width="100%">
<Layout.Stack direction="row" justifyContent="space-between" alignItems="center">