diff --git a/agency-dashboard/src/DashboardView.styles.tsx b/agency-dashboard/src/DashboardView.styles.tsx
index 7c855c6dd..a2396126f 100644
--- a/agency-dashboard/src/DashboardView.styles.tsx
+++ b/agency-dashboard/src/DashboardView.styles.tsx
@@ -16,10 +16,11 @@
// =============================================================================
import {
+ COMMON_DESKTOP_WIDTH,
palette,
+ TABLET_WIDTH,
typography,
} from "@justice-counts/common/components/GlobalStyles";
-import { Dropdown } from "@recidiviz/design-system";
import styled from "styled-components/macro";
export const Container = styled.div`
@@ -33,12 +34,15 @@ export const Container = styled.div`
`;
export const LeftPanel = styled.div`
- margin-top: 16px;
margin-left: 24px;
margin-right: 24px;
width: 424px;
min-width: 424px;
margin-right: 126px;
+
+ @media only screen and (max-width: ${COMMON_DESKTOP_WIDTH - 1}px) {
+ display: none;
+ }
`;
export const RightPanel = styled.div`
@@ -46,18 +50,23 @@ export const RightPanel = styled.div`
flex-grow: 1;
flex-direction: column;
align-items: stretch;
-`;
+ width: calc(100% - 574px);
+ height: 100%;
+ padding-left: 24px;
+ padding-right: 24px;
-export const RightPanelTopContainer = styled.div`
- display: flex;
+ @media only screen and (max-width: ${TABLET_WIDTH - 1}px) {
+ padding-left: 16px;
+ padding-right: 16px;
+ }
`;
-export const LeftPanelBackButtonContainer = styled.div`
+export const BackButtonContainer = styled.div`
${typography.sizeCSS.normal}
- float: left;
padding-top: 8px;
padding-right: 8px;
padding-bottom: 8px;
+ margin-top: 16px;
display: flex;
align-items: center;
gap: 8px;
@@ -76,28 +85,66 @@ export const LeftPanelBackButtonContainer = styled.div`
}
`;
+export const RightPanelBackButtonContainer = styled(BackButtonContainer)`
+ @media only screen and (min-width: ${COMMON_DESKTOP_WIDTH}px) {
+ display: none;
+ }
+`;
+
export const MetricTitle = styled.div`
${typography.sizeCSS.headline}
- margin-top: 86px;
+ margin-top: 36px;
+ margin-bottom: 16px;
+ hyphens: auto;
+ overflow-wrap: break-word;
`;
-export const MetricOverviewTitle = styled.div`
- ${typography.sizeCSS.large}
- margin-top: 48px;
+export const RightPanelMetricTitle = styled(MetricTitle)`
+ margin-bottom: 40px;
- &::after {
- content: "Metric Overview";
+ @media only screen and (min-width: ${COMMON_DESKTOP_WIDTH}px) {
+ display: none;
+ }
+
+ @media only screen and (max-width: ${TABLET_WIDTH - 1}px) {
+ ${typography.sizeCSS.title}
+ margin-bottom: 16px;
}
`;
export const MetricOverviewContent = styled.div`
${typography.sizeCSS.medium}
+
+ @media only screen and (max-width: ${TABLET_WIDTH - 1}px) {
+ ${typography.sizeCSS.normal}
+ }
+`;
+
+export const RightPanelMetricOverviewContent = styled(MetricOverviewContent)`
margin-top: 16px;
+
+ @media only screen and (min-width: ${COMMON_DESKTOP_WIDTH}px) {
+ display: none;
+ }
`;
export const MetricOverviewActionsContainer = styled.div`
display: flex;
margin-top: 24px;
+ padding-bottom: 32px;
+`;
+
+export const RightPanelMetricOverviewActionsContainer = styled(
+ MetricOverviewActionsContainer
+)`
+ @media only screen and (min-width: ${COMMON_DESKTOP_WIDTH}px) {
+ display: none;
+ }
+
+ @media only screen and (max-width: ${TABLET_WIDTH - 1}px) {
+ flex-direction: column;
+ padding-bottom: 64px;
+ }
`;
export const MetricOverviewActionButtonContainer = styled.div`
@@ -117,51 +164,13 @@ export const MetricOverviewActionButtonContainer = styled.div`
&:first-child {
padding-left: 0px;
}
-`;
-
-export const MetricOverviewActionButtonText = styled.div`
- ${typography.sizeCSS.normal}
- margin-left: 8px;
-`;
-
-export const AllMetricsButtonContainer = styled.div`
- padding-left: 16px;
- padding-right: 16px;
- padding-top: 8px;
- padding-bottom: 8px;
- display: flex;
- align-items: center;
- border-radius: 2px;
- background: ${palette.solid.blue};
- gap: 8px;
- color: ${palette.solid.white};
- &:hover {
- cursor: pointer;
- background: ${palette.solid.darkblue};
+ @media only screen and (max-width: ${TABLET_WIDTH - 1}px) {
+ padding-left: 0px;
}
`;
-export const AllMetricsButtonText = styled.div`
+export const MetricOverviewActionButtonText = styled.div`
${typography.sizeCSS.normal}
- font-weight: 400;
-
- &::after {
- content: "Select Metric";
- }
-`;
-
-export const ExtendedDropdown = styled(Dropdown)`
- & > button {
- margin-top: 8px;
- margin-bottom: 8px;
- margin-left: 15px;
- transition-duration: 0ms;
- background: none;
- padding: 0;
- border: none;
- }
- &:hover > button {
- background: none;
- }
+ margin-left: 8px;
`;
diff --git a/agency-dashboard/src/DashboardView.tsx b/agency-dashboard/src/DashboardView.tsx
index 3bd326844..d6f3cfaf4 100644
--- a/agency-dashboard/src/DashboardView.tsx
+++ b/agency-dashboard/src/DashboardView.tsx
@@ -16,40 +16,48 @@
// =============================================================================
import { ReactComponent as DownloadIcon } from "@justice-counts/common/assets/download-icon.svg";
-import { ReactComponent as GridIcon } from "@justice-counts/common/assets/grid-icon.svg";
import { ReactComponent as InfoIcon } from "@justice-counts/common/assets/info-icon.svg";
import { ReactComponent as LeftArrowIcon } from "@justice-counts/common/assets/left-arrow-icon.svg";
import { ReactComponent as ShareIcon } from "@justice-counts/common/assets/share-icon.svg";
import { DatapointsView } from "@justice-counts/common/components/DataViz/DatapointsView";
-import { ExtendedDropdownMenuItem } from "@justice-counts/common/components/DataViz/DatapointsView.styles";
-import { DropdownMenu, DropdownToggle } from "@recidiviz/design-system";
+import { COMMON_DESKTOP_WIDTH } from "@justice-counts/common/components/GlobalStyles";
import { observer } from "mobx-react-lite";
-import React, { useEffect } from "react";
+import React, { useEffect, useState } from "react";
import { useLocation, useNavigate, useParams } from "react-router-dom";
import {
- AllMetricsButtonContainer as SelectMetricButtonContainer,
- AllMetricsButtonText,
+ BackButtonContainer,
Container,
- ExtendedDropdown,
LeftPanel,
- LeftPanelBackButtonContainer,
MetricOverviewActionButtonContainer,
MetricOverviewActionButtonText,
MetricOverviewActionsContainer,
MetricOverviewContent,
- MetricOverviewTitle,
MetricTitle,
RightPanel,
- RightPanelTopContainer,
+ RightPanelBackButtonContainer,
+ RightPanelMetricOverviewActionsContainer,
+ RightPanelMetricOverviewContent,
+ RightPanelMetricTitle,
} from "./DashboardView.styles";
import { HeaderBar } from "./Header/HeaderBar";
import { useStore } from "./stores";
-const LeftPanelBackButton = () => (
-
+const getScreenWidth = () =>
+ window.innerWidth ||
+ document.documentElement.clientWidth ||
+ document.body.clientWidth;
+
+const BackButton = ({ onClick }: { onClick: () => void }) => (
+
+
+
+);
+
+const RightPanelBackButton = ({ onClick }: { onClick: () => void }) => (
+
-
+
);
const MetricOverviewActionInfoButton = () => (
@@ -75,37 +83,9 @@ const MetricOverviewActionShareButton = () => (
);
-const SelectMetricButton = () => (
-
-
-
-
-);
-
-const SelectMetricButtonDropdown: React.FC<{
- onSelect: (metricKey: string) => void;
- options: string[];
-}> = ({ onSelect, options }) => (
-
-
-
-
-
- {options.map((value) => (
- {
- onSelect(value);
- }}
- >
- {value}
-
- ))}
-
-
-);
-
const DashboardView = () => {
+ const [shouldResizeChartHeight, setShouldResizeChartHeight] =
+ useState(getScreenWidth() >= COMMON_DESKTOP_WIDTH);
const navigate = useNavigate();
const params = useParams();
const agencyId = Number(params.id);
@@ -131,6 +111,28 @@ const DashboardView = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [datapointsStore.loading]);
+ useEffect(() => {
+ const resizeListener = () => {
+ // change width from the state object
+ if (shouldResizeChartHeight && getScreenWidth() < COMMON_DESKTOP_WIDTH) {
+ setShouldResizeChartHeight(false);
+ } else if (
+ !shouldResizeChartHeight &&
+ getScreenWidth() >= COMMON_DESKTOP_WIDTH
+ ) {
+ setShouldResizeChartHeight(true);
+ }
+ };
+ // set resize listener
+ window.addEventListener("resize", resizeListener);
+
+ // clean up function
+ return () => {
+ // remove resize listener
+ window.removeEventListener("resize", resizeListener);
+ };
+ }, [shouldResizeChartHeight]);
+
if (
!metricKey ||
(!datapointsStore.loading &&
@@ -151,30 +153,25 @@ const DashboardView = () => {
-
+ navigate(`/agency/${agencyId}`)} />
{datapointsStore.metricKeyToDisplayName[metricKey] || metricKey}
-
Measures the number of individuals with at least one parole violation
during the reporting period.
-
-
+
+
-
-
- navigate(`/agency/${agencyId}/dashboard?metric=${metric}`)
- }
- options={metricNames}
- />
-
+ navigate(`/agency/${agencyId}`)} />
+
+ {datapointsStore.metricKeyToDisplayName[metricKey] || metricKey}
+
{
dimensionNamesByDisaggregation={
datapointsStore.dimensionNamesByMetricAndDisaggregation[metricKey]
}
+ metricNames={metricNames}
+ onMetricsSelect={(metric) =>
+ navigate(`/agency/${agencyId}/dashboard?metric=${metric}`)
+ }
+ resizeHeight={shouldResizeChartHeight}
/>
+
+ Measures the number of individuals with at least one parole violation
+ during the reporting period.
+
+
+
+
+
+
);
diff --git a/agency-dashboard/src/Header/HeaderBar.styles.tsx b/agency-dashboard/src/Header/HeaderBar.styles.tsx
index 8dd19743e..c6cfa66fc 100644
--- a/agency-dashboard/src/Header/HeaderBar.styles.tsx
+++ b/agency-dashboard/src/Header/HeaderBar.styles.tsx
@@ -18,6 +18,7 @@
import {
HEADER_BAR_HEIGHT,
palette,
+ TABLET_WIDTH,
typography,
} from "@justice-counts/common/components/GlobalStyles";
import styled from "styled-components/macro";
@@ -59,6 +60,10 @@ export const Logo = styled.img`
export const HeaderTitle = styled.div`
flex-grow: 1;
padding-left: 16px;
+
+ @media only screen and (max-width: ${TABLET_WIDTH - 1}px) {
+ display: none;
+ }
`;
export const HeaderButtonsContainer = styled.div`
diff --git a/agency-dashboard/src/Header/HeaderBar.tsx b/agency-dashboard/src/Header/HeaderBar.tsx
index a7acbd35e..4018f57ba 100644
--- a/agency-dashboard/src/Header/HeaderBar.tsx
+++ b/agency-dashboard/src/Header/HeaderBar.tsx
@@ -16,7 +16,7 @@
// =============================================================================
import logo from "@justice-counts/common/assets/jc-logo-vector.png";
-import React, { useState } from "react";
+import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { AboutModal } from "./AboutModal";
@@ -41,6 +41,16 @@ export const HeaderBar = () => {
setAboutModalVisible(false);
};
+ /** Prevent body from scrolling when modal is open */
+ useEffect(() => {
+ if (aboutModalVisible) {
+ document.body.style.overflow = "hidden";
+ }
+ return () => {
+ document.body.style.overflow = "unset";
+ };
+ }, [aboutModalVisible]);
+
return (
{aboutModalVisible && }
diff --git a/common/assets/share-icon.svg b/common/assets/share-icon.svg
index 2f796dada..98569909c 100644
--- a/common/assets/share-icon.svg
+++ b/common/assets/share-icon.svg
@@ -1,4 +1,12 @@
-