feat: merge red and orange prose palettes into vermilion orange
This commit is contained in:
1 parent
be93432e78
commit
eb618af80a
7 files changed
+36
-33
No files matched your search
@@ -1022,8 +1022,7 @@ export const enUS = {
|
||||
editorBodyPaletteTitle: "Text colors",
|
||||
editorBodyPalettes: {
|
||||
native: "Native",
|
||||
clay: "Red",
|
||||
orange: "Orange",
|
||||
clay: "Vermilion orange",
|
||||
dawn: "Gold",
|
||||
teal: "Teal",
|
||||
azure: "Blue",
|
||||
|
||||
@@ -1011,8 +1011,7 @@ export const ja = {
|
||||
editorBodyPaletteTitle: "本文の配色",
|
||||
editorBodyPalettes: {
|
||||
native: "標準",
|
||||
clay: "赤",
|
||||
orange: "オレンジ",
|
||||
clay: "朱橙",
|
||||
dawn: "金",
|
||||
teal: "青緑",
|
||||
azure: "青",
|
||||
|
||||
@@ -1011,8 +1011,7 @@ export const pl = {
|
||||
editorBodyPaletteTitle: "Kolory tekstu",
|
||||
editorBodyPalettes: {
|
||||
native: "Natywne",
|
||||
clay: "Czerwony",
|
||||
orange: "Pomarańczowy",
|
||||
clay: "Cynobrowy pomarańcz",
|
||||
dawn: "Złoty",
|
||||
teal: "Morski",
|
||||
azure: "Niebieski",
|
||||
|
||||
@@ -1022,8 +1022,7 @@ export const zhCN = {
|
||||
editorBodyPaletteTitle: "正文配色",
|
||||
editorBodyPalettes: {
|
||||
native: "原生",
|
||||
clay: "红色",
|
||||
orange: "橙色",
|
||||
clay: "朱橙",
|
||||
dawn: "金色",
|
||||
teal: "青色",
|
||||
azure: "蓝色",
|
||||
|
||||
@@ -2,7 +2,10 @@ import { describe, expect, test } from "bun:test";
|
||||
import {
|
||||
MAX_NOTE_PROSE_CSS_BYTES,
|
||||
NOTE_PROSE_PALETTES,
|
||||
NOTE_PROSE_PALETTE_CHOICES,
|
||||
NOTE_PROSE_DARK_ACCENTS,
|
||||
accountNoteProseFromRow,
|
||||
publicNoteProseFromAccount,
|
||||
noteProseCssVariables,
|
||||
NoteProseUpdateSchema,
|
||||
noteProseCodeFontSize,
|
||||
@@ -24,7 +27,21 @@ const emptyAccount = () => ({
|
||||
});
|
||||
|
||||
describe("note prose", () => {
|
||||
test("checks reading contrast with an intentional bright teal emphasis exception", () => {
|
||||
test("merges old red and orange choices without dropping account or public share preferences", () => {
|
||||
expect(NOTE_PROSE_PALETTE_CHOICES).toContain("clay");
|
||||
expect(NOTE_PROSE_PALETTE_CHOICES).not.toContain("orange");
|
||||
for (const oldPalette of ["clay", "orange"]) {
|
||||
const account = accountNoteProseFromRow({ note_prose_palette: oldPalette });
|
||||
expect(account.palette).toBe("clay");
|
||||
expect(resolveNoteProse(account).palette).toBe("clay");
|
||||
expect(publicNoteProseFromAccount(account).palette).toBe("clay");
|
||||
expect(NoteProseUpdateSchema.parse({ palette: oldPalette }).palette).toBe("clay");
|
||||
}
|
||||
expect(noteProseMigrationPatch(emptyAccount(), { palette: "orange", customCss: null, customColors: null }))
|
||||
.toEqual({ palette: "clay" });
|
||||
});
|
||||
|
||||
test("checks reading contrast with intentional bright teal and vermilion emphasis exceptions", () => {
|
||||
const luminance = (hex) => {
|
||||
const channels = [1, 3, 5].map((offset) => {
|
||||
const value = parseInt(hex.slice(offset, offset + 2), 16) / 255;
|
||||
@@ -38,9 +55,9 @@ describe("note prose", () => {
|
||||
};
|
||||
for (const [id, colors] of Object.entries(NOTE_PROSE_PALETTES)) {
|
||||
for (const background of ["#FFFFFF", "#F8FAFB"]) {
|
||||
// Teal emphasis intentionally stays close to the original bright hue.
|
||||
// It does not meet normal-text AA; links and code retain the 4.5 minimum.
|
||||
expect(contrast(colors.accent, background)).toBeGreaterThanOrEqual(id === "teal" ? 2.5 : 4.5);
|
||||
// Bright emphasis is intentional; links and code retain normal-text AA.
|
||||
const minimumAccentContrast = id === "teal" ? 2.5 : id === "clay" ? 3 : 4.5;
|
||||
expect(contrast(colors.accent, background)).toBeGreaterThanOrEqual(minimumAccentContrast);
|
||||
for (const foreground of [colors.link, colors.codeText]) {
|
||||
expect(contrast(foreground, background)).toBeGreaterThanOrEqual(4.5);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ export const DEFAULT_NOTE_PROSE_LINE_HEIGHT: NoteProseLineHeight = 1.65;
|
||||
|
||||
export const NOTE_PROSE_PALETTE_IDS = [
|
||||
"clay",
|
||||
"orange",
|
||||
"dawn",
|
||||
"teal",
|
||||
"azure",
|
||||
@@ -110,25 +109,14 @@ const palette = (colors: NoteProsePaletteColors): NoteProsePaletteColors => colo
|
||||
|
||||
export const NOTE_PROSE_PALETTES: Record<NoteProsePaletteId, NoteProsePaletteColors> = {
|
||||
clay: palette({
|
||||
accent: "#C13C42",
|
||||
text: "#374151",
|
||||
muted: "#374151",
|
||||
surface: "#FFF7F7",
|
||||
divider: "#FFD6D6",
|
||||
link: "#B42318",
|
||||
codeBackground: "#FFF1F1",
|
||||
codeText: "#B42318",
|
||||
background: "#FFFFFF",
|
||||
}),
|
||||
orange: palette({
|
||||
accent: "#A65B24",
|
||||
accent: "#FF4C01",
|
||||
text: "#3A2E28",
|
||||
muted: "#746055",
|
||||
surface: "#FFF4EA",
|
||||
divider: "#F6D7BE",
|
||||
link: "#B45309",
|
||||
codeBackground: "#FFF4EA",
|
||||
codeText: "#B45309",
|
||||
surface: "#FFF4EE",
|
||||
divider: "#F6D5C6",
|
||||
link: "#C63C00",
|
||||
codeBackground: "#FFF4EE",
|
||||
codeText: "#C63C00",
|
||||
background: "#FFFFFF",
|
||||
}),
|
||||
dawn: palette({
|
||||
@@ -201,8 +189,7 @@ export const NOTE_PROSE_PALETTES: Record<NoteProsePaletteId, NoteProsePaletteCol
|
||||
|
||||
// Dark reading surfaces need lighter accents than the white-background palette.
|
||||
export const NOTE_PROSE_DARK_ACCENTS: Record<NoteProsePaletteId, string> = {
|
||||
clay: "#F08B8E",
|
||||
orange: "#E7A16A",
|
||||
clay: "#FF996E",
|
||||
dawn: "#D9B65C",
|
||||
teal: "#70C7B8",
|
||||
azure: "#8CB4F0",
|
||||
@@ -262,6 +249,8 @@ export const parseNoteProseLineHeight = (value: unknown): NoteProseLineHeight |
|
||||
};
|
||||
|
||||
export const parseNoteProsePalette = (value: unknown): NoteProsePaletteChoice | null => {
|
||||
// Red and orange now share the existing red identifier for older clients.
|
||||
if (value === "orange") return "clay";
|
||||
// Removed palettes and the custom color editor read as native.
|
||||
if (value === "emerald" || value === "green" || value === "plum" || value === "custom") return "native";
|
||||
return typeof value === "string" && (NOTE_PROSE_PALETTE_CHOICES as readonly string[]).includes(value)
|
||||
|
||||
@@ -444,7 +444,8 @@ const noteProseCustomColorSetSchema = z.object({
|
||||
export const NoteProseUpdateSchema = z.object({
|
||||
fontSize: z.union([z.literal(14), z.literal(16), z.literal(18), z.literal(20)]).nullable().optional(),
|
||||
lineHeight: z.union([z.literal(1.5), z.literal(1.65), z.literal(2)]).nullable().optional(),
|
||||
palette: z.enum(NOTE_PROSE_PALETTE_CHOICES).nullable().optional(),
|
||||
palette: z.union([z.enum(NOTE_PROSE_PALETTE_CHOICES), z.literal("orange")])
|
||||
.transform((value) => value === "orange" ? "clay" as const : value).nullable().optional(),
|
||||
customCss: z.string().refine((value) => new TextEncoder().encode(value).byteLength <= MAX_NOTE_PROSE_CSS_BYTES).nullable().optional(),
|
||||
customColors: z.object({
|
||||
light: noteProseCustomColorSetSchema,
|
||||
|
||||
Reference in new issue
Block a user