feat(ui): implement terminal-style theme for omnibox components
Omnibox Container: - Switch to monospace font (JetBrains Mono, Fira Code) - Remove border-radius (sharp corners throughout) - Adjust margins (20vh top instead of 8vh) - Update backdrop blur (1.5px instead of 2px) - Refine color mixing ratios for better contrast - Add layered box-shadow for depth - Only apply fading effect in find mode, not omnibox mode - Remove text-shadow from fade effects Suggestions List: - Add proper CSS classes instead of inline Tailwind - Use dashed borders for items - Update hover/selection states - Adjust spacing and typography (uppercase, letter-spacing) - Update favicon styling (square borders, proper sizing) - Add gradient mask for text overflow Find List: - Match suggestions styling with proper CSS classes - Use dashed borders and consistent spacing - Update header styling (uppercase, letter-spacing) Highlight Marks: - Remove border-radius from find highlights for consistency
- commit
- 27396fb72bc823ca91cc677c335a05c2d38fc01e
- author
- bamen · · 2025-10-06 20:11 UTC
- committer
- bamen · · 2025-10-06 16:13 UTC
- parent
- babf2f5
- signature
- unsigned
4 files · +194 -73
M gui/src/components/omnibox/Omnibox.svelte +59 -35
| @@ -177,18 +177,20 @@ | |||
| 177 | 177 | // defensive: ignore if setting styles fails for some reason | |
| 178 | 178 | } | |
| 179 | 179 | ||
| 180 | - | const surfaceMix = isDarkMode ? '65%' : '92%'; | |
| 181 | - | const inputMix = isDarkMode ? '60%' : '94%'; | |
| 182 | - | const borderMix = isDarkMode ? '70%' : '90%'; | |
| 183 | - | const blurMix = isDarkMode ? '28%' : '16%'; | |
| 180 | + | const surfaceMix = isDarkMode ? '55%' : '88%'; | |
| 181 | + | const inputMix = isDarkMode ? '52%' : '90%'; | |
| 182 | + | const borderMix = isDarkMode ? '62%' : '85%'; | |
| 183 | + | const blurMix = isDarkMode ? '22%' : '12%'; | |
| 184 | 184 | ||
| 185 | - | const containerBackground = faded | |
| 185 | + | const applyFade = faded && mode === 'find'; | |
| 186 | + | ||
| 187 | + | const containerBackground = applyFade | |
| 186 | 188 | ? `color-mix(in srgb, var(--dynamic-surface) ${surfaceMix}, transparent)` | |
| 187 | 189 | : 'var(--dynamic-surface)'; | |
| 188 | - | const inputBackground = faded | |
| 190 | + | const inputBackground = applyFade | |
| 189 | 191 | ? `color-mix(in srgb, var(--dynamic-bg) ${inputMix}, transparent)` | |
| 190 | 192 | : 'var(--dynamic-bg)'; | |
| 191 | - | const borderColor = faded | |
| 193 | + | const borderColor = applyFade | |
| 192 | 194 | ? `color-mix(in srgb, var(--dynamic-border) ${borderMix}, transparent)` | |
| 193 | 195 | : 'var(--dynamic-border)'; | |
| 194 | 196 | const blurTint = `color-mix(in srgb, var(--dynamic-bg) ${blurMix}, transparent)`; | |
| @@ -196,7 +198,8 @@ | |||
| 196 | 198 | boxElement.style.background = containerBackground; | |
| 197 | 199 | boxElement.style.color = 'var(--dynamic-text)'; | |
| 198 | 200 | boxElement.style.setProperty('--dumber-border-color', borderColor); | |
| 199 | - | boxElement.style.setProperty('--dumber-omnibox-surface', containerBackground); | |
| 201 | + | // 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%)'); | |
| 200 | 203 | ||
| 201 | 204 | inputElement.style.background = inputBackground; | |
| 202 | 205 | inputElement.style.color = 'var(--dynamic-text)'; | |
| @@ -217,24 +220,17 @@ | |||
| 217 | 220 | // If computed styles fail, keep fallback accent color | |
| 218 | 221 | } | |
| 219 | 222 | inputElement.style.setProperty('--dumber-input-accent', accentColor); | |
| 220 | - | boxElement.style.setProperty('--dumber-input-accent', accentColor); | |
| 223 | + | boxElement.style.setProperty('--dumber-input-accent', 'var(--dynamic-muted)'); | |
| 221 | 224 | ||
| 222 | 225 | const isFocused = document.activeElement === inputElement; | |
| 223 | 226 | ||
| 224 | 227 | if (!isFocused) { | |
| 225 | - | inputElement.style.setProperty('--dumber-input-border-color', borderColor); | |
| 228 | + | inputElement.style.setProperty('--dumber-input-border-color', 'var(--dynamic-border)'); | |
| 226 | 229 | } | |
| 227 | 230 | ||
| 228 | - | if (faded) { | |
| 229 | - | const textShadow = isDarkMode | |
| 230 | - | ? '1px 1px 1px rgba(0,0,0,0.65)' | |
| 231 | - | : '1px 1px 1px rgba(255,255,255,0.65)'; | |
| 232 | - | inputElement.style.textShadow = textShadow; | |
| 233 | - | boxElement.style.textShadow = textShadow; | |
| 231 | + | if (applyFade) { | |
| 234 | 232 | blurLayerElement.style.opacity = '1'; | |
| 235 | 233 | } else { | |
| 236 | - | inputElement.style.textShadow = ''; | |
| 237 | - | boxElement.style.textShadow = ''; | |
| 238 | 234 | blurLayerElement.style.opacity = '0'; | |
| 239 | 235 | } | |
| 240 | 236 | }); | |
| @@ -388,21 +384,26 @@ | |||
| 388 | 384 | <!-- Main omnibox container --> | |
| 389 | 385 | <div | |
| 390 | 386 | bind:this={boxElement} | |
| 391 | - | class="dumber-omnibox-container omnibox-base rounded shadow-[0_10px_30px_rgba(0,0,0,0.6)]" | |
| 387 | + | class="dumber-omnibox-container omnibox-base terminal-omnibox" | |
| 392 | 388 | style="position: relative !important; | |
| 393 | 389 | left: 50% !important; | |
| 394 | 390 | transform: translateX(-50%) !important; | |
| 395 | - | margin-top: 8vh !important; | |
| 391 | + | margin-top: 20vh !important; | |
| 396 | 392 | margin-left: 0 !important; | |
| 397 | 393 | margin-right: 0 !important; | |
| 398 | 394 | width: {responsiveStyles.width}; | |
| 399 | 395 | padding: {responsiveStyles.padding}; | |
| 400 | - | font-family: 'Fira sans', system-ui, -apple-system, 'Segoe UI', Roboto, Ubuntu, 'Helvetica Neue', Arial, sans-serif; | |
| 396 | + | font-family: 'JetBrains Mono', 'Fira Code', 'SFMono-Regular', Menlo, monospace; | |
| 401 | 397 | pointer-events: auto !important; | |
| 402 | 398 | box-sizing: border-box !important; | |
| 403 | - | background: var(--dumber-omnibox-surface, var(--dynamic-surface)); | |
| 399 | + | background: var(--dumber-omnibox-surface, color-mix(in srgb, var(--dynamic-bg) 88%, var(--dynamic-surface) 12%)); | |
| 404 | 400 | color: var(--dynamic-text); | |
| 405 | - | border: 2px solid var(--dumber-border-color, var(--dynamic-border)); | |
| 401 | + | border: 1px solid var(--dumber-border-color, var(--dynamic-border)); | |
| 402 | + | box-shadow: | |
| 403 | + | 0 20px 60px rgba(0, 0, 0, 0.45), | |
| 404 | + | 0 10px 30px rgba(0, 0, 0, 0.35), | |
| 405 | + | 0 5px 15px rgba(0, 0, 0, 0.25), | |
| 406 | + | inset 0 0 0 1px color-mix(in srgb, var(--dynamic-border) 22%, transparent); | |
| 406 | 407 | --dumber-border-color: var(--dynamic-border);" | |
| 407 | 408 | onmousedown={handleBoxClick} | |
| 408 | 409 | onmouseenter={handleMouseEnter} | |
| @@ -418,7 +419,7 @@ | |||
| 418 | 419 | bind:this={blurLayerElement} | |
| 419 | 420 | class="dumber-omnibox-blur-layer" | |
| 420 | 421 | aria-hidden="true" | |
| 421 | - | style="position: absolute; inset: 0; pointer-events: none; border-radius: inherit; opacity: 0;" | |
| 422 | + | style="position: absolute; inset: 0; pointer-events: none; border-radius: 0; opacity: 0;" | |
| 422 | 423 | ></div> | |
| 423 | 424 | <div class="dumber-omnibox-content"> | |
| 424 | 425 | <!-- Input component --> | |
| @@ -436,36 +437,59 @@ | |||
| 436 | 437 | ||
| 437 | 438 | <style> | |
| 438 | 439 | .dumber-omnibox-container { | |
| 439 | - | background: var(--dumber-omnibox-surface, var(--dynamic-surface)); | |
| 440 | + | background: var(--dumber-omnibox-surface, color-mix(in srgb, var(--dynamic-bg) 88%, var(--dynamic-surface) 12%)); | |
| 440 | 441 | color: var(--dynamic-text); | |
| 441 | - | border: 2px solid var(--dumber-border-color, var(--dynamic-border)); | |
| 442 | - | transition: background-color 160ms ease, border-color 160ms ease; | |
| 442 | + | border: 1px solid var(--dumber-border-color, var(--dynamic-border)); | |
| 443 | + | transition: background-color 140ms ease, border-color 140ms ease, box-shadow 140ms ease; | |
| 444 | + | border-radius: 0; | |
| 445 | + | box-shadow: | |
| 446 | + | 0 20px 60px rgba(0, 0, 0, 0.45), | |
| 447 | + | 0 10px 30px rgba(0, 0, 0, 0.35), | |
| 448 | + | 0 5px 15px rgba(0, 0, 0, 0.25), | |
| 449 | + | inset 0 0 0 1px color-mix(in srgb, var(--dynamic-border) 22%, transparent); | |
| 443 | 450 | } | |
| 444 | 451 | ||
| 445 | 452 | .dumber-omnibox-container:focus-within { | |
| 446 | - | border-color: var(--dumber-input-accent, var(--dynamic-accent)); | |
| 453 | + | border-color: color-mix(in srgb, var(--dumber-border-color, var(--dynamic-border)) 55%, var(--dynamic-text) 45%); | |
| 454 | + | box-shadow: | |
| 455 | + | 0 25px 75px rgba(0, 0, 0, 0.5), | |
| 456 | + | 0 15px 40px rgba(0, 0, 0, 0.4), | |
| 457 | + | 0 8px 20px rgba(0, 0, 0, 0.3), | |
| 458 | + | inset 0 0 0 1px color-mix(in srgb, var(--dynamic-border) 28%, transparent); | |
| 447 | 459 | } | |
| 448 | 460 | ||
| 449 | 461 | :global(.dumber-omnibox-container input) { | |
| 450 | - | background: var(--dumber-input-bg, var(--dynamic-bg)); | |
| 462 | + | background: var(--dumber-input-bg, color-mix(in srgb, var(--dynamic-bg) 92%, var(--dynamic-surface) 8%)); | |
| 451 | 463 | color: var(--dynamic-text); | |
| 452 | - | border-color: var(--dumber-input-border-color, var(--dynamic-border)); | |
| 453 | - | transition: border-color 120ms ease, background-color 120ms ease; | |
| 464 | + | border: 1px solid var(--dumber-input-border-color, var(--dynamic-border)); | |
| 465 | + | transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease; | |
| 466 | + | font-family: | |
| 467 | + | "JetBrains Mono", | |
| 468 | + | "Fira Code", | |
| 469 | + | "SFMono-Regular", | |
| 470 | + | Menlo, | |
| 471 | + | monospace; | |
| 472 | + | font-size: inherit; | |
| 473 | + | letter-spacing: 0.05em; | |
| 474 | + | text-transform: none; | |
| 454 | 475 | } | |
| 455 | 476 | ||
| 456 | 477 | :global(.dumber-omnibox-container input::placeholder) { | |
| 457 | 478 | color: var(--dynamic-muted); | |
| 479 | + | letter-spacing: 0.08em; | |
| 480 | + | text-transform: uppercase; | |
| 458 | 481 | } | |
| 459 | 482 | ||
| 460 | 483 | /* Blur layer styles: use `backdrop-filter` but animate opacity only. */ | |
| 461 | 484 | .dumber-omnibox-blur-layer { | |
| 462 | - | backdrop-filter: blur(2px) saturate(110%); | |
| 463 | - | -webkit-backdrop-filter: blur(2px) saturate(110%); | |
| 464 | - | background: var(--dumber-blur-color, color-mix(in srgb, var(--dynamic-bg) 16%, transparent)); | |
| 465 | - | transition: opacity 160ms ease; | |
| 485 | + | backdrop-filter: blur(1.5px) saturate(105%); | |
| 486 | + | -webkit-backdrop-filter: blur(1.5px) saturate(105%); | |
| 487 | + | background: var(--dumber-blur-color, color-mix(in srgb, var(--dynamic-bg) 12%, transparent)); | |
| 488 | + | transition: opacity 140ms ease; | |
| 466 | 489 | will-change: opacity; | |
| 467 | 490 | z-index: 0; | |
| 468 | 491 | mix-blend-mode: normal; | |
| 492 | + | border-radius: 0; | |
| 469 | 493 | } | |
| 470 | 494 | ||
| 471 | 495 | /* Ensure the actual content (input, suggestions) sits above the blur layer */ | |
| @@ -177,18 +177,20 @@ | |||||
| 177 | // defensive: ignore if setting styles fails for some reason | 177 | // defensive: ignore if setting styles fails for some reason | ||
| 178 | } | 178 | } | ||
| 179 | 179 | ||||
| 180 | - | const surfaceMix = isDarkMode ? '65%' : '92%'; | 180 | + | const surfaceMix = isDarkMode ? '55%' : '88%'; |
| 181 | - | const inputMix = isDarkMode ? '60%' : '94%'; | 181 | + | const inputMix = isDarkMode ? '52%' : '90%'; |
| 182 | - | const borderMix = isDarkMode ? '70%' : '90%'; | 182 | + | const borderMix = isDarkMode ? '62%' : '85%'; |
| 183 | - | const blurMix = isDarkMode ? '28%' : '16%'; | 183 | + | const blurMix = isDarkMode ? '22%' : '12%'; |
| 184 | 184 | ||||
| 185 | - | const containerBackground = faded | 185 | + | const applyFade = faded && mode === 'find'; |
| 186 | + | ||||
| 187 | + | const containerBackground = applyFade | |||
| 186 | ? `color-mix(in srgb, var(--dynamic-surface) ${surfaceMix}, transparent)` | 188 | ? `color-mix(in srgb, var(--dynamic-surface) ${surfaceMix}, transparent)` | ||
| 187 | : 'var(--dynamic-surface)'; | 189 | : 'var(--dynamic-surface)'; | ||
| 188 | - | const inputBackground = faded | 190 | + | const inputBackground = applyFade |
| 189 | ? `color-mix(in srgb, var(--dynamic-bg) ${inputMix}, transparent)` | 191 | ? `color-mix(in srgb, var(--dynamic-bg) ${inputMix}, transparent)` | ||
| 190 | : 'var(--dynamic-bg)'; | 192 | : 'var(--dynamic-bg)'; | ||
| 191 | - | const borderColor = faded | 193 | + | const borderColor = applyFade |
| 192 | ? `color-mix(in srgb, var(--dynamic-border) ${borderMix}, transparent)` | 194 | ? `color-mix(in srgb, var(--dynamic-border) ${borderMix}, transparent)` | ||
| 193 | : 'var(--dynamic-border)'; | 195 | : 'var(--dynamic-border)'; | ||
| 194 | const blurTint = `color-mix(in srgb, var(--dynamic-bg) ${blurMix}, transparent)`; | 196 | const blurTint = `color-mix(in srgb, var(--dynamic-bg) ${blurMix}, transparent)`; | ||
| @@ -196,7 +198,8 @@ | |||||
| 196 | boxElement.style.background = containerBackground; | 198 | boxElement.style.background = containerBackground; | ||
| 197 | boxElement.style.color = 'var(--dynamic-text)'; | 199 | boxElement.style.color = 'var(--dynamic-text)'; | ||
| 198 | boxElement.style.setProperty('--dumber-border-color', borderColor); | 200 | boxElement.style.setProperty('--dumber-border-color', borderColor); | ||
| 199 | - | boxElement.style.setProperty('--dumber-omnibox-surface', containerBackground); | 201 | + | // 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%)'); | |||
| 200 | 203 | ||||
| 201 | inputElement.style.background = inputBackground; | 204 | inputElement.style.background = inputBackground; | ||
| 202 | inputElement.style.color = 'var(--dynamic-text)'; | 205 | inputElement.style.color = 'var(--dynamic-text)'; | ||
| @@ -217,24 +220,17 @@ | |||||
| 217 | // If computed styles fail, keep fallback accent color | 220 | // If computed styles fail, keep fallback accent color | ||
| 218 | } | 221 | } | ||
| 219 | inputElement.style.setProperty('--dumber-input-accent', accentColor); | 222 | inputElement.style.setProperty('--dumber-input-accent', accentColor); | ||
| 220 | - | boxElement.style.setProperty('--dumber-input-accent', accentColor); | 223 | + | boxElement.style.setProperty('--dumber-input-accent', 'var(--dynamic-muted)'); |
| 221 | 224 | ||||
| 222 | const isFocused = document.activeElement === inputElement; | 225 | const isFocused = document.activeElement === inputElement; | ||
| 223 | 226 | ||||
| 224 | if (!isFocused) { | 227 | if (!isFocused) { | ||
| 225 | - | inputElement.style.setProperty('--dumber-input-border-color', borderColor); | 228 | + | inputElement.style.setProperty('--dumber-input-border-color', 'var(--dynamic-border)'); |
| 226 | } | 229 | } | ||
| 227 | 230 | ||||
| 228 | - | if (faded) { | 231 | + | if (applyFade) { |
| 229 | - | const textShadow = isDarkMode | |||
| 230 | - | ? '1px 1px 1px rgba(0,0,0,0.65)' | |||
| 231 | - | : '1px 1px 1px rgba(255,255,255,0.65)'; | |||
| 232 | - | inputElement.style.textShadow = textShadow; | |||
| 233 | - | boxElement.style.textShadow = textShadow; | |||
| 234 | blurLayerElement.style.opacity = '1'; | 232 | blurLayerElement.style.opacity = '1'; | ||
| 235 | } else { | 233 | } else { | ||
| 236 | - | inputElement.style.textShadow = ''; | |||
| 237 | - | boxElement.style.textShadow = ''; | |||
| 238 | blurLayerElement.style.opacity = '0'; | 234 | blurLayerElement.style.opacity = '0'; | ||
| 239 | } | 235 | } | ||
| 240 | }); | 236 | }); | ||
| @@ -388,21 +384,26 @@ | |||||
| 388 | <!-- Main omnibox container --> | 384 | <!-- Main omnibox container --> | ||
| 389 | <div | 385 | <div | ||
| 390 | bind:this={boxElement} | 386 | bind:this={boxElement} | ||
| 391 | - | class="dumber-omnibox-container omnibox-base rounded shadow-[0_10px_30px_rgba(0,0,0,0.6)]" | 387 | + | class="dumber-omnibox-container omnibox-base terminal-omnibox" |
| 392 | style="position: relative !important; | 388 | style="position: relative !important; | ||
| 393 | left: 50% !important; | 389 | left: 50% !important; | ||
| 394 | transform: translateX(-50%) !important; | 390 | transform: translateX(-50%) !important; | ||
| 395 | - | margin-top: 8vh !important; | 391 | + | margin-top: 20vh !important; |
| 396 | margin-left: 0 !important; | 392 | margin-left: 0 !important; | ||
| 397 | margin-right: 0 !important; | 393 | margin-right: 0 !important; | ||
| 398 | width: {responsiveStyles.width}; | 394 | width: {responsiveStyles.width}; | ||
| 399 | padding: {responsiveStyles.padding}; | 395 | padding: {responsiveStyles.padding}; | ||
| 400 | - | font-family: 'Fira sans', system-ui, -apple-system, 'Segoe UI', Roboto, Ubuntu, 'Helvetica Neue', Arial, sans-serif; | 396 | + | font-family: 'JetBrains Mono', 'Fira Code', 'SFMono-Regular', Menlo, monospace; |
| 401 | pointer-events: auto !important; | 397 | pointer-events: auto !important; | ||
| 402 | box-sizing: border-box !important; | 398 | box-sizing: border-box !important; | ||
| 403 | - | background: var(--dumber-omnibox-surface, var(--dynamic-surface)); | 399 | + | background: var(--dumber-omnibox-surface, color-mix(in srgb, var(--dynamic-bg) 88%, var(--dynamic-surface) 12%)); |
| 404 | color: var(--dynamic-text); | 400 | color: var(--dynamic-text); | ||
| 405 | - | border: 2px solid var(--dumber-border-color, var(--dynamic-border)); | 401 | + | border: 1px solid var(--dumber-border-color, var(--dynamic-border)); |
| 402 | + | box-shadow: | |||
| 403 | + | 0 20px 60px rgba(0, 0, 0, 0.45), | |||
| 404 | + | 0 10px 30px rgba(0, 0, 0, 0.35), | |||
| 405 | + | 0 5px 15px rgba(0, 0, 0, 0.25), | |||
| 406 | + | inset 0 0 0 1px color-mix(in srgb, var(--dynamic-border) 22%, transparent); | |||
| 406 | --dumber-border-color: var(--dynamic-border);" | 407 | --dumber-border-color: var(--dynamic-border);" | ||
| 407 | onmousedown={handleBoxClick} | 408 | onmousedown={handleBoxClick} | ||
| 408 | onmouseenter={handleMouseEnter} | 409 | onmouseenter={handleMouseEnter} | ||
| @@ -418,7 +419,7 @@ | |||||
| 418 | bind:this={blurLayerElement} | 419 | bind:this={blurLayerElement} | ||
| 419 | class="dumber-omnibox-blur-layer" | 420 | class="dumber-omnibox-blur-layer" | ||
| 420 | aria-hidden="true" | 421 | aria-hidden="true" | ||
| 421 | - | style="position: absolute; inset: 0; pointer-events: none; border-radius: inherit; opacity: 0;" | 422 | + | style="position: absolute; inset: 0; pointer-events: none; border-radius: 0; opacity: 0;" |
| 422 | ></div> | 423 | ></div> | ||
| 423 | <div class="dumber-omnibox-content"> | 424 | <div class="dumber-omnibox-content"> | ||
| 424 | <!-- Input component --> | 425 | <!-- Input component --> | ||
| @@ -436,36 +437,59 @@ | |||||
| 436 | 437 | ||||
| 437 | <style> | 438 | <style> | ||
| 438 | .dumber-omnibox-container { | 439 | .dumber-omnibox-container { | ||
| 439 | - | background: var(--dumber-omnibox-surface, var(--dynamic-surface)); | 440 | + | background: var(--dumber-omnibox-surface, color-mix(in srgb, var(--dynamic-bg) 88%, var(--dynamic-surface) 12%)); |
| 440 | color: var(--dynamic-text); | 441 | color: var(--dynamic-text); | ||
| 441 | - | border: 2px solid var(--dumber-border-color, var(--dynamic-border)); | 442 | + | border: 1px solid var(--dumber-border-color, var(--dynamic-border)); |
| 442 | - | transition: background-color 160ms ease, border-color 160ms ease; | 443 | + | transition: background-color 140ms ease, border-color 140ms ease, box-shadow 140ms ease; |
| 444 | + | border-radius: 0; | |||
| 445 | + | box-shadow: | |||
| 446 | + | 0 20px 60px rgba(0, 0, 0, 0.45), | |||
| 447 | + | 0 10px 30px rgba(0, 0, 0, 0.35), | |||
| 448 | + | 0 5px 15px rgba(0, 0, 0, 0.25), | |||
| 449 | + | inset 0 0 0 1px color-mix(in srgb, var(--dynamic-border) 22%, transparent); | |||
| 443 | } | 450 | } | ||
| 444 | 451 | ||||
| 445 | .dumber-omnibox-container:focus-within { | 452 | .dumber-omnibox-container:focus-within { | ||
| 446 | - | border-color: var(--dumber-input-accent, var(--dynamic-accent)); | 453 | + | border-color: color-mix(in srgb, var(--dumber-border-color, var(--dynamic-border)) 55%, var(--dynamic-text) 45%); |
| 454 | + | box-shadow: | |||
| 455 | + | 0 25px 75px rgba(0, 0, 0, 0.5), | |||
| 456 | + | 0 15px 40px rgba(0, 0, 0, 0.4), | |||
| 457 | + | 0 8px 20px rgba(0, 0, 0, 0.3), | |||
| 458 | + | inset 0 0 0 1px color-mix(in srgb, var(--dynamic-border) 28%, transparent); | |||
| 447 | } | 459 | } | ||
| 448 | 460 | ||||
| 449 | :global(.dumber-omnibox-container input) { | 461 | :global(.dumber-omnibox-container input) { | ||
| 450 | - | background: var(--dumber-input-bg, var(--dynamic-bg)); | 462 | + | background: var(--dumber-input-bg, color-mix(in srgb, var(--dynamic-bg) 92%, var(--dynamic-surface) 8%)); |
| 451 | color: var(--dynamic-text); | 463 | color: var(--dynamic-text); | ||
| 452 | - | border-color: var(--dumber-input-border-color, var(--dynamic-border)); | 464 | + | border: 1px solid var(--dumber-input-border-color, var(--dynamic-border)); |
| 453 | - | transition: border-color 120ms ease, background-color 120ms ease; | 465 | + | transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease; |
| 466 | + | font-family: | |||
| 467 | + | "JetBrains Mono", | |||
| 468 | + | "Fira Code", | |||
| 469 | + | "SFMono-Regular", | |||
| 470 | + | Menlo, | |||
| 471 | + | monospace; | |||
| 472 | + | font-size: inherit; | |||
| 473 | + | letter-spacing: 0.05em; | |||
| 474 | + | text-transform: none; | |||
| 454 | } | 475 | } | ||
| 455 | 476 | ||||
| 456 | :global(.dumber-omnibox-container input::placeholder) { | 477 | :global(.dumber-omnibox-container input::placeholder) { | ||
| 457 | color: var(--dynamic-muted); | 478 | color: var(--dynamic-muted); | ||
| 479 | + | letter-spacing: 0.08em; | |||
| 480 | + | text-transform: uppercase; | |||
| 458 | } | 481 | } | ||
| 459 | 482 | ||||
| 460 | /* Blur layer styles: use `backdrop-filter` but animate opacity only. */ | 483 | /* Blur layer styles: use `backdrop-filter` but animate opacity only. */ | ||
| 461 | .dumber-omnibox-blur-layer { | 484 | .dumber-omnibox-blur-layer { | ||
| 462 | - | backdrop-filter: blur(2px) saturate(110%); | 485 | + | backdrop-filter: blur(1.5px) saturate(105%); |
| 463 | - | -webkit-backdrop-filter: blur(2px) saturate(110%); | 486 | + | -webkit-backdrop-filter: blur(1.5px) saturate(105%); |
| 464 | - | background: var(--dumber-blur-color, color-mix(in srgb, var(--dynamic-bg) 16%, transparent)); | 487 | + | background: var(--dumber-blur-color, color-mix(in srgb, var(--dynamic-bg) 12%, transparent)); |
| 465 | - | transition: opacity 160ms ease; | 488 | + | transition: opacity 140ms ease; |
| 466 | will-change: opacity; | 489 | will-change: opacity; | ||
| 467 | z-index: 0; | 490 | z-index: 0; | ||
| 468 | mix-blend-mode: normal; | 491 | mix-blend-mode: normal; | ||
| 492 | + | border-radius: 0; | |||
| 469 | } | 493 | } | ||
| 470 | 494 | ||||
| 471 | /* Ensure the actual content (input, suggestions) sits above the blur layer */ | 495 | /* Ensure the actual content (input, suggestions) sits above the blur layer */ | ||
M gui/src/components/omnibox/OmniboxFind.svelte +49 -17
| @@ -54,17 +54,9 @@ | |||
| 54 | 54 | }); | |
| 55 | 55 | </script> | |
| 56 | 56 | ||
| 57 | - | <div | |
| 58 | - | id="find-list" | |
| 59 | - | class="mt-2 max-h-[50vh] overflow-auto border-t border-[#333]" | |
| 60 | - | role="listbox" | |
| 61 | - | aria-label="Find results" | |
| 62 | - | > | |
| 57 | + | <div id="find-list" class="find-list" role="listbox" aria-label="Find results"> | |
| 63 | 58 | <!-- Header with match count --> | |
| 64 | - | <div | |
| 65 | - | class="px-2.5 py-1.5 text-xs text-[#bbb] | |
| 66 | - | border-b border-[#2a2a2a]" | |
| 67 | - | > | |
| 59 | + | <div class="find-header"> | |
| 68 | 60 | {#if totalMatches > 0} | |
| 69 | 61 | {totalMatches} match{totalMatches === 1 ? '' : 'es'} | |
| 70 | 62 | {:else} | |
| @@ -79,9 +71,7 @@ | |||
| 79 | 71 | ||
| 80 | 72 | <div | |
| 81 | 73 | id="find-item-{index}" | |
| 82 | - | class="px-2.5 py-2 cursor-pointer | |
| 83 | - | border-b border-[#2a2a2a] last:border-b-0 | |
| 84 | - | {isSelected ? 'bg-[#0a0a0a]' : ''}" | |
| 74 | + | class={isSelected ? 'find-item selected' : 'find-item'} | |
| 85 | 75 | role="option" | |
| 86 | 76 | tabindex="-1" | |
| 87 | 77 | aria-selected={isSelected} | |
| @@ -90,10 +80,7 @@ | |||
| 90 | 80 | onkeydown={(e) => e.key === 'Enter' && handleItemClick(index)} | |
| 91 | 81 | > | |
| 92 | 82 | <!-- Match context --> | |
| 93 | - | <div | |
| 94 | - | class="text-[#ddd] text-sm | |
| 95 | - | whitespace-nowrap overflow-hidden text-ellipsis" | |
| 96 | - | > | |
| 83 | + | <div class="find-context"> | |
| 97 | 84 | {match.context || ''} | |
| 98 | 85 | </div> | |
| 99 | 86 | </div> | |
| @@ -101,3 +88,48 @@ | |||
| 101 | 88 | {/if} | |
| 102 | 89 | </div> | |
| 103 | 90 | ||
| 91 | + | <style> | |
| 92 | + | .find-list { | |
| 93 | + | margin-top: 0.75rem; | |
| 94 | + | max-height: 50vh; | |
| 95 | + | overflow-y: auto; | |
| 96 | + | border-top: 1px solid var(--dynamic-border); | |
| 97 | + | background: color-mix(in srgb, var(--dynamic-bg) 94%, var(--dynamic-surface) 6%); | |
| 98 | + | } | |
| 99 | + | ||
| 100 | + | .find-header { | |
| 101 | + | padding: 0.65rem 0.85rem; | |
| 102 | + | font-size: 0.7rem; | |
| 103 | + | text-transform: uppercase; | |
| 104 | + | letter-spacing: 0.08em; | |
| 105 | + | color: var(--dynamic-muted); | |
| 106 | + | border-bottom: 1px dashed var(--dynamic-border); | |
| 107 | + | } | |
| 108 | + | ||
| 109 | + | .find-item { | |
| 110 | + | padding: 0.65rem 0.85rem; | |
| 111 | + | border-bottom: 1px dashed var(--dynamic-border); | |
| 112 | + | cursor: pointer; | |
| 113 | + | transition: background-color 120ms ease, color 120ms ease; | |
| 114 | + | } | |
| 115 | + | ||
| 116 | + | .find-item:last-child { | |
| 117 | + | border-bottom: none; | |
| 118 | + | } | |
| 119 | + | ||
| 120 | + | .find-item.selected, | |
| 121 | + | .find-item:hover, | |
| 122 | + | .find-item:focus-visible { | |
| 123 | + | background: color-mix(in srgb, var(--dynamic-bg) 75%, var(--dynamic-surface) 25%); | |
| 124 | + | color: var(--dynamic-text); | |
| 125 | + | outline: none; | |
| 126 | + | } | |
| 127 | + | ||
| 128 | + | .find-context { | |
| 129 | + | color: var(--dynamic-text); | |
| 130 | + | font-size: 0.75rem; | |
| 131 | + | white-space: nowrap; | |
| 132 | + | overflow: hidden; | |
| 133 | + | text-overflow: ellipsis; | |
| 134 | + | } | |
| 135 | + | </style> | |
| @@ -54,17 +54,9 @@ | |||||
| 54 | }); | 54 | }); | ||
| 55 | </script> | 55 | </script> | ||
| 56 | 56 | ||||
| 57 | - | <div | 57 | + | <div id="find-list" class="find-list" role="listbox" aria-label="Find results"> |
| 58 | - | id="find-list" | |||
| 59 | - | class="mt-2 max-h-[50vh] overflow-auto border-t border-[#333]" | |||
| 60 | - | role="listbox" | |||
| 61 | - | aria-label="Find results" | |||
| 62 | - | > | |||
| 63 | <!-- Header with match count --> | 58 | <!-- Header with match count --> | ||
| 64 | - | <div | 59 | + | <div class="find-header"> |
| 65 | - | class="px-2.5 py-1.5 text-xs text-[#bbb] | |||
| 66 | - | border-b border-[#2a2a2a]" | |||
| 67 | - | > | |||
| 68 | {#if totalMatches > 0} | 60 | {#if totalMatches > 0} | ||
| 69 | {totalMatches} match{totalMatches === 1 ? '' : 'es'} | 61 | {totalMatches} match{totalMatches === 1 ? '' : 'es'} | ||
| 70 | {:else} | 62 | {:else} | ||
| @@ -79,9 +71,7 @@ | |||||
| 79 | 71 | ||||
| 80 | <div | 72 | <div | ||
| 81 | id="find-item-{index}" | 73 | id="find-item-{index}" | ||
| 82 | - | class="px-2.5 py-2 cursor-pointer | 74 | + | class={isSelected ? 'find-item selected' : 'find-item'} |
| 83 | - | border-b border-[#2a2a2a] last:border-b-0 | |||
| 84 | - | {isSelected ? 'bg-[#0a0a0a]' : ''}" | |||
| 85 | role="option" | 75 | role="option" | ||
| 86 | tabindex="-1" | 76 | tabindex="-1" | ||
| 87 | aria-selected={isSelected} | 77 | aria-selected={isSelected} | ||
| @@ -90,10 +80,7 @@ | |||||
| 90 | onkeydown={(e) => e.key === 'Enter' && handleItemClick(index)} | 80 | onkeydown={(e) => e.key === 'Enter' && handleItemClick(index)} | ||
| 91 | > | 81 | > | ||
| 92 | <!-- Match context --> | 82 | <!-- Match context --> | ||
| 93 | - | <div | 83 | + | <div class="find-context"> |
| 94 | - | class="text-[#ddd] text-sm | |||
| 95 | - | whitespace-nowrap overflow-hidden text-ellipsis" | |||
| 96 | - | > | |||
| 97 | {match.context || ''} | 84 | {match.context || ''} | ||
| 98 | </div> | 85 | </div> | ||
| 99 | </div> | 86 | </div> | ||
| @@ -101,3 +88,48 @@ | |||||
| 101 | {/if} | 88 | {/if} | ||
| 102 | </div> | 89 | </div> | ||
| 103 | 90 | ||||
| 91 | + | <style> | |||
| 92 | + | .find-list { | |||
| 93 | + | margin-top: 0.75rem; | |||
| 94 | + | max-height: 50vh; | |||
| 95 | + | overflow-y: auto; | |||
| 96 | + | border-top: 1px solid var(--dynamic-border); | |||
| 97 | + | background: color-mix(in srgb, var(--dynamic-bg) 94%, var(--dynamic-surface) 6%); | |||
| 98 | + | } | |||
| 99 | + | ||||
| 100 | + | .find-header { | |||
| 101 | + | padding: 0.65rem 0.85rem; | |||
| 102 | + | font-size: 0.7rem; | |||
| 103 | + | text-transform: uppercase; | |||
| 104 | + | letter-spacing: 0.08em; | |||
| 105 | + | color: var(--dynamic-muted); | |||
| 106 | + | border-bottom: 1px dashed var(--dynamic-border); | |||
| 107 | + | } | |||
| 108 | + | ||||
| 109 | + | .find-item { | |||
| 110 | + | padding: 0.65rem 0.85rem; | |||
| 111 | + | border-bottom: 1px dashed var(--dynamic-border); | |||
| 112 | + | cursor: pointer; | |||
| 113 | + | transition: background-color 120ms ease, color 120ms ease; | |||
| 114 | + | } | |||
| 115 | + | ||||
| 116 | + | .find-item:last-child { | |||
| 117 | + | border-bottom: none; | |||
| 118 | + | } | |||
| 119 | + | ||||
| 120 | + | .find-item.selected, | |||
| 121 | + | .find-item:hover, | |||
| 122 | + | .find-item:focus-visible { | |||
| 123 | + | background: color-mix(in srgb, var(--dynamic-bg) 75%, var(--dynamic-surface) 25%); | |||
| 124 | + | color: var(--dynamic-text); | |||
| 125 | + | outline: none; | |||
| 126 | + | } | |||
| 127 | + | ||||
| 128 | + | .find-context { | |||
| 129 | + | color: var(--dynamic-text); | |||
| 130 | + | font-size: 0.75rem; | |||
| 131 | + | white-space: nowrap; | |||
| 132 | + | overflow: hidden; | |||
| 133 | + | text-overflow: ellipsis; | |||
| 134 | + | } | |||
| 135 | + | </style> | |||
M gui/src/components/omnibox/OmniboxSuggestions.svelte +85 -20
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | // Handle suggestion item mouse enter | |
| 21 | 21 | function handleItemMouseEnter(index: number) { | |
| 22 | 22 | omniboxStore.setSelectedIndex(index); | |
| 23 | - | omniboxStore.setFaded(true); | |
| 23 | + | omniboxStore.setFaded(false); | |
| 24 | 24 | scrollToSelection(); | |
| 25 | 25 | } | |
| 26 | 26 | ||
| @@ -86,7 +86,7 @@ | |||
| 86 | 86 | {#if hasContent} | |
| 87 | 87 | <div | |
| 88 | 88 | id="omnibox-list" | |
| 89 | - | class="mt-2 max-h-[50vh] overflow-auto border-t border-[#333]" | |
| 89 | + | class="suggestion-list" | |
| 90 | 90 | role="listbox" | |
| 91 | 91 | aria-label="Search suggestions" | |
| 92 | 92 | > | |
| @@ -96,9 +96,7 @@ | |||
| 96 | 96 | ||
| 97 | 97 | <div | |
| 98 | 98 | id="omnibox-item-{index}" | |
| 99 | - | class="px-2.5 py-2 flex gap-2.5 items-center cursor-pointer | |
| 100 | - | border-b border-[#2a2a2a] last:border-b-0 | |
| 101 | - | {isSelected ? 'bg-[#0a0a0a]' : ''}" | |
| 99 | + | class={isSelected ? 'suggestion-item selected' : 'suggestion-item'} | |
| 102 | 100 | role="option" | |
| 103 | 101 | tabindex={isSelected ? 0 : -1} | |
| 104 | 102 | aria-selected={isSelected} | |
| @@ -108,15 +106,11 @@ | |||
| 108 | 106 | > | |
| 109 | 107 | <!-- Favicon chip --> | |
| 110 | 108 | {#if suggestion.favicon} | |
| 111 | - | <div | |
| 112 | - | class="flex-shrink-0 w-5 h-5 rounded-full | |
| 113 | - | bg-[#ccc] border border-black/12 | |
| 114 | - | shadow-sm flex items-center justify-center" | |
| 115 | - | > | |
| 109 | + | <div class="suggestion-favicon"> | |
| 116 | 110 | <img | |
| 117 | 111 | src={suggestion.favicon} | |
| 118 | 112 | alt="" | |
| 119 | - | class="w-4 h-4 filter brightness-105 contrast-103" | |
| 113 | + | class="suggestion-favicon-img" | |
| 120 | 114 | loading="lazy" | |
| 121 | 115 | onerror={handleFaviconError} | |
| 122 | 116 | style="image-rendering: -webkit-optimize-contrast;" | |
| @@ -125,24 +119,19 @@ | |||
| 125 | 119 | {/if} | |
| 126 | 120 | ||
| 127 | 121 | <!-- URL text with gradient fade --> | |
| 128 | - | <div | |
| 129 | - | class="flex-1 min-w-0 flex gap-2 items-center | |
| 130 | - | whitespace-nowrap overflow-hidden | |
| 131 | - | [mask-image:linear-gradient(90deg,black_85%,transparent_100%)] | |
| 132 | - | [-webkit-mask-image:linear-gradient(90deg,black_85%,transparent_100%)]" | |
| 133 | - | > | |
| 122 | + | <div class="suggestion-text"> | |
| 134 | 123 | <!-- Domain --> | |
| 135 | - | <span class="text-[#e6e6e6] opacity-95"> | |
| 124 | + | <span class="suggestion-domain"> | |
| 136 | 125 | {domain} | |
| 137 | 126 | </span> | |
| 138 | 127 | ||
| 139 | 128 | <!-- Separator --> | |
| 140 | - | <span class="text-[#777]"> | |
| 129 | + | <span class="suggestion-separator"> | |
| 141 | 130 | {' | '} | |
| 142 | 131 | </span> | |
| 143 | 132 | ||
| 144 | 133 | <!-- Path --> | |
| 145 | - | <span class="text-[#99aadd]"> | |
| 134 | + | <span class="suggestion-path"> | |
| 146 | 135 | {path || '/'} | |
| 147 | 136 | </span> | |
| 148 | 137 | </div> | |
| @@ -151,3 +140,79 @@ | |||
| 151 | 140 | </div> | |
| 152 | 141 | {/if} | |
| 153 | 142 | ||
| 143 | + | ||
| 144 | + | ||
| 145 | + | <style> | |
| 146 | + | .suggestion-list { | |
| 147 | + | margin-top: 0.75rem; | |
| 148 | + | max-height: 50vh; | |
| 149 | + | overflow-y: auto; | |
| 150 | + | border-top: 1px solid var(--dynamic-border); | |
| 151 | + | background: color-mix(in srgb, var(--dynamic-bg) 94%, var(--dynamic-surface) 6%); | |
| 152 | + | } | |
| 153 | + | ||
| 154 | + | .suggestion-item { | |
| 155 | + | display: flex; | |
| 156 | + | gap: 0.75rem; | |
| 157 | + | align-items: center; | |
| 158 | + | padding: 0.65rem 0.85rem; | |
| 159 | + | border-bottom: 1px dashed var(--dynamic-border); | |
| 160 | + | cursor: pointer; | |
| 161 | + | transition: background-color 120ms ease, color 120ms ease; | |
| 162 | + | letter-spacing: 0.04em; | |
| 163 | + | } | |
| 164 | + | ||
| 165 | + | .suggestion-item:last-child { | |
| 166 | + | border-bottom: none; | |
| 167 | + | } | |
| 168 | + | ||
| 169 | + | .suggestion-item.selected, | |
| 170 | + | .suggestion-item:hover, | |
| 171 | + | .suggestion-item:focus-visible { | |
| 172 | + | background: color-mix(in srgb, var(--dynamic-bg) 60%, var(--dynamic-surface) 40%); | |
| 173 | + | color: var(--dynamic-text); | |
| 174 | + | outline: none; | |
| 175 | + | } | |
| 176 | + | ||
| 177 | + | .suggestion-item .suggestion-domain { | |
| 178 | + | color: var(--dynamic-text); | |
| 179 | + | opacity: 0.95; | |
| 180 | + | } | |
| 181 | + | ||
| 182 | + | .suggestion-item .suggestion-separator { | |
| 183 | + | color: var(--dynamic-muted); | |
| 184 | + | } | |
| 185 | + | ||
| 186 | + | .suggestion-item .suggestion-path { | |
| 187 | + | color: var(--dynamic-muted); | |
| 188 | + | } | |
| 189 | + | ||
| 190 | + | .suggestion-favicon { | |
| 191 | + | width: 20px; | |
| 192 | + | height: 20px; | |
| 193 | + | border: 1px solid var(--dynamic-border); | |
| 194 | + | display: flex; | |
| 195 | + | align-items: center; | |
| 196 | + | justify-content: center; | |
| 197 | + | background: var(--dynamic-bg); | |
| 198 | + | } | |
| 199 | + | ||
| 200 | + | .suggestion-favicon-img { | |
| 201 | + | width: 16px; | |
| 202 | + | height: 16px; | |
| 203 | + | object-fit: contain; | |
| 204 | + | } | |
| 205 | + | ||
| 206 | + | .suggestion-text { | |
| 207 | + | flex: 1; | |
| 208 | + | min-width: 0; | |
| 209 | + | display: flex; | |
| 210 | + | gap: 0.75rem; | |
| 211 | + | align-items: center; | |
| 212 | + | white-space: nowrap; | |
| 213 | + | overflow: hidden; | |
| 214 | + | text-overflow: ellipsis; | |
| 215 | + | mask-image: linear-gradient(90deg, black 85%, transparent 100%); | |
| 216 | + | -webkit-mask-image: linear-gradient(90deg, black 85%, transparent 100%); | |
| 217 | + | } | |
| 218 | + | </style> | |
| @@ -20,7 +20,7 @@ | |||||
| 20 | // Handle suggestion item mouse enter | 20 | // Handle suggestion item mouse enter | ||
| 21 | function handleItemMouseEnter(index: number) { | 21 | function handleItemMouseEnter(index: number) { | ||
| 22 | omniboxStore.setSelectedIndex(index); | 22 | omniboxStore.setSelectedIndex(index); | ||
| 23 | - | omniboxStore.setFaded(true); | 23 | + | omniboxStore.setFaded(false); |
| 24 | scrollToSelection(); | 24 | scrollToSelection(); | ||
| 25 | } | 25 | } | ||
| 26 | 26 | ||||
| @@ -86,7 +86,7 @@ | |||||
| 86 | {#if hasContent} | 86 | {#if hasContent} | ||
| 87 | <div | 87 | <div | ||
| 88 | id="omnibox-list" | 88 | id="omnibox-list" | ||
| 89 | - | class="mt-2 max-h-[50vh] overflow-auto border-t border-[#333]" | 89 | + | class="suggestion-list" |
| 90 | role="listbox" | 90 | role="listbox" | ||
| 91 | aria-label="Search suggestions" | 91 | aria-label="Search suggestions" | ||
| 92 | > | 92 | > | ||
| @@ -96,9 +96,7 @@ | |||||
| 96 | 96 | ||||
| 97 | <div | 97 | <div | ||
| 98 | id="omnibox-item-{index}" | 98 | id="omnibox-item-{index}" | ||
| 99 | - | class="px-2.5 py-2 flex gap-2.5 items-center cursor-pointer | 99 | + | class={isSelected ? 'suggestion-item selected' : 'suggestion-item'} |
| 100 | - | border-b border-[#2a2a2a] last:border-b-0 | |||
| 101 | - | {isSelected ? 'bg-[#0a0a0a]' : ''}" | |||
| 102 | role="option" | 100 | role="option" | ||
| 103 | tabindex={isSelected ? 0 : -1} | 101 | tabindex={isSelected ? 0 : -1} | ||
| 104 | aria-selected={isSelected} | 102 | aria-selected={isSelected} | ||
| @@ -108,15 +106,11 @@ | |||||
| 108 | > | 106 | > | ||
| 109 | <!-- Favicon chip --> | 107 | <!-- Favicon chip --> | ||
| 110 | {#if suggestion.favicon} | 108 | {#if suggestion.favicon} | ||
| 111 | - | <div | 109 | + | <div class="suggestion-favicon"> |
| 112 | - | class="flex-shrink-0 w-5 h-5 rounded-full | |||
| 113 | - | bg-[#ccc] border border-black/12 | |||
| 114 | - | shadow-sm flex items-center justify-center" | |||
| 115 | - | > | |||
| 116 | <img | 110 | <img | ||
| 117 | src={suggestion.favicon} | 111 | src={suggestion.favicon} | ||
| 118 | alt="" | 112 | alt="" | ||
| 119 | - | class="w-4 h-4 filter brightness-105 contrast-103" | 113 | + | class="suggestion-favicon-img" |
| 120 | loading="lazy" | 114 | loading="lazy" | ||
| 121 | onerror={handleFaviconError} | 115 | onerror={handleFaviconError} | ||
| 122 | style="image-rendering: -webkit-optimize-contrast;" | 116 | style="image-rendering: -webkit-optimize-contrast;" | ||
| @@ -125,24 +119,19 @@ | |||||
| 125 | {/if} | 119 | {/if} | ||
| 126 | 120 | ||||
| 127 | <!-- URL text with gradient fade --> | 121 | <!-- URL text with gradient fade --> | ||
| 128 | - | <div | 122 | + | <div class="suggestion-text"> |
| 129 | - | class="flex-1 min-w-0 flex gap-2 items-center | |||
| 130 | - | whitespace-nowrap overflow-hidden | |||
| 131 | - | [mask-image:linear-gradient(90deg,black_85%,transparent_100%)] | |||
| 132 | - | [-webkit-mask-image:linear-gradient(90deg,black_85%,transparent_100%)]" | |||
| 133 | - | > | |||
| 134 | <!-- Domain --> | 123 | <!-- Domain --> | ||
| 135 | - | <span class="text-[#e6e6e6] opacity-95"> | 124 | + | <span class="suggestion-domain"> |
| 136 | {domain} | 125 | {domain} | ||
| 137 | </span> | 126 | </span> | ||
| 138 | 127 | ||||
| 139 | <!-- Separator --> | 128 | <!-- Separator --> | ||
| 140 | - | <span class="text-[#777]"> | 129 | + | <span class="suggestion-separator"> |
| 141 | {' | '} | 130 | {' | '} | ||
| 142 | </span> | 131 | </span> | ||
| 143 | 132 | ||||
| 144 | <!-- Path --> | 133 | <!-- Path --> | ||
| 145 | - | <span class="text-[#99aadd]"> | 134 | + | <span class="suggestion-path"> |
| 146 | {path || '/'} | 135 | {path || '/'} | ||
| 147 | </span> | 136 | </span> | ||
| 148 | </div> | 137 | </div> | ||
| @@ -151,3 +140,79 @@ | |||||
| 151 | </div> | 140 | </div> | ||
| 152 | {/if} | 141 | {/if} | ||
| 153 | 142 | ||||
| 143 | + | ||||
| 144 | + | ||||
| 145 | + | <style> | |||
| 146 | + | .suggestion-list { | |||
| 147 | + | margin-top: 0.75rem; | |||
| 148 | + | max-height: 50vh; | |||
| 149 | + | overflow-y: auto; | |||
| 150 | + | border-top: 1px solid var(--dynamic-border); | |||
| 151 | + | background: color-mix(in srgb, var(--dynamic-bg) 94%, var(--dynamic-surface) 6%); | |||
| 152 | + | } | |||
| 153 | + | ||||
| 154 | + | .suggestion-item { | |||
| 155 | + | display: flex; | |||
| 156 | + | gap: 0.75rem; | |||
| 157 | + | align-items: center; | |||
| 158 | + | padding: 0.65rem 0.85rem; | |||
| 159 | + | border-bottom: 1px dashed var(--dynamic-border); | |||
| 160 | + | cursor: pointer; | |||
| 161 | + | transition: background-color 120ms ease, color 120ms ease; | |||
| 162 | + | letter-spacing: 0.04em; | |||
| 163 | + | } | |||
| 164 | + | ||||
| 165 | + | .suggestion-item:last-child { | |||
| 166 | + | border-bottom: none; | |||
| 167 | + | } | |||
| 168 | + | ||||
| 169 | + | .suggestion-item.selected, | |||
| 170 | + | .suggestion-item:hover, | |||
| 171 | + | .suggestion-item:focus-visible { | |||
| 172 | + | background: color-mix(in srgb, var(--dynamic-bg) 60%, var(--dynamic-surface) 40%); | |||
| 173 | + | color: var(--dynamic-text); | |||
| 174 | + | outline: none; | |||
| 175 | + | } | |||
| 176 | + | ||||
| 177 | + | .suggestion-item .suggestion-domain { | |||
| 178 | + | color: var(--dynamic-text); | |||
| 179 | + | opacity: 0.95; | |||
| 180 | + | } | |||
| 181 | + | ||||
| 182 | + | .suggestion-item .suggestion-separator { | |||
| 183 | + | color: var(--dynamic-muted); | |||
| 184 | + | } | |||
| 185 | + | ||||
| 186 | + | .suggestion-item .suggestion-path { | |||
| 187 | + | color: var(--dynamic-muted); | |||
| 188 | + | } | |||
| 189 | + | ||||
| 190 | + | .suggestion-favicon { | |||
| 191 | + | width: 20px; | |||
| 192 | + | height: 20px; | |||
| 193 | + | border: 1px solid var(--dynamic-border); | |||
| 194 | + | display: flex; | |||
| 195 | + | align-items: center; | |||
| 196 | + | justify-content: center; | |||
| 197 | + | background: var(--dynamic-bg); | |||
| 198 | + | } | |||
| 199 | + | ||||
| 200 | + | .suggestion-favicon-img { | |||
| 201 | + | width: 16px; | |||
| 202 | + | height: 16px; | |||
| 203 | + | object-fit: contain; | |||
| 204 | + | } | |||
| 205 | + | ||||
| 206 | + | .suggestion-text { | |||
| 207 | + | flex: 1; | |||
| 208 | + | min-width: 0; | |||
| 209 | + | display: flex; | |||
| 210 | + | gap: 0.75rem; | |||
| 211 | + | align-items: center; | |||
| 212 | + | white-space: nowrap; | |||
| 213 | + | overflow: hidden; | |||
| 214 | + | text-overflow: ellipsis; | |||
| 215 | + | mask-image: linear-gradient(90deg, black 85%, transparent 100%); | |||
| 216 | + | -webkit-mask-image: linear-gradient(90deg, black 85%, transparent 100%); | |||
| 217 | + | } | |||
| 218 | + | </style> | |||
M gui/src/components/omnibox/find.ts +1 -1
| @@ -23,7 +23,7 @@ function ensureFindStyles(): void { | |||
| 23 | 23 | background-color: rgb(255 235 59); | |
| 24 | 24 | color: rgb(0 0 0); | |
| 25 | 25 | padding: 0 0.125rem; | |
| 26 | - | border-radius: 0.125rem; | |
| 26 | + | border-radius: 0; | |
| 27 | 27 | box-shadow: 0 0 0 1px rgb(200 185 0) inset; | |
| 28 | 28 | } | |
| 29 | 29 | ||
| @@ -23,7 +23,7 @@ function ensureFindStyles(): void { | |||||
| 23 | background-color: rgb(255 235 59); | 23 | background-color: rgb(255 235 59); | ||
| 24 | color: rgb(0 0 0); | 24 | color: rgb(0 0 0); | ||
| 25 | padding: 0 0.125rem; | 25 | padding: 0 0.125rem; | ||
| 26 | - | border-radius: 0.125rem; | 26 | + | border-radius: 0; |
| 27 | box-shadow: 0 0 0 1px rgb(200 185 0) inset; | 27 | box-shadow: 0 0 0 1px rgb(200 185 0) inset; | ||
| 28 | } | 28 | } | ||
| 29 | 29 | ||||