mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-08 18:04:14 +01:00
[PORT] gitea#29831: Prevent layout shift in <overflow-menu>
items
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 <wxiaoguang@gmail.com> --- Conflict resolution: Moved an `:focus` selector to the new CSS rule. Ref: https://codeberg.org/forgejo/forgejo/issues/2776 (cherry picked from commit 99d7ef50917e8d61798715e1b0b3dc1a99709f27)
This commit is contained in:
parent
a11116602e
commit
18d13000e9
3 changed files with 41 additions and 11 deletions
|
@ -1842,15 +1842,6 @@ table th[data-sortt-desc] .svg {
|
|||
border-color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.ui.tabular.menu .item {
|
||||
padding: 11px 12px;
|
||||
color: var(--color-text-light-2);
|
||||
}
|
||||
|
||||
.ui.tabular.menu .item:hover {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.ui.tabular.menu .active.item,
|
||||
.ui.tabular.menu .active.item:hover {
|
||||
background: var(--color-body);
|
||||
|
@ -1867,17 +1858,36 @@ table th[data-sortt-desc] .svg {
|
|||
border-color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.ui.tabular.menu .item,
|
||||
.ui.secondary.pointing.menu .item {
|
||||
padding: 11px 12px !important;
|
||||
color: var(--color-text-light-2);
|
||||
}
|
||||
|
||||
.ui.tabular.menu .item:hover,
|
||||
.ui.secondary.pointing.menu a.item:hover, .ui.secondary.pointing.menu a.item:focus {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.ui.secondary.pointing.menu .active.item,
|
||||
.ui.secondary.pointing.menu .active.item:hover, .ui.secondary.pointing.menu .active.item:focus,
|
||||
.ui.secondary.pointing.menu .dropdown.item:hover, .ui.secondary.pointing.menu .dropdown.item:focus,
|
||||
.ui.secondary.pointing.menu a.item:hover, .ui.secondary.pointing.menu a.item:focus {
|
||||
.ui.secondary.pointing.menu .dropdown.item:hover, .ui.secondary.pointing.menu .dropdown.item:focus {
|
||||
color: var(--color-text-dark);
|
||||
}
|
||||
|
||||
.ui.tabular.menu .active.item,
|
||||
.ui.secondary.pointing.menu .active.item,
|
||||
.resize-for-semibold::before {
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
.resize-for-semibold::before {
|
||||
content: attr(data-text);
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.ui.header {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.repo-header .flex-item {
|
||||
|
|
|
@ -127,6 +127,25 @@ window.customElements.define('overflow-menu', class extends HTMLElement {
|
|||
});
|
||||
|
||||
init() {
|
||||
// for horizontal menus where fomantic boldens active items, prevent this bold text from
|
||||
// enlarging the menu's active item replacing the text node with a div that renders a
|
||||
// invisible pseudo-element that enlarges the box.
|
||||
if (this.matches('.ui.secondary.pointing.menu, .ui.tabular.menu')) {
|
||||
for (const item of this.querySelectorAll('.item')) {
|
||||
for (const child of item.childNodes) {
|
||||
if (child.nodeType === Node.TEXT_NODE) {
|
||||
const text = child.textContent.trim(); // whitespace is insignificant inside flexbox
|
||||
if (!text) continue;
|
||||
const span = document.createElement('span');
|
||||
span.classList.add('resize-for-semibold');
|
||||
span.setAttribute('data-text', text);
|
||||
span.textContent = text;
|
||||
child.replaceWith(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ResizeObserver triggers on initial render, so we don't manually call `updateItems` here which
|
||||
// also avoids a full-page FOUC in Firefox that happens when `updateItems` is called too soon.
|
||||
this.resizeObserver = new ResizeObserver((entries) => {
|
||||
|
|
Loading…
Reference in a new issue