detached 411f859

feat(gui): improve omnibox styling with GTK4-native design

- Replace heavy web-overlay shadows with subtle GTK4-style depth cues
- Use palette colors directly for borders instead of mixed formulas
- Invert color hierarchy: lighter container (raised), darker input (recessed)
- Change font from monospace to Fira Sans throughout omnibox
- Normalize letter-spacing and remove uppercase placeholders
- Add 3px left accent border on selected suggestions for better feedback
- Increase favicon size from 16x16 to 24x24px for improved quality
- Add subtle border radius (3px container, 2px input) for GTK4 look
commit
411f8591544d2da70e74ce0ba95819490266f48d
author
bnema · · 2025-11-16 22:05 UTC
committer
bnema · · 2025-11-16 17:08 UTC
parent
956f1eb
signature
unsigned
3 files · +97 -55
M gui/src/components/omnibox/Omnibox.svelte +64 -39
@@ -178,33 +178,49 @@
178178 }
179179
180180 const surfaceMix = isDarkMode ? '55%' : '88%';
181- const inputMix = isDarkMode ? '52%' : '90%';
182- const borderMix = isDarkMode ? '62%' : '85%';
183181 const blurMix = isDarkMode ? '22%' : '12%';
184182
185183 const applyFade = faded && mode === 'find';
186184
185+ // GTK4-style: Container is slightly raised (use surface)
187186 const containerBackground = applyFade
188187 ? `color-mix(in srgb, var(--dynamic-surface) ${surfaceMix}, transparent)`
189188 : 'var(--dynamic-surface)';
189+
190+ // GTK4-style: Input is recessed (darker background)
190191 const inputBackground = applyFade
191- ? `color-mix(in srgb, var(--dynamic-bg) ${inputMix}, transparent)`
192- : 'var(--dynamic-bg)';
193- const borderColor = applyFade
194- ? `color-mix(in srgb, var(--dynamic-border) ${borderMix}, transparent)`
192+ ? isDarkMode
193+ ? `color-mix(in srgb, color-mix(in srgb, var(--dynamic-bg) 85%, black 15%) ${surfaceMix}, transparent)`
194+ : `color-mix(in srgb, color-mix(in srgb, var(--dynamic-bg) 95%, black 5%) ${surfaceMix}, transparent)`
195+ : isDarkMode
196+ ? 'color-mix(in srgb, var(--dynamic-bg) 85%, black 15%)'
197+ : 'color-mix(in srgb, var(--dynamic-bg) 95%, black 5%)';
198+
199+ // GTK4-style: Use palette border directly, slightly darker for input
200+ const containerBorderColor = applyFade
201+ ? `color-mix(in srgb, var(--dynamic-border) ${surfaceMix}, transparent)`
195202 : 'var(--dynamic-border)';
203+
204+ const inputBorderColor = applyFade
205+ ? isDarkMode
206+ ? `color-mix(in srgb, color-mix(in srgb, var(--dynamic-border) 80%, black 20%) ${surfaceMix}, transparent)`
207+ : `color-mix(in srgb, color-mix(in srgb, var(--dynamic-border) 85%, black 15%) ${surfaceMix}, transparent)`
208+ : isDarkMode
209+ ? 'color-mix(in srgb, var(--dynamic-border) 80%, black 20%)'
210+ : 'color-mix(in srgb, var(--dynamic-border) 85%, black 15%)';
211+
196212 const blurTint = `color-mix(in srgb, var(--dynamic-bg) ${blurMix}, transparent)`;
197213
198214 boxElement.style.background = containerBackground;
199215 boxElement.style.color = 'var(--dynamic-text)';
200- boxElement.style.setProperty('--dumber-border-color', borderColor);
216+ boxElement.style.setProperty('--dumber-border-color', containerBorderColor);
201217 // Force the omnibox to use our neutral surfaces so it stays in sync with the shell palette
202- boxElement.style.setProperty('--dumber-omnibox-surface', 'color-mix(in srgb, var(--dynamic-bg) 88%, var(--dynamic-surface) 12%)');
218+ boxElement.style.setProperty('--dumber-omnibox-surface', containerBackground);
203219
204220 inputElement.style.background = inputBackground;
205221 inputElement.style.color = 'var(--dynamic-text)';
206222 inputElement.style.setProperty('--dumber-input-bg', inputBackground);
207- inputElement.style.setProperty('--dumber-input-border-base', borderColor);
223+ inputElement.style.setProperty('--dumber-input-border-base', inputBorderColor);
208224 inputElement.style.setProperty('--dumber-placeholder-color', 'var(--dynamic-muted)');
209225
210226 blurLayerElement.style.setProperty('--dumber-blur-color', blurTint);
@@ -399,17 +415,18 @@
399415 margin-right: 0 !important;
400416 width: {responsiveStyles.width};
401417 padding: {responsiveStyles.padding};
402- font-family: 'JetBrains Mono', 'Fira Code', 'SFMono-Regular', Menlo, monospace;
418+ font-family: 'Fira Sans', system-ui, -apple-system, 'Segoe UI', 'Ubuntu', 'Cantarell', sans-serif;
403419 pointer-events: auto !important;
404420 box-sizing: border-box !important;
405- background: var(--dumber-omnibox-surface, color-mix(in srgb, var(--dynamic-bg) 88%, var(--dynamic-surface) 12%));
421+ background: var(--dumber-omnibox-surface, var(--dynamic-surface));
406422 color: var(--dynamic-text);
407423 border: 1px solid var(--dumber-border-color, var(--dynamic-border));
424+ border-radius: 3px;
408425 box-shadow:
409- 0 20px 60px rgba(0, 0, 0, 0.45),
410- 0 10px 30px rgba(0, 0, 0, 0.35),
411- 0 5px 15px rgba(0, 0, 0, 0.25),
412- inset 0 0 0 1px color-mix(in srgb, var(--dynamic-border) 22%, transparent);
426+ 0 4px 12px rgba(0, 0, 0, 0.2),
427+ 0 2px 6px rgba(0, 0, 0, 0.15),
428+ 0 1px 3px rgba(0, 0, 0, 0.1),
429+ inset 0 1px 0 rgba(255, 255, 255, 0.04);
413430 --dumber-border-color: var(--dynamic-border);"
414431 onmousedown={handleBoxClick}
415432 onmouseenter={handleMouseEnter}
@@ -443,54 +460,62 @@
443460
444461 <style>
445462 .dumber-omnibox-container {
446- background: var(--dumber-omnibox-surface, color-mix(in srgb, var(--dynamic-bg) 88%, var(--dynamic-surface) 12%));
463+ background: var(--dumber-omnibox-surface, var(--dynamic-surface));
447464 color: var(--dynamic-text);
448465 border: 1px solid var(--dumber-border-color, var(--dynamic-border));
449466 transition: background-color 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
450- border-radius: 0;
467+ border-radius: 3px;
451468 box-shadow:
452- 0 20px 60px rgba(0, 0, 0, 0.45),
453- 0 10px 30px rgba(0, 0, 0, 0.35),
454- 0 5px 15px rgba(0, 0, 0, 0.25),
455- inset 0 0 0 1px color-mix(in srgb, var(--dynamic-border) 22%, transparent);
469+ 0 4px 12px rgba(0, 0, 0, 0.2),
470+ 0 2px 6px rgba(0, 0, 0, 0.15),
471+ 0 1px 3px rgba(0, 0, 0, 0.1),
472+ inset 0 1px 0 rgba(255, 255, 255, 0.04);
456473 }
457474
458475 .dumber-omnibox-container:focus-within {
459- border-color: color-mix(in srgb, var(--dumber-border-color, var(--dynamic-border)) 55%, var(--dynamic-text) 45%);
476+ border-color: var(--dynamic-accent);
460477 box-shadow:
461- 0 25px 75px rgba(0, 0, 0, 0.5),
462- 0 15px 40px rgba(0, 0, 0, 0.4),
463- 0 8px 20px rgba(0, 0, 0, 0.3),
464- inset 0 0 0 1px color-mix(in srgb, var(--dynamic-border) 28%, transparent);
478+ 0 6px 16px rgba(0, 0, 0, 0.24),
479+ 0 3px 8px rgba(0, 0, 0, 0.18),
480+ 0 2px 4px rgba(0, 0, 0, 0.12),
481+ inset 0 1px 0 rgba(255, 255, 255, 0.06),
482+ 0 0 0 1px var(--dynamic-accent);
465483 }
466484
467485 :global(.dumber-omnibox-container input) {
468- background: var(--dumber-input-bg, color-mix(in srgb, var(--dynamic-bg) 92%, var(--dynamic-surface) 8%));
486+ background: var(--dumber-input-bg, var(--dynamic-bg));
469487 color: var(--dynamic-text);
470488 border: 1px solid var(--dumber-input-border-color, var(--dynamic-border));
471- transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease;
489+ border-radius: 2px;
490+ box-shadow:
491+ inset 0 1px 2px rgba(0, 0, 0, 0.15),
492+ inset 0 0 0 1px rgba(0, 0, 0, 0.03);
493+ transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease, box-shadow 120ms ease;
472494 font-family:
473- "JetBrains Mono",
474- "Fira Code",
475- "SFMono-Regular",
476- Menlo,
477- monospace;
495+ "Fira Sans",
496+ system-ui,
497+ -apple-system,
498+ "Segoe UI",
499+ "Ubuntu",
500+ "Cantarell",
501+ sans-serif;
478502 font-size: inherit;
479- letter-spacing: 0.05em;
503+ letter-spacing: normal;
480504 text-transform: none;
481505 }
482506
483507 :global(.dumber-omnibox-container input::placeholder) {
484508 color: var(--dynamic-muted);
485- letter-spacing: 0.08em;
486- text-transform: uppercase;
509+ letter-spacing: normal;
510+ text-transform: none;
487511 }
488512
489513 /* Blur layer styles: use `backdrop-filter` but animate opacity only. */
514+ /* GTK4-style: Minimal blur for faded state */
490515 .dumber-omnibox-blur-layer {
491- backdrop-filter: blur(1.5px) saturate(105%);
492- -webkit-backdrop-filter: blur(1.5px) saturate(105%);
493- background: var(--dumber-blur-color, color-mix(in srgb, var(--dynamic-bg) 12%, transparent));
516+ backdrop-filter: blur(0.5px) saturate(102%);
517+ -webkit-backdrop-filter: blur(0.5px) saturate(102%);
518+ background: var(--dumber-blur-color, color-mix(in srgb, var(--dynamic-bg) 8%, transparent));
494519 transition: opacity 140ms ease;
495520 will-change: opacity;
496521 z-index: 0;
@@ -178,33 +178,49 @@
178 }178 }
179 179
180 const surfaceMix = isDarkMode ? '55%' : '88%';180 const surfaceMix = isDarkMode ? '55%' : '88%';
181- const inputMix = isDarkMode ? '52%' : '90%';
182- const borderMix = isDarkMode ? '62%' : '85%';
183 const blurMix = isDarkMode ? '22%' : '12%';181 const blurMix = isDarkMode ? '22%' : '12%';
184 182
185 const applyFade = faded && mode === 'find';183 const applyFade = faded && mode === 'find';
186 184
185+ // GTK4-style: Container is slightly raised (use surface)
187 const containerBackground = applyFade186 const containerBackground = applyFade
188 ? `color-mix(in srgb, var(--dynamic-surface) ${surfaceMix}, transparent)`187 ? `color-mix(in srgb, var(--dynamic-surface) ${surfaceMix}, transparent)`
189 : 'var(--dynamic-surface)';188 : 'var(--dynamic-surface)';
189+
190+ // GTK4-style: Input is recessed (darker background)
190 const inputBackground = applyFade191 const inputBackground = applyFade
191- ? `color-mix(in srgb, var(--dynamic-bg) ${inputMix}, transparent)`192+ ? isDarkMode
192- : 'var(--dynamic-bg)';193+ ? `color-mix(in srgb, color-mix(in srgb, var(--dynamic-bg) 85%, black 15%) ${surfaceMix}, transparent)`
193- const borderColor = applyFade194+ : `color-mix(in srgb, color-mix(in srgb, var(--dynamic-bg) 95%, black 5%) ${surfaceMix}, transparent)`
194- ? `color-mix(in srgb, var(--dynamic-border) ${borderMix}, transparent)`195+ : isDarkMode
196+ ? 'color-mix(in srgb, var(--dynamic-bg) 85%, black 15%)'
197+ : 'color-mix(in srgb, var(--dynamic-bg) 95%, black 5%)';
198+
199+ // GTK4-style: Use palette border directly, slightly darker for input
200+ const containerBorderColor = applyFade
201+ ? `color-mix(in srgb, var(--dynamic-border) ${surfaceMix}, transparent)`
195 : 'var(--dynamic-border)';202 : 'var(--dynamic-border)';
203+
204+ const inputBorderColor = applyFade
205+ ? isDarkMode
206+ ? `color-mix(in srgb, color-mix(in srgb, var(--dynamic-border) 80%, black 20%) ${surfaceMix}, transparent)`
207+ : `color-mix(in srgb, color-mix(in srgb, var(--dynamic-border) 85%, black 15%) ${surfaceMix}, transparent)`
208+ : isDarkMode
209+ ? 'color-mix(in srgb, var(--dynamic-border) 80%, black 20%)'
210+ : 'color-mix(in srgb, var(--dynamic-border) 85%, black 15%)';
211+
196 const blurTint = `color-mix(in srgb, var(--dynamic-bg) ${blurMix}, transparent)`;212 const blurTint = `color-mix(in srgb, var(--dynamic-bg) ${blurMix}, transparent)`;
197 213
198 boxElement.style.background = containerBackground;214 boxElement.style.background = containerBackground;
199 boxElement.style.color = 'var(--dynamic-text)';215 boxElement.style.color = 'var(--dynamic-text)';
200- boxElement.style.setProperty('--dumber-border-color', borderColor);216+ boxElement.style.setProperty('--dumber-border-color', containerBorderColor);
201 // Force the omnibox to use our neutral surfaces so it stays in sync with the shell palette217 // Force the omnibox to use our neutral surfaces so it stays in sync with the shell palette
202- boxElement.style.setProperty('--dumber-omnibox-surface', 'color-mix(in srgb, var(--dynamic-bg) 88%, var(--dynamic-surface) 12%)');218+ boxElement.style.setProperty('--dumber-omnibox-surface', containerBackground);
203 219
204 inputElement.style.background = inputBackground;220 inputElement.style.background = inputBackground;
205 inputElement.style.color = 'var(--dynamic-text)';221 inputElement.style.color = 'var(--dynamic-text)';
206 inputElement.style.setProperty('--dumber-input-bg', inputBackground);222 inputElement.style.setProperty('--dumber-input-bg', inputBackground);
207- inputElement.style.setProperty('--dumber-input-border-base', borderColor);223+ inputElement.style.setProperty('--dumber-input-border-base', inputBorderColor);
208 inputElement.style.setProperty('--dumber-placeholder-color', 'var(--dynamic-muted)');224 inputElement.style.setProperty('--dumber-placeholder-color', 'var(--dynamic-muted)');
209 225
210 blurLayerElement.style.setProperty('--dumber-blur-color', blurTint);226 blurLayerElement.style.setProperty('--dumber-blur-color', blurTint);
@@ -399,17 +415,18 @@
399 margin-right: 0 !important;415 margin-right: 0 !important;
400 width: {responsiveStyles.width};416 width: {responsiveStyles.width};
401 padding: {responsiveStyles.padding};417 padding: {responsiveStyles.padding};
402- font-family: 'JetBrains Mono', 'Fira Code', 'SFMono-Regular', Menlo, monospace;418+ font-family: 'Fira Sans', system-ui, -apple-system, 'Segoe UI', 'Ubuntu', 'Cantarell', sans-serif;
403 pointer-events: auto !important;419 pointer-events: auto !important;
404 box-sizing: border-box !important;420 box-sizing: border-box !important;
405- background: var(--dumber-omnibox-surface, color-mix(in srgb, var(--dynamic-bg) 88%, var(--dynamic-surface) 12%));421+ background: var(--dumber-omnibox-surface, var(--dynamic-surface));
406 color: var(--dynamic-text);422 color: var(--dynamic-text);
407 border: 1px solid var(--dumber-border-color, var(--dynamic-border));423 border: 1px solid var(--dumber-border-color, var(--dynamic-border));
424+ border-radius: 3px;
408 box-shadow:425 box-shadow:
409- 0 20px 60px rgba(0, 0, 0, 0.45),426+ 0 4px 12px rgba(0, 0, 0, 0.2),
410- 0 10px 30px rgba(0, 0, 0, 0.35),427+ 0 2px 6px rgba(0, 0, 0, 0.15),
411- 0 5px 15px rgba(0, 0, 0, 0.25),428+ 0 1px 3px rgba(0, 0, 0, 0.1),
412- inset 0 0 0 1px color-mix(in srgb, var(--dynamic-border) 22%, transparent);429+ inset 0 1px 0 rgba(255, 255, 255, 0.04);
413 --dumber-border-color: var(--dynamic-border);"430 --dumber-border-color: var(--dynamic-border);"
414 onmousedown={handleBoxClick}431 onmousedown={handleBoxClick}
415 onmouseenter={handleMouseEnter}432 onmouseenter={handleMouseEnter}
@@ -443,54 +460,62 @@
443 460
444 <style>461 <style>
445 .dumber-omnibox-container {462 .dumber-omnibox-container {
446- background: var(--dumber-omnibox-surface, color-mix(in srgb, var(--dynamic-bg) 88%, var(--dynamic-surface) 12%));463+ background: var(--dumber-omnibox-surface, var(--dynamic-surface));
447 color: var(--dynamic-text);464 color: var(--dynamic-text);
448 border: 1px solid var(--dumber-border-color, var(--dynamic-border));465 border: 1px solid var(--dumber-border-color, var(--dynamic-border));
449 transition: background-color 140ms ease, border-color 140ms ease, box-shadow 140ms ease;466 transition: background-color 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
450- border-radius: 0;467+ border-radius: 3px;
451 box-shadow:468 box-shadow:
452- 0 20px 60px rgba(0, 0, 0, 0.45),469+ 0 4px 12px rgba(0, 0, 0, 0.2),
453- 0 10px 30px rgba(0, 0, 0, 0.35),470+ 0 2px 6px rgba(0, 0, 0, 0.15),
454- 0 5px 15px rgba(0, 0, 0, 0.25),471+ 0 1px 3px rgba(0, 0, 0, 0.1),
455- inset 0 0 0 1px color-mix(in srgb, var(--dynamic-border) 22%, transparent);472+ inset 0 1px 0 rgba(255, 255, 255, 0.04);
456 }473 }
457 474
458 .dumber-omnibox-container:focus-within {475 .dumber-omnibox-container:focus-within {
459- border-color: color-mix(in srgb, var(--dumber-border-color, var(--dynamic-border)) 55%, var(--dynamic-text) 45%);476+ border-color: var(--dynamic-accent);
460 box-shadow:477 box-shadow:
461- 0 25px 75px rgba(0, 0, 0, 0.5),478+ 0 6px 16px rgba(0, 0, 0, 0.24),
462- 0 15px 40px rgba(0, 0, 0, 0.4),479+ 0 3px 8px rgba(0, 0, 0, 0.18),
463- 0 8px 20px rgba(0, 0, 0, 0.3),480+ 0 2px 4px rgba(0, 0, 0, 0.12),
464- inset 0 0 0 1px color-mix(in srgb, var(--dynamic-border) 28%, transparent);481+ inset 0 1px 0 rgba(255, 255, 255, 0.06),
482+ 0 0 0 1px var(--dynamic-accent);
465 }483 }
466 484
467 :global(.dumber-omnibox-container input) {485 :global(.dumber-omnibox-container input) {
468- background: var(--dumber-input-bg, color-mix(in srgb, var(--dynamic-bg) 92%, var(--dynamic-surface) 8%));486+ background: var(--dumber-input-bg, var(--dynamic-bg));
469 color: var(--dynamic-text);487 color: var(--dynamic-text);
470 border: 1px solid var(--dumber-input-border-color, var(--dynamic-border));488 border: 1px solid var(--dumber-input-border-color, var(--dynamic-border));
471- transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease;489+ border-radius: 2px;
490+ box-shadow:
491+ inset 0 1px 2px rgba(0, 0, 0, 0.15),
492+ inset 0 0 0 1px rgba(0, 0, 0, 0.03);
493+ transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease, box-shadow 120ms ease;
472 font-family:494 font-family:
473- "JetBrains Mono",495+ "Fira Sans",
474- "Fira Code",496+ system-ui,
475- "SFMono-Regular",497+ -apple-system,
476- Menlo,498+ "Segoe UI",
477- monospace;499+ "Ubuntu",
500+ "Cantarell",
501+ sans-serif;
478 font-size: inherit;502 font-size: inherit;
479- letter-spacing: 0.05em;503+ letter-spacing: normal;
480 text-transform: none;504 text-transform: none;
481 }505 }
482 506
483 :global(.dumber-omnibox-container input::placeholder) {507 :global(.dumber-omnibox-container input::placeholder) {
484 color: var(--dynamic-muted);508 color: var(--dynamic-muted);
485- letter-spacing: 0.08em;509+ letter-spacing: normal;
486- text-transform: uppercase;510+ text-transform: none;
487 }511 }
488 512
489 /* Blur layer styles: use `backdrop-filter` but animate opacity only. */513 /* Blur layer styles: use `backdrop-filter` but animate opacity only. */
514+ /* GTK4-style: Minimal blur for faded state */
490 .dumber-omnibox-blur-layer {515 .dumber-omnibox-blur-layer {
491- backdrop-filter: blur(1.5px) saturate(105%);516+ backdrop-filter: blur(0.5px) saturate(102%);
492- -webkit-backdrop-filter: blur(1.5px) saturate(105%);517+ -webkit-backdrop-filter: blur(0.5px) saturate(102%);
493- background: var(--dumber-blur-color, color-mix(in srgb, var(--dynamic-bg) 12%, transparent));518+ background: var(--dumber-blur-color, color-mix(in srgb, var(--dynamic-bg) 8%, transparent));
494 transition: opacity 140ms ease;519 transition: opacity 140ms ease;
495 will-change: opacity;520 will-change: opacity;
496 z-index: 0;521 z-index: 0;
M gui/src/components/omnibox/OmniboxInput.svelte +12 -2
@@ -325,16 +325,26 @@
325325 background: var(--dumber-input-bg, var(--dynamic-bg));
326326 color: var(--dynamic-text);
327327 border: 1px solid var(--dumber-input-border-color, var(--dynamic-border));
328- border-radius: 0;
329- transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease;
328+ border-radius: 2px;
329+ box-shadow:
330+ inset 0 1px 2px rgba(0, 0, 0, 0.15),
331+ inset 0 0 0 1px rgba(0, 0, 0, 0.03);
332+ transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease, box-shadow 120ms ease;
333+ font-family: 'Fira Sans', system-ui, -apple-system, 'Segoe UI', 'Ubuntu', 'Cantarell', sans-serif;
334+ letter-spacing: normal;
330335 }
331336
332337 .omnibox-input-field::placeholder {
333338 color: var(--dynamic-muted);
339+ letter-spacing: normal;
334340 }
335341
336342 .omnibox-input-field:focus {
337343 color: var(--dynamic-text);
344+ border-color: var(--dynamic-accent);
345+ box-shadow:
346+ inset 0 1px 2px rgba(0, 0, 0, 0.15),
347+ 0 0 0 1px var(--dynamic-accent);
338348 }
339349
340350 .omnibox-prefix-badge {
@@ -325,16 +325,26 @@
325 background: var(--dumber-input-bg, var(--dynamic-bg));325 background: var(--dumber-input-bg, var(--dynamic-bg));
326 color: var(--dynamic-text);326 color: var(--dynamic-text);
327 border: 1px solid var(--dumber-input-border-color, var(--dynamic-border));327 border: 1px solid var(--dumber-input-border-color, var(--dynamic-border));
328- border-radius: 0;328+ border-radius: 2px;
329- transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease;329+ box-shadow:
330+ inset 0 1px 2px rgba(0, 0, 0, 0.15),
331+ inset 0 0 0 1px rgba(0, 0, 0, 0.03);
332+ transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease, box-shadow 120ms ease;
333+ font-family: 'Fira Sans', system-ui, -apple-system, 'Segoe UI', 'Ubuntu', 'Cantarell', sans-serif;
334+ letter-spacing: normal;
330 }335 }
331 336
332 .omnibox-input-field::placeholder {337 .omnibox-input-field::placeholder {
333 color: var(--dynamic-muted);338 color: var(--dynamic-muted);
339+ letter-spacing: normal;
334 }340 }
335 341
336 .omnibox-input-field:focus {342 .omnibox-input-field:focus {
337 color: var(--dynamic-text);343 color: var(--dynamic-text);
344+ border-color: var(--dynamic-accent);
345+ box-shadow:
346+ inset 0 1px 2px rgba(0, 0, 0, 0.15),
347+ 0 0 0 1px var(--dynamic-accent);
338 }348 }
339 349
340 .omnibox-prefix-badge {350 .omnibox-prefix-badge {
M gui/src/components/omnibox/OmniboxSuggestions.svelte +21 -14
@@ -113,7 +113,6 @@
113113 class="suggestion-favicon-img"
114114 loading="lazy"
115115 onerror={handleFaviconError}
116- style="image-rendering: -webkit-optimize-contrast;"
117116 />
118117 </div>
119118 {/if}
@@ -144,11 +143,12 @@
144143
145144 <style>
146145 .suggestion-list {
147- margin-top: 0.75rem;
146+ margin-top: 0.5rem;
148147 max-height: 50vh;
149148 overflow-y: auto;
150149 border-top: 1px solid var(--dynamic-border);
151- background: color-mix(in srgb, var(--dynamic-bg) 94%, var(--dynamic-surface) 6%);
150+ background: var(--dynamic-bg);
151+ border-radius: 0 0 2px 2px;
152152 }
153153
154154 .suggestion-item {
@@ -156,10 +156,13 @@
156156 gap: 0.75rem;
157157 align-items: center;
158158 padding: 0.65rem 0.85rem;
159- border-bottom: 1px dashed var(--dynamic-border);
159+ border-bottom: 1px solid color-mix(in srgb, var(--dynamic-border) 50%, transparent);
160160 cursor: pointer;
161- transition: background-color 120ms ease, color 120ms ease;
162- letter-spacing: 0.04em;
161+ transition: background-color 100ms ease, border-left-color 100ms ease;
162+ letter-spacing: normal;
163+ border-left: 3px solid transparent;
164+ position: relative;
165+ font-family: 'Fira Sans', system-ui, -apple-system, 'Segoe UI', 'Ubuntu', 'Cantarell', sans-serif;
163166 }
164167
165168 .suggestion-item:last-child {
@@ -169,11 +172,16 @@
169172 .suggestion-item.selected,
170173 .suggestion-item:hover,
171174 .suggestion-item:focus-visible {
172- background: color-mix(in srgb, var(--dynamic-bg) 60%, var(--dynamic-surface) 40%);
175+ background: color-mix(in srgb, var(--dynamic-accent) 15%, var(--dynamic-bg));
176+ border-left-color: var(--dynamic-accent);
173177 color: var(--dynamic-text);
174178 outline: none;
175179 }
176180
181+ .suggestion-item.selected {
182+ font-weight: 500;
183+ }
184+
177185 .suggestion-item .suggestion-domain {
178186 color: var(--dynamic-text);
179187 opacity: 0.95;
@@ -188,24 +196,23 @@
188196 }
189197
190198 .suggestion-favicon {
191- width: 20px;
192- height: 20px;
199+ width: 24px;
200+ height: 24px;
193201 border: none;
194202 border-radius: 3px;
195203 display: flex;
196204 align-items: center;
197205 justify-content: center;
198- background: var(--dynamic-bg);
206+ background: transparent;
199207 flex-shrink: 0;
200208 overflow: hidden;
201209 }
202210
203211 .suggestion-favicon-img {
204- width: 16px;
205- height: 16px;
212+ width: 24px;
213+ height: 24px;
206214 object-fit: contain;
207- image-rendering: -webkit-optimize-contrast;
208- -ms-interpolation-mode: nearest-neighbor;
215+ image-rendering: auto;
209216 }
210217
211218 .suggestion-text {
@@ -113,7 +113,6 @@
113 class="suggestion-favicon-img"113 class="suggestion-favicon-img"
114 loading="lazy"114 loading="lazy"
115 onerror={handleFaviconError}115 onerror={handleFaviconError}
116- style="image-rendering: -webkit-optimize-contrast;"
117 />116 />
118 </div>117 </div>
119 {/if}118 {/if}
@@ -144,11 +143,12 @@
144 143
145 <style>144 <style>
146 .suggestion-list {145 .suggestion-list {
147- margin-top: 0.75rem;146+ margin-top: 0.5rem;
148 max-height: 50vh;147 max-height: 50vh;
149 overflow-y: auto;148 overflow-y: auto;
150 border-top: 1px solid var(--dynamic-border);149 border-top: 1px solid var(--dynamic-border);
151- background: color-mix(in srgb, var(--dynamic-bg) 94%, var(--dynamic-surface) 6%);150+ background: var(--dynamic-bg);
151+ border-radius: 0 0 2px 2px;
152 }152 }
153 153
154 .suggestion-item {154 .suggestion-item {
@@ -156,10 +156,13 @@
156 gap: 0.75rem;156 gap: 0.75rem;
157 align-items: center;157 align-items: center;
158 padding: 0.65rem 0.85rem;158 padding: 0.65rem 0.85rem;
159- border-bottom: 1px dashed var(--dynamic-border);159+ border-bottom: 1px solid color-mix(in srgb, var(--dynamic-border) 50%, transparent);
160 cursor: pointer;160 cursor: pointer;
161- transition: background-color 120ms ease, color 120ms ease;161+ transition: background-color 100ms ease, border-left-color 100ms ease;
162- letter-spacing: 0.04em;162+ letter-spacing: normal;
163+ border-left: 3px solid transparent;
164+ position: relative;
165+ font-family: 'Fira Sans', system-ui, -apple-system, 'Segoe UI', 'Ubuntu', 'Cantarell', sans-serif;
163 }166 }
164 167
165 .suggestion-item:last-child {168 .suggestion-item:last-child {
@@ -169,11 +172,16 @@
169 .suggestion-item.selected,172 .suggestion-item.selected,
170 .suggestion-item:hover,173 .suggestion-item:hover,
171 .suggestion-item:focus-visible {174 .suggestion-item:focus-visible {
172- background: color-mix(in srgb, var(--dynamic-bg) 60%, var(--dynamic-surface) 40%);175+ background: color-mix(in srgb, var(--dynamic-accent) 15%, var(--dynamic-bg));
176+ border-left-color: var(--dynamic-accent);
173 color: var(--dynamic-text);177 color: var(--dynamic-text);
174 outline: none;178 outline: none;
175 }179 }
176 180
181+ .suggestion-item.selected {
182+ font-weight: 500;
183+ }
184+
177 .suggestion-item .suggestion-domain {185 .suggestion-item .suggestion-domain {
178 color: var(--dynamic-text);186 color: var(--dynamic-text);
179 opacity: 0.95;187 opacity: 0.95;
@@ -188,24 +196,23 @@
188 }196 }
189 197
190 .suggestion-favicon {198 .suggestion-favicon {
191- width: 20px;199+ width: 24px;
192- height: 20px;200+ height: 24px;
193 border: none;201 border: none;
194 border-radius: 3px;202 border-radius: 3px;
195 display: flex;203 display: flex;
196 align-items: center;204 align-items: center;
197 justify-content: center;205 justify-content: center;
198- background: var(--dynamic-bg);206+ background: transparent;
199 flex-shrink: 0;207 flex-shrink: 0;
200 overflow: hidden;208 overflow: hidden;
201 }209 }
202 210
203 .suggestion-favicon-img {211 .suggestion-favicon-img {
204- width: 16px;212+ width: 24px;
205- height: 16px;213+ height: 24px;
206 object-fit: contain;214 object-fit: contain;
207- image-rendering: -webkit-optimize-contrast;215+ image-rendering: auto;
208- -ms-interpolation-mode: nearest-neighbor;
209 }216 }
210 217
211 .suggestion-text {218 .suggestion-text {

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