Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0110a86858 | ||
|
|
c868be8f89 |
@@ -4755,3 +4755,69 @@ test('et indsat billede kan åbnes stort og kopieres', async ({ page, context })
|
||||
|
||||
expect(trouble).toEqual([]);
|
||||
});
|
||||
/**
|
||||
* En opgaves tekst kan læses færdig, også på en telefon.
|
||||
*
|
||||
* Rapporteret fra en telefon, med et billede af en beskrivelse, der manglede sit
|
||||
* første bogstav på hver linje: "hermostat RU0910301440" og "atteries". Det er
|
||||
* ikke manglende tegn — det er et felt, der er rullet til højre. En beskrivelse er
|
||||
* tit et klippet stykke mail med en URL i, et <textarea> ombryder ved mellemrum,
|
||||
* og en URL har ingen.
|
||||
*
|
||||
* Og titlen var et <input>, som ikke kan ombryde overhovedet. "tado°: Your Smart
|
||||
* Thermostat needs new batteries" er en almindelig opgavetitel, og halvdelen af
|
||||
* den stod uden for kanten.
|
||||
*/
|
||||
test('en opgaves tekst kan læses færdig på en telefon', async ({ page }) => {
|
||||
const trouble = watchForTrouble(page);
|
||||
await page.setViewportSize({ width: 390, height: 844 });
|
||||
await page.goto('/');
|
||||
|
||||
const langTitel = 'tado°: Your Smart Thermostat needs new batteries';
|
||||
// "i dag" for at den lander på siden, prøven står på — parseren klipper det ud
|
||||
// af titlen igen, så den hedder præcis det, den skal.
|
||||
await page.getByLabel('Ny opgave').fill(`${langTitel} i dag`);
|
||||
await page.getByLabel('Ny opgave').press('Enter');
|
||||
await page.getByText('tado°', { exact: false }).first().click();
|
||||
|
||||
const titel = page.getByLabel('Opgavens tekst');
|
||||
await expect(titel).toBeVisible();
|
||||
await expect(titel).toHaveValue(langTitel);
|
||||
|
||||
// Beskrivelsen: en URL uden et eneste mellemrum at bryde ved.
|
||||
const url = 'https://link.tado.com/emails/8/ttid/1-a37f2c9b4e6d8a1f0c3b5e7d9a2f4c6b8e0d1a3f5c7b9e2d4a6f8c0b3e5d7a9f';
|
||||
const beskrivelse = page.getByLabel('Beskrivelse');
|
||||
await beskrivelse.fill(`Thermostat RU0910301440\nBatteries\n${url}`);
|
||||
await beskrivelse.blur();
|
||||
|
||||
// Målt frem for beskrevet: et felt, der ruller vandret, har en scrollWidth
|
||||
// større end sin clientWidth. Det var dét, der klippede venstre kant.
|
||||
//
|
||||
// Felterne måles gennem deres egne lokatorer og ikke med en forespørgsel på
|
||||
// aria-label: beskrivelsen har et <label for>, ikke et aria-label, så en
|
||||
// forespørgsel fandt ingenting og ville have bestået tomt.
|
||||
const spild = [];
|
||||
for (const [navn, felt] of [
|
||||
['Opgavens tekst', titel],
|
||||
['Beskrivelse', beskrivelse]
|
||||
]) {
|
||||
const m = await felt.evaluate((el) => ({ ind: el.scrollWidth, ude: el.clientWidth }));
|
||||
if (m.ind - m.ude > 1) spild.push(`${navn}: ${m.ind} > ${m.ude}`);
|
||||
}
|
||||
expect(spild).toEqual([]);
|
||||
|
||||
// Beskrivelsen løber ikke over i Chromium, heller ikke uden reglen — det var
|
||||
// Safari, den blev set i, og det er en anden motor. Prøven måler derfor reglen
|
||||
// selv frem for dens virkning. Det er svagere, og det står her, så den næste
|
||||
// ved det: den vogter mod at reglen bliver slettet, ikke mod at den er forkert.
|
||||
await expect(beskrivelse).toHaveCSS('overflow-wrap', 'break-word');
|
||||
|
||||
// Og titlen er blevet høj nok til at rumme sig selv frem for at klippe.
|
||||
const linjer = await titel.evaluate((el) => ({
|
||||
hoejde: el.clientHeight,
|
||||
linje: parseFloat(getComputedStyle(el).lineHeight)
|
||||
}));
|
||||
expect(linjer.hoejde).toBeGreaterThan(linjer.linje * 1.5);
|
||||
|
||||
expect(trouble).toEqual([]);
|
||||
});
|
||||
|
||||
@@ -171,6 +171,32 @@
|
||||
* took is said out loud, because a title that edits itself without a word is
|
||||
* worse than one that does nothing.
|
||||
*/
|
||||
/**
|
||||
* Lader et felt være lige så højt som sin tekst.
|
||||
*
|
||||
* `height: auto` først, og så `scrollHeight`: uden nulstillingen kan feltet kun
|
||||
* vokse, for scrollHeight på et felt, der allerede er for højt, er dets egen
|
||||
* højde.
|
||||
*/
|
||||
function grow(node) {
|
||||
const fit = () => {
|
||||
node.style.height = 'auto';
|
||||
node.style.height = `${node.scrollHeight}px`;
|
||||
};
|
||||
fit();
|
||||
node.addEventListener('input', fit);
|
||||
// Bredden skifter, når ruden gør — og en tekst, der fyldte to linjer, fylder
|
||||
// tre på en smallere skærm uden at der er rørt ved den.
|
||||
const watch = new ResizeObserver(fit);
|
||||
watch.observe(node);
|
||||
return {
|
||||
destroy() {
|
||||
node.removeEventListener('input', fit);
|
||||
watch.disconnect();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function saveContent() {
|
||||
if (!task) return;
|
||||
const trimmed = content.trim();
|
||||
@@ -418,13 +444,27 @@
|
||||
|
||||
<div class="scroll">
|
||||
<div class="field">
|
||||
<input
|
||||
<!-- Et felt frem for en linje. En opgavetitel er tit længere end en telefon
|
||||
er bred — "tado°: Your Smart Thermostat needs new batteries" er en
|
||||
almindelig en — og et <input> kan ikke ombryde: det ruller, og så står
|
||||
halvdelen af overskriften uden for kanten. -->
|
||||
<textarea
|
||||
class="title"
|
||||
rows="1"
|
||||
use:focusOnMount
|
||||
use:grow
|
||||
bind:value={content}
|
||||
onblur={saveContent}
|
||||
onkeydown={(e) => {
|
||||
// Retur gemmer frem for at lave en ny linje. En titel er én linje,
|
||||
// uanset hvor mange den fylder på skærmen.
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
e.currentTarget.blur();
|
||||
}
|
||||
}}
|
||||
aria-label={t('detail.text')}
|
||||
/>
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
@@ -894,6 +934,16 @@
|
||||
resize: vertical;
|
||||
font-family: inherit;
|
||||
line-height: 1.5;
|
||||
/* En beskrivelse er tit et klippet stykke mail med en URL i. Et <textarea>
|
||||
ombryder ved mellemrum, og en URL har ingen — så feltet rullede vandret,
|
||||
og på en telefon stod teksten forskudt med venstre kant klippet af. Det
|
||||
ser ikke ud som rulning; det ser ud som manglende bogstaver.
|
||||
|
||||
`break-word` og ikke `anywhere`: den første bryder kun et ord, der ikke kan
|
||||
stå på en linje alene, mens den anden bryder ved først givne lejlighed og
|
||||
delte "GarageRisteriet" midt i en stavelse. Se h1 på projektets side — den
|
||||
lektion er betalt én gang. */
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
/* The title is the one field that should not look like a field until you are in
|
||||
@@ -905,6 +955,10 @@
|
||||
background: transparent;
|
||||
border-color: transparent;
|
||||
padding-left: 0;
|
||||
/* Højden sættes af `grow`, så håndtaget ville love noget, det ikke kan
|
||||
holde: trækker man i det, retter det næste bogstav det tilbage. */
|
||||
resize: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.title:hover {
|
||||
|
||||
Reference in New Issue
Block a user