Skip to content

Commit 4d9bfdf

Browse files
committed
feat(chrome): detect Footer automatically with context
1 parent 6263ced commit 4d9bfdf

File tree

9 files changed

+46
-30
lines changed

9 files changed

+46
-30
lines changed

docs/migration.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ consider additional positioning prop support on a case-by-case basis.
4747
#### @zendeskgarden/react-chrome
4848

4949
- Removed `PRODUCT` type export. Use `IHeaderItemProps['product']` instead.
50+
- `Body` prop `hasFooter` has been removed. Footer detection now happens automatically.
5051
- The following React component types have changed:
5152
- Renamed `ICollapsibleSubNavItemProps` type export to `ISubNavCollapsibleItemProps`.
5253
- `Header.ItemIcon`: `HTMLAttributes<HTMLElement>` -> `SVGAttributes<SVGElement>`

packages/chrome/demo/stories/ChromeStory.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ export const ChromeStory: Story<IArgs> = ({
195195
)}
196196
</SubNav>
197197
)}
198-
<Body hasFooter={hasFooter}>
198+
<Body>
199199
{hasHeader && (
200200
<Header isStandalone={!(hasNav || hasSubNav)}>
201201
{hasLogo && (

packages/chrome/src/elements/body/Body.tsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,27 @@
55
* found at http://www.apache.org/licenses/LICENSE-2.0.
66
*/
77

8-
import React, { useMemo } from 'react';
9-
import PropTypes from 'prop-types';
10-
import { IBodyProps } from '../../types';
8+
import React, { HTMLAttributes, useMemo, useState } from 'react';
119
import { StyledBody } from '../../styled';
1210
import { BodyContext } from '../../utils/useBodyContext';
1311

1412
/**
1513
* @extends HTMLAttributes<HTMLDivElement>
1614
*/
17-
export const Body = React.forwardRef<HTMLDivElement, IBodyProps>(({ hasFooter, ...props }, ref) => {
18-
const bodyContextValue = useMemo(() => ({ hasFooter: !!hasFooter }), [hasFooter]);
15+
export const Body = React.forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
16+
(props, ref) => {
17+
const [hasFooter, setHasFooter] = useState(true);
18+
const bodyContextValue = useMemo(
19+
() => ({ hasFooter, setHasFooter }),
20+
[hasFooter, setHasFooter]
21+
);
1922

20-
return (
21-
<BodyContext.Provider value={bodyContextValue}>
22-
<StyledBody ref={ref} {...props} />
23-
</BodyContext.Provider>
24-
);
25-
});
23+
return (
24+
<BodyContext.Provider value={bodyContextValue}>
25+
<StyledBody ref={ref} {...props} />
26+
</BodyContext.Provider>
27+
);
28+
}
29+
);
2630

2731
Body.displayName = 'Body';
28-
29-
Body.propTypes = {
30-
hasFooter: PropTypes.bool
31-
};

packages/chrome/src/elements/body/Content.spec.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@
88
import React from 'react';
99
import { render } from 'garden-test-utils';
1010
import { Content } from './Content';
11+
import { Body } from './Body';
1112

1213
describe('Content', () => {
1314
it('passes ref to underlying DOM element', () => {
1415
const ref = React.createRef<HTMLDivElement>();
15-
const { container } = render(<Content ref={ref} />);
16+
const { queryByTestId } = render(
17+
<Body>
18+
<Content ref={ref} data-test-id="content" />
19+
</Body>
20+
);
1621

17-
expect(container.firstChild).toBe(ref.current);
22+
expect(queryByTestId('content')).toBe(ref.current);
1823
});
1924
});

packages/chrome/src/elements/body/Content.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { useBodyContext } from '../../utils/useBodyContext';
1414
*/
1515
export const Content = React.forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
1616
(props, ref) => {
17-
const { hasFooter } = useBodyContext();
17+
const { hasFooter } = useBodyContext() || {};
1818

1919
return <StyledContent ref={ref} hasFooter={hasFooter} {...props} />;
2020
}

packages/chrome/src/elements/footer/Footer.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,32 @@
55
* found at http://www.apache.org/licenses/LICENSE-2.0.
66
*/
77

8-
import React, { HTMLAttributes } from 'react';
8+
import React, { HTMLAttributes, useEffect } from 'react';
99
import { StyledFooter } from '../../styled';
10+
import { useBodyContext } from '../../utils/useBodyContext';
1011
import { FooterItem } from './FooterItem';
1112

1213
/**
1314
* @extends HTMLAttributes<HTMLElement>
1415
*/
1516
export const FooterComponent = React.forwardRef<HTMLElement, HTMLAttributes<HTMLElement>>(
16-
(props, ref) => <StyledFooter ref={ref} {...props} />
17+
(props, ref) => {
18+
const { hasFooter, setHasFooter } = useBodyContext() || {};
19+
20+
useEffect(() => {
21+
if (!hasFooter && setHasFooter) {
22+
setHasFooter(true);
23+
}
24+
25+
return () => {
26+
if (hasFooter && setHasFooter) {
27+
setHasFooter(false);
28+
}
29+
};
30+
}, [hasFooter, setHasFooter]);
31+
32+
return <StyledFooter ref={ref} {...props} />;
33+
}
1734
);
1835

1936
FooterComponent.displayName = 'Footer';

packages/chrome/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ export {
3333
PRODUCTS,
3434
type IChromeProps,
3535
type ISkipNavProps,
36-
type IBodyProps,
3736
type IHeaderProps,
3837
type IHeaderItemProps,
3938
type IHeaderItemTextProps,

packages/chrome/src/types/index.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,6 @@ export interface ISkipNavProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
3535
zIndex?: number;
3636
}
3737

38-
export interface IBodyProps extends HTMLAttributes<HTMLDivElement> {
39-
/** Adjusts the body content height to allow space for a footer component */
40-
hasFooter?: boolean;
41-
}
42-
4338
export interface IHeaderProps extends HTMLAttributes<HTMLElement> {
4439
/** Displays logo for standlone usage */
4540
isStandalone?: boolean;

packages/chrome/src/utils/useBodyContext.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ import React, { useContext } from 'react';
99

1010
interface IBodyContext {
1111
hasFooter: boolean;
12+
setHasFooter: (footerPresent: boolean) => void;
1213
}
1314

14-
export const BodyContext = React.createContext<IBodyContext>({
15-
hasFooter: true
16-
});
15+
export const BodyContext = React.createContext<IBodyContext | undefined>(undefined);
1716

1817
export const useBodyContext = () => {
1918
return useContext(BodyContext);

0 commit comments

Comments
 (0)