Skip to content

Commit 2eed610

Browse files
committed
Add option to display chart full screen
1 parent 09fc137 commit 2eed610

File tree

6 files changed

+88
-22
lines changed

6 files changed

+88
-22
lines changed

src/components/PackageCard.tsx

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,19 @@ import styles from "../styles/PackageCard.module.scss";
33

44
import { Text, ThemeProvider, ITheme, Shimmer } from "@fluentui/react";
55

6-
import { CalculatorPercentageIcon } from "@fluentui/react-icons-mdl2";
6+
import {
7+
CalculatorPercentageIcon,
8+
FullScreenIcon,
9+
} from "@fluentui/react-icons-mdl2";
710

811
import { PackageIdentifier, packages } from "../PackageDescription";
912

1013
import { lightTheme } from "../styles/Themes";
11-
import useHistory from "../hooks/useHistory";
1214
import TooltipButton from "./TooltipButton";
1315

16+
import useHistory from "../hooks/useHistory";
17+
import useSearchParamsState from "../hooks/useSearchParamsState";
18+
1419
import React from "react";
1520
import usePersistentState from "../hooks/usePersistentState";
1621

@@ -82,6 +87,19 @@ const PackageCard: React.FC<PackageCardProps> = ({
8287
showAsPercentageKey,
8388
false
8489
);
90+
const [fullScreenKey, setFullScreenKey] = useSearchParamsState<string | null>(
91+
"fullScreen",
92+
null
93+
);
94+
const fullScreen = fullScreenKey === identifier;
95+
96+
const setFullScreen = (value: boolean) => {
97+
if (value) {
98+
setFullScreenKey(identifier);
99+
} else {
100+
setFullScreenKey(null);
101+
}
102+
};
85103

86104
const history = useHistory(identifier, versionFilter);
87105
const packageDesc = packages[identifier];
@@ -99,6 +117,7 @@ const PackageCard: React.FC<PackageCardProps> = ({
99117
<CardFrame
100118
theme={theme ?? lightTheme}
101119
disabled={history?.points.length === 0}
120+
fullScreen={fullScreen}
102121
>
103122
<div className={styles.header}>
104123
<div className={styles.headerLeft} />
@@ -110,13 +129,22 @@ const PackageCard: React.FC<PackageCardProps> = ({
110129
</div>
111130
<div className={styles.headerControls}>
112131
<TooltipButton
113-
toggle
114-
content="Show as percentage"
115132
aria-label="Show as percentage"
116-
disabled={disabled}
117-
onRenderIcon={() => <CalculatorPercentageIcon />}
118133
checked={showAsPercentage}
134+
content="Show as percentage"
135+
disabled={disabled}
119136
onClick={() => setShowAsPercentage(!showAsPercentage)}
137+
onRenderIcon={() => <CalculatorPercentageIcon />}
138+
toggle
139+
/>
140+
<TooltipButton
141+
aria-label="Show full screen"
142+
checked={fullScreen}
143+
content="Show full screen"
144+
disabled={disabled}
145+
onClick={() => setFullScreen(!fullScreen)}
146+
onRenderIcon={() => <FullScreenIcon />}
147+
toggle
120148
/>
121149
</div>
122150
</div>
@@ -125,15 +153,16 @@ const PackageCard: React.FC<PackageCardProps> = ({
125153
{!dataIsReady && <ChartFallback />}
126154
<VersionDownloadChart
127155
className={!disabled ? styles.visibleChart : styles.invisibleChart}
156+
fullScreen={fullScreen}
128157
history={dataIsReady ? history : undefined}
129158
maxDaysShown={maxDays(versionFilter)}
130-
tickInterval={tickInterval(versionFilter)}
131159
maxVersionsShown={maxVersionsShown ?? 4}
132160
popularDuring={popularDuring(versionFilter)}
133-
unit={showAsPercentage ? "percentage" : "totalDownloads"}
134-
versionLabeler={packageDesc.versionLabeler}
135161
theme={theme}
162+
tickInterval={tickInterval(versionFilter)}
136163
tooltipTheme={tooltipTheme}
164+
unit={showAsPercentage ? "percentage" : "totalDownloads"}
165+
versionLabeler={packageDesc.versionLabeler}
137166
/>
138167
</Suspense>
139168
</div>
@@ -144,15 +173,14 @@ const PackageCard: React.FC<PackageCardProps> = ({
144173
const CardFrame: React.FC<{
145174
children: React.ReactNode;
146175
disabled: boolean;
176+
fullScreen?: boolean;
147177
theme: ITheme;
148-
}> = ({ children, disabled, theme }) => {
178+
}> = ({ children, disabled, fullScreen, theme }) => {
149179
return (
150180
<ThemeProvider
151-
className={
152-
disabled
153-
? `${styles.cardFrame} ${styles.disabledCardFrame}`
154-
: styles.cardFrame
155-
}
181+
className={`${styles.cardFrame} ${
182+
disabled ? styles.disabledCardFrame : ""
183+
} ${fullScreen ? styles.fullScreenCardFrame : ""}`}
156184
theme={theme}
157185
>
158186
<div

src/components/VersionDownloadChart.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ export type VersionDownloadChartProps = {
3030
*/
3131
className?: string;
3232

33+
/**
34+
* Whether to show the chart in full screen
35+
*/
36+
fullScreen?: boolean;
37+
3338
/**
3439
* Points to render
3540
*/
@@ -94,17 +99,18 @@ export type VersionDownloadChartProps = {
9499

95100
const VersionDownloadChart: React.FC<VersionDownloadChartProps> = ({
96101
className,
102+
fullScreen,
97103
history,
98104
maxDaysShown,
99105
maxVersionsShown,
100106
popularDuring,
101107
showLegend,
102108
showTooltip,
103-
unit,
104-
versionLabeler,
105-
tickInterval = 7,
106109
theme,
110+
tickInterval = 7,
107111
tooltipTheme,
112+
unit,
113+
versionLabeler,
108114
}) => {
109115
const styles = styleProps({ theme, unit });
110116

@@ -190,7 +196,11 @@ const VersionDownloadChart: React.FC<VersionDownloadChartProps> = ({
190196

191197
return (
192198
<div className={className}>
193-
<ResponsiveContainer {...styles.responsiveContainer}>
199+
<ResponsiveContainer
200+
{...styles[
201+
fullScreen ? "responsiveContainerFullScreen" : "responsiveContainer"
202+
]}
203+
>
194204
<AreaChart
195205
{...styles.areaChart}
196206
data={filteredHistory?.points}

src/hooks/useSearchParamsState.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useCallback, useState } from "react";
22

3-
export default function useSearchParamsState<T extends string>(
3+
export default function useSearchParamsState<T extends string | null>(
44
storageKey: string,
55
defaultValue: T
66
) {
@@ -13,7 +13,11 @@ export default function useSearchParamsState<T extends string>(
1313
const setAndPersistState = useCallback(
1414
(newState: T) => {
1515
const url = new URL(window.location.href);
16-
url.searchParams.set(storageKey, newState);
16+
if (newState === null) {
17+
url.searchParams.delete(storageKey);
18+
} else {
19+
url.searchParams.set(storageKey, newState);
20+
}
1721
window.history.replaceState({}, "", url.href);
1822
setState(newState);
1923
},

src/styles/App.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
justify-items: center;
2424
justify-content: center;
2525
gap: 10px;
26+
position: relative;
2627

2728
// recharts toolbars may transiently overflow the content area during
2829
// animation.

src/styles/PackageCard.module.scss

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@
2222
z-index: 1;
2323
}
2424

25+
.disabledCardFrame {
26+
opacity: 0.6;
27+
}
28+
29+
.fullScreenCardFrame {
30+
max-width: unset;
31+
position: fixed;
32+
inset: 0;
33+
z-index: 10000;
34+
}
35+
36+
.fullScreenCardFrame:hover,
37+
.fullScreenCardFrame:focus-within {
38+
z-index: 10000;
39+
}
40+
2541
.silhouette {
2642
position: absolute;
2743
box-sizing: border-box;
@@ -45,7 +61,6 @@
4561
}
4662

4763
.disabledContentWrapper {
48-
opacity: 0.6;
4964
}
5065

5166
.cardContent {
@@ -129,6 +144,8 @@
129144
}
130145

131146
.chartContainer {
147+
max-height: 100%;
148+
overflow: hidden;
132149
flex-grow: 1;
133150

134151
display: flex;
@@ -146,4 +163,5 @@
146163

147164
.visibleChart {
148165
@include ms-motion-fadeIn;
166+
height: 100%;
149167
}

src/styles/VersionDownloadChart.styles.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export type VersionDownloadChartStyle = (opts?: {
3434
};
3535
area: Pick<AreaProps, AnimationProps | DimensionProps>;
3636
responsiveContainer: Pick<ResponsiveContainerProps, DimensionProps>;
37+
responsiveContainerFullScreen: Pick<ResponsiveContainerProps, DimensionProps>;
3738
grid: Pick<CartesianGridProps, DimensionProps | StrokeProps>;
3839
xAxis: Pick<XAxisProps, DimensionProps | PaddingProps | TickProps>;
3940
yAxis: Pick<YAxisProps, DimensionProps | PaddingProps | TickProps>;
@@ -55,6 +56,10 @@ const styles: VersionDownloadChartStyle = ({ theme, unit } = {}) => ({
5556
width: "100%",
5657
height: 260,
5758
},
59+
responsiveContainerFullScreen: {
60+
width: "100%",
61+
height: "100%",
62+
},
5863
grid: {
5964
stroke: theme?.isInverted
6065
? theme.palette.whiteTranslucent40

0 commit comments

Comments
 (0)