Skip to content

Commit

Permalink
feat: measure container width and use it in ItemGrid
Browse files Browse the repository at this point in the history
  • Loading branch information
HendrikThePendric committed Dec 12, 2024
1 parent 7764bcf commit a4baaac
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 73 deletions.
35 changes: 10 additions & 25 deletions src/components/DashboardContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,19 @@ import React, {
createContext,
useContext,
} from 'react'
import { detectOsScrollbarWidth } from '../modules/detectOsScrollbarWidth.js'
import classes from './styles/DashboardContainer.module.css'

const ContainerScrollbarWidthContext = createContext(0)
const osScrollbarWidth = detectOsScrollbarWidth()
const ContainerWidthContext = createContext(0)

const DashboardContainer = ({ children, covered }) => {
const [scrollbarWidth, setScrollbarWidth] = useState(0)
const containerRef = useRef(null)
const contentWrapRef = useRef(null)
const [containerWidth, setContainerWidth] = useState(0)
const ref = useRef(null)

useEffect(() => {
const resizeObserver = new ResizeObserver(() => {
const el = containerRef.current
if (!el) {
throw new Error('Could not find scroll container')
}
/* This first condition is true in mobile portrait when there is
* a scrollbar on the outer scroll-container */
const isNarrowerThanWindow = window.innerWidth > el.offsetWidth
const hasInnerScrollbar = el.scrollHeight > el.clientHeight
setScrollbarWidth(
isNarrowerThanWindow || hasInnerScrollbar ? osScrollbarWidth : 0
)
const resizeObserver = new ResizeObserver((entries) => {
setContainerWidth(entries[0].contentRect.width)
})
resizeObserver.observe(contentWrapRef.current)
resizeObserver.observe(ref.current)

return () => {
resizeObserver.disconnect()
Expand All @@ -46,13 +33,12 @@ const DashboardContainer = ({ children, covered }) => {
'dashboard-scroll-container',
covered && classes.covered
)}
ref={containerRef}
data-test="inner-scroll-container"
>
<div ref={contentWrapRef} className={classes.contentWrap}>
<ContainerScrollbarWidthContext.Provider value={scrollbarWidth}>
<div ref={ref} className={classes.contentWrap}>
<ContainerWidthContext.Provider value={containerWidth}>
{children}
</ContainerScrollbarWidthContext.Provider>
</ContainerWidthContext.Provider>
</div>
</div>
)
Expand All @@ -63,6 +49,5 @@ DashboardContainer.propTypes = {
covered: PropTypes.bool,
}

export const useContainerScrollbarWidth = () =>
useContext(ContainerScrollbarWidthContext)
export const useContainerWidth = () => useContext(ContainerWidthContext)
export default DashboardContainer
28 changes: 0 additions & 28 deletions src/modules/detectOsScrollbarWidth.js

This file was deleted.

9 changes: 1 addition & 8 deletions src/modules/gridUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ const SM_SCREEN_MIN_ITEM_GRID_HEIGHT = 13 // minimum of ~320px
export const SM_SCREEN_GRID_COLUMNS = 1
export const MARGIN_SM_PX = [0, 16]
export const GRID_PADDING_PX = [0, 0]
// sum of left+right padding of dashboard-wrapper (App.css)
export const DASHBOARD_WRAPPER_LR_MARGIN_PX = 28
// make an assumption about the original item w/h ratio
// assumes grid width of ~1200px at time dashboard was created
const GRID_COL_WIDTH_PX = 10
Expand Down Expand Up @@ -87,15 +85,12 @@ export const withShape = (items = []) => {
)
}

export const getGridWidth = (windowWidthPx) =>
windowWidthPx - DASHBOARD_WRAPPER_LR_MARGIN_PX

const getGridUnitsForSmFromPx = (hPx) => {
const gridUnitHeightPx = GRID_ROW_HEIGHT_PX + MARGIN_SM_PX[1]
return Math.round((hPx + MARGIN_SM_PX[1]) / gridUnitHeightPx)
}

export const getProportionalHeight = (item, windowWidthPx) => {
export const getProportionalHeight = (item, gridWidthPx) => {
// get w/h ratio of the original item
const wPx = getItemWHPx(item.w, GRID_COL_WIDTH_PX, MARGIN_PX[0])
const hPx = getItemWHPx(item.h, GRID_ROW_HEIGHT_PX, MARGIN_PX[1])
Expand All @@ -105,8 +100,6 @@ export const getProportionalHeight = (item, windowWidthPx) => {
return getGridUnitsForSmFromPx(hPx)
}

const gridWidthPx = getGridWidth(windowWidthPx)

// get new height in px based on the ratio
const newColWidthPx =
(gridWidthPx -
Expand Down
6 changes: 2 additions & 4 deletions src/modules/smallScreen.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { DASHBOARD_WRAPPER_LR_MARGIN_PX } from './gridUtil.js'

const SMALL_SCREEN_BREAKPOINT = 480

export const isSmallScreen = (width) => width <= SMALL_SCREEN_BREAKPOINT

export const getBreakpoint = () =>
SMALL_SCREEN_BREAKPOINT - DASHBOARD_WRAPPER_LR_MARGIN_PX
export const getBreakpoint = (containerWidth) =>
SMALL_SCREEN_BREAKPOINT - (window.innerWidth - containerWidth)
9 changes: 4 additions & 5 deletions src/pages/edit/ItemGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import React, { useState } from 'react'
import { Responsive as ResponsiveReactGridLayout } from 'react-grid-layout'
import { connect } from 'react-redux'
import { acUpdateDashboardItemShapes } from '../../actions/editDashboard.js'
import { useContainerWidth } from '../../components/DashboardContainer.js'
import { Item } from '../../components/Item/Item.js'
import NoContentMessage from '../../components/NoContentMessage.js'
import ProgressiveLoadingContainer from '../../components/ProgressiveLoadingContainer.js'
import { useWindowDimensions } from '../../components/WindowDimensionsProvider.js'
import { EDIT } from '../../modules/dashboardModes.js'
import { getFirstOfTypes } from '../../modules/getFirstOfType.js'
import { getGridItemDomElementClassName } from '../../modules/getGridItemDomElementClassName.js'
Expand All @@ -19,7 +19,6 @@ import {
GRID_PADDING_PX,
GRID_COLUMNS,
hasShape,
getGridWidth,
hasLayout,
} from '../../modules/gridUtil.js'
import { getBreakpoint } from '../../modules/smallScreen.js'
Expand All @@ -37,8 +36,8 @@ const EditItemGrid = ({
hasLayout,
hideGrid,
}) => {
const containerWidth = useContainerWidth()
const [gridWidth, setGridWidth] = useState({ width: 0 })
const { width } = useWindowDimensions()
const firstOfTypes = getFirstOfTypes(dashboardItems)

const onLayoutChange = (newLayout) => {
Expand Down Expand Up @@ -90,10 +89,10 @@ const EditItemGrid = ({
<ResponsiveReactGridLayout
className={classes.grid}
rowHeight={GRID_ROW_HEIGHT_PX}
width={getGridWidth(width)}
width={containerWidth}
cols={{ lg: GRID_COLUMNS }}
breakpoints={{
lg: getBreakpoint(),
lg: getBreakpoint(containerWidth),
}}
layouts={{ lg: dashboardItems }}
compactType={GRID_COMPACT_TYPE}
Expand Down
7 changes: 4 additions & 3 deletions src/pages/view/ItemGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import PropTypes from 'prop-types'
import React, { useState, useEffect } from 'react'
import { Responsive as ResponsiveReactGridLayout } from 'react-grid-layout'
import { connect } from 'react-redux'
import { useContainerWidth } from '../../components/DashboardContainer.js'
import { Item } from '../../components/Item/Item.js'
import NoContentMessage from '../../components/NoContentMessage.js'
import ProgressiveLoadingContainer from '../../components/ProgressiveLoadingContainer.js'
Expand All @@ -20,7 +21,6 @@ import {
MARGIN_SM_PX,
GRID_COLUMNS,
getSmallLayout,
getGridWidth,
getProportionalHeight,
} from '../../modules/gridUtil.js'
import { getBreakpoint, isSmallScreen } from '../../modules/smallScreen.js'
Expand All @@ -36,6 +36,7 @@ const EXPANDED_HEIGHT_SM = 15

const ResponsiveItemGrid = ({ dashboardId, dashboardItems }) => {
const { width } = useWindowDimensions()
const containerWidth = useContainerWidth()
const [expandedItems, setExpandedItems] = useState({})
const [displayItems, setDisplayItems] = useState(dashboardItems)
const [layoutSm, setLayoutSm] = useState([])
Expand Down Expand Up @@ -134,10 +135,10 @@ const ResponsiveItemGrid = ({ dashboardId, dashboardItems }) => {
<ResponsiveReactGridLayout
className={classes.grid}
rowHeight={GRID_ROW_HEIGHT_PX}
width={getGridWidth(width)}
width={containerWidth}
cols={{ lg: GRID_COLUMNS, sm: SM_SCREEN_GRID_COLUMNS }}
breakpoints={{
lg: getBreakpoint(),
lg: getBreakpoint(containerWidth),
sm: 0,
}}
layouts={{ lg: displayItems, sm: layoutSm }}
Expand Down

0 comments on commit a4baaac

Please sign in to comment.