tags: one ink, chip and inline, and the chip edge solved for 3:1
CI & Build / Python lint (push) Successful in 3s
CI & Build / Build now, or wait for Android? (push) Successful in 5s
CI & Build / TypeScript typecheck (push) Successful in 11s
CI & Build / Python tests (push) Successful in 14s
CI & Build / integration (push) Successful in 21s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 3m31s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 6m1s
Desktop (Tauri) / Update manifest (push) Successful in 5s
Android / Kotlin + Rust (APK) (push) Successful in 8m45s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Build now, or wait for Android? (push) Successful in 5s
CI & Build / TypeScript typecheck (push) Successful in 11s
CI & Build / Python tests (push) Successful in 14s
CI & Build / integration (push) Successful in 21s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 3m31s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 6m1s
Desktop (Tauri) / Update manifest (push) Successful in 5s
Android / Kotlin + Rust (APK) (push) Successful in 8m45s
Step 1 left one card surface per theme, so the tag ink is no longer
choosing a value that has to clear twenty backgrounds. Re-measured against
the one it actually lands on, the two tables collapse into one.
`-800` in light, `-300` in dark, for a `#tag` in the prose AND for a chip's
text. Dark needed no decision at all — the two tables already held the same
value for all ten hues, which is most of the argument on its own. Light
collapses onto the INLINE column deliberately: since M311 a tag whose text
is in the body is drawn where it was typed and not repeated as a chip, so
inline is the common case and this leaves what is seen most exactly as it
was. The chip is strictly better for the move:
inline, on the card as a chip, on its own fill
light `-800` 7.09 - 15.13 6.37 - 12.01 (was 4.52 - 8.23)
dark `-300` 9.45 - 14.23 8.23 - 11.88 (unchanged)
The chip edge goes 0.60 -> 0.65, and this is the first time that number
could be solved rather than judged. 0.60 was picked against a chip sitting
on a card of its own colour, a case that no longer exists; against a known
fill the smallest alpha clearing the 3:1 of WCAG 1.4.11 for all ten hues is
arithmetic. 0.60 gives 2.75-3.82 and misses for six of them, 0.65 gives
3.03-4.36 and misses for none. Dark runs 4.52-5.76.
That edge is doing more work than it looks: a chip's fill measures 1.02-1.26
against the card in light and 1.02-1.73 in dark, and dark red at 1.02 is
invisible. The ring is the pill; the fill only tints it.
`LABEL_CHIP_CLASSES` becomes `LABEL_CHIP_SHELL` — fill and edge, no ink —
and `labelChipClasses(label)` composes shell and ink in one place. The board
and the editor each had their own copy of that composition, with a comment
on one of them asking the other to stay in step. Now it is one call.
Fixed on the way past: the web drew `default`'s chip ring at `black/10`
(1.36 against its own fill) where Compose derived it from the ink (3.21) —
the same chip, visibly different pills. Both are the ink at 65% now.
`chipForeground` stays, narrowed to what it always actually was: the
REMINDER pill's ink, transcribed from NoteCard.vue's literal red-700 /
neutral-600. It is not a tag and must not move with one.
Also gone: `NOTE_NODE_FILL`, a per-hue table of solid hexes for graph nodes
with no consumer anywhere in the repo.
Step 2 of M315. #3149
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -331,7 +331,7 @@ fun EditorLabelRow(
|
||||
// "from tag" hint beside one is what says why it has no cross.
|
||||
text = "#${label.name}",
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
color = tint.chipForeground(dark),
|
||||
color = tint.tagInk(dark),
|
||||
modifier =
|
||||
Modifier
|
||||
.clip(CircleShape)
|
||||
|
||||
@@ -375,7 +375,7 @@ private fun LabelChips(labels: List<NoteLabel>) {
|
||||
// also keeps a lifted chip reading as the `#todo` somebody wrote.
|
||||
text = "#${label.name}",
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = tint.chipForeground(dark),
|
||||
color = tint.tagInk(dark),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier =
|
||||
|
||||
@@ -33,24 +33,33 @@ data class NoteTint(
|
||||
val darkBackground: Color,
|
||||
val darkBorder: Color,
|
||||
val lightChipBackground: Color,
|
||||
val lightChipForeground: Color,
|
||||
val darkChipBackground: Color,
|
||||
/**
|
||||
* The REMINDER pill's ink, and nothing else's — see [chipForeground].
|
||||
*
|
||||
* Only two of these ten are ever read (`red` when a reminder has passed, `default`
|
||||
* otherwise). They stay a per-hue column because they are transcribed from the
|
||||
* web's literals rather than derived from anything here.
|
||||
*/
|
||||
val lightChipForeground: Color,
|
||||
val darkChipForeground: Color,
|
||||
/**
|
||||
* The colour a `#tag` is drawn in when it is left in the prose — see [tagInk].
|
||||
* THE INK A TAG IS DRAWN IN — inline in the prose AND as a chip's text — see
|
||||
* [tagInk].
|
||||
*
|
||||
* A SEPARATE value from [lightChipForeground] rather than a reuse of it, and the
|
||||
* difference is not cosmetic. A chip brings its own `-100` fill, so its text only
|
||||
* ever has to read against that one colour. Inline text sits on whatever the card
|
||||
* happens to be, which includes the gray-tagged card at `neutral-200` — and there
|
||||
* the chip's `-700` measured 3.98 (green), 4.11 (orange) and 4.34 (teal), all
|
||||
* under the 4.5 body text needs. One step deeper puts every hue between 5.63 and
|
||||
* 12.01 in light and 7.20 and 10.84 in dark, across every fill that existed then,
|
||||
* so it was one rule rather than three exceptions.
|
||||
* These were two columns until M315, and the split was real while it lasted: a chip
|
||||
* brought its own `-100` fill and could afford `-700`, while inline text sat on
|
||||
* whatever the card was, which included a gray-tagged card at `neutral-200` where
|
||||
* `-700` measured 3.98 (green), 4.11 (orange) and 4.34 (teal), all under the 4.5
|
||||
* body text needs. One step deeper cleared every fill at once.
|
||||
*
|
||||
* THE CONSTRAINT IS GONE as of M315 — one card fill per theme means this is solving
|
||||
* for two backgrounds instead of twenty. Left here unchanged because it still
|
||||
* clears 4.5 on both; re-measuring against one known background is #3149.
|
||||
* The twenty card fills that split was solving for are gone, so both jobs take this
|
||||
* one value. The direction is deliberate: since M311 a tag whose text is in the body
|
||||
* is drawn where it was typed and NOT repeated as a chip, so the inline token is the
|
||||
* common case and collapsing onto ITS column leaves what is seen most exactly as it
|
||||
* was. The chip is strictly better for the move — on its own fill it goes from
|
||||
* 4.52-8.23 to 6.37-12.01 in light. Dark needed no decision: the two columns already
|
||||
* held the same value for all ten hues.
|
||||
*/
|
||||
val lightTagInk: Color,
|
||||
val darkTagInk: Color,
|
||||
@@ -66,10 +75,19 @@ data class NoteTint(
|
||||
|
||||
fun chipBackground(dark: Boolean): Color = if (dark) darkChipBackground else lightChipBackground
|
||||
|
||||
/**
|
||||
* The REMINDER pill's ink. NOT a tag's — a tag takes [tagInk] wherever it is drawn.
|
||||
*
|
||||
* Kept apart from [tagInk] because the reminder pill is not a tag: it borrows the
|
||||
* chip's shape and its `red-100`/`black-5` fills, and its `red-700`/`neutral-600`
|
||||
* text is transcribed from NoteCard.vue's literal classes. The two happened to be
|
||||
* one value; making the tag ink one step deeper (M315) is where they parted, and
|
||||
* moving the reminder with it would have silently broken that mirror instead.
|
||||
*/
|
||||
fun chipForeground(dark: Boolean): Color = if (dark) darkChipForeground else lightChipForeground
|
||||
|
||||
/**
|
||||
* The colour for a `#tag` still sitting in the note's own words.
|
||||
* The colour a `#tag` is drawn in — in the note's own words, or as a chip.
|
||||
*
|
||||
* A tag whose text is in the body is no longer repeated as a chip (the card was
|
||||
* printing every tag twice — once where it was typed, once at the top). It is
|
||||
@@ -79,32 +97,37 @@ data class NoteTint(
|
||||
fun tagInk(dark: Boolean): Color = if (dark) darkTagInk else lightTagInk
|
||||
|
||||
/**
|
||||
* A hairline edge for a chip, in its own text colour at low alpha.
|
||||
* A hairline edge for a chip, in its own ink at low alpha.
|
||||
*
|
||||
* Needed because a chip's fill can no longer be trusted to differ from what is
|
||||
* behind it. A tagged note takes its FIRST tag's colour, and that card is drawn
|
||||
* at exactly [lightChipBackground] — the same value the chip uses — so in light
|
||||
* mode the pill was measured at a contrast ratio of 1.00 against the card it had
|
||||
* itself coloured. Perfectly invisible: the tag name read as loose text.
|
||||
* THE EDGE IS THE PILL. Against the one card surface a chip's fill measures
|
||||
* 1.02-1.26 in light and 1.02-1.73 in dark — very nearly nothing, and dark red at
|
||||
* 1.02 is literally invisible. Without this the tag name would read as loose text.
|
||||
* The fill only tints a shape the edge is drawing.
|
||||
*
|
||||
* An edge rather than shifting the fill, because the fill can collide with any
|
||||
* card colour and chasing that needs the chip to know what it is sitting on. A
|
||||
* border in the chip's own foreground always reads, against any background, and
|
||||
* needs no plumbing.
|
||||
* An edge rather than a heavier fill, because a fill loud enough to hold its own
|
||||
* shape would be the loudest thing on a board whose whole point is now that the tag
|
||||
* is the one coloured thing on it.
|
||||
*/
|
||||
fun chipBorder(dark: Boolean): Color = chipForeground(dark).copy(alpha = CHIP_EDGE_ALPHA)
|
||||
fun chipBorder(dark: Boolean): Color = tagInk(dark).copy(alpha = CHIP_EDGE_ALPHA)
|
||||
}
|
||||
|
||||
// How strongly a chip's edge is drawn, as a fraction of its own text colour.
|
||||
// How strongly a chip's edge is drawn, as a fraction of its own ink.
|
||||
//
|
||||
// 0.60 measured, not guessed: against the worst case — a chip on a card of its own
|
||||
// colour — this is a 2.32:1 boundary, where 0.30 gave only 1.49:1 and was effectively
|
||||
// no edge at all. It does NOT reach the 3:1 of WCAG 1.4.11, which needs 0.80 and
|
||||
// draws a hard outline rather than a hairline. 1.4.11 governs boundaries that carry
|
||||
// REQUIRED information, and a chip's information is its text — which passes AA at
|
||||
// 8:1 or better on every card in the palette. The edge restores the pill's shape;
|
||||
// it does not carry the meaning. Raise to 0.80 if that judgment is ever overruled.
|
||||
private const val CHIP_EDGE_ALPHA = 0.60f
|
||||
// SOLVED FOR, NOT GUESSED — and re-solved once the answer became solvable. 0.60 was
|
||||
// picked against the worst case of the time: a chip on a card of its OWN colour, back
|
||||
// when a note took its first tag's fill. It gave 2.32:1 there, missed the 3:1 of WCAG
|
||||
// 1.4.11, and the comment here reasoned its way out of that on the grounds that a
|
||||
// chip's information is its text.
|
||||
//
|
||||
// M315 removed that worst case. The edge is now the ink at alpha over a KNOWN fill, so
|
||||
// the smallest alpha clearing 3:1 for all ten hues is arithmetic rather than judgment:
|
||||
// 0.60 gives 2.75-3.82 in light and misses for six of the ten, 0.65 gives 3.03-4.36 and
|
||||
// misses for none. Dark runs 4.52-5.76. The old comment named 0.80 as the fallback if
|
||||
// the judgment were ever overruled; it is not needed, and it draws a hard outline where
|
||||
// a hairline does the job.
|
||||
//
|
||||
// Mirrored on the web as the `/65` in LABEL_CHIP_SHELL's ring.
|
||||
private const val CHIP_EDGE_ALPHA = 0.65f
|
||||
|
||||
/** Keyed by the core's colour vocabulary. Order matches the web's picker. */
|
||||
val NOTE_TINTS: Map<String, NoteTint> =
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
import { computed, onBeforeUnmount, ref, watch } from "vue";
|
||||
import { useNotesStore } from "../stores/notes";
|
||||
import {
|
||||
LABEL_CHIP_CLASSES,
|
||||
NOTE_CARD_SURFACE,
|
||||
NOTE_COLOR_KEYS,
|
||||
NOTE_COLOR_LABELS,
|
||||
NOTE_SWATCH_CLASSES,
|
||||
resolveLabelColor,
|
||||
labelChipClasses,
|
||||
type NoteColor,
|
||||
} from "../notes/colors";
|
||||
import type { Note } from "../stores/notes";
|
||||
@@ -190,12 +189,6 @@ async function snoozeReminder(minutes: number): Promise<void> {
|
||||
emit("reminder-changed");
|
||||
}
|
||||
|
||||
// Takes the label, not its colour: a tag nobody has coloured derives one from its
|
||||
// name, so chips carry the tag's identity rather than all being the same grey.
|
||||
function labelChip(label: { name: string; color: string }): string {
|
||||
return LABEL_CHIP_CLASSES[resolveLabelColor(label)] ?? LABEL_CHIP_CLASSES.default;
|
||||
}
|
||||
|
||||
// Only the tags the BODY is not already showing. `via_tag` means exactly "backed by
|
||||
// text still in the note" since M311, so a chip for one printed the same tag twice —
|
||||
// once where it was typed, once in this row — and the loud copy was the duplicate. A
|
||||
@@ -300,7 +293,7 @@ onBeforeUnmount(() => document.removeEventListener("mousedown", onDocMousedown))
|
||||
v-for="lb in chipLabels"
|
||||
:key="lb.id"
|
||||
class="rounded-full px-2 py-0.5 text-xs"
|
||||
:class="labelChip(lb)"
|
||||
:class="labelChipClasses(lb)"
|
||||
>#{{ lb.name }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { fromLocalInput, toLocalInput } from "../notes/datetime";
|
||||
import { takeMorphOrigin } from "../composables/useEditorMorph";
|
||||
import { prefersReducedMotion } from "../composables/useReducedMotion";
|
||||
import type { Note, NoteLabel, NoteRevision } from "../stores/notes";
|
||||
import { LABEL_CHIP_CLASSES, resolveLabelColor, type NoteColor } from "../notes/colors";
|
||||
import { labelChipClasses, type NoteColor } from "../notes/colors";
|
||||
import {
|
||||
afterEnter,
|
||||
type EditorBlock,
|
||||
@@ -376,13 +376,6 @@ async function onLabelsChange(next: NoteLabel[]) {
|
||||
async function removeLabel(id: string) {
|
||||
await onLabelsChange(labelList.value.filter((lb) => lb.id !== id));
|
||||
}
|
||||
// Takes the label, not its colour — a tag nobody has coloured derives one from its
|
||||
// name. Must match NoteCard's chip exactly: the same tag either side of opening a
|
||||
// note changing colour would be worse than both being grey.
|
||||
function labelChip(label: { name: string; color: string }): string {
|
||||
return LABEL_CHIP_CLASSES[resolveLabelColor(label)] ?? LABEL_CHIP_CLASSES.default;
|
||||
}
|
||||
|
||||
// ---- add a checklist ----
|
||||
//
|
||||
// Appends an empty item and puts the caret in it. Unlike every other toolbar button
|
||||
@@ -630,7 +623,7 @@ function revPreview(rev: NoteRevision): string {
|
||||
v-for="lb in labelList"
|
||||
:key="lb.id"
|
||||
class="inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs"
|
||||
:class="labelChip(lb)"
|
||||
:class="labelChipClasses(lb)"
|
||||
>
|
||||
<!-- `#` on every chip, matching the card. This row still lists the tags
|
||||
the BODY owns too — it is the control surface, and `via_tag` is what
|
||||
|
||||
@@ -35,44 +35,65 @@ export const NOTE_SWATCH_CLASSES: Record<NoteColor, string> = {
|
||||
gray: "bg-neutral-400 dark:bg-neutral-500",
|
||||
};
|
||||
|
||||
// Label chip tints (bg + readable text + a hairline edge), keyed by the same color
|
||||
// vocabulary.
|
||||
// A chip's SHELL: its fill and its hairline edge, keyed by the colour vocabulary. The
|
||||
// INK is not here — see TAG_TEXT_CLASSES, which one table now serves both a chip's text
|
||||
// and a `#tag` left in the prose. Compose the two with `labelChipClasses`.
|
||||
//
|
||||
// The RING is not decoration. A tagged note takes its first tag's colour and is drawn
|
||||
// at that hue's `-100` — exactly what the chip uses as its fill — so in light mode the
|
||||
// chip measured a contrast ratio of 1.00 against the card it had itself coloured.
|
||||
// Perfectly invisible; the tag name read as loose text. An edge holds the pill's shape
|
||||
// against ANY background, where shifting the fill only moves which card it collides
|
||||
// THE RING IS NOT DECORATION. A chip's fill measures 1.02-1.26 against the card in
|
||||
// light and 1.02-1.73 in dark — that is to say, very nearly nothing. The pill's shape
|
||||
// is the edge; the fill only tints it. (Dark red is the extreme at 1.02, which is
|
||||
// invisible: without the ring that chip would be loose text.) An edge holds the shape
|
||||
// against any background, where shifting the fill only moves which card it collides
|
||||
// with.
|
||||
export const LABEL_CHIP_CLASSES: Record<NoteColor, string> = {
|
||||
default: "bg-black/5 text-neutral-600 dark:bg-white/10 dark:text-neutral-300 ring-1 ring-inset ring-black/10 dark:ring-white/15",
|
||||
red: "bg-red-100 text-red-700 dark:bg-red-950/50 dark:text-red-300 ring-1 ring-inset ring-red-700/60 dark:ring-red-300/60",
|
||||
orange: "bg-orange-100 text-orange-700 dark:bg-orange-950/50 dark:text-orange-300 ring-1 ring-inset ring-orange-700/60 dark:ring-orange-300/60",
|
||||
yellow: "bg-amber-100 text-amber-800 dark:bg-amber-950/50 dark:text-amber-300 ring-1 ring-inset ring-amber-700/60 dark:ring-amber-300/60",
|
||||
green: "bg-green-100 text-green-700 dark:bg-green-950/50 dark:text-green-300 ring-1 ring-inset ring-green-700/60 dark:ring-green-300/60",
|
||||
teal: "bg-teal-100 text-teal-700 dark:bg-teal-950/50 dark:text-teal-300 ring-1 ring-inset ring-teal-700/60 dark:ring-teal-300/60",
|
||||
blue: "bg-blue-100 text-blue-700 dark:bg-blue-950/50 dark:text-blue-300 ring-1 ring-inset ring-blue-700/60 dark:ring-blue-300/60",
|
||||
purple: "bg-purple-100 text-purple-700 dark:bg-purple-950/50 dark:text-purple-300 ring-1 ring-inset ring-purple-700/60 dark:ring-purple-300/60",
|
||||
pink: "bg-pink-100 text-pink-700 dark:bg-pink-950/50 dark:text-pink-300 ring-1 ring-inset ring-pink-700/60 dark:ring-pink-300/60",
|
||||
gray: "bg-neutral-200 text-neutral-700 dark:bg-neutral-700 dark:text-neutral-200 ring-1 ring-inset ring-neutral-700/60 dark:ring-neutral-200/60",
|
||||
//
|
||||
// AT 65%, NOT 60%, AND SOLVED FOR RATHER THAN GUESSED. 0.60 was chosen against a worst
|
||||
// case that no longer exists — a chip sitting on a card of its own colour, back when a
|
||||
// note took its first tag's fill. Against the one card surface (M315) the ring is the
|
||||
// ink at alpha over a known fill, so the alpha that clears the 3:1 of WCAG 1.4.11 for
|
||||
// all ten hues can simply be solved: 0.60 gives 2.75-3.82 in light and misses for six
|
||||
// of them, 0.65 gives 3.03-4.36 and misses for none. Dark is 4.52-5.76. 0.80 was the
|
||||
// number the old comment named as the fallback and it is more than is needed — it
|
||||
// draws a hard outline where a hairline does the job.
|
||||
//
|
||||
// `default`'s ring was `black/10 dark:white/15` here and the ink at alpha on the phone —
|
||||
// 1.36 against its own fill in light against Compose's 3.21, so the two surfaces were
|
||||
// drawing visibly different pills for the same chip. It is the ink at 65% on both now,
|
||||
// like every other key: one rule for ten hues, not nine and an exception.
|
||||
//
|
||||
// Mirrored in NoteTint.kt as `chipBackground` and `chipBorder` / CHIP_EDGE_ALPHA.
|
||||
export const LABEL_CHIP_SHELL: Record<NoteColor, string> = {
|
||||
default: "bg-black/5 dark:bg-white/10 ring-1 ring-inset ring-neutral-700/65 dark:ring-neutral-300/65",
|
||||
red: "bg-red-100 dark:bg-red-950/50 ring-1 ring-inset ring-red-800/65 dark:ring-red-300/65",
|
||||
orange: "bg-orange-100 dark:bg-orange-950/50 ring-1 ring-inset ring-orange-800/65 dark:ring-orange-300/65",
|
||||
yellow: "bg-amber-100 dark:bg-amber-950/50 ring-1 ring-inset ring-amber-800/65 dark:ring-amber-300/65",
|
||||
green: "bg-green-100 dark:bg-green-950/50 ring-1 ring-inset ring-green-800/65 dark:ring-green-300/65",
|
||||
teal: "bg-teal-100 dark:bg-teal-950/50 ring-1 ring-inset ring-teal-800/65 dark:ring-teal-300/65",
|
||||
blue: "bg-blue-100 dark:bg-blue-950/50 ring-1 ring-inset ring-blue-800/65 dark:ring-blue-300/65",
|
||||
purple: "bg-purple-100 dark:bg-purple-950/50 ring-1 ring-inset ring-purple-800/65 dark:ring-purple-300/65",
|
||||
pink: "bg-pink-100 dark:bg-pink-950/50 ring-1 ring-inset ring-pink-800/65 dark:ring-pink-300/65",
|
||||
gray: "bg-neutral-200 dark:bg-neutral-700 ring-1 ring-inset ring-neutral-800/65 dark:ring-neutral-200/65",
|
||||
};
|
||||
|
||||
// The ink for a `#tag` drawn where it was typed, rather than repeated as a chip.
|
||||
// THE INK A TAG IS DRAWN IN — one table, for a `#tag` left in the prose AND for a
|
||||
// chip's text. It was two, and the split was real while it lasted: a chip carried its
|
||||
// own `-100` fill and could afford `-700`, while inline text sat on whatever the card
|
||||
// was, which included a gray-tagged card at `neutral-200` where `-700` measured 3.98
|
||||
// (green), 4.11 (orange) and 4.34 (teal) — all under the 4.5 body text needs. One step
|
||||
// deeper cleared every fill at once, so inline got `-800` and the chip kept `-700`.
|
||||
//
|
||||
// ONE Tailwind step deeper than LABEL_CHIP_CLASSES' text. A chip carries its own
|
||||
// `-100` fill, so its text has exactly one background to read against; inline text
|
||||
// sits on whatever the CARD is. When the card could be any of twenty fills that was a
|
||||
// hard constraint — on a gray-tagged card at `neutral-200` the chip's `-700` measured
|
||||
// 3.98 (green), 4.11 (orange) and 4.34 (teal), all under the 4.5 body text needs,
|
||||
// where `-800` put every hue between 5.63 and 12.01 in light and `-300` gave 7.20 to
|
||||
// 10.84 in dark, across every fill. One step for all ten beat three per-hue exceptions.
|
||||
// M315 removed the twenty card fills the split was solving for, and this is the payoff:
|
||||
// against ONE card surface both jobs can take the same value. `-800`/`-300` is the one
|
||||
// they take, and the direction is deliberate — the inline token is the common case
|
||||
// (since M311 a tag whose text is in the body is drawn where it was typed and NOT
|
||||
// repeated as a chip), so collapsing onto the inline column leaves what is seen most
|
||||
// exactly as it was, and moves only the chip. The chip is strictly better for it:
|
||||
//
|
||||
// THE CONSTRAINT IS GONE as of M315: there is one card fill per theme now
|
||||
// (NOTE_CARD_SURFACE), so this table is solving for two backgrounds instead of twenty.
|
||||
// Left at these values here deliberately — they still clear 4.5 on white and on
|
||||
// `neutral-900`, so nothing is broken, and re-measuring the tag ink against one known
|
||||
// background (including whether the chip and inline tables can now collapse into one)
|
||||
// is its own step: #3149.
|
||||
// inline, on the card as a chip, on its own fill
|
||||
// light `-800` 7.09 - 15.13 6.37 - 12.01 (was 4.52 - 8.23)
|
||||
// dark `-300` 9.45 - 14.23 8.23 - 11.88 (unchanged)
|
||||
//
|
||||
// Dark needed no decision at all: the two tables were already the same value for all
|
||||
// ten hues, which is on its own most of the argument that one table was always enough.
|
||||
//
|
||||
// Mirrored in NoteTint.kt as `lightTagInk` / `darkTagInk`.
|
||||
export const TAG_TEXT_CLASSES: Record<NoteColor, string> = {
|
||||
@@ -100,20 +121,21 @@ export function tagTextClasses(name: string, picked?: Record<string, string>): s
|
||||
return TAG_TEXT_CLASSES[resolveLabelColor({ name, color: picked?.[name.toLowerCase()] })];
|
||||
}
|
||||
|
||||
// Solid fills for graph nodes (SVG needs concrete colors, not Tailwind bg classes).
|
||||
// Mid-tone hues read on both the light and dark graph background.
|
||||
export const NOTE_NODE_FILL: Record<NoteColor, string> = {
|
||||
default: "#9ca3af",
|
||||
red: "#ef4444",
|
||||
orange: "#f97316",
|
||||
yellow: "#f59e0b",
|
||||
green: "#22c55e",
|
||||
teal: "#14b8a6",
|
||||
blue: "#3b82f6",
|
||||
purple: "#a855f7",
|
||||
pink: "#ec4899",
|
||||
gray: "#6b7280",
|
||||
};
|
||||
/**
|
||||
* The whole class list for a label CHIP: the shell and the ink, composed.
|
||||
*
|
||||
* One function rather than the composition written out at each call site, because the
|
||||
* board's chip and the editor's chip have to be the same pill — the same tag changing
|
||||
* colour on opening a note would be worse than both being grey. That was a comment
|
||||
* asking two files to stay in step; it is one call now.
|
||||
*
|
||||
* Takes the LABEL, not its colour: a tag nobody has coloured derives one from its name,
|
||||
* so chips carry the tag's identity rather than all being the same grey.
|
||||
*/
|
||||
export function labelChipClasses(label: { name: string; color?: string | null }): string {
|
||||
const color = resolveLabelColor(label);
|
||||
return `${LABEL_CHIP_SHELL[color]} ${TAG_TEXT_CLASSES[color]}`;
|
||||
}
|
||||
|
||||
export const NOTE_COLOR_LABELS: Record<NoteColor, string> = {
|
||||
default: "Default",
|
||||
|
||||
Reference in New Issue
Block a user