Centralize duplicated card shell, press animation, and color tokens
Extract the rounded-card shell and button press animation into a shared CSS module composed by PageFrame, TitleScreen, and all buttons, add color tokens for repeated values, and load the saved game once on mount. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+2
-4
@@ -21,10 +21,8 @@ function clearGame() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [page, setPage] = useState<Page>(() =>
|
const [game, setGame] = useState<GameState | null>(loadGame)
|
||||||
loadGame() ? 'scoresheet' : 'title'
|
const [page, setPage] = useState<Page>(() => (game ? 'scoresheet' : 'title'))
|
||||||
)
|
|
||||||
const [game, setGame] = useState<GameState | null>(() => loadGame())
|
|
||||||
|
|
||||||
function handleNewGame() {
|
function handleNewGame() {
|
||||||
clearGame()
|
clearGame()
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
.frame {
|
.frame {
|
||||||
position: fixed;
|
composes: card from '../styles/shared.module.css';
|
||||||
inset: 1rem;
|
background: var(--color-parchment);
|
||||||
border: 2px solid black;
|
|
||||||
border-radius: 2rem;
|
|
||||||
background: #f5f0e4;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
@@ -23,7 +17,7 @@
|
|||||||
.rule {
|
.rule {
|
||||||
position: relative;
|
position: relative;
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 1px solid #c8b99a;
|
border-top: 1px solid var(--color-parchment-border);
|
||||||
margin: 0.75rem 0 0;
|
margin: 0.75rem 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,10 +27,10 @@
|
|||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
background: #f5f0e4;
|
background: var(--color-parchment);
|
||||||
padding: 0 0.35em;
|
padding: 0 0.35em;
|
||||||
font-size: 0.55rem;
|
font-size: 0.55rem;
|
||||||
color: #c8b99a;
|
color: var(--color-parchment-border);
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,13 @@
|
|||||||
.button {
|
.button {
|
||||||
|
composes: pressable from '../styles/shared.module.css';
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
background: #a8d5e8;
|
background: var(--color-blue);
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
|
||||||
transition: transform 80ms ease, box-shadow 80ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:active:not(:disabled) {
|
|
||||||
transform: translateY(2px);
|
|
||||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button:disabled {
|
.button:disabled {
|
||||||
|
|||||||
+7
-1
@@ -1,8 +1,14 @@
|
|||||||
|
:root {
|
||||||
|
--color-blue: #a8d5e8;
|
||||||
|
--color-parchment: #f5f0e4;
|
||||||
|
--color-parchment-border: #c8b99a;
|
||||||
|
}
|
||||||
|
|
||||||
*, *::before, *::after { box-sizing: border-box; }
|
*, *::before, *::after { box-sizing: border-box; }
|
||||||
button { min-height: 2.75rem; font-size: 1rem; font-family: inherit; cursor: pointer; }
|
button { min-height: 2.75rem; font-size: 1rem; font-family: inherit; cursor: pointer; }
|
||||||
html, body, #root { margin: 0; height: 100%; }
|
html, body, #root { margin: 0; height: 100%; }
|
||||||
body {
|
body {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
background: linear-gradient(to bottom, #a8d5e8, #4a9e6a);
|
background: linear-gradient(to bottom, var(--color-blue), #4a9e6a);
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
padding: 0.85rem 1rem;
|
padding: 0.85rem 1rem;
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
border: 1.5px solid #c8b99a;
|
border: 1.5px solid var(--color-parchment-border);
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
background: #fdfaf4;
|
background: #fdfaf4;
|
||||||
}
|
}
|
||||||
@@ -20,27 +20,25 @@
|
|||||||
background: #fff5f5;
|
background: #fff5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.removeBtn {
|
.circleBtn {
|
||||||
flex-shrink: 0;
|
composes: pressable from '../styles/shared.module.css';
|
||||||
width: 2.5rem;
|
|
||||||
height: 2.5rem;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border: none;
|
border: none;
|
||||||
background: #d94f4f;
|
|
||||||
color: white;
|
|
||||||
font-size: 1.25rem;
|
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
|
||||||
transition: transform 80ms ease, box-shadow 80ms ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.removeBtn:active {
|
.removeBtn {
|
||||||
transform: translateY(2px);
|
composes: circleBtn;
|
||||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
flex-shrink: 0;
|
||||||
|
width: 2.5rem;
|
||||||
|
height: 2.5rem;
|
||||||
|
background: #d94f4f;
|
||||||
|
color: white;
|
||||||
|
font-size: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.addRow {
|
.addRow {
|
||||||
@@ -50,22 +48,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.addBtn {
|
.addBtn {
|
||||||
|
composes: circleBtn;
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
border-radius: 50%;
|
background: var(--color-blue);
|
||||||
border: none;
|
|
||||||
background: #a8d5e8;
|
|
||||||
font-size: 1.75rem;
|
font-size: 1.75rem;
|
||||||
line-height: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
cursor: pointer;
|
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
|
||||||
transition: transform 80ms ease, box-shadow 80ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.addBtn:active {
|
|
||||||
transform: translateY(2px);
|
|
||||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,8 @@
|
|||||||
.frame {
|
.frame {
|
||||||
position: fixed;
|
composes: card from '../styles/shared.module.css';
|
||||||
inset: 1rem;
|
|
||||||
border: 2px solid black;
|
|
||||||
border-radius: 2rem;
|
|
||||||
background: transparent;
|
background: transparent;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
.card {
|
||||||
|
position: fixed;
|
||||||
|
inset: 1rem;
|
||||||
|
border: 2px solid black;
|
||||||
|
border-radius: 2rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pressable {
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
||||||
|
transition: transform 80ms ease, box-shadow 80ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pressable:active:not(:disabled) {
|
||||||
|
transform: translateY(2px);
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user