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.
|
// "from tag" hint beside one is what says why it has no cross.
|
||||||
text = "#${label.name}",
|
text = "#${label.name}",
|
||||||
style = MaterialTheme.typography.labelLarge,
|
style = MaterialTheme.typography.labelLarge,
|
||||||
color = tint.chipForeground(dark),
|
color = tint.tagInk(dark),
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ private fun LabelChips(labels: List<NoteLabel>) {
|
|||||||
// also keeps a lifted chip reading as the `#todo` somebody wrote.
|
// also keeps a lifted chip reading as the `#todo` somebody wrote.
|
||||||
text = "#${label.name}",
|
text = "#${label.name}",
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = MaterialTheme.typography.labelSmall,
|
||||||
color = tint.chipForeground(dark),
|
color = tint.tagInk(dark),
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
modifier =
|
modifier =
|
||||||
|
|||||||
@@ -33,24 +33,33 @@ data class NoteTint(
|
|||||||
val darkBackground: Color,
|
val darkBackground: Color,
|
||||||
val darkBorder: Color,
|
val darkBorder: Color,
|
||||||
val lightChipBackground: Color,
|
val lightChipBackground: Color,
|
||||||
val lightChipForeground: Color,
|
|
||||||
val darkChipBackground: 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,
|
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
|
* These were two columns until M315, and the split was real while it lasted: a chip
|
||||||
* difference is not cosmetic. A chip brings its own `-100` fill, so its text only
|
* brought its own `-100` fill and could afford `-700`, while inline text sat on
|
||||||
* ever has to read against that one colour. Inline text sits on whatever the card
|
* whatever the card was, which included a gray-tagged card at `neutral-200` where
|
||||||
* happens to be, which includes the gray-tagged card at `neutral-200` — and there
|
* `-700` measured 3.98 (green), 4.11 (orange) and 4.34 (teal), all under the 4.5
|
||||||
* the chip's `-700` measured 3.98 (green), 4.11 (orange) and 4.34 (teal), all
|
* body text needs. One step deeper cleared every fill at once.
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
* THE CONSTRAINT IS GONE as of M315 — one card fill per theme means this is solving
|
* The twenty card fills that split was solving for are gone, so both jobs take this
|
||||||
* for two backgrounds instead of twenty. Left here unchanged because it still
|
* one value. The direction is deliberate: since M311 a tag whose text is in the body
|
||||||
* clears 4.5 on both; re-measuring against one known background is #3149.
|
* 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 lightTagInk: Color,
|
||||||
val darkTagInk: Color,
|
val darkTagInk: Color,
|
||||||
@@ -66,10 +75,19 @@ data class NoteTint(
|
|||||||
|
|
||||||
fun chipBackground(dark: Boolean): Color = if (dark) darkChipBackground else lightChipBackground
|
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
|
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
|
* 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
|
* 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
|
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
|
* THE EDGE IS THE PILL. Against the one card surface a chip's fill measures
|
||||||
* behind it. A tagged note takes its FIRST tag's colour, and that card is drawn
|
* 1.02-1.26 in light and 1.02-1.73 in dark — very nearly nothing, and dark red at
|
||||||
* at exactly [lightChipBackground] — the same value the chip uses — so in light
|
* 1.02 is literally invisible. Without this the tag name would read as loose text.
|
||||||
* mode the pill was measured at a contrast ratio of 1.00 against the card it had
|
* The fill only tints a shape the edge is drawing.
|
||||||
* itself coloured. Perfectly invisible: the tag name read as loose text.
|
|
||||||
*
|
*
|
||||||
* An edge rather than shifting the fill, because the fill can collide with any
|
* An edge rather than a heavier fill, because a fill loud enough to hold its own
|
||||||
* card colour and chasing that needs the chip to know what it is sitting on. A
|
* shape would be the loudest thing on a board whose whole point is now that the tag
|
||||||
* border in the chip's own foreground always reads, against any background, and
|
* is the one coloured thing on it.
|
||||||
* needs no plumbing.
|
|
||||||
*/
|
*/
|
||||||
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
|
// SOLVED FOR, NOT GUESSED — and re-solved once the answer became solvable. 0.60 was
|
||||||
// colour — this is a 2.32:1 boundary, where 0.30 gave only 1.49:1 and was effectively
|
// picked against the worst case of the time: a chip on a card of its OWN colour, back
|
||||||
// no edge at all. It does NOT reach the 3:1 of WCAG 1.4.11, which needs 0.80 and
|
// when a note took its first tag's fill. It gave 2.32:1 there, missed the 3:1 of WCAG
|
||||||
// draws a hard outline rather than a hairline. 1.4.11 governs boundaries that carry
|
// 1.4.11, and the comment here reasoned its way out of that on the grounds that a
|
||||||
// REQUIRED information, and a chip's information is its text — which passes AA at
|
// chip's information is its text.
|
||||||
// 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.
|
// M315 removed that worst case. The edge is now the ink at alpha over a KNOWN fill, so
|
||||||
private const val CHIP_EDGE_ALPHA = 0.60f
|
// 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. */
|
/** Keyed by the core's colour vocabulary. Order matches the web's picker. */
|
||||||
val NOTE_TINTS: Map<String, NoteTint> =
|
val NOTE_TINTS: Map<String, NoteTint> =
|
||||||
|
|||||||
@@ -2,12 +2,11 @@
|
|||||||
import { computed, onBeforeUnmount, ref, watch } from "vue";
|
import { computed, onBeforeUnmount, ref, watch } from "vue";
|
||||||
import { useNotesStore } from "../stores/notes";
|
import { useNotesStore } from "../stores/notes";
|
||||||
import {
|
import {
|
||||||
LABEL_CHIP_CLASSES,
|
|
||||||
NOTE_CARD_SURFACE,
|
NOTE_CARD_SURFACE,
|
||||||
NOTE_COLOR_KEYS,
|
NOTE_COLOR_KEYS,
|
||||||
NOTE_COLOR_LABELS,
|
NOTE_COLOR_LABELS,
|
||||||
NOTE_SWATCH_CLASSES,
|
NOTE_SWATCH_CLASSES,
|
||||||
resolveLabelColor,
|
labelChipClasses,
|
||||||
type NoteColor,
|
type NoteColor,
|
||||||
} from "../notes/colors";
|
} from "../notes/colors";
|
||||||
import type { Note } from "../stores/notes";
|
import type { Note } from "../stores/notes";
|
||||||
@@ -190,12 +189,6 @@ async function snoozeReminder(minutes: number): Promise<void> {
|
|||||||
emit("reminder-changed");
|
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
|
// 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 —
|
// 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
|
// 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"
|
v-for="lb in chipLabels"
|
||||||
:key="lb.id"
|
:key="lb.id"
|
||||||
class="rounded-full px-2 py-0.5 text-xs"
|
class="rounded-full px-2 py-0.5 text-xs"
|
||||||
:class="labelChip(lb)"
|
:class="labelChipClasses(lb)"
|
||||||
>#{{ lb.name }}</span
|
>#{{ lb.name }}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { fromLocalInput, toLocalInput } from "../notes/datetime";
|
|||||||
import { takeMorphOrigin } from "../composables/useEditorMorph";
|
import { takeMorphOrigin } from "../composables/useEditorMorph";
|
||||||
import { prefersReducedMotion } from "../composables/useReducedMotion";
|
import { prefersReducedMotion } from "../composables/useReducedMotion";
|
||||||
import type { Note, NoteLabel, NoteRevision } from "../stores/notes";
|
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 {
|
import {
|
||||||
afterEnter,
|
afterEnter,
|
||||||
type EditorBlock,
|
type EditorBlock,
|
||||||
@@ -376,13 +376,6 @@ async function onLabelsChange(next: NoteLabel[]) {
|
|||||||
async function removeLabel(id: string) {
|
async function removeLabel(id: string) {
|
||||||
await onLabelsChange(labelList.value.filter((lb) => lb.id !== id));
|
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 ----
|
// ---- add a checklist ----
|
||||||
//
|
//
|
||||||
// Appends an empty item and puts the caret in it. Unlike every other toolbar button
|
// 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"
|
v-for="lb in labelList"
|
||||||
:key="lb.id"
|
:key="lb.id"
|
||||||
class="inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs"
|
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
|
<!-- `#` 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
|
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",
|
gray: "bg-neutral-400 dark:bg-neutral-500",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Label chip tints (bg + readable text + a hairline edge), keyed by the same color
|
// A chip's SHELL: its fill and its hairline edge, keyed by the colour vocabulary. The
|
||||||
// vocabulary.
|
// 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
|
// THE RING IS NOT DECORATION. A chip's fill measures 1.02-1.26 against the card in
|
||||||
// at that hue's `-100` — exactly what the chip uses as its fill — so in light mode the
|
// light and 1.02-1.73 in dark — that is to say, very nearly nothing. The pill's shape
|
||||||
// chip measured a contrast ratio of 1.00 against the card it had itself coloured.
|
// is the edge; the fill only tints it. (Dark red is the extreme at 1.02, which is
|
||||||
// Perfectly invisible; the tag name read as loose text. An edge holds the pill's shape
|
// 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
|
// against any background, where shifting the fill only moves which card it collides
|
||||||
// with.
|
// 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",
|
// AT 65%, NOT 60%, AND SOLVED FOR RATHER THAN GUESSED. 0.60 was chosen against a worst
|
||||||
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",
|
// case that no longer exists — a chip sitting on a card of its own colour, back when a
|
||||||
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",
|
// note took its first tag's fill. Against the one card surface (M315) the ring is the
|
||||||
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",
|
// ink at alpha over a known fill, so the alpha that clears the 3:1 of WCAG 1.4.11 for
|
||||||
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",
|
// all ten hues can simply be solved: 0.60 gives 2.75-3.82 in light and misses for six
|
||||||
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",
|
// of them, 0.65 gives 3.03-4.36 and misses for none. Dark is 4.52-5.76. 0.80 was the
|
||||||
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",
|
// number the old comment named as the fallback and it is more than is needed — it
|
||||||
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",
|
// draws a hard outline where a hairline does the job.
|
||||||
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",
|
// `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
|
// M315 removed the twenty card fills the split was solving for, and this is the payoff:
|
||||||
// `-100` fill, so its text has exactly one background to read against; inline text
|
// against ONE card surface both jobs can take the same value. `-800`/`-300` is the one
|
||||||
// sits on whatever the CARD is. When the card could be any of twenty fills that was a
|
// they take, and the direction is deliberate — the inline token is the common case
|
||||||
// hard constraint — on a gray-tagged card at `neutral-200` the chip's `-700` measured
|
// (since M311 a tag whose text is in the body is drawn where it was typed and NOT
|
||||||
// 3.98 (green), 4.11 (orange) and 4.34 (teal), all under the 4.5 body text needs,
|
// repeated as a chip), so collapsing onto the inline column leaves what is seen most
|
||||||
// where `-800` put every hue between 5.63 and 12.01 in light and `-300` gave 7.20 to
|
// exactly as it was, and moves only the chip. The chip is strictly better for it:
|
||||||
// 10.84 in dark, across every fill. One step for all ten beat three per-hue exceptions.
|
|
||||||
//
|
//
|
||||||
// THE CONSTRAINT IS GONE as of M315: there is one card fill per theme now
|
// inline, on the card as a chip, on its own fill
|
||||||
// (NOTE_CARD_SURFACE), so this table is solving for two backgrounds instead of twenty.
|
// light `-800` 7.09 - 15.13 6.37 - 12.01 (was 4.52 - 8.23)
|
||||||
// Left at these values here deliberately — they still clear 4.5 on white and on
|
// dark `-300` 9.45 - 14.23 8.23 - 11.88 (unchanged)
|
||||||
// `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)
|
// Dark needed no decision at all: the two tables were already the same value for all
|
||||||
// is its own step: #3149.
|
// ten hues, which is on its own most of the argument that one table was always enough.
|
||||||
//
|
//
|
||||||
// Mirrored in NoteTint.kt as `lightTagInk` / `darkTagInk`.
|
// Mirrored in NoteTint.kt as `lightTagInk` / `darkTagInk`.
|
||||||
export const TAG_TEXT_CLASSES: Record<NoteColor, string> = {
|
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()] })];
|
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.
|
* The whole class list for a label CHIP: the shell and the ink, composed.
|
||||||
export const NOTE_NODE_FILL: Record<NoteColor, string> = {
|
*
|
||||||
default: "#9ca3af",
|
* One function rather than the composition written out at each call site, because the
|
||||||
red: "#ef4444",
|
* board's chip and the editor's chip have to be the same pill — the same tag changing
|
||||||
orange: "#f97316",
|
* colour on opening a note would be worse than both being grey. That was a comment
|
||||||
yellow: "#f59e0b",
|
* asking two files to stay in step; it is one call now.
|
||||||
green: "#22c55e",
|
*
|
||||||
teal: "#14b8a6",
|
* Takes the LABEL, not its colour: a tag nobody has coloured derives one from its name,
|
||||||
blue: "#3b82f6",
|
* so chips carry the tag's identity rather than all being the same grey.
|
||||||
purple: "#a855f7",
|
*/
|
||||||
pink: "#ec4899",
|
export function labelChipClasses(label: { name: string; color?: string | null }): string {
|
||||||
gray: "#6b7280",
|
const color = resolveLabelColor(label);
|
||||||
};
|
return `${LABEL_CHIP_SHELL[color]} ${TAG_TEXT_CLASSES[color]}`;
|
||||||
|
}
|
||||||
|
|
||||||
export const NOTE_COLOR_LABELS: Record<NoteColor, string> = {
|
export const NOTE_COLOR_LABELS: Record<NoteColor, string> = {
|
||||||
default: "Default",
|
default: "Default",
|
||||||
|
|||||||
Reference in New Issue
Block a user