From 6678ca024324dbf2c9ebd2460ad9310c6055fd08 Mon Sep 17 00:00:00 2001 From: Xiphe Date: Fri, 5 Feb 2021 12:50:41 +0100 Subject: [PATCH] fix: take scrollbar dimensions into account for layout fix https://github.com/Xiphe/budgetbudget/issues/76 fix https://github.com/Xiphe/budgetbudget/issues/74 --- src/components/Content/Content.module.scss | 1 - src/components/Content/Content.tsx | 5 ++- src/components/ScrollBarDimensionProvider.tsx | 45 +++++++++++++++++++ .../CategorySidebar.module.scss | 4 +- src/views/Month/Month.module.scss | 22 ++++++--- 5 files changed, 66 insertions(+), 11 deletions(-) create mode 100644 src/components/ScrollBarDimensionProvider.tsx diff --git a/src/components/Content/Content.module.scss b/src/components/Content/Content.module.scss index 85b2933..a5205ba 100644 --- a/src/components/Content/Content.module.scss +++ b/src/components/Content/Content.module.scss @@ -1,7 +1,6 @@ .content { margin-top: var(--header-height); height: calc(100vh - var(--header-height)); - overflow: scroll; } .padding { padding: 0 2rem; diff --git a/src/components/Content/Content.tsx b/src/components/Content/Content.tsx index f24d015..e95a66d 100644 --- a/src/components/Content/Content.tsx +++ b/src/components/Content/Content.tsx @@ -1,6 +1,7 @@ import React, { ReactNode } from 'react'; import classNames from 'classnames'; import styles from './Content.module.scss'; +import ScrollbarDimensionProvider from '../ScrollBarDimensionProvider'; type Props = { className?: string; @@ -21,7 +22,7 @@ export default function Content({ return ( <> {header} -
{children} -
+ ); } diff --git a/src/components/ScrollBarDimensionProvider.tsx b/src/components/ScrollBarDimensionProvider.tsx new file mode 100644 index 0000000..555d53e --- /dev/null +++ b/src/components/ScrollBarDimensionProvider.tsx @@ -0,0 +1,45 @@ +import React, { useState, useEffect, useMemo } from 'react'; + +export default function ScrollBarWidthProvider({ + children, + style, + ...props +}: React.HTMLAttributes) { + const [elm, setElm] = useState(null); + const [scrollBarStyles, setScrollBarStyles] = useState({}); + const observer = useMemo( + () => + new ResizeObserver(([{ target }]) => { + requestAnimationFrame(() => { + const { width, height } = target.getBoundingClientRect(); + + setScrollBarStyles({ + '--scrollbar-x': `${200 - width}px`, + '--scrollbar-y': `${200 - height}px`, + }); + }); + }), + [setScrollBarStyles], + ); + useEffect(() => { + if (elm === null) { + return; + } + + observer.observe(elm); + + return () => { + observer.unobserve(elm); + }; + }, [elm, observer]); + return ( +
+
+
+
+
+
+ {children} +
+ ); +} diff --git a/src/views/CategorySidebar/CategorySidebar.module.scss b/src/views/CategorySidebar/CategorySidebar.module.scss index c9759fd..ee247df 100644 --- a/src/views/CategorySidebar/CategorySidebar.module.scss +++ b/src/views/CategorySidebar/CategorySidebar.module.scss @@ -39,7 +39,9 @@ .categorySidebar { border-right: none; height: calc(100% - var(--month-header-height)); - padding-bottom: calc(300px - var(--month-header-height)); + padding-bottom: calc( + 300px - var(--month-header-height) + var(--scrollbar-y, 0) + ); transition: height, padding 200ms ease-out; overflow-y: scroll; &::-webkit-scrollbar { diff --git a/src/views/Month/Month.module.scss b/src/views/Month/Month.module.scss index c689315..a16bdb4 100644 --- a/src/views/Month/Month.module.scss +++ b/src/views/Month/Month.module.scss @@ -1,17 +1,25 @@ @import '../../lib/mixins.scss'; .month { - min-height: calc(100vh - var(--header-height)); - min-width: calc(100vw - var(--sidebar-width)); - max-width: calc(100vw - var(--sidebar-width)); + min-height: calc(100vh - var(--header-height) - var(--scrollbar-y, 0)); + min-width: calc(100vw - var(--sidebar-width) - var(--scrollbar-x, 0)); + max-width: calc(100vw - var(--sidebar-width) - var(--scrollbar-x, 0)); height: var(--sidebar-height, 'auto'); @media (min-width: 800px) { - min-width: calc(calc(100vw - var(--sidebar-width)) / 2); - max-width: calc(calc(100vw - var(--sidebar-width)) / 2); + min-width: calc( + calc(100vw - var(--sidebar-width) - var(--scrollbar-x, 0)) / 2 + ); + max-width: calc( + calc(100vw - var(--sidebar-width) - var(--scrollbar-x, 0)) / 2 + ); } @media (min-width: 1100px) { - min-width: calc(calc(100vw - var(--sidebar-width)) / 3); - max-width: calc(calc(100vw - var(--sidebar-width)) / 3); + min-width: calc( + calc(100vw - var(--sidebar-width) - var(--scrollbar-x, 0)) / 3 + ); + max-width: calc( + calc(100vw - var(--sidebar-width) - var(--scrollbar-x, 0)) / 3 + ); } }