discourse/app/assets/stylesheets/common/components/horizontal-overflow-nav.scss
Kris 57f9b10146
UX: fix RTL overflow scroll in composer controls and other nav (#39141)
Our overflow scroll buttons were broken in RTL languages, for example
here in the composer toolbar:

<img width="450" alt="image"
src="https://github.com/user-attachments/assets/9b935073-e86f-4789-ba56-e5c529be9c67"
/>

This fixes it by:
- Use /*! rtl:ignore */ CSS directives to keep buttons, icons, and fades
in physical positions (prevent rtlcss auto-swapping)
- Swap button visibility logic in RTL (which button shows based on
scroll position)
  - Use Math.abs() on scrollLeft to fix negative value in Chrome
2026-04-07 19:40:40 -04:00

100 lines
1.9 KiB
SCSS
Vendored

.horizontal-overflow-nav {
position: relative;
min-width: 0;
width: 100%;
.nav-pills {
overflow: auto;
min-width: 0;
margin: 0;
height: 100%;
position: relative;
// avoids auto-scroll on initial load if active nav item is overflowed
scroll-behavior: auto;
// hides scrollbars, but allows mouse scrolling
scrollbar-width: none;
&::-webkit-scrollbar {
height: 0;
}
}
&.has-scroll {
.nav-pills {
scroll-behavior: smooth; // smooth scrolling on user interaction
}
}
}
.horizontal-overflow-nav__scroll-right,
.horizontal-overflow-nav__scroll-left {
--fade-width: 1.5em;
--fade-color: var(--secondary);
opacity: 1;
position: absolute;
z-index: 2;
background-color: var(--secondary);
top: 0;
bottom: 0;
display: flex;
align-items: center;
transition: opacity 0.25s;
.d-icon {
pointer-events: none;
margin-bottom: 0.2em;
color: var(--d-nav-color--active);
}
&.disabled {
// hiding with opacity so we can transition visibility
opacity: 0;
pointer-events: none;
}
}
.horizontal-overflow-nav__scroll-right {
/*! rtl:ignore */
right: 0;
&::before {
content: "";
/*! rtl:ignore */
margin-left: calc(var(--fade-width) * -1);
height: 100%;
width: var(--fade-width);
/*! rtl:ignore */
background: linear-gradient(to left, var(--fade-color), transparent);
}
// Undo automatic icon flip since button stays in physical position
.rtl & .d-icon {
transform: scaleX(1);
}
}
.horizontal-overflow-nav__scroll-left {
/*! rtl:ignore */
left: 0;
&::after {
content: "";
/*! rtl:ignore */
margin-right: calc(var(--fade-width) * -1);
height: 100%;
width: var(--fade-width);
/*! rtl:ignore */
background: linear-gradient(to right, var(--fade-color), transparent);
}
// Undo automatic icon flip since button stays in physical position
.rtl & .d-icon {
transform: scaleX(1);
}
}