Skip to content

Commit ab9a79e

Browse files
committed
feat: show/hide optional controls
1 parent 72f9d17 commit ab9a79e

10 files changed

+97
-24
lines changed

src/App.tsx

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,32 @@ import TimerCountdown from "./pages/TimerCountdown.page";
66
import Footer from "./components/Footer.component";
77
import { MuteButton } from "./components/MuteButton.component";
88
import { MuteProvider } from "./contexts/Mute.context";
9+
import { HideProvider } from "./contexts/Hide.context";
10+
import { HideButton } from "./components/HideButton.component";
911

1012
function App() {
1113
const location = useLocation();
1214
const queryParams = new URLSearchParams(location.search);
1315
const timeParam = queryParams.get("time");
1416

1517
return (
16-
<MuteProvider>
17-
<div className="flex flex-col items-center justify-between min-h-screen h-screen min-w-96">
18-
<div className="flex justify-end w-full p-4">
19-
<MuteButton />
18+
<HideProvider>
19+
<MuteProvider>
20+
<div className="flex flex-col items-center justify-between min-h-screen h-screen min-w-96">
21+
<div className="flex justify-end w-full p-4">
22+
<HideButton />
23+
<MuteButton />
24+
</div>
25+
<Routes>
26+
<Route
27+
path={routes.root.path}
28+
element={timeParam ? <TimerCountdown /> : <TimerSetup />}
29+
/>
30+
</Routes>
31+
<Footer />
2032
</div>
21-
<Routes>
22-
<Route
23-
path={routes.root.path}
24-
element={timeParam ? <TimerCountdown /> : <TimerSetup />}
25-
/>
26-
</Routes>
27-
<Footer />
28-
</div>
29-
</MuteProvider>
33+
</MuteProvider>
34+
</HideProvider>
3035
);
3136
}
3237

src/components/BitButton.component.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { forwardRef, useImperativeHandle, useState } from "react";
2-
32
import NumberFlow from "@number-flow/react";
4-
53
import "@fontsource/montserrat/400.css";
64
import styles from "./BitButton.module.css";
75

src/components/Button.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
2-
import styles from "./Button.module.css";
32
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3+
import styles from "./Button.module.css";
44

55
const Button = ({
66
type,

src/components/EditableTitle.component.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { useCallback, useEffect, useMemo, useState } from "react";
2+
import { faPenToSquare, faSquareCheck, faSquareXmark } from "@fortawesome/free-solid-svg-icons";
23
import { IconButton } from "./IconButton.component";
3-
44
import styles from "./EditableTitle.component.module.css";
5-
import { faPenToSquare, faSquareCheck, faSquareXmark } from "@fortawesome/free-solid-svg-icons";
65

76
const EditableTitle = () => {
87
const countdownTitleSettingKey = "title";
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { useEffect } from "react";
2+
import { faEye, faEyeSlash } from "@fortawesome/free-solid-svg-icons";
3+
import { useHideContext } from "../hooks/useHideContext.hook";
4+
import { IconButton } from "./IconButton.component";
5+
6+
const HideButton = () => {
7+
const IsHiddenSettingKey = "hide";
8+
const { isHidden, toggleHide } = useHideContext();
9+
10+
useEffect(() => {
11+
const isHiddenSettingValue = localStorage.getItem(IsHiddenSettingKey);
12+
if (isHiddenSettingValue && isHiddenSettingValue !== isHidden.toString()) {
13+
toggleHide();
14+
}
15+
// eslint-disable-next-line react-hooks/exhaustive-deps
16+
}, []);
17+
18+
useEffect(() => {
19+
localStorage.setItem(IsHiddenSettingKey, isHidden.toString());
20+
}, [isHidden]);
21+
22+
return (
23+
<IconButton
24+
icon={isHidden ? faEyeSlash : faEye}
25+
tooltip={isHidden ? "Show optional controls" : "Hide optional controls"}
26+
onClick={() => toggleHide()}
27+
/>
28+
);
29+
};
30+
31+
export { HideButton };

src/components/IconButton.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
2-
import styles from "./IconButton.component.module.css";
32
import { IconDefinition } from "@fortawesome/free-solid-svg-icons";
3+
import styles from "./IconButton.component.module.css";
44

55
const IconButton = ({
66
icon,

src/components/MuteButton.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useEffect } from "react";
2+
import { faVolumeHigh, faVolumeXmark } from "@fortawesome/free-solid-svg-icons";
23
import { useMuteContext } from "../hooks/useMuteContext.hook";
34
import { IconButton } from "./IconButton.component";
4-
import { faVolumeHigh, faVolumeXmark } from "@fortawesome/free-solid-svg-icons";
55

66
const MuteButton = () => {
77
const IsMutedSettingKey = "mute";

src/contexts/Hide.context.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { createContext, useState } from "react";
2+
3+
const HideContext = createContext({
4+
isHidden: false,
5+
toggleHide: () => {},
6+
});
7+
8+
const HideProvider = ({ children }: { children: React.ReactNode }) => {
9+
const [isHidden, setIsHidden] = useState(false);
10+
11+
const toggleHide = () => {
12+
setIsHidden(!isHidden);
13+
};
14+
15+
return (
16+
<HideContext.Provider value={{ isHidden, toggleHide }}>
17+
{children}
18+
</HideContext.Provider>
19+
);
20+
};
21+
22+
export { HideContext, HideProvider };

src/hooks/useHideContext.hook.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { useContext } from "react";
2+
import { HideContext } from "../contexts/Hide.context";
3+
4+
const useHideContext = () => {
5+
const context = useContext(HideContext);
6+
if (!context) {
7+
throw new Error("useHideContext must be used within a MuteProvider");
8+
}
9+
return context;
10+
};
11+
12+
export { useHideContext };

src/pages/TimerCountdown.page.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ import BitCounter from "../BitCounter";
88
import EditableTitle from "../components/EditableTitle.component";
99
import { Button, ButtonType } from "../components/Button.component";
1010
import { useMuteContext } from "../hooks/useMuteContext.hook";
11+
import { useHideContext } from "../hooks/useHideContext.hook";
1112
import { faStop } from "@fortawesome/free-solid-svg-icons";
1213

1314
function TimerCountdown() {
1415
const navigate = useNavigate();
1516
const location = useLocation();
1617
const { isMuted } = useMuteContext();
18+
const { isHidden } = useHideContext();
1719
const queryParams = new URLSearchParams(location.search);
1820
const timeParam = queryParams.get("time");
1921

@@ -145,10 +147,14 @@ function TimerCountdown() {
145147
timeLeft <= 0 ? "pointer-events-none opacity-50" : ""
146148
}`}
147149
>
148-
<p className="mb-4">Add time:</p>
149-
<div className="flex flex-row justify-center align-center flex-wrap">
150-
{addTimeButtons}
151-
</div>
150+
{!isHidden && (
151+
<>
152+
<p className="mb-4">Add time:</p>
153+
<div className="flex flex-row justify-center align-center flex-wrap">
154+
{addTimeButtons}
155+
</div>
156+
</>
157+
)}
152158
</div>
153159
</div>
154160
</>

0 commit comments

Comments
 (0)