Three stops — purple into blue into black — matches ios!144
#3A1E9E purple, #0B3080 blue, #070A1A black, top down. Less purple than the two-stop version, because the purple is a third of the sweep rather than half. 🔴 One card colour against three stops has to lift off all three. #0E1745 looked right against the purple and the blue and measured 1.15:1 against the black end — a card that disappears at the bottom of a long screen. #141C52 lifts 1.41 / 1.33 / 1.23. The palette test checks the middle stop too. A three-stop gradient checked only at its ends is two thirds measured, and the middle is where most of a screen actually sits. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
15e678d593
commit
b824e626e7
@@ -79,11 +79,12 @@ object Palette {
|
||||
// the top and 8.4:1 at the bottom, secondary text 8.1:1 and 5.5:1 — the
|
||||
// bottom stop binds, and it is where most of the explanatory copy sits.
|
||||
// White cards lift off the bottom at 2.4:1, which keeps a card a card.
|
||||
val GroundTop = Color(0xFF3A0CA3)
|
||||
val GroundBottom = Color(0xFF062C8C)
|
||||
val GroundTop = Color(0xFF3A1E9E) // purple
|
||||
val GroundMid = Color(0xFF0B3080) // blue
|
||||
val GroundBottom = Color(0xFF070A1A) // black
|
||||
// Kept as the same two colours: there is one theme now.
|
||||
val NightGroundTop = Color(0xFF3A0CA3)
|
||||
val NightGroundBottom = Color(0xFF062C8C)
|
||||
val NightGroundTop = Color(0xFF3A1E9E)
|
||||
val NightGroundBottom = Color(0xFF070A1A)
|
||||
|
||||
val Teal = Color(0xFF4BE3C0) // success and presence
|
||||
val Pink = Color(0xFFFF819F) // the kit's alert accent
|
||||
@@ -93,13 +94,13 @@ object Palette {
|
||||
// ⚠️ Still needed where a gradient cannot go (a single Color parameter, a
|
||||
// system bar tint). This is the gradient's mid-tone, so the two never read
|
||||
// as different surfaces.
|
||||
val Mist = Color(0xFF201C98) // the page ground, flat
|
||||
val SurfaceAlt = Color(0xFF2A1875) // received bubbles, pills, bands
|
||||
val IncomingBubble = Color(0xFF2A1875)
|
||||
val Mist = Color(0xFF191D68) // the page ground, flat
|
||||
val SurfaceAlt = Color(0xFF1E2A70) // received bubbles, pills, bands
|
||||
val IncomingBubble = Color(0xFF1E2A70)
|
||||
// ⚠️ A blue-tinted grey rather than the flat #F3F3F3: an initials avatar
|
||||
// needs to read as a circle against the surface behind it, and two greys a
|
||||
// shade apart do not.
|
||||
val AvatarFill = Color(0xFF31207F)
|
||||
val AvatarFill = Color(0xFF243480)
|
||||
// 🔴 **Darkened with the ground, not left behind it.** #505C69 read 5.0:1
|
||||
// on the old bottom stop and only 3.5:1 on the darker one — below AA, and
|
||||
// most of the explanatory copy on these screens is set in it. Measured now:
|
||||
@@ -126,8 +127,12 @@ object Palette {
|
||||
// card lighter than a saturated violet has to be lighter still than that,
|
||||
// which puts secondary text below AA on it. Recessed panels invert the
|
||||
// problem: the gradient is the bright thing, content sits in dark wells.
|
||||
val InkSurface = Color(0xFF190B4E) // --panel
|
||||
val NightGround = Color(0xFF201C98) // --bg, the gradient's mid-tone
|
||||
// 🔴 One card colour against a THREE-stop ground, so it must lift off all
|
||||
// three. #0E1745 looked right against the purple and the blue and measured
|
||||
// 1.15:1 against the black end — a card that disappears at the bottom of a
|
||||
// long screen. This lifts 1.41 / 1.33 / 1.23.
|
||||
val InkSurface = Color(0xFF141C52) // --panel
|
||||
val NightGround = Color(0xFF191D68) // --bg, the gradient's mid-tone
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,7 +147,8 @@ fun groundBrush(): Brush =
|
||||
// One theme, so no branch. The Night* pair is kept pointing at the same two
|
||||
// colours rather than deleted, because several screens name it directly and
|
||||
// a rename across both apps is a separate change.
|
||||
Brush.verticalGradient(listOf(Palette.GroundTop, Palette.GroundBottom))
|
||||
Brush.verticalGradient(
|
||||
listOf(Palette.GroundTop, Palette.GroundMid, Palette.GroundBottom))
|
||||
|
||||
/** The primary action's fill. Matches `Theme.primaryGradient*` on iOS. */
|
||||
fun accentBrush(): Brush =
|
||||
|
||||
@@ -88,8 +88,11 @@ class PaletteMatchesIOSTest {
|
||||
@Test
|
||||
fun `text clears AA on every surface it is read on`() {
|
||||
val surfaces = listOf(
|
||||
"ground top" to Palette.GroundTop,
|
||||
"ground bottom" to Palette.GroundBottom,
|
||||
"ground top (purple)" to Palette.GroundTop,
|
||||
// ⚠️ The middle stop is a surface too. A three-stop gradient
|
||||
// checked only at its ends is two thirds measured.
|
||||
"ground middle (blue)" to Palette.GroundMid,
|
||||
"ground bottom (black)" to Palette.GroundBottom,
|
||||
"card" to Palette.InkSurface,
|
||||
"field and incoming bubble" to Palette.SurfaceAlt,
|
||||
"avatar" to Palette.AvatarFill,
|
||||
@@ -111,8 +114,15 @@ class PaletteMatchesIOSTest {
|
||||
*/
|
||||
@Test
|
||||
fun `cards and fields lift off what is behind them`() {
|
||||
val cardLift = contrast(Palette.InkSurface, Palette.GroundBottom)
|
||||
assertTrue(cardLift >= 1.15, "a card lifts off the ground by only %.2f:1".format(cardLift))
|
||||
// 🔴 Against ALL THREE stops. One card colour has to survive the whole
|
||||
// sweep, and the black end is the one it fails on.
|
||||
for ((name, stop) in listOf("purple" to Palette.GroundTop,
|
||||
"blue" to Palette.GroundMid,
|
||||
"black" to Palette.GroundBottom)) {
|
||||
val lift = contrast(Palette.InkSurface, stop)
|
||||
assertTrue(lift >= 1.15,
|
||||
"a card lifts off the $name end of the ground by only %.2f:1".format(lift))
|
||||
}
|
||||
val fieldLift = contrast(Palette.SurfaceAlt, Palette.InkSurface)
|
||||
assertTrue(fieldLift >= 1.15, "a field lifts off its card by only %.2f:1".format(fieldLift))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user