Fix: card text contrast, stable grid order, independent highlight/input states, highlight dismiss
- Explicit dark colors on .result-value, .result-label, .result-symbol, .highlighted-value, .highlighted-label - Include from-unit in results grid (stable definition-order); from-unit tile shows Big(inputValue) and gets is-input-unit dashed-border class - Shift+click no longer clears highlightedUnitId — fromUnitId and highlightedUnitId are now fully independent states - Add × dismiss button (aria-label="Remove highlight") to .highlighted-result banner; .highlighted-result gains position:relative Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
37
src/app.css
37
src/app.css
@@ -68,16 +68,17 @@
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
|
color: #2C2C2C; /* explicit dark charcoal, do not rely on inheritance */
|
||||||
}
|
}
|
||||||
|
|
||||||
.result-label {
|
.result-label {
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
color: var(--pico-muted-color, #666);
|
color: #555550;
|
||||||
}
|
}
|
||||||
|
|
||||||
.result-symbol {
|
.result-symbol {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
color: var(--pico-muted-color, #666);
|
color: #888880;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +95,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.4rem;
|
gap: 0.4rem;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.highlighted-value {
|
.highlighted-value {
|
||||||
@@ -102,11 +104,12 @@
|
|||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
|
color: #2C2C2C;
|
||||||
}
|
}
|
||||||
|
|
||||||
.highlighted-label {
|
.highlighted-label {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
color: var(--pico-color, inherit);
|
color: #2C2C2C;
|
||||||
}
|
}
|
||||||
|
|
||||||
.highlighted-symbol {
|
.highlighted-symbol {
|
||||||
@@ -133,6 +136,34 @@
|
|||||||
min-width: 160px;
|
min-width: 160px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Input unit tile indicator ─────────────────────────────────────────────── */
|
||||||
|
.result-tile.is-input-unit {
|
||||||
|
border-style: dashed;
|
||||||
|
border-color: var(--pico-primary);
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Highlight dismiss button ──────────────────────────────────────────────── */
|
||||||
|
.highlight-dismiss {
|
||||||
|
position: absolute;
|
||||||
|
top: 0.5rem;
|
||||||
|
right: 0.75rem;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--pico-muted-color, #888);
|
||||||
|
padding: 0.15rem 0.3rem;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
transition: color 0.15s ease, background-color 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-dismiss:hover {
|
||||||
|
color: #2C2C2C;
|
||||||
|
background-color: rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Hotkey hint ───────────────────────────────────────────────────────────── */
|
/* ── Hotkey hint ───────────────────────────────────────────────────────────── */
|
||||||
.hotkey-hint {
|
.hotkey-hint {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
|
|||||||
@@ -12,12 +12,14 @@
|
|||||||
value,
|
value,
|
||||||
unit,
|
unit,
|
||||||
highlighted,
|
highlighted,
|
||||||
|
isInputUnit = false,
|
||||||
onclick,
|
onclick,
|
||||||
onshiftclick
|
onshiftclick
|
||||||
}: {
|
}: {
|
||||||
value: Big;
|
value: Big;
|
||||||
unit: Unit;
|
unit: Unit;
|
||||||
highlighted: boolean;
|
highlighted: boolean;
|
||||||
|
isInputUnit?: boolean;
|
||||||
onclick: () => void;
|
onclick: () => void;
|
||||||
onshiftclick: () => void;
|
onshiftclick: () => void;
|
||||||
} = $props();
|
} = $props();
|
||||||
@@ -39,6 +41,7 @@
|
|||||||
<div
|
<div
|
||||||
class="result-tile"
|
class="result-tile"
|
||||||
class:highlighted
|
class:highlighted
|
||||||
|
class:is-input-unit={isInputUnit}
|
||||||
onclick={handleClick}
|
onclick={handleClick}
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
value={item.convertedValue}
|
value={item.convertedValue}
|
||||||
unit={item.unit}
|
unit={item.unit}
|
||||||
highlighted={item.unit.id === highlightedUnitId}
|
highlighted={item.unit.id === highlightedUnitId}
|
||||||
|
isInputUnit={item.unit.id === fromUnitId}
|
||||||
onclick={() => onhighlight(item.unit.id)}
|
onclick={() => onhighlight(item.unit.id)}
|
||||||
onshiftclick={() => onsetinput(item.unit.id)}
|
onshiftclick={() => onsetinput(item.unit.id)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
|
import { Big } from 'big.js';
|
||||||
import { florpUnits } from '$lib/units/definitions';
|
import { florpUnits } from '$lib/units/definitions';
|
||||||
import { convertById } from '$lib/convert';
|
import { convertById } from '$lib/convert';
|
||||||
import { FRACTIONAL_DIGITS } from '$lib/config';
|
import { FRACTIONAL_DIGITS } from '$lib/config';
|
||||||
@@ -41,18 +42,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Derived: results for all units except fromUnit ─────────────────────────
|
// ── Derived: results for ALL units in definition order ─────────────────────
|
||||||
let results = $derived<ResultItem[]>(
|
let results = $derived<ResultItem[]>(
|
||||||
units
|
units.map((u) => ({
|
||||||
.filter((u) => u.id !== fromUnitId)
|
|
||||||
.map((u) => ({
|
|
||||||
unit: u,
|
unit: u,
|
||||||
convertedValue: convertById(inputValue, fromUnitId, u.id, units)
|
convertedValue:
|
||||||
|
u.id === fromUnitId
|
||||||
|
? Big(inputValue) // from-unit always equals inputValue
|
||||||
|
: convertById(inputValue, fromUnitId, u.id, units)
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
// ── Derived: highlighted result (unit + value) sourced from results array ──
|
// ── Derived: highlighted result (unit + value) sourced from full results ────
|
||||||
// The highlighted unit is always a non-from unit, so it's always in results.
|
// Results now includes all units, so from-unit can be highlighted too.
|
||||||
let highlightedResult = $derived(
|
let highlightedResult = $derived(
|
||||||
highlightedUnitId !== null
|
highlightedUnitId !== null
|
||||||
? (results.find((r) => r.unit.id === highlightedUnitId) ?? null)
|
? (results.find((r) => r.unit.id === highlightedUnitId) ?? null)
|
||||||
@@ -90,10 +92,10 @@
|
|||||||
function handleSetInput(id: string) {
|
function handleSetInput(id: string) {
|
||||||
// Shift+click: promote result unit to from-unit.
|
// Shift+click: promote result unit to from-unit.
|
||||||
// Re-express the current value in terms of the new from-unit.
|
// Re-express the current value in terms of the new from-unit.
|
||||||
|
// highlightedUnitId is NOT cleared — the two states are independent.
|
||||||
const convertedValue = convertById(inputValue, fromUnitId, id, units);
|
const convertedValue = convertById(inputValue, fromUnitId, id, units);
|
||||||
inputValue = parseFloat(convertedValue.toFixed(FRACTIONAL_DIGITS));
|
inputValue = parseFloat(convertedValue.toFixed(FRACTIONAL_DIGITS));
|
||||||
fromUnitId = id;
|
fromUnitId = id;
|
||||||
highlightedUnitId = null;
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -103,6 +105,11 @@
|
|||||||
|
|
||||||
{#if highlightedResult !== null}
|
{#if highlightedResult !== null}
|
||||||
<div class="highlighted-result">
|
<div class="highlighted-result">
|
||||||
|
<button
|
||||||
|
class="highlight-dismiss"
|
||||||
|
aria-label="Remove highlight"
|
||||||
|
onclick={() => (highlightedUnitId = null)}
|
||||||
|
>×</button>
|
||||||
<span class="highlighted-value">{formatBig(highlightedResult.convertedValue)}</span>
|
<span class="highlighted-value">{formatBig(highlightedResult.convertedValue)}</span>
|
||||||
<span class="highlighted-label">{highlightedResult.unit.labelPlural}</span>
|
<span class="highlighted-label">{highlightedResult.unit.labelPlural}</span>
|
||||||
<span class="highlighted-symbol">{highlightedResult.unit.symbol}</span>
|
<span class="highlighted-symbol">{highlightedResult.unit.symbol}</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user