Skip to content

Commit 54114eb

Browse files
committed
feat: make title editable
1 parent 77b962e commit 54114eb

9 files changed

+149
-14
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"scripts": {
88
"dev": "vite",
99
"build": "tsc -b && vite build",
10+
"publish": "surge ./dist binarytimer.surge.sh",
1011
"lint": "eslint .",
1112
"preview": "vite preview"
1213
},

src/components/BitButton.component.module.css

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
margin-left: .25rem;
55
margin-right: .25rem;
66
margin-bottom: 1rem;
7-
background-color: #61dafb;
7+
background-color: var(--secondary-color);
88
border: none;
99
border-radius: 5px;
1010
cursor: pointer;
1111
font-size: 3rem;
1212
font-family: 'Montserrat', sans-serif;
1313
overflow: hidden;
14-
transition: background-color 0.3s, border-color 0.3s;
14+
transition: .2s linear;
1515

16-
& > .text {
16+
&>.text {
1717
display: inline-block;
1818
}
1919
}
@@ -32,5 +32,5 @@
3232

3333
.hovered,
3434
.selected {
35-
background-color: #21a1f1;
36-
}
35+
background-color: var(--primary-color);
36+
}

src/components/Button.component.module.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
font-family: inherit;
1313
cursor: pointer;
1414
width: fit-content;
15-
transition: background-color 0.3s, border-color 0.3s;
15+
transition: .2s linear;
1616
}
1717

1818
.button:disabled {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
input {
2+
color: var(--text-color);
3+
text-transform: uppercase;
4+
background-color: var(--background-color);
5+
outline: none;
6+
margin: .5rem;
7+
padding: 1rem;
8+
width: 80%;
9+
border: none;
10+
border: .5px solid var(--text-color);
11+
border-radius: .25rem;
12+
transition: .2s linear;
13+
14+
&:focus {
15+
box-shadow: -5px -5px 0px whitesmoke;
16+
}
17+
}
18+
19+
@media (prefers-color-scheme: light) {
20+
input {
21+
color: var(--background-color);
22+
background-color: var(--text-color);
23+
border: .5px solid var(--background-color);
24+
25+
&:focus {
26+
box-shadow: -5px -5px 0px black;
27+
}
28+
}
29+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { useCallback, useEffect, useMemo, useState } from "react";
2+
import { IconButton } from "./IconButton.component";
3+
4+
import styles from "./EditableTitle.component.module.css";
5+
6+
const EditableTitle = () => {
7+
const countdownTitleSettingKey = "title";
8+
const [displayText, setDisplayText] = useState("Please stand by");
9+
const [newText, setNewText] = useState("Please stand by");
10+
const [isEditVisible, setEditVisible] = useState(false);
11+
const [isEditMode, setEditMode] = useState(false);
12+
13+
const accept = useCallback(() => {
14+
setDisplayText(newText);
15+
setEditMode(false);
16+
setEditVisible(false);
17+
}, [newText]);
18+
19+
const discard = useCallback(() => {
20+
setEditMode(false);
21+
setEditVisible(false);
22+
}, []);
23+
24+
const confirmDiscardButtons = useMemo(
25+
() => (
26+
<div>
27+
<IconButton text="✅" tooltip="Accept" onClick={accept} />
28+
<IconButton text="❌" tooltip="Discard" onClick={discard} />
29+
</div>
30+
),
31+
[accept, discard]
32+
);
33+
34+
useEffect(() => {
35+
const titleSettingValue = localStorage.getItem(countdownTitleSettingKey);
36+
if (titleSettingValue) {
37+
setDisplayText(titleSettingValue);
38+
}
39+
}, []);
40+
41+
useEffect(() => {
42+
localStorage.setItem(countdownTitleSettingKey, displayText);
43+
}, [displayText]);
44+
45+
const editButton = useMemo(
46+
() => (
47+
<IconButton
48+
text="✏️"
49+
tooltip="Edit text"
50+
onClick={() => setEditMode(true)}
51+
/>
52+
),
53+
[]
54+
);
55+
56+
return (
57+
<div
58+
className="flex flex-row flex-wrap items-center justify-center mb-8 w-full min-h-12"
59+
onMouseOver={() => setEditVisible(true)}
60+
onMouseOut={() => setEditVisible(false)}
61+
>
62+
{!isEditMode && (
63+
<>
64+
<h1 className="text-5xl uppercase">{displayText}</h1>
65+
{isEditVisible && editButton}
66+
</>
67+
)}
68+
{isEditMode && (
69+
<>
70+
<input
71+
type="text"
72+
style={styles}
73+
defaultValue={newText}
74+
autoFocus
75+
onChange={(e) => {
76+
setNewText(e.target.value);
77+
}}
78+
onKeyDown={(e) => {
79+
switch (e.key) {
80+
case "Escape":
81+
discard();
82+
break;
83+
case "Enter":
84+
accept();
85+
break;
86+
default:
87+
break;
88+
}
89+
}}
90+
/>
91+
{confirmDiscardButtons}
92+
</>
93+
)}
94+
</div>
95+
);
96+
};
97+
98+
export default EditableTitle;

src/components/IconButton.component.module.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
font-family: inherit;
1313
cursor: pointer;
1414
width: fit-content;
15-
transition: background-color 0.3s, border-color 0.3s;
15+
transition: .2s linear;
1616
}
1717

1818
.button {
1919
font-weight: 500;
20-
margin: 1rem .5rem;
20+
margin: .5rem;
2121
}
2222

2323
.button:last-child {

src/components/MuteButton.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useMuteContext } from "../hooks/useMuteContext.hook";
33
import { IconButton } from "./IconButton.component";
44

55
const MuteButton = () => {
6-
const IsMutedSettingKey = "isMuted";
6+
const IsMutedSettingKey = "mute";
77
const { isMuted, toggleMute } = useMuteContext();
88

99
useEffect(() => {

src/index.css

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
@import 'tailwindcss';
22

33
:root {
4+
--primary-color: #21a1f1;
5+
--secondary-color: #61dafb;
6+
--background-color: #242424;
7+
--text-color: rgba(255, 255, 255, 0.87);
8+
49
color-scheme: light dark;
5-
color: rgba(255, 255, 255, 0.87);
6-
background-color: #242424;
10+
color: var(--text-color);
11+
background-color: var(--background-color);
712

813
font-size: 1em;
914
font-synthesis: none;
@@ -19,6 +24,7 @@ body {
1924
a {
2025
text-decoration: none;
2126
color: #3498dbcc;
27+
transition: .2s linear;
2228

2329
&:hover {
2430
text-decoration: underline;
@@ -28,8 +34,8 @@ a {
2834

2935
@media (prefers-color-scheme: light) {
3036
:root {
31-
color: #242424;
32-
background-color: rgba(255, 255, 255, 0.87);
37+
color: var(--background-color);
38+
background-color: var(--text-color);
3339
}
3440
}
3541

src/pages/TimerCountdown.page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useLocation, useNavigate } from "react-router-dom";
55
import routes from "../routes";
66
import BitButton from "../components/BitButton.component";
77
import BitCounter from "../BitCounter";
8+
import EditableTitle from "../components/EditableTitle.component";
89
import { Button, ButtonType } from "../components/Button.component";
910
import { useMuteContext } from "../hooks/useMuteContext.hook";
1011

@@ -120,7 +121,7 @@ function TimerCountdown() {
120121
/>
121122
<div className="flex flex-col items-center justify-center text-center">
122123
<div className="flex flex-col items-center justify-center text-center">
123-
<h1 className="text-5xl uppercase mb-8">Please stand by</h1>
124+
<EditableTitle />
124125
<div className="flex flex-row justify-center align-center flex-wrap mt-8">
125126
{refs.map((_, index) => (
126127
<BitButton

0 commit comments

Comments
 (0)