stackedContent.tsx 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. import React, {useCallback, useRef, useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import {useResizeObserver} from '@react-aria/utils';
  4. type Dimensions = {height: number; width: number};
  5. type Props = {
  6. children: (props: Dimensions) => React.ReactElement | null;
  7. };
  8. /**
  9. * Overlap rows of content on top of each other using grid.
  10. * Similar to how `posisition: absolute;` could force content to be on-top of
  11. * each other, but this does so without taking the content out of the page flow.
  12. *
  13. * Injest the width/height of the container, so children can adjust and expand
  14. * to fill the whole area.
  15. */
  16. function StackedContent({children}: Props) {
  17. const el = useRef<HTMLDivElement>(null);
  18. const [dimensions, setDimensions] = useState({height: 0, width: 0});
  19. const onResize = useCallback(() => {
  20. setDimensions({
  21. height: el.current?.clientHeight || 0,
  22. width: el.current?.clientWidth || 0,
  23. });
  24. }, [setDimensions]);
  25. useResizeObserver({ref: el, onResize});
  26. return <Stack ref={el}>{children(dimensions)}</Stack>;
  27. }
  28. const Stack = styled('div')`
  29. height: 100%;
  30. display: grid;
  31. grid-template: 1 / 1;
  32. > * {
  33. grid-area: 1 /1;
  34. }
  35. `;
  36. export default StackedContent;