The border was the thing making every note look the same
CI & Build / Build now, or wait for Android? (push) Successful in 3s
CI & Build / Python lint (push) Successful in 4s
CI & Build / TypeScript typecheck (push) Successful in 9s
CI & Build / Python tests (push) Successful in 14s
CI & Build / integration (push) Successful in 18s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 3m8s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 5m23s
Desktop (Tauri) / Update manifest (push) Successful in 4s
Android / Kotlin + Rust (APK) (push) Successful in 8m4s
CI & Build / Build now, or wait for Android? (push) Successful in 3s
CI & Build / Python lint (push) Successful in 4s
CI & Build / TypeScript typecheck (push) Successful in 9s
CI & Build / Python tests (push) Successful in 14s
CI & Build / integration (push) Successful in 18s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 3m8s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 5m23s
Desktop (Tauri) / Update manifest (push) Successful in 4s
Android / Kotlin + Rust (APK) (push) Successful in 8m4s
A note card carried a 1px tint border. Measured against its own fill, that
line was a 1.56-2.09 contrast in dark mode while the fill managed only
1.03-1.05 against the board — so the loudest thing on every card was an
identical line in an identical place, and a field of them read as a grid of
outlined rectangles however different the colours inside were.
Removed from the note card on both surfaces. `border` survives for panels,
banners, the update card and the pickers: those are single elements, not a
field of them.
What replaces it differs by theme, because elevation does.
Light leans on a shadow. An untagged card is `bg-red-50` on a `neutral-50`
board — a 1.04 contrast that can only read as a card by sitting above one.
The web goes `shadow-sm` -> `shadow`; Android had no shadow at all and gets
2dp.
Dark cannot use one, black on near-black. So the subdued fills moved onto
the card surface instead: `{hue}-950` composited at 0.18 over #171717 and
baked, rather than the same hue at 0.25 over the near-black board. An
untagged card now sits where the plain white card always sat (1.11-1.14
against the board, against `bg-neutral-900`'s 1.10) while carrying LESS hue
than before — chroma 7-17 where the old ramp had 10-23.
Subtler and more visible at once, which is only a contradiction if subtlety
has to come from lightness. Here it comes from chroma, and lightness is left
to say "this is a card". Which also reframes the two weights: in dark they
now sit within a hair of each other (red: 1.11 vs 1.12) and differ threefold
in colour (chroma 10 vs 41).
The chosen ramp is untouched — the operator signed those colours off, and a
ramp somebody likes is not something to redo while fixing something else.
Light was already built this way: `-50` and `-100` are both white plus a
different amount of hue.
Body text still measures 14.3-16.4 against the 4.5 it needs, meta 6.9-7.1
against 3.0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontStyle
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
import androidx.compose.ui.text.style.TextDecoration
|
import androidx.compose.ui.text.style.TextDecoration
|
||||||
@@ -44,12 +45,23 @@ fun NoteCard(
|
|||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
// Elevation instead of an edge line. The card used to be framed by a
|
||||||
|
// 1px tint border, which measured a higher contrast against its own
|
||||||
|
// fill (1.56-2.09) than the fill managed against the board
|
||||||
|
// (1.03-1.05) — so the loudest thing on every card was the same line
|
||||||
|
// in the same place, and a board of them read as a grid of outlines
|
||||||
|
// however different the colours inside. See NoteTint.cardBackground.
|
||||||
|
//
|
||||||
|
// It matters most in LIGHT mode, where an untagged card is a 1.04
|
||||||
|
// contrast against the board and nothing but a shadow can lift it
|
||||||
|
// off. In dark the shadow is black on near-black and invisible, which
|
||||||
|
// is why the subdued fills were moved onto the card surface instead.
|
||||||
|
.shadow(CARD_ELEVATION, RoundedCornerShape(CARD_RADIUS))
|
||||||
// Clipped BEFORE clickable, so the ripple is bounded by the card's
|
// Clipped BEFORE clickable, so the ripple is bounded by the card's
|
||||||
// rounded corners instead of a rectangle overhanging them.
|
// rounded corners instead of a rectangle overhanging them.
|
||||||
.clip(RoundedCornerShape(CARD_RADIUS))
|
.clip(RoundedCornerShape(CARD_RADIUS))
|
||||||
.clickable(onClickLabel = stringResource(R.string.board_open_note), onClick = onOpen)
|
.clickable(onClickLabel = stringResource(R.string.board_open_note), onClick = onOpen)
|
||||||
.background(tint.cardBackground(dark, strong))
|
.background(tint.cardBackground(dark, strong))
|
||||||
.border(1.dp, tint.border(dark), RoundedCornerShape(CARD_RADIUS))
|
|
||||||
.padding(12.dp),
|
.padding(12.dp),
|
||||||
) {
|
) {
|
||||||
// Body then checklist, in order — a note can carry both (M13 step 2), and
|
// Body then checklist, in order — a note can carry both (M13 step 2), and
|
||||||
@@ -236,4 +248,10 @@ private const val MAX_PREVIEW_LINES = 8
|
|||||||
private const val MAX_WRAPPED_LINES = 2
|
private const val MAX_WRAPPED_LINES = 2
|
||||||
private const val MAX_LABEL_CHIPS = 3
|
private const val MAX_LABEL_CHIPS = 3
|
||||||
private val CARD_RADIUS = 12.dp
|
private val CARD_RADIUS = 12.dp
|
||||||
|
|
||||||
|
// Enough to lift a white card off a #fafafa board and no more. Material's own
|
||||||
|
// resting card elevation is 1dp; this is a shade above it because the board is a
|
||||||
|
// masonry field of cards rather than one card on a page, and at 1dp the whole field
|
||||||
|
// reads flat again — which is what the removed border was compensating for.
|
||||||
|
private val CARD_ELEVATION = 2.dp
|
||||||
private val CHIP_RADIUS = 6.dp
|
private val CHIP_RADIUS = 6.dp
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ import com.fabledsword.thoughtsync.core.Note
|
|||||||
* is amber on the desktop is the same amber on the phone rather than a near-miss.
|
* is amber on the desktop is the same amber on the phone rather than a near-miss.
|
||||||
* Generated from tailwindcss 3.4's palette rather than transcribed by eye.
|
* Generated from tailwindcss 3.4's palette rather than transcribed by eye.
|
||||||
*
|
*
|
||||||
* Dark tints keep the web's ALPHA (`dark:bg-red-950/40`) instead of a
|
* Most dark tints keep the web's ALPHA (`dark:bg-red-950/70`) instead of a
|
||||||
* precomputed blend — Compose composites a translucent colour over what's beneath
|
* precomputed blend — Compose composites a translucent colour over what's beneath
|
||||||
* exactly as CSS does, so the card sits on the background the same way in both.
|
* exactly as CSS does, so the card sits on the background the same way in both. The
|
||||||
|
* one exception is [NoteTint.darkCardSubdued], which is baked; see its own note.
|
||||||
*
|
*
|
||||||
* `yellow` maps to Tailwind's *amber*, matching colors.ts; plain yellow is too
|
* `yellow` maps to Tailwind's *amber*, matching colors.ts; plain yellow is too
|
||||||
* acid against the neutral surfaces.
|
* acid against the neutral surfaces.
|
||||||
@@ -31,6 +32,28 @@ data class NoteTint(
|
|||||||
val lightChipForeground: Color,
|
val lightChipForeground: Color,
|
||||||
val darkChipBackground: Color,
|
val darkChipBackground: Color,
|
||||||
val darkChipForeground: Color,
|
val darkChipForeground: Color,
|
||||||
|
/**
|
||||||
|
* The DARK subdued card fill, opaque, as a colour rather than an alpha.
|
||||||
|
*
|
||||||
|
* Every other dark value in this table is `{hue}-950` at an alpha, composited by
|
||||||
|
* whoever draws it over the near-black BOARD — which put an untagged card at the
|
||||||
|
* board's own lightness (a 1.03 contrast) and left the border doing all the work
|
||||||
|
* of saying "card". The border is gone (see [cardBackground]), so these are
|
||||||
|
* `{hue}-950` composited at 0.18 over the CARD SURFACE, #171717, and baked: the
|
||||||
|
* card now sits where the plain white card always sat, 1.11–1.14 against the
|
||||||
|
* board, while carrying LESS hue than the old ramp did — chroma 7–17 against
|
||||||
|
* 10–23.
|
||||||
|
*
|
||||||
|
* Opaque rather than another alpha because the backdrop is no longer the board
|
||||||
|
* alone: the editor draws the same fill on a sheet. A colour that means one thing
|
||||||
|
* on the board and another in the editor is the bug this whole milestone exists
|
||||||
|
* to stop.
|
||||||
|
*
|
||||||
|
* Baked rather than lerped at draw time: Compose's `lerp(Color, Color, Float)`
|
||||||
|
* interpolates in Oklab, CSS alpha-composites in sRGB, and the mirror in
|
||||||
|
* colors.ts is only worth having if both sides land on the same byte.
|
||||||
|
*/
|
||||||
|
val darkCardSubdued: Color,
|
||||||
/**
|
/**
|
||||||
* False only for `default`, which is the ABSENCE of a colour rather than one of
|
* False only for `default`, which is the ABSENCE of a colour rather than one of
|
||||||
* them. Everything else has two weights (see [cardBackground]); `default` has one,
|
* them. Everything else has two weights (see [cardBackground]); `default` has one,
|
||||||
@@ -42,21 +65,34 @@ data class NoteTint(
|
|||||||
fun background(dark: Boolean): Color = if (dark) darkBackground else lightBackground
|
fun background(dark: Boolean): Color = if (dark) darkBackground else lightBackground
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A NOTE card's fill, at one of two weights.
|
* A NOTE card's fill, at one of two weights, and the card's ONLY boundary.
|
||||||
*
|
*
|
||||||
* `strong` means the colour was CHOSEN — by a tag, or (until step 5) by the
|
* `strong` means the colour was CHOSEN — by a tag, or (until step 5) by the
|
||||||
* picker. Subdued means it was derived from the note's id purely so the board is
|
* picker. Subdued means it was derived from the note's id purely so the board is
|
||||||
* not a wall of white. Drawing those at the same weight is what prompted the
|
* not a wall of white. Drawing those at the same weight is what prompted the
|
||||||
* operator's "the tints look the same as the chosen colors".
|
* operator's "the tints look the same as the chosen colors".
|
||||||
*
|
*
|
||||||
* The two weights move in OPPOSITE directions per theme, because that is where
|
* THE CARD NO LONGER HAS A BORDER. It used to carry a 1px `{hue}-900` edge, and
|
||||||
* each has headroom. Light cannot go lighter than `-50` without being white again,
|
* measured against its own fill that line was a 1.56–2.09 contrast where the fill
|
||||||
* so the gap opens by deepening the chosen end to `-100` — which is exactly
|
* managed 1.03–1.05 against the board. The loudest thing on every card was an
|
||||||
* [lightChipBackground], already in this table, so no new hex is transcribed.
|
* identical line in an identical place, so a board of them read as a grid of
|
||||||
* Dark CAN go lighter, so the derived end drops to a quarter opacity: closer to
|
* outlined rectangles whatever colour was inside — the operator's "too samey even
|
||||||
* the board, which gives the light body text MORE contrast, not less.
|
* with the color differences". [border] survives for panels, banners and pickers,
|
||||||
|
* which are single elements rather than a field of them; a note card gets none.
|
||||||
*
|
*
|
||||||
* Borders are untouched. The fill is the signal; moving both muddies the edge.
|
* What replaces it differs by theme, because elevation does. Dark leans on
|
||||||
|
* [darkCardSubdued] sitting above the near-black board. Light leans on a real
|
||||||
|
* shadow (`NoteCard.kt`), since white-on-#fafafa is a 1.04 contrast and no fill
|
||||||
|
* is going to rescue it.
|
||||||
|
*
|
||||||
|
* WHAT SEPARATES THE TWO WEIGHTS IS CHROMA, NOT LIGHTNESS. In dark they now sit
|
||||||
|
* within a hair of each other (red: 1.11 against the board versus 1.12) and
|
||||||
|
* differ threefold in colour (chroma 10 versus 41). Lightness is what says "this
|
||||||
|
* is a card"; spending it on emphasis is what left untagged cards flat.
|
||||||
|
*
|
||||||
|
* Light was already built this way and is untouched: `-50` and `-100` are both
|
||||||
|
* white plus a different amount of hue, and `-100` is exactly
|
||||||
|
* [lightChipBackground], already in this table, so no new hex is transcribed.
|
||||||
*/
|
*/
|
||||||
fun cardBackground(
|
fun cardBackground(
|
||||||
dark: Boolean,
|
dark: Boolean,
|
||||||
@@ -64,7 +100,8 @@ data class NoteTint(
|
|||||||
): Color =
|
): Color =
|
||||||
when {
|
when {
|
||||||
!tintable -> background(dark)
|
!tintable -> background(dark)
|
||||||
dark -> darkBackground.copy(alpha = if (strong) STRONG_DARK_ALPHA else SUBDUED_DARK_ALPHA)
|
dark && strong -> darkBackground.copy(alpha = STRONG_DARK_ALPHA)
|
||||||
|
dark -> darkCardSubdued
|
||||||
strong -> lightChipBackground
|
strong -> lightChipBackground
|
||||||
else -> lightBackground
|
else -> lightBackground
|
||||||
}
|
}
|
||||||
@@ -103,10 +140,9 @@ data class NoteTint(
|
|||||||
// it does not carry the meaning. Raise to 0.80 if that judgment is ever overruled.
|
// it does not carry the meaning. Raise to 0.80 if that judgment is ever overruled.
|
||||||
private const val CHIP_EDGE_ALPHA = 0.60f
|
private const val CHIP_EDGE_ALPHA = 0.60f
|
||||||
|
|
||||||
// The two dark-theme weights, as fractions. Mirror `dark:bg-{hue}-950/25` and `/70`
|
// The chosen weight in dark, as a fraction. Mirrors `dark:bg-{hue}-950/70` in
|
||||||
// in colors.ts — these are the only two numbers that have to agree by hand, since the
|
// colors.ts. Its counterpart is no longer an alpha at all — the subdued weight is a
|
||||||
// light weights are both already columns of the table below.
|
// baked colour, [NoteTint.darkCardSubdued], for the reasons recorded there.
|
||||||
private const val SUBDUED_DARK_ALPHA = 0.25f
|
|
||||||
private const val STRONG_DARK_ALPHA = 0.70f
|
private const val STRONG_DARK_ALPHA = 0.70f
|
||||||
|
|
||||||
/** 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. */
|
||||||
@@ -123,6 +159,7 @@ val NOTE_TINTS: Map<String, NoteTint> =
|
|||||||
lightChipForeground = Color(0xFF525252),
|
lightChipForeground = Color(0xFF525252),
|
||||||
darkChipBackground = Color(0x1AFFFFFF),
|
darkChipBackground = Color(0x1AFFFFFF),
|
||||||
darkChipForeground = Color(0xFFD4D4D4),
|
darkChipForeground = Color(0xFFD4D4D4),
|
||||||
|
darkCardSubdued = Color(0xFF171717),
|
||||||
tintable = false,
|
tintable = false,
|
||||||
),
|
),
|
||||||
"red" to
|
"red" to
|
||||||
@@ -136,6 +173,7 @@ val NOTE_TINTS: Map<String, NoteTint> =
|
|||||||
lightChipForeground = Color(0xFFB91C1C),
|
lightChipForeground = Color(0xFFB91C1C),
|
||||||
darkChipBackground = Color(0x80450A0A),
|
darkChipBackground = Color(0x80450A0A),
|
||||||
darkChipForeground = Color(0xFFFCA5A5),
|
darkChipForeground = Color(0xFFFCA5A5),
|
||||||
|
darkCardSubdued = Color(0xFF1F1515),
|
||||||
),
|
),
|
||||||
"orange" to
|
"orange" to
|
||||||
NoteTint(
|
NoteTint(
|
||||||
@@ -148,6 +186,7 @@ val NOTE_TINTS: Map<String, NoteTint> =
|
|||||||
lightChipForeground = Color(0xFFC2410C),
|
lightChipForeground = Color(0xFFC2410C),
|
||||||
darkChipBackground = Color(0x80431407),
|
darkChipBackground = Color(0x80431407),
|
||||||
darkChipForeground = Color(0xFFFDBA74),
|
darkChipForeground = Color(0xFFFDBA74),
|
||||||
|
darkCardSubdued = Color(0xFF1F1614),
|
||||||
),
|
),
|
||||||
"yellow" to
|
"yellow" to
|
||||||
NoteTint(
|
NoteTint(
|
||||||
@@ -160,6 +199,7 @@ val NOTE_TINTS: Map<String, NoteTint> =
|
|||||||
lightChipForeground = Color(0xFF92400E),
|
lightChipForeground = Color(0xFF92400E),
|
||||||
darkChipBackground = Color(0x80451A03),
|
darkChipBackground = Color(0x80451A03),
|
||||||
darkChipForeground = Color(0xFFFCD34D),
|
darkChipForeground = Color(0xFFFCD34D),
|
||||||
|
darkCardSubdued = Color(0xFF1F1813),
|
||||||
),
|
),
|
||||||
"green" to
|
"green" to
|
||||||
NoteTint(
|
NoteTint(
|
||||||
@@ -172,6 +212,7 @@ val NOTE_TINTS: Map<String, NoteTint> =
|
|||||||
lightChipForeground = Color(0xFF15803D),
|
lightChipForeground = Color(0xFF15803D),
|
||||||
darkChipBackground = Color(0x80052E16),
|
darkChipBackground = Color(0x80052E16),
|
||||||
darkChipForeground = Color(0xFF86EFAC),
|
darkChipForeground = Color(0xFF86EFAC),
|
||||||
|
darkCardSubdued = Color(0xFF141B17),
|
||||||
),
|
),
|
||||||
"teal" to
|
"teal" to
|
||||||
NoteTint(
|
NoteTint(
|
||||||
@@ -184,6 +225,7 @@ val NOTE_TINTS: Map<String, NoteTint> =
|
|||||||
lightChipForeground = Color(0xFF0F766E),
|
lightChipForeground = Color(0xFF0F766E),
|
||||||
darkChipBackground = Color(0x80042F2E),
|
darkChipBackground = Color(0x80042F2E),
|
||||||
darkChipForeground = Color(0xFF5EEAD4),
|
darkChipForeground = Color(0xFF5EEAD4),
|
||||||
|
darkCardSubdued = Color(0xFF141B1B),
|
||||||
),
|
),
|
||||||
"blue" to
|
"blue" to
|
||||||
NoteTint(
|
NoteTint(
|
||||||
@@ -196,6 +238,7 @@ val NOTE_TINTS: Map<String, NoteTint> =
|
|||||||
lightChipForeground = Color(0xFF1D4ED8),
|
lightChipForeground = Color(0xFF1D4ED8),
|
||||||
darkChipBackground = Color(0x80172554),
|
darkChipBackground = Color(0x80172554),
|
||||||
darkChipForeground = Color(0xFF93C5FD),
|
darkChipForeground = Color(0xFF93C5FD),
|
||||||
|
darkCardSubdued = Color(0xFF171A22),
|
||||||
),
|
),
|
||||||
"purple" to
|
"purple" to
|
||||||
NoteTint(
|
NoteTint(
|
||||||
@@ -208,6 +251,7 @@ val NOTE_TINTS: Map<String, NoteTint> =
|
|||||||
lightChipForeground = Color(0xFF7E22CE),
|
lightChipForeground = Color(0xFF7E22CE),
|
||||||
darkChipBackground = Color(0x803B0764),
|
darkChipBackground = Color(0x803B0764),
|
||||||
darkChipForeground = Color(0xFFD8B4FE),
|
darkChipForeground = Color(0xFFD8B4FE),
|
||||||
|
darkCardSubdued = Color(0xFF1D1425),
|
||||||
),
|
),
|
||||||
"pink" to
|
"pink" to
|
||||||
NoteTint(
|
NoteTint(
|
||||||
@@ -220,6 +264,7 @@ val NOTE_TINTS: Map<String, NoteTint> =
|
|||||||
lightChipForeground = Color(0xFFBE185D),
|
lightChipForeground = Color(0xFFBE185D),
|
||||||
darkChipBackground = Color(0x80500724),
|
darkChipBackground = Color(0x80500724),
|
||||||
darkChipForeground = Color(0xFFF9A8D4),
|
darkChipForeground = Color(0xFFF9A8D4),
|
||||||
|
darkCardSubdued = Color(0xFF211419),
|
||||||
),
|
),
|
||||||
"gray" to
|
"gray" to
|
||||||
NoteTint(
|
NoteTint(
|
||||||
@@ -232,6 +277,7 @@ val NOTE_TINTS: Map<String, NoteTint> =
|
|||||||
lightChipForeground = Color(0xFF404040),
|
lightChipForeground = Color(0xFF404040),
|
||||||
darkChipBackground = Color(0xFF404040),
|
darkChipBackground = Color(0xFF404040),
|
||||||
darkChipForeground = Color(0xFFE5E5E5),
|
darkChipForeground = Color(0xFFE5E5E5),
|
||||||
|
darkCardSubdued = Color(0xFF1A1A1A),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ onBeforeUnmount(() => document.removeEventListener("mousedown", onDocMousedown))
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
ref="root"
|
ref="root"
|
||||||
class="group relative mb-4 break-inside-avoid rounded-xl border p-3 shadow-sm transition hover:shadow-md"
|
class="group relative mb-4 break-inside-avoid rounded-xl p-3 shadow transition hover:shadow-md"
|
||||||
:class="[
|
:class="[
|
||||||
noteCardClasses(note),
|
noteCardClasses(note),
|
||||||
dragging ? 'opacity-40' : '',
|
dragging ? 'opacity-40' : '',
|
||||||
@@ -233,6 +233,14 @@ onBeforeUnmount(() => document.removeEventListener("mousedown", onDocMousedown))
|
|||||||
]"
|
]"
|
||||||
:data-note-id="note.id"
|
:data-note-id="note.id"
|
||||||
>
|
>
|
||||||
|
<!-- No `border`. The hue border that used to frame every card outshouted the fill
|
||||||
|
it framed and turned the board into a grid of identical outlines — see the
|
||||||
|
measurements above NOTE_CARD_CLASSES. `shadow` rather than `shadow-sm` because
|
||||||
|
it is now the ONLY thing separating a light-mode card from the board: an
|
||||||
|
untagged card is `bg-red-50` on `bg-neutral-50`, a 1.05 contrast that reads as
|
||||||
|
a card purely by sitting above one. Dark mode gets no shadow worth the name
|
||||||
|
against a near-black board, which is why the subdued fills moved onto the card
|
||||||
|
surface instead. -->
|
||||||
<img
|
<img
|
||||||
v-if="firstImage"
|
v-if="firstImage"
|
||||||
:src="firstImage.url"
|
:src="firstImage.url"
|
||||||
|
|||||||
@@ -17,17 +17,43 @@ export const NOTE_COLOR_KEYS = [
|
|||||||
|
|
||||||
export type NoteColor = (typeof NOTE_COLOR_KEYS)[number];
|
export type NoteColor = (typeof NOTE_COLOR_KEYS)[number];
|
||||||
|
|
||||||
|
// The SUBDUED ramp — what a note wears when nothing chose a colour for it.
|
||||||
|
//
|
||||||
|
// NO BORDER, here or in the strong ramp below. A note card used to carry a 1px
|
||||||
|
// `border-{hue}-900`, and measured against its own fill that line was a 1.56–2.09
|
||||||
|
// contrast while the fill managed only 1.03–1.05 against the board. The loudest
|
||||||
|
// thing on every card was therefore an identical line in an identical place, and a
|
||||||
|
// board of them read as a grid of outlined rectangles no matter what colour was
|
||||||
|
// inside — "too samey even with the color differences". The card's boundary now
|
||||||
|
// comes from its fill in dark mode and from `shadow` in light (NoteCard.vue), both
|
||||||
|
// of which vary with the card instead of framing it.
|
||||||
|
//
|
||||||
|
// The dark values are COMPOSITED HEX rather than a Tailwind step, and that is the
|
||||||
|
// whole idea. `dark:bg-red-950/25` laid a hue over the near-black BOARD, which put
|
||||||
|
// the card at the board's own lightness (1.03) — invisible without the border it
|
||||||
|
// has just lost. These lay the same hue over the CARD SURFACE (`neutral-900`,
|
||||||
|
// #171717) at 18%, so an untagged card sits exactly where the default white card
|
||||||
|
// always sat (1.11–1.14 vs the board, against `bg-neutral-900`'s 1.10) while
|
||||||
|
// carrying LESS colour than before: chroma 7–17 where the old ramp had 10–23.
|
||||||
|
//
|
||||||
|
// Subtler and more visible at once, which is only a contradiction if you assume
|
||||||
|
// subtlety has to come from lightness. Here it comes from chroma, and lightness is
|
||||||
|
// left to say "this is a card".
|
||||||
|
//
|
||||||
|
// Recipe, so these can be regenerated rather than guessed at: sRGB alpha
|
||||||
|
// compositing of `{hue}-950` at 0.18 over #171717 — `round(fg*0.18 + 23*0.82)` per
|
||||||
|
// channel. `gray` uses `neutral-800` as its 950, matching the strong ramp.
|
||||||
export const NOTE_CARD_CLASSES: Record<NoteColor, string> = {
|
export const NOTE_CARD_CLASSES: Record<NoteColor, string> = {
|
||||||
default: "bg-white border-neutral-200 dark:bg-neutral-900 dark:border-neutral-700",
|
default: "bg-white dark:bg-neutral-900",
|
||||||
red: "bg-red-50 border-red-200 dark:bg-red-950/25 dark:border-red-900",
|
red: "bg-red-50 dark:bg-[#1f1515]",
|
||||||
orange: "bg-orange-50 border-orange-200 dark:bg-orange-950/25 dark:border-orange-900",
|
orange: "bg-orange-50 dark:bg-[#1f1614]",
|
||||||
yellow: "bg-amber-50 border-amber-200 dark:bg-amber-950/25 dark:border-amber-900",
|
yellow: "bg-amber-50 dark:bg-[#1f1813]",
|
||||||
green: "bg-green-50 border-green-200 dark:bg-green-950/25 dark:border-green-900",
|
green: "bg-green-50 dark:bg-[#141b17]",
|
||||||
teal: "bg-teal-50 border-teal-200 dark:bg-teal-950/25 dark:border-teal-900",
|
teal: "bg-teal-50 dark:bg-[#141b1b]",
|
||||||
blue: "bg-blue-50 border-blue-200 dark:bg-blue-950/25 dark:border-blue-900",
|
blue: "bg-blue-50 dark:bg-[#171a22]",
|
||||||
purple: "bg-purple-50 border-purple-200 dark:bg-purple-950/25 dark:border-purple-900",
|
purple: "bg-purple-50 dark:bg-[#1d1425]",
|
||||||
pink: "bg-pink-50 border-pink-200 dark:bg-pink-950/25 dark:border-pink-900",
|
pink: "bg-pink-50 dark:bg-[#211419]",
|
||||||
gray: "bg-neutral-100 border-neutral-300 dark:bg-neutral-800/25 dark:border-neutral-700",
|
gray: "bg-neutral-100 dark:bg-[#1a1a1a]",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NOTE_SWATCH_CLASSES: Record<NoteColor, string> = {
|
export const NOTE_SWATCH_CLASSES: Record<NoteColor, string> = {
|
||||||
@@ -204,24 +230,30 @@ export function resolveLabelColor(label: { name: string; color?: string | null }
|
|||||||
// (until step 5) by the picker. One Tailwind step deeper in light mode, and a much
|
// (until step 5) by the picker. One Tailwind step deeper in light mode, and a much
|
||||||
// heavier fill in dark.
|
// heavier fill in dark.
|
||||||
//
|
//
|
||||||
// The two ramps move in opposite directions per theme, because that is where each has
|
// UNCHANGED by the border pass, deliberately. The operator's complaint was the edge
|
||||||
// headroom. Light mode cannot go lighter than `-50` without being white again, so the
|
// line and the loudness of the DERIVED tint; the chosen colours were "pretty well"
|
||||||
// gap is opened by deepening the tagged end to `-100`. Dark mode CAN go lighter, so
|
// where they landed, and a ramp somebody has already signed off on is not something
|
||||||
// the untagged end drops to `/25` — closer to the board, which also gives the light
|
// to redo while fixing something else.
|
||||||
// body text MORE contrast rather than less.
|
|
||||||
//
|
//
|
||||||
// Borders stay put. The fill is the signal; moving both just muddies the edge.
|
// WHAT SEPARATES THE TWO RAMPS IS NOW CHROMA, NOT LIGHTNESS. Since the subdued ramp
|
||||||
|
// moved onto the card surface, the two sit at almost the same lightness in dark mode
|
||||||
|
// (red: 1.11 vs 1.12 against the board) and differ threefold in colour (chroma 10 vs
|
||||||
|
// 41). That is the better axis anyway: lightness is what says "this is a card", and
|
||||||
|
// spending it on emphasis is what left untagged cards flat against the board.
|
||||||
|
//
|
||||||
|
// Light mode was already built this way and needed no change — `-50` and `-100` are
|
||||||
|
// both essentially white plus a different amount of hue.
|
||||||
export const NOTE_CARD_CLASSES_STRONG: Record<NoteColor, string> = {
|
export const NOTE_CARD_CLASSES_STRONG: Record<NoteColor, string> = {
|
||||||
default: "bg-white border-neutral-200 dark:bg-neutral-900 dark:border-neutral-700",
|
default: "bg-white dark:bg-neutral-900",
|
||||||
red: "bg-red-100 border-red-200 dark:bg-red-950/70 dark:border-red-900",
|
red: "bg-red-100 dark:bg-red-950/70",
|
||||||
orange: "bg-orange-100 border-orange-200 dark:bg-orange-950/70 dark:border-orange-900",
|
orange: "bg-orange-100 dark:bg-orange-950/70",
|
||||||
yellow: "bg-amber-100 border-amber-200 dark:bg-amber-950/70 dark:border-amber-900",
|
yellow: "bg-amber-100 dark:bg-amber-950/70",
|
||||||
green: "bg-green-100 border-green-200 dark:bg-green-950/70 dark:border-green-900",
|
green: "bg-green-100 dark:bg-green-950/70",
|
||||||
teal: "bg-teal-100 border-teal-200 dark:bg-teal-950/70 dark:border-teal-900",
|
teal: "bg-teal-100 dark:bg-teal-950/70",
|
||||||
blue: "bg-blue-100 border-blue-200 dark:bg-blue-950/70 dark:border-blue-900",
|
blue: "bg-blue-100 dark:bg-blue-950/70",
|
||||||
purple: "bg-purple-100 border-purple-200 dark:bg-purple-950/70 dark:border-purple-900",
|
purple: "bg-purple-100 dark:bg-purple-950/70",
|
||||||
pink: "bg-pink-100 border-pink-200 dark:bg-pink-950/70 dark:border-pink-900",
|
pink: "bg-pink-100 dark:bg-pink-950/70",
|
||||||
gray: "bg-neutral-200 border-neutral-300 dark:bg-neutral-800/70 dark:border-neutral-700",
|
gray: "bg-neutral-200 dark:bg-neutral-800/70",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user