Skip to content

Commit 4b89ae8

Browse files
authored
#237 Expand StackedLayout tokens to include autohide classes (#238)
1 parent 429ff34 commit 4b89ae8

File tree

5 files changed

+48
-24
lines changed

5 files changed

+48
-24
lines changed

libs/menu/src/StackedLayout.tsx

+22-23
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import * as React from "react";
1919

2020
import { Container } from "@tiller-ds/core";
2121
import { ComponentTokens, cx, TokenProps, useTokens } from "@tiller-ds/theme";
22-
import { createNamedContext } from "@tiller-ds/util";
22+
import { createNamedContext, useWindowEvent } from "@tiller-ds/util";
2323

2424
type StackedLayoutProps = {
2525
/**
@@ -48,6 +48,12 @@ type StackedLayoutProps = {
4848
*/
4949
navigation: React.ReactNode;
5050

51+
/**
52+
* Defines whether the StackedLayout header statys fixed or hides when page is scrolled.
53+
* Defaults to true.
54+
*/
55+
hideOnScroll?: boolean;
56+
5157
/**
5258
* Custom additional class name for the main container component.
5359
*/
@@ -82,8 +88,6 @@ type StackedLayoutContext = {
8288
containerVariant?: "max" | "fullWidth" | "constrainedPadded" | "fullWidthContainer" | "narrowConstrained" | undefined;
8389
isScrolling?: boolean;
8490
isFixed?: boolean;
85-
headingHeight: number;
86-
setHeadingHeight: React.Dispatch<number>;
8791
};
8892

8993
const StackedLayoutContext = createNamedContext<StackedLayoutContext>("StackedLayoutContext");
@@ -94,15 +98,16 @@ function StackedLayout({
9498
isFixed,
9599
children,
96100
background = "gray",
101+
hideOnScroll = true,
97102
className,
98103
...props
99104
}: StackedLayoutProps) {
100105
const tokens = useTokens("StackedLayout", props.tokens);
101106
const [isScrolling, setIsScrolling] = React.useState<boolean>(false);
102-
const [headingHeight, setHeadingHeight] = React.useState<number>(0);
103107

104108
const navigationContainerClassName = cx({
105-
"transition duration-300 w-full sticky top-0 z-30": isFixed,
109+
[tokens.navigationContainer.fixed]: isFixed,
110+
[tokens.navigationContainer.scrolled]: isScrolling,
106111
});
107112

108113
const containerClassName = cx(
@@ -112,21 +117,20 @@ function StackedLayout({
112117
{ [tokens.grayBackgroundColor]: background !== "white" }
113118
);
114119

115-
window.onscroll = function () {
116-
if (window.pageYOffset > 80) {
117-
setIsScrolling(true);
118-
} else {
119-
setIsScrolling(false);
120+
useWindowEvent("scroll", () => {
121+
if (hideOnScroll) {
122+
if (window.pageYOffset > 80) {
123+
setIsScrolling(true);
124+
} else {
125+
setIsScrolling(false);
126+
}
120127
}
121-
};
128+
});
122129

123130
return (
124-
<StackedLayoutContext.Provider value={{ containerVariant, isScrolling, isFixed, headingHeight, setHeadingHeight }}>
131+
<StackedLayoutContext.Provider value={{ containerVariant, isScrolling, isFixed }}>
125132
<div className={containerClassName}>
126-
<div
127-
className={navigationContainerClassName}
128-
style={{ transform: isScrolling && isFixed ? "translate(0, -64px)" : "" }}
129-
>
133+
<div className={navigationContainerClassName}>
130134
{navigation}
131135
</div>
132136
{children}
@@ -143,14 +147,9 @@ function StackedLayoutHeading({
143147
}: StackedLayoutHeadingProps) {
144148
const tokens = useTokens("StackedLayout", props.tokens);
145149
const layoutContext = React.useContext(StackedLayoutContext) as StackedLayoutContext;
146-
const ref = React.useRef<HTMLDivElement>(null);
147-
148-
React.useEffect(() => {
149-
layoutContext.setHeadingHeight(ref.current?.clientHeight ?? 0);
150-
}, [ref.current]);
151150

152151
const headingContainerClassName = cx({
153-
"bg-gray-100 transition duration-300 sticky top-0 w-full z-20": layoutContext?.isFixed,
152+
[tokens.heading.fixed]: layoutContext?.isFixed,
154153
});
155154

156155
const headingClassName = cx(
@@ -160,7 +159,7 @@ function StackedLayoutHeading({
160159
);
161160

162161
return (
163-
<div ref={ref} className={headingContainerClassName}>
162+
<div className={headingContainerClassName}>
164163
<div className={headingClassName}>
165164
<Container variant={layoutContext.containerVariant}>{children}</Container>
166165
</div>

libs/theme/src/defaultTheme.tsx

+7
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,13 @@ const defaultComponentConfig = {
16191619
compactPadding: "py-4",
16201620
padding: "py-6",
16211621
contentContainer: "px-4 py-8 sm:px-0 z-0",
1622+
navigationContainer: {
1623+
fixed: "transition duration-300 w-full sticky top-0 z-30",
1624+
scrolled: "-translate-y-full"
1625+
},
1626+
heading: {
1627+
fixed: "bg-gray-100 transition duration-300 sticky top-0 w-full z-20",
1628+
}
16221629
},
16231630
StatusButton: {
16241631
icon: {

libs/util/src/index.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export { default as useInterval } from "./useInterval";
2525
export { default as useTimeout } from "./useTimeout";
2626
export { default as useViewport } from "./useViewport";
2727
export { default as usePrevious } from "./usePrevious";
28+
export { default as useWindowEvent } from "./useWindowEvent";
2829

2930
export { default as createNamedContext } from "./createNamedContext";
3031
export {

libs/util/src/useWindowEvent.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { useEffect } from "react";
2+
3+
export default function useWindowEvent<K extends keyof WindowEventMap>(
4+
type: K,
5+
listener: (this: Window, ev: WindowEventMap[K]) => void
6+
) {
7+
useEffect(() => {
8+
window.addEventListener(type, listener);
9+
return () => window.removeEventListener(type, listener);
10+
}, [type, listener]);
11+
}

storybook/src/base-documentation/ReleaseNotes.stories.mdx

+7-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ import { Meta } from "@storybook/addon-docs";
1818

1919
# 📝 Release Notes
2020

21-
## **1.11.0 - latest** <span>_(Mar 26th 2024)_</span>
21+
## **1.12.0 - latest** <span>_(Apr 3rd 2024)_</span>
22+
23+
**<h4>⚡ Component Improvements</h4>**
24+
25+
- Improved `StackedLayout` autohide header functionality, so it can be controlled via tokens ([#237](https://github.com/croz-ltd/tiller/issues/237))
26+
27+
## **1.11.0 ** <span>_(Mar 26th 2024)_</span>
2228

2329
**<h4>🐛 Bug Fixes</h4>**
2430

0 commit comments

Comments
 (0)