self-resizing text
This commit is contained in:
parent
bc29510bb5
commit
9649d407fd
4 changed files with 63 additions and 10 deletions
|
@ -12,14 +12,14 @@
|
|||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"solid-js": "^1.9.3",
|
||||
"@tauri-apps/api": "^2",
|
||||
"@tauri-apps/plugin-opener": "^2"
|
||||
"@tauri-apps/plugin-opener": "^2",
|
||||
"solid-js": "^1.9.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2",
|
||||
"typescript": "~5.6.2",
|
||||
"vite": "^6.0.3",
|
||||
"vite-plugin-solid": "^2.11.0",
|
||||
"@tauri-apps/cli": "^2"
|
||||
"vite-plugin-solid": "^2.11.0"
|
||||
}
|
||||
}
|
||||
|
|
10
src/App.css
10
src/App.css
|
@ -76,13 +76,13 @@
|
|||
flex-direction: column;
|
||||
gap: calc(1 * var(--unit));
|
||||
font-size: calc(3 * var(--unit));
|
||||
font-weight: 700;
|
||||
width: calc((20 * 4 + 3) * var(--unit));
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.puzzle-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
> h1 {
|
||||
flex-grow: 1;
|
||||
|
@ -112,10 +112,11 @@
|
|||
user-select: none;
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
padding: 0;
|
||||
padding: calc(1 * var(--unit));
|
||||
border-radius: calc(1 * var(--unit));
|
||||
background-color: var(--color-foreground-trace);
|
||||
font-weight: 500;
|
||||
font-size: calc(5 * var(--unit));
|
||||
font-weight: 600;
|
||||
}
|
||||
.badge {
|
||||
position: absolute;
|
||||
|
@ -194,6 +195,7 @@ h1 {
|
|||
button {
|
||||
appearance: none;
|
||||
overflow: visible;
|
||||
min-width: 2em;
|
||||
background: var(--color-foreground-faint);
|
||||
color: var(--color-foreground);
|
||||
font-size: inherit;
|
||||
|
@ -202,7 +204,7 @@ button {
|
|||
border-radius: calc(1 * var(--unit, 0.5em));
|
||||
}
|
||||
button:disabled {
|
||||
opacity: 0.5;
|
||||
opacity: 0.25;
|
||||
}
|
||||
button:focus-visible, button:hover {
|
||||
box-shadow: 0 0 3em -1.5em inset var(--color-foreground)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { For } from "solid-js";
|
||||
import "./App.css";
|
||||
import useAppModel from "./useAppModel";
|
||||
import FitText from "./FitText";
|
||||
|
||||
function App() {
|
||||
const {
|
||||
|
@ -35,6 +36,7 @@ function App() {
|
|||
on:input={({ target: { value } }) =>
|
||||
handleSelectGame(parseInt(value, 10))
|
||||
}
|
||||
value={store.puzzleId}
|
||||
>
|
||||
<For each={connections}>
|
||||
{({ id }) => <option value={id}>{id}</option>}
|
||||
|
@ -53,6 +55,7 @@ function App() {
|
|||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<div>Create four groups of four words!</div>
|
||||
<For each={store.solvedGroups}>
|
||||
{({ group, level, members }) => (
|
||||
<div class="puzzle-row">
|
||||
|
@ -68,7 +71,7 @@ function App() {
|
|||
<div class="puzzle-row">
|
||||
{[0, 1, 2, 3].map((col) => {
|
||||
const index = 4 * row + col;
|
||||
const answer = getFromPuzzle(index).answer;
|
||||
const answer = () => getFromPuzzle(index).answer;
|
||||
return (
|
||||
<button
|
||||
classList={{
|
||||
|
@ -85,7 +88,7 @@ function App() {
|
|||
});
|
||||
}}
|
||||
>
|
||||
{answer}
|
||||
<FitText body={answer} />
|
||||
{store.pinnedCount > index && <div class="badge">🔒</div>}
|
||||
</button>
|
||||
);
|
||||
|
|
48
src/FitText.tsx
Normal file
48
src/FitText.tsx
Normal file
|
@ -0,0 +1,48 @@
|
|||
import { createEffect, createSignal, on, type Accessor } from "solid-js";
|
||||
|
||||
export default function FitText(props: { body: Accessor<string> }) {
|
||||
let textRef: SVGTextElement | undefined;
|
||||
const [width, setWidth] = createSignal(100);
|
||||
const [height, setHeight] = createSignal(100);
|
||||
|
||||
createEffect(
|
||||
on(
|
||||
props.body,
|
||||
async () => {
|
||||
setWidth(100)
|
||||
setHeight(100)
|
||||
await new Promise(resolve => setTimeout(resolve, 1))
|
||||
const bounds = textRef?.getBBox();
|
||||
if (bounds === undefined) {
|
||||
return;
|
||||
}
|
||||
setWidth(bounds.width);
|
||||
setHeight(bounds.height);
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
return (
|
||||
<svg
|
||||
style={{
|
||||
width: "100%",
|
||||
"max-height": "50%",
|
||||
}}
|
||||
viewBox={`0 0 ${width()} ${height()}`}
|
||||
overflow="visible"
|
||||
fill="currentcolor"
|
||||
>
|
||||
<text
|
||||
ref={textRef}
|
||||
x="50%"
|
||||
y="50%"
|
||||
dominant-baseline="central"
|
||||
text-anchor="middle"
|
||||
font-size="1rem"
|
||||
font-family="inherit"
|
||||
>
|
||||
{props.body()}
|
||||
</text>
|
||||
</svg>
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue