detached 77f7e1c

fix(webkit): improve omnibox responsive scaling and layout

- Fix over-aggressive viewport scaling that made omnibox too large at high zoom
- Add box-sizing: border-box to prevent input overflow beyond container
- Implement conditional separator display (hidden when no results)
- Replace viewport units with conservative fixed values for better zoom behavior
- Maintain responsive width while preventing overflow on small screens
- Omnibox now scales proportionally with webpage content
commit
77f7e1c17d958de9f3d76dabc59437b7f1ba8735
author
bamen · · 2025-09-10 18:36 UTC
committer
bamen · · 2025-09-10 18:31 UTC
parent
0220350
signature
unsigned
1 file · +28 -4
M pkg/webkit/ucm_js_cgo.go +28 -4
@@ -85,18 +85,37 @@ func getOmniboxScript() string {
8585 root.id = 'dumber-omnibox-root';
8686 root.style.cssText = 'position:fixed;inset:0;z-index:2147483647;display:none;';
8787 const box = document.createElement('div');
88- box.style.cssText = 'max-width:720px;margin:8vh auto;padding:8px 10px;background:#1b1b1b;color:#eee;border:1px solid #444;border-radius:8px;box-shadow:0 10px 30px rgba(0,0,0,.6);font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,"Helvetica Neue",Arial,sans-serif;';
88+ box.style.cssText = 'width:min(90vw, 720px);margin:8vh auto;padding:8px 12px;background:#1b1b1b;color:#eee;border:1px solid #444;border-radius:8px;box-shadow:0 10px 30px rgba(0,0,0,.6);font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,"Helvetica Neue",Arial,sans-serif;';
8989 const input = document.createElement('input');
9090 input.type = 'text';
9191 input.placeholder = 'Type URL or search…';
92- input.style.cssText = 'width:100%;padding:10px 12px;border-radius:6px;border:1px solid #555;background:#121212;color:#eee;font-size:16px;outline:none;';
92+ input.style.cssText = 'width:100%;box-sizing:border-box;padding:10px 12px;border-radius:6px;border:1px solid #555;background:#121212;color:#eee;font-size:16px;outline:none;';
9393 const list = document.createElement('div');
94- list.style.cssText = 'margin-top:8px;max-height:50vh;overflow:auto;border-top:1px solid #333;';
94+ list.style.cssText = 'margin-top:8px;max-height:50vh;overflow:auto;';
9595 const style = document.createElement('style');
9696 style.textContent = '.dumber-find-highlight{background:#ffeb3b;color:#000;padding:0 1px;border-radius:2px;box-shadow:0 0 0 1px #c8b900 inset}.dumber-find-active{background:#ff9800 !important;color:#000;box-shadow:0 0 0 1px #b36b00 inset}';
9797 document.documentElement.appendChild(style);
9898 box.appendChild(input); box.appendChild(list); root.appendChild(box); document.documentElement.appendChild(root);
9999 H.box = box;
100+ // Dynamic style updater for responsive behavior
101+ const updateStyles = () => {
102+ const vw = window.innerWidth;
103+ const isSmall = vw < 640;
104+ const isLarge = vw > 1920;
105+
106+ if (box) {
107+ box.style.width = isSmall ? '95vw' : isLarge ? 'min(90vw, 840px)' : 'min(90vw, 720px)';
108+ box.style.padding = isSmall ? '6px 8px' : '8px 12px';
109+ }
110+
111+ if (input) {
112+ input.style.fontSize = isSmall ? '14px' : isLarge ? '17px' : '16px';
113+ input.style.padding = isSmall ? '8px 10px' : '10px 12px';
114+ input.style.boxSizing = 'border-box';
115+ }
116+ };
117+ updateStyles();
118+ window.addEventListener('resize', updateStyles);
100119 // Click outside the box closes the overlay
101120 root.addEventListener('mousedown', (e)=>{
102121 const tgt = e.target;
@@ -164,6 +183,11 @@ func getOmniboxScript() string {
164183 },
165184 paintList(){
166185 const list = H.list; if (!list) return; list.textContent = '';
186+
187+ // Show/hide separator based on content
188+ const hasContent = (H.mode==='omnibox' && H.suggestions.length > 0) || (H.mode==='find' && H.matches.length > 0);
189+ list.style.borderTop = hasContent ? '1px solid #333' : 'none';
190+
167191 if (H.mode==='omnibox'){
168192 H.suggestions.forEach((s, i)=>{
169193 const item = document.createElement('div');
@@ -173,7 +197,7 @@ func getOmniboxScript() string {
173197 chip.style.cssText = 'flex:0 0 20px;width:20px;height:20px;border-radius:50%;background:#ccc;border:1px solid rgba(0,0,0,.12);box-shadow:0 1px 2px rgba(0,0,0,.12);display:flex;align-items:center;justify-content:center;';
174198 const icon = document.createElement('img');
175199 icon.src = s.favicon || '';
176- icon.width = 16; icon.height = 16; icon.loading = 'lazy';
200+ icon.loading = 'lazy';
177201 icon.style.cssText = 'width:16px;height:16px;filter:brightness(1.06) contrast(1.03);image-rendering:-webkit-optimize-contrast;';
178202 icon.onerror = ()=>{ chip.style.display='none'; };
179203 chip.appendChild(icon);
@@ -85,18 +85,37 @@ func getOmniboxScript() string {
85 root.id = 'dumber-omnibox-root';85 root.id = 'dumber-omnibox-root';
86 root.style.cssText = 'position:fixed;inset:0;z-index:2147483647;display:none;';86 root.style.cssText = 'position:fixed;inset:0;z-index:2147483647;display:none;';
87 const box = document.createElement('div');87 const box = document.createElement('div');
88- box.style.cssText = 'max-width:720px;margin:8vh auto;padding:8px 10px;background:#1b1b1b;color:#eee;border:1px solid #444;border-radius:8px;box-shadow:0 10px 30px rgba(0,0,0,.6);font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,"Helvetica Neue",Arial,sans-serif;';88+ box.style.cssText = 'width:min(90vw, 720px);margin:8vh auto;padding:8px 12px;background:#1b1b1b;color:#eee;border:1px solid #444;border-radius:8px;box-shadow:0 10px 30px rgba(0,0,0,.6);font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,"Helvetica Neue",Arial,sans-serif;';
89 const input = document.createElement('input');89 const input = document.createElement('input');
90 input.type = 'text';90 input.type = 'text';
91 input.placeholder = 'Type URL or search…';91 input.placeholder = 'Type URL or search…';
92- input.style.cssText = 'width:100%;padding:10px 12px;border-radius:6px;border:1px solid #555;background:#121212;color:#eee;font-size:16px;outline:none;';92+ input.style.cssText = 'width:100%;box-sizing:border-box;padding:10px 12px;border-radius:6px;border:1px solid #555;background:#121212;color:#eee;font-size:16px;outline:none;';
93 const list = document.createElement('div');93 const list = document.createElement('div');
94- list.style.cssText = 'margin-top:8px;max-height:50vh;overflow:auto;border-top:1px solid #333;';94+ list.style.cssText = 'margin-top:8px;max-height:50vh;overflow:auto;';
95 const style = document.createElement('style');95 const style = document.createElement('style');
96 style.textContent = '.dumber-find-highlight{background:#ffeb3b;color:#000;padding:0 1px;border-radius:2px;box-shadow:0 0 0 1px #c8b900 inset}.dumber-find-active{background:#ff9800 !important;color:#000;box-shadow:0 0 0 1px #b36b00 inset}';96 style.textContent = '.dumber-find-highlight{background:#ffeb3b;color:#000;padding:0 1px;border-radius:2px;box-shadow:0 0 0 1px #c8b900 inset}.dumber-find-active{background:#ff9800 !important;color:#000;box-shadow:0 0 0 1px #b36b00 inset}';
97 document.documentElement.appendChild(style);97 document.documentElement.appendChild(style);
98 box.appendChild(input); box.appendChild(list); root.appendChild(box); document.documentElement.appendChild(root);98 box.appendChild(input); box.appendChild(list); root.appendChild(box); document.documentElement.appendChild(root);
99 H.box = box;99 H.box = box;
100+ // Dynamic style updater for responsive behavior
101+ const updateStyles = () => {
102+ const vw = window.innerWidth;
103+ const isSmall = vw < 640;
104+ const isLarge = vw > 1920;
105+
106+ if (box) {
107+ box.style.width = isSmall ? '95vw' : isLarge ? 'min(90vw, 840px)' : 'min(90vw, 720px)';
108+ box.style.padding = isSmall ? '6px 8px' : '8px 12px';
109+ }
110+
111+ if (input) {
112+ input.style.fontSize = isSmall ? '14px' : isLarge ? '17px' : '16px';
113+ input.style.padding = isSmall ? '8px 10px' : '10px 12px';
114+ input.style.boxSizing = 'border-box';
115+ }
116+ };
117+ updateStyles();
118+ window.addEventListener('resize', updateStyles);
100 // Click outside the box closes the overlay119 // Click outside the box closes the overlay
101 root.addEventListener('mousedown', (e)=>{120 root.addEventListener('mousedown', (e)=>{
102 const tgt = e.target;121 const tgt = e.target;
@@ -164,6 +183,11 @@ func getOmniboxScript() string {
164 },183 },
165 paintList(){184 paintList(){
166 const list = H.list; if (!list) return; list.textContent = '';185 const list = H.list; if (!list) return; list.textContent = '';
186+
187+ // Show/hide separator based on content
188+ const hasContent = (H.mode==='omnibox' && H.suggestions.length > 0) || (H.mode==='find' && H.matches.length > 0);
189+ list.style.borderTop = hasContent ? '1px solid #333' : 'none';
190+
167 if (H.mode==='omnibox'){191 if (H.mode==='omnibox'){
168 H.suggestions.forEach((s, i)=>{192 H.suggestions.forEach((s, i)=>{
169 const item = document.createElement('div');193 const item = document.createElement('div');
@@ -173,7 +197,7 @@ func getOmniboxScript() string {
173 chip.style.cssText = 'flex:0 0 20px;width:20px;height:20px;border-radius:50%;background:#ccc;border:1px solid rgba(0,0,0,.12);box-shadow:0 1px 2px rgba(0,0,0,.12);display:flex;align-items:center;justify-content:center;';197 chip.style.cssText = 'flex:0 0 20px;width:20px;height:20px;border-radius:50%;background:#ccc;border:1px solid rgba(0,0,0,.12);box-shadow:0 1px 2px rgba(0,0,0,.12);display:flex;align-items:center;justify-content:center;';
174 const icon = document.createElement('img');198 const icon = document.createElement('img');
175 icon.src = s.favicon || '';199 icon.src = s.favicon || '';
176- icon.width = 16; icon.height = 16; icon.loading = 'lazy';200+ icon.loading = 'lazy';
177 icon.style.cssText = 'width:16px;height:16px;filter:brightness(1.06) contrast(1.03);image-rendering:-webkit-optimize-contrast;';201 icon.style.cssText = 'width:16px;height:16px;filter:brightness(1.06) contrast(1.03);image-rendering:-webkit-optimize-contrast;';
178 icon.onerror = ()=>{ chip.style.display='none'; };202 icon.onerror = ()=>{ chip.style.display='none'; };
179 chip.appendChild(icon);203 chip.appendChild(icon);

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