Skip to content

Commit 4d4bac8

Browse files
committed
add: triggered based focus.
1 parent eb40103 commit 4d4bac8

File tree

5 files changed

+95
-42
lines changed

5 files changed

+95
-42
lines changed

src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte

Lines changed: 78 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,8 @@
7272
import { chunks } from '$lib/helpers/array';
7373
import { Submit, trackEvent } from '$lib/actions/analytics';
7474
75-
import IndexesSuggestions from '../(suggestions)/indexes.svelte';
76-
import { showIndexesSuggestions, tableColumnSuggestions } from '../(suggestions)';
7775
import { isTabletViewport } from '$lib/stores/viewport';
76+
import IndexesSuggestions from '../(suggestions)/indexes.svelte';
7877
7978
let editRow: EditRow;
8079
let editRelatedRow: EditRelatedRow;
@@ -87,6 +86,33 @@
8786
8887
let columnCreationHandler: ((response: RealtimeResponse) => void) | null = null;
8988
89+
// manual management of focus is needed!
90+
const autoFocusAction = (node: HTMLElement, shouldFocus: boolean) => {
91+
const button = node.querySelector('button');
92+
if (!button) return;
93+
94+
const handleBlur = () => button.classList.remove('focus-visible');
95+
const applyFocus = (focus: boolean) => {
96+
if (focus) {
97+
button.classList.add('focus-visible');
98+
button.focus();
99+
} else {
100+
button.classList.remove('focus-visible');
101+
}
102+
};
103+
104+
button.addEventListener('blur', handleBlur);
105+
applyFocus(shouldFocus);
106+
107+
return {
108+
update: applyFocus,
109+
destroy() {
110+
button.removeEventListener('blur', handleBlur);
111+
button.classList.remove('focus-visible');
112+
}
113+
};
114+
};
115+
90116
onMount(() => {
91117
expandTabs.set(preferences.getKey('tableHeaderExpanded', true));
92118
@@ -464,47 +490,56 @@
464490
{@const isLastRow = currentIndex >= rows.length - 1}
465491

466492
{#if !$isTabletViewport}
467-
<Button
468-
icon
469-
text
470-
size="xs"
471-
on:click={() => {
472-
if (currentIndex > 0) {
473-
databaseRowSheetOptions.update((opts) => ({
474-
...opts,
475-
row: rows[currentIndex - 1],
476-
rowIndex: currentIndex - 1
477-
}));
478-
}
479-
}}
480-
disabled={isFirstRow}>
481-
<Icon icon={IconChevronUp} />
482-
</Button>
483-
484-
<Button
485-
icon
486-
text
487-
size="xs"
488-
on:click={() => {
489-
if (currentIndex < rows.length - 1) {
490-
databaseRowSheetOptions.update((opts) => ({
491-
...opts,
492-
row: rows[currentIndex + 1],
493-
rowIndex: currentIndex + 1
494-
}));
495-
}
496-
}}
497-
disabled={isLastRow}>
498-
<Icon icon={IconChevronDown} />
499-
</Button>
493+
{@const shouldFocusPrev = !$databaseRowSheetOptions.autoFocus && !isFirstRow}
494+
{@const shouldFocusNext =
495+
!$databaseRowSheetOptions.autoFocus && isFirstRow && !isLastRow}
496+
497+
<div use:autoFocusAction={shouldFocusPrev} class:nav-button-wrapper={shouldFocusPrev}>
498+
<Button
499+
icon
500+
text
501+
size="xs"
502+
on:click={() => {
503+
if (currentIndex > 0) {
504+
databaseRowSheetOptions.update((opts) => ({
505+
...opts,
506+
row: rows[currentIndex - 1],
507+
rowIndex: currentIndex - 1
508+
}));
509+
}
510+
}}
511+
disabled={isFirstRow}>
512+
<Icon icon={IconChevronUp} />
513+
</Button>
514+
</div>
515+
516+
<div use:autoFocusAction={shouldFocusNext} class:nav-button-wrapper={shouldFocusNext}>
517+
<Button
518+
icon
519+
text
520+
size="xs"
521+
on:click={() => {
522+
if (currentIndex < rows.length - 1) {
523+
databaseRowSheetOptions.update((opts) => ({
524+
...opts,
525+
row: rows[currentIndex + 1],
526+
rowIndex: currentIndex + 1
527+
}));
528+
}
529+
}}
530+
disabled={isLastRow}>
531+
<Icon icon={IconChevronDown} />
532+
</Button>
533+
</div>
500534
{/if}
501535
{/snippet}
502536

503537
{#key currentRowId}
504538
<EditRow
505539
bind:this={editRow}
506540
bind:row={$databaseRowSheetOptions.row}
507-
bind:rowId={$databaseRowSheetOptions.rowId} />
541+
bind:rowId={$databaseRowSheetOptions.rowId}
542+
autoFocus={$databaseRowSheetOptions.autoFocus} />
508543
{/key}
509544
</SideSheet>
510545

@@ -574,3 +609,10 @@
574609
</Dialog>
575610

576611
<IndexesSuggestions />
612+
613+
<style lang="scss">
614+
// not the best solution but needed!
615+
.nav-button-wrapper :global(button.focus-visible) {
616+
outline: var(--border-width-l) solid var(--border-focus);
617+
}
618+
</style>

src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/layout/sidesheet.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
</Layout.Stack>
9393

9494
{#if topEndActions}
95-
<Layout.Stack direction="row" gap="m" alignItems="center" inline>
95+
<Layout.Stack direction="row" gap="xs" alignItems="center" inline>
9696
{@render topEndActions()}
9797
</Layout.Stack>
9898
{/if}

src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/rows/edit.svelte

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@
2525
2626
let {
2727
row = $bindable(),
28-
rowId = $bindable(null)
28+
rowId = $bindable(null),
29+
autoFocus = true
2930
}: {
3031
row?: Models.Row | null;
3132
rowId?: string | null;
33+
autoFocus?: boolean;
3234
} = $props();
3335
3436
let loading = $state(false);
@@ -82,7 +84,9 @@
8284
$effect(() => {
8385
if (row) {
8486
work = initWork();
85-
requestAnimationFrame(() => focusFirstInput());
87+
if (autoFocus) {
88+
requestAnimationFrame(() => focusFirstInput());
89+
}
8690
} else {
8791
work = null;
8892
}

src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/spreadsheet.svelte

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,7 @@
809809
const focusedRow = $paginatedRows.items.find((row) => row.$id === focusedRowId);
810810

811811
previouslyFocusedElement = document.activeElement;
812+
$databaseRowSheetOptions.autoFocus = false;
812813
onSelectSheetOption('update', null, 'row', focusedRow);
813814
}}>
814815
<svelte:fragment slot="header" let:root>
@@ -935,6 +936,7 @@
935936
hide();
936937
previouslyFocusedElement =
937938
document.activeElement;
939+
$databaseRowSheetOptions.autoFocus = false;
938940
onSelectSheetOption(
939941
'update',
940942
null,
@@ -985,8 +987,10 @@
985987
<SheetOptions
986988
type="row"
987989
column={rowColumn}
988-
onSelect={(option) =>
989-
onSelectSheetOption(option, null, 'row', row)}
990+
onSelect={(option) => {
991+
$databaseRowSheetOptions.autoFocus = true;
992+
onSelectSheetOption(option, null, 'row', row);
993+
}}
990994
onVisibilityChanged={(visible) => {
991995
canShowDatetimePopover = !visible;
992996
}}>
@@ -1113,6 +1117,7 @@
11131117
rowColumn
11141118
);
11151119
} else {
1120+
$databaseRowSheetOptions.autoFocus = true;
11161121
onSelectSheetOption('update', null, 'row', row);
11171122
}
11181123
}} />

src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/store.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,16 @@ export const databaseRowSheetOptions = writable<
7272
rowId?: string;
7373
rows: Models.Row[];
7474
rowIndex?: number;
75+
autoFocus?: boolean;
7576
}
7677
>({
7778
title: null,
7879
show: false,
7980
row: null,
8081
rowId: null, // for loading from a given id
8182
rows: [],
82-
rowIndex: -1
83+
rowIndex: -1,
84+
autoFocus: true
8385
});
8486

8587
export const databaseRelatedRowSheetOptions = writable<

0 commit comments

Comments
 (0)