v0.27.1 c78ce83

FavoriteGrid.svelte RawHistoryFolder

1<script lang="ts">
2  import type { Favorite } from '../types';
3  import { homepageState } from '../state.svelte';
4  import FavoriteCard from './FavoriteCard.svelte';
5
6  interface Props {
7    favorites: Favorite[];
8    onSelectFavorite?: (fav: Favorite) => void;
9    onEditFavorite?: (fav: Favorite) => void;
10  }
11
12  let { favorites, onSelectFavorite, onEditFavorite }: Props = $props();
13
14  let containerRef = $state<HTMLElement | null>(null);
15
16  const getFocusedFavorite = () => {
17    return favorites[homepageState.focusedIndex] ?? null;
18  };
19
20  // Track previous focused index to only scroll on actual navigation
21  let prevFocusedIndex = $state(-1);
22
23  // Scroll focused item into view when focusedIndex changes via keyboard navigation
24  $effect(() => {
25    // Skip if panel not active or command palette is open
26    if (!containerRef || homepageState.activePanel !== 'favorites') return;
27    if (homepageState.commandPaletteOpen) return;
28
29    const currentIndex = homepageState.focusedIndex;
30
31    // Only scroll if index actually changed (not on initial render or modal close)
32    if (prevFocusedIndex === currentIndex) return;
33    if (prevFocusedIndex === -1) {
34      // First render - just track, don't scroll
35      prevFocusedIndex = currentIndex;
36      return;
37    }
38
39    prevFocusedIndex = currentIndex;
40
41    const focusedFav = getFocusedFavorite();
42    if (!focusedFav) return;
43
44    // Find the focused element by favorite ID
45    const el = containerRef.querySelector(`[data-favorite-id="${focusedFav.id}"]`);
46    if (el) {
47      el.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
48    }
49  });
50</script>
51
52<div class="favorite-grid" bind:this={containerRef}>
53  {#if favorites.length === 0}
54    <div class="empty-state">
55      <span class="empty-icon"></span>
56      <span class="empty-text">NO FAVORITES</span>
57      <span class="empty-hint">Pin sites from history to add them here</span>
58    </div>
59  {:else}
60    {#each favorites as favorite (favorite.id)}
61      <FavoriteCard
62        {favorite}
63        focused={getFocusedFavorite()?.id === favorite.id}
64        onSelect={onSelectFavorite}
65        onEdit={onEditFavorite}
66      />
67    {/each}
68  {/if}
69</div>
70
71<style>
72  .favorite-grid {
73    display: flex;
74    flex-direction: column;
75    gap: 0.5rem;
76  }
77
78  .empty-state {
79    flex: 1;
80    display: flex;
81    flex-direction: column;
82    align-items: center;
83    justify-content: center;
84    gap: 0.5rem;
85    padding: 2rem;
86    color: var(--muted-foreground);
87    text-align: center;
88    border: 1px dashed var(--border);
89    background: color-mix(in srgb, var(--background) 95%, var(--card) 5%);
90  }
91
92  .empty-icon {
93    font-size: 1.5rem;
94    opacity: 0.5;
95  }
96
97  .empty-text {
98    font-size: 0.75rem;
99    font-weight: 600;
100    letter-spacing: 0.12em;
101  }
102
103  .empty-hint {
104    font-size: 0.68rem;
105    letter-spacing: 0.06em;
106    opacity: 0.7;
107  }
108</style>

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close