Silly task tracker to track silly things for silly friend silly.bwc9876.dev

Layout for mobile

bwc9876.dev 4c244aa0 6fb0db88

verified
+42 -36
+8 -3
src/App.tsx
··· 3 3 import silly from "./assets/silly.png"; 4 4 import Entry from "./Entry"; 5 5 6 - export type Entry = { id: number, name: string; progress: number }; 6 + export type Entry = { id: number; name: string; progress: number }; 7 7 type State = Entry[]; 8 8 9 9 const current = JSON.parse(window.localStorage.getItem("state") ?? "[]") as State; ··· 13 13 const [state, setState] = useState<State>(current); 14 14 15 15 const addGuy = () => { 16 - setState(s => { 16 + setState((s) => { 17 17 const newId = Math.random() * Number.MAX_SAFE_INTEGER; 18 18 const newState = [{ id: newId, name: guyVal, progress: 0 }, ...s]; 19 19 return newState.sort((a, b) => { ··· 65 65 </button> 66 66 <div className="list"> 67 67 {state.map((e, i) => ( 68 - <Entry key={e.id} onDelete={() => setState(s => s.filter((_, j) => j !== i))} onChange={(newVal) => setState(s => s.with(i, { ...e, progress: newVal }))} {...e} /> 68 + <Entry 69 + key={e.id} 70 + onDelete={() => setState((s) => s.filter((_, j) => j !== i))} 71 + onChange={(newVal) => setState((s) => s.with(i, { ...e, progress: newVal }))} 72 + {...e} 73 + /> 69 74 ))} 70 75 </div> 71 76 </>
+15 -15
src/Entry.tsx
··· 1 1 import type { Entry } from "./App"; 2 2 3 - export type Props = Entry & { onChange: (newVal: number) => void, onDelete: () => void, }; 3 + export type Props = Entry & { onChange: (newVal: number) => void; onDelete: () => void }; 4 4 5 5 export default function Entry({ name, progress, onChange, onDelete }: Props) { 6 - return <label className={progress === 100 ? "done" : undefined}> 7 - <span>{name}</span> 8 - <input 9 - type="range" 10 - value={progress} 11 - min={0} 12 - max={100} 13 - onChange={(ev) => onChange(parseInt(ev.target.value))} 14 - /> 15 - <small> 16 - {progress}% 17 - </small> 18 - <button onClick={onDelete}>X</button> 19 - </label>; 6 + return ( 7 + <label className={progress === 100 ? "done" : undefined}> 8 + <span>{name}</span> 9 + <input 10 + type="range" 11 + value={progress} 12 + min={0} 13 + max={100} 14 + onChange={(ev) => onChange(parseInt(ev.target.value))} 15 + /> 16 + <small>{progress}%</small> 17 + <button onClick={onDelete}>X</button> 18 + </label> 19 + ); 20 20 }
+19 -18
src/index.css
··· 4 4 5 5 --level: 65%; 6 6 --saturation-offset: 20%; 7 - --rainbow: linear-gradient(90deg, 8 - hsl(0, calc(100% - var(--saturation-offset)), var(--level)) 0%, 9 - hsl(36, calc(100% - var(--saturation-offset)), var(--level)) 10%, 10 - hsl(64, calc(74% - var(--saturation-offset)), var(--level)) 20%, 11 - hsl(118, calc(68% - var(--saturation-offset)), var(--level)) 30%, 12 - hsl(179, calc(68% - var(--saturation-offset)), var(--level)) 40%, 13 - hsl(188, calc(76% - var(--saturation-offset)), var(--level)) 50%, 14 - hsl(212, calc(86% - var(--saturation-offset)), var(--level)) 60%, 15 - hsl(260, calc(89% - var(--saturation-offset)), var(--level)) 70%, 16 - hsl(284, calc(94% - var(--saturation-offset)), var(--level)) 80%, 17 - hsl(308, calc(97% - var(--saturation-offset)), var(--level)) 90%, 18 - hsl(0, calc(100% - var(--saturation-offset)), var(--level)) 100%); 7 + --rainbow: linear-gradient( 8 + 90deg, 9 + hsl(0, calc(100% - var(--saturation-offset)), var(--level)) 0%, 10 + hsl(36, calc(100% - var(--saturation-offset)), var(--level)) 10%, 11 + hsl(64, calc(74% - var(--saturation-offset)), var(--level)) 20%, 12 + hsl(118, calc(68% - var(--saturation-offset)), var(--level)) 30%, 13 + hsl(179, calc(68% - var(--saturation-offset)), var(--level)) 40%, 14 + hsl(188, calc(76% - var(--saturation-offset)), var(--level)) 50%, 15 + hsl(212, calc(86% - var(--saturation-offset)), var(--level)) 60%, 16 + hsl(260, calc(89% - var(--saturation-offset)), var(--level)) 70%, 17 + hsl(284, calc(94% - var(--saturation-offset)), var(--level)) 80%, 18 + hsl(308, calc(97% - var(--saturation-offset)), var(--level)) 90%, 19 + hsl(0, calc(100% - var(--saturation-offset)), var(--level)) 100% 20 + ); 19 21 } 20 22 21 23 @keyframes scroll { ··· 73 75 font-size: 18pt; 74 76 } 75 77 76 - &>button { 78 + & > button { 77 79 transition: background-color 100ms linear; 78 80 background-color: #6c7; 79 81 font-size: 18pt; ··· 89 91 flex-direction: column; 90 92 gap: 0.5em; 91 93 92 - &>label { 94 + & > label { 93 95 display: grid; 94 - position: relative; 95 - grid-template-columns: 1fr 3fr .6fr .2fr; 96 + grid: row / 1fr 3fr 0.6fr 0.2fr; 96 97 align-items: center; 97 98 gap: 0.5em; 98 99 margin: 0; 99 - transition: scale .2s cubic-bezier(.68, -0.55, .27, 1.55); 100 + transition: scale 0.2s cubic-bezier(0.68, -0.55, 0.27, 1.55); 100 101 border: solid 2px black; 101 102 padding: 1em; 102 103 103 104 @starting-style { 104 - scale: .2; 105 + scale: 0.2; 105 106 } 106 107 107 108 &.done {