Skip to content

Commit d2e7f19

Browse files
Prevent layout shift in <overflow-menu> items (go-gitea#29831)
There is a small layout shift in when active tab changes. Notice how the actions SVG is unstable: ![](https://github.com/go-gitea/gitea/assets/115237/a6928e89-5d47-4a91-8f36-1fa22fddbce7) This is because the active item with bold text is wider then the inactive one. I have applied [this trick](https://stackoverflow.com/a/32570813/808699) to prevent this layout shift. It's only active inside `<overflow-menu>` because I wanted to avoid changing HTML and doing it in regular JS would cause a flicker. I don't expect us to introduce other similar menus without `<overflow-menu>`, so that place is likely fine. ![after](https://github.com/go-gitea/gitea/assets/115237/d6089924-8de6-4ee0-8db4-15f16069a131) I also changed the weight from 500 to 600, slightly reduced horizontal padding, merged some tab-bar related CSS rules and a added a small margin below repo-header so it does not look so crammed against the buttons on top. --------- Co-authored-by: wxiaoguang <[email protected]>
1 parent 0db1944 commit d2e7f19

File tree

3 files changed

+41
-11
lines changed

3 files changed

+41
-11
lines changed

web_src/css/base.css

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,15 +1778,6 @@ table th[data-sortt-desc] .svg {
17781778
border-color: var(--color-secondary);
17791779
}
17801780

1781-
.ui.tabular.menu .item {
1782-
padding: 11px 12px;
1783-
color: var(--color-text-light-2);
1784-
}
1785-
1786-
.ui.tabular.menu .item:hover {
1787-
color: var(--color-text);
1788-
}
1789-
17901781
.ui.tabular.menu .active.item,
17911782
.ui.tabular.menu .active.item:hover {
17921783
background: var(--color-body);
@@ -1803,17 +1794,36 @@ table th[data-sortt-desc] .svg {
18031794
border-color: var(--color-secondary);
18041795
}
18051796

1797+
.ui.tabular.menu .item,
18061798
.ui.secondary.pointing.menu .item {
1799+
padding: 11px 12px !important;
18071800
color: var(--color-text-light-2);
18081801
}
18091802

1803+
.ui.tabular.menu .item:hover,
1804+
.ui.secondary.pointing.menu a.item:hover {
1805+
color: var(--color-text);
1806+
}
1807+
18101808
.ui.secondary.pointing.menu .active.item,
18111809
.ui.secondary.pointing.menu .active.item:hover,
1812-
.ui.secondary.pointing.menu .dropdown.item:hover,
1813-
.ui.secondary.pointing.menu a.item:hover {
1810+
.ui.secondary.pointing.menu .dropdown.item:hover {
18141811
color: var(--color-text-dark);
18151812
}
18161813

1814+
.ui.tabular.menu .active.item,
1815+
.ui.secondary.pointing.menu .active.item,
1816+
.resize-for-semibold::before {
1817+
font-weight: var(--font-weight-semibold);
1818+
}
1819+
1820+
.resize-for-semibold::before {
1821+
content: attr(data-text);
1822+
visibility: hidden;
1823+
display: block;
1824+
height: 0;
1825+
}
1826+
18171827
.ui.header {
18181828
color: var(--color-text);
18191829
}

web_src/css/repo/header.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
flex-flow: row wrap;
99
justify-content: space-between;
1010
gap: 0.5rem;
11+
margin-bottom: 4px;
1112
}
1213

1314
.repo-header .flex-item {

web_src/js/webcomponents/overflow-menu.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,25 @@ window.customElements.define('overflow-menu', class extends HTMLElement {
127127
});
128128

129129
init() {
130+
// for horizontal menus where fomantic boldens active items, prevent this bold text from
131+
// enlarging the menu's active item replacing the text node with a div that renders a
132+
// invisible pseudo-element that enlarges the box.
133+
if (this.matches('.ui.secondary.pointing.menu, .ui.tabular.menu')) {
134+
for (const item of this.querySelectorAll('.item')) {
135+
for (const child of item.childNodes) {
136+
if (child.nodeType === Node.TEXT_NODE) {
137+
const text = child.textContent.trim(); // whitespace is insignificant inside flexbox
138+
if (!text) continue;
139+
const span = document.createElement('span');
140+
span.classList.add('resize-for-semibold');
141+
span.setAttribute('data-text', text);
142+
span.textContent = text;
143+
child.replaceWith(span);
144+
}
145+
}
146+
}
147+
}
148+
130149
// ResizeObserver triggers on initial render, so we don't manually call `updateItems` here which
131150
// also avoids a full-page FOUC in Firefox that happens when `updateItems` is called too soon.
132151
this.resizeObserver = new ResizeObserver((entries) => {

0 commit comments

Comments
 (0)