Polish sticky Header implementation

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2026-04-26 15:05:45 +01:00
parent dceca05fb4
commit 6c4606a71c
3 changed files with 15 additions and 7 deletions
+2
View File
@@ -3,3 +3,5 @@
---
Added a `sticky` prop to the `Header` component. When `true`, the title-and-actions bar stays fixed to the top of its scroll container while the rest of the header (tags, description, metadata) scrolls away. The sticky bar background color automatically matches the container surface using the bg-consumer system.
**Affected components:** Header
@@ -116,8 +116,10 @@
.bui-HeaderTitleStack {
position: relative;
flex: 1 1 auto;
height: calc(var(--bui-font-size-6) * 1.4);
height: 1lh;
min-width: 0;
font-size: var(--bui-font-size-6);
line-height: 140%;
overflow: hidden;
}
@@ -151,13 +153,13 @@
overflow: hidden;
font-family: var(--bui-font-regular);
font-weight: var(--bui-font-weight-bold);
line-height: 140%;
line-height: inherit;
text-overflow: ellipsis;
white-space: nowrap;
}
.bui-HeaderBreadcrumbs .bui-HeaderBreadcrumbLink {
font-size: var(--bui-font-size-6);
font-size: inherit;
}
.bui-HeaderBreadcrumbsSmall .bui-HeaderBreadcrumbLinkSmall {
@@ -176,14 +178,14 @@
min-width: 0;
font-family: var(--bui-font-regular);
font-weight: var(--bui-font-weight-bold);
line-height: 140%;
line-height: inherit;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.bui-HeaderTitle {
font-size: var(--bui-font-size-6);
font-size: inherit;
}
.bui-HeaderTitleSmall {
+6 -2
View File
@@ -29,9 +29,11 @@ const getScrollParent = (element: HTMLElement | null): Element | null => {
let parent = element?.parentElement;
while (parent) {
const { overflowY } = window.getComputedStyle(parent);
const { overflow, overflowX, overflowY } = window.getComputedStyle(parent);
if (/(auto|scroll|overlay)/.test(overflowY)) {
if (
/(auto|scroll|overlay|hidden)/.test(`${overflow}${overflowX}${overflowY}`)
) {
return parent;
}
@@ -85,6 +87,8 @@ export const Header = (props: HeaderProps) => {
() => (description ? renderInlineMarkdown(description) : null),
[description],
);
// The sentinel sits directly before the sticky content and leaves the
// viewport when the content becomes stuck, letting us toggle stuck styling.
const stickySentinelRef = useRef<HTMLDivElement>(null);
const [isStuck, setIsStuck] = useState(false);