v0.26.2 3cd9d2e

ConfigShell.svelte RawHistoryFolder

1<script lang="ts">
2  import { onMount } from 'svelte';
3  import { Home } from '@lucide/svelte';
4
5  interface Props {
6    children?: import('svelte').Snippet;
7  }
8
9  let { children }: Props = $props();
10
11  function navigateWithViewTransition(url: string) {
12    if (typeof document.startViewTransition !== 'function') {
13      window.location.href = url;
14      return;
15    }
16
17    const transition = document.startViewTransition(() => {
18      document.documentElement.dataset.vt = 'leaving';
19    });
20
21    transition.finished.finally(() => {
22      window.location.href = url;
23    });
24  }
25
26  onMount(() => {
27    // Avoid default WebKit focus rings.
28    document.documentElement.dataset.vt = 'ready';
29  });
30</script>
31
32<svelte:head>
33  <title>dumb://config</title>
34  <meta name="description" content="Dumber Browser - Settings" />
35  <!-- eslint-disable-next-line svelte/no-at-html-tags -- trusted static styles for shell initialization -->
36  {@html `<style>
37    html, body { margin: 0; padding: 0; }
38    html { background: var(--background, #0a0a0a); }
39    body { background: var(--background, #0a0a0a); color: var(--foreground, #e5e5e5); }
40    *:focus { outline: none !important; }
41    *:focus-visible { outline: none !important; }
42    button:focus, input:focus, a:focus { outline: none !important; box-shadow: none !important; }
43    * { -webkit-overflow-scrolling: touch; }
44  </style>`}
45</svelte:head>
46
47<div class="config-shell browser-ui">
48  <div class="terminal-frame">
49    <header class="terminal-header">
50      <div class="header-left">
51        <span class="terminal-path">dumb://config</span>
52      </div>
53      <div class="header-right">
54        <button
55          class="action-button"
56          type="button"
57          onclick={() => navigateWithViewTransition('dumb://home')}
58          title="Back to Home"
59        >
60          <Home size={14} strokeWidth={2} />
61          <span class="button-text">HOME</span>
62        </button>
63      </div>
64    </header>
65
66    <main class="terminal-body scrollable">
67      {#if children}
68        {@render children()}
69      {/if}
70    </main>
71
72    <footer class="terminal-footer">
73      <span class="footer-text">Dumber Browser</span>
74    </footer>
75  </div>
76</div>
77
78<style>
79  :global(html),
80  :global(body) {
81    height: 100%;
82  }
83
84  :global(body) {
85    overflow: hidden;
86    overscroll-behavior: contain;
87  }
88
89  .config-shell {
90    height: 100vh;
91    min-height: 100vh;
92    display: flex;
93    flex-direction: column;
94    font-family: ui-monospace, 'Fira Code', 'Cascadia Code', Menlo, Monaco, Consolas, monospace;
95    line-height: 1.5;
96    color: var(--foreground);
97    background: var(--background);
98    overflow: hidden;
99  }
100
101  .terminal-frame {
102    flex: 1;
103    display: grid;
104    grid-template-rows: auto 1fr auto;
105    width: 100%;
106    height: 100%;
107    background: color-mix(in srgb, var(--card) 60%, var(--background) 40%);
108  }
109
110  :global(.dark) .terminal-frame {
111    box-shadow: 0 24px 48px -12px rgb(0 0 0 / 0.5);
112  }
113
114  .terminal-header {
115    display: flex;
116    align-items: center;
117    justify-content: space-between;
118    gap: 1rem;
119    padding: 0.75rem 1rem;
120    min-height: 3.5rem;
121    border-bottom: 1px solid var(--border);
122    background: color-mix(in srgb, var(--background) 90%, var(--card) 10%);
123    position: sticky;
124    top: 0;
125    z-index: 5;
126  }
127
128  .header-left {
129    display: flex;
130    align-items: center;
131    gap: 1.5rem;
132  }
133
134  .terminal-path {
135    font-size: 0.8rem;
136    font-weight: 600;
137    color: var(--primary, #4ade80);
138    letter-spacing: 0.05em;
139  }
140
141  .header-right {
142    display: flex;
143    align-items: center;
144    gap: 0.5rem;
145  }
146
147  .action-button {
148    display: flex;
149    align-items: center;
150    gap: 0.5rem;
151    padding: 0.4rem 0.75rem;
152    font-size: 0.7rem;
153    font-weight: 500;
154    letter-spacing: 0.08em;
155    color: var(--muted-foreground);
156    background: transparent;
157    border-width: 1px;
158    border-style: solid;
159    border-color: var(--border);
160    cursor: pointer;
161    transition: all 120ms ease;
162  }
163
164  .action-button:hover,
165  .action-button:focus-visible {
166    color: var(--foreground);
167    border-color: color-mix(in srgb, var(--border) 50%, var(--foreground) 50%);
168    background: color-mix(in srgb, var(--card) 30%, transparent);
169    outline: none;
170  }
171
172  .terminal-body {
173    display: flex;
174    flex-direction: column;
175    min-height: 0;
176    overflow: hidden;
177    background: var(--background);
178  }
179
180  .terminal-body.scrollable {
181    overflow-y: auto;
182    -webkit-overflow-scrolling: touch;
183    touch-action: pan-y;
184  }
185
186  .terminal-footer {
187    display: flex;
188    align-items: center;
189    justify-content: center;
190    padding: 0.75rem 1rem;
191    border-top: 1px solid var(--border);
192    background: color-mix(in srgb, var(--background) 92%, var(--card) 8%);
193  }
194
195  .footer-text {
196    font-size: 0.7rem;
197    letter-spacing: 0.08em;
198    color: var(--muted-foreground);
199  }
200
201  /* View Transition helpers */
202  :global(html[data-vt='leaving']) {
203    view-transition-name: config-root;
204  }
205
206  :global(::view-transition-old(config-root)) {
207    animation: vt-fade-out 180ms ease both;
208  }
209
210  :global(::view-transition-new(config-root)) {
211    animation: vt-fade-in 220ms ease both;
212  }
213
214  @keyframes vt-fade-out {
215    to {
216      opacity: 0;
217      transform: translateY(6px);
218    }
219  }
220
221  @keyframes vt-fade-in {
222    from {
223      opacity: 0;
224      transform: translateY(-6px);
225    }
226  }
227</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