Skip to content

Commit e3d8261

Browse files
committed
fix(desktop): let calendar and timeline chips fall back to the area color when the project keeps its default grey (#1124)
1 parent 9604387 commit e3d8261

3 files changed

Lines changed: 68 additions & 3 deletions

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { DEFAULT_PROJECT_COLOR, type Area, type Project, type Task } from '@mindwtr/core';
3+
import { getTaskAccentColor } from './task-accent-color';
4+
5+
const task = (overrides: Partial<Task>): Task => ({
6+
id: 't1',
7+
title: 'test',
8+
status: 'next',
9+
createdAt: '2026-01-01T00:00:00.000Z',
10+
updatedAt: '2026-01-01T00:00:00.000Z',
11+
...overrides,
12+
} as Task);
13+
14+
const project = (overrides: Partial<Project>): Project => ({
15+
id: 'p1',
16+
title: 'Project',
17+
status: 'active',
18+
color: DEFAULT_PROJECT_COLOR,
19+
order: 0,
20+
tagIds: [],
21+
createdAt: '2026-01-01T00:00:00.000Z',
22+
updatedAt: '2026-01-01T00:00:00.000Z',
23+
...overrides,
24+
} as Project);
25+
26+
const area = (overrides: Partial<Area>): Area => ({
27+
id: 'a1',
28+
name: 'Area',
29+
order: 0,
30+
createdAt: '2026-01-01T00:00:00.000Z',
31+
updatedAt: '2026-01-01T00:00:00.000Z',
32+
...overrides,
33+
} as Area);
34+
35+
const maps = (projects: Project[], areas: Area[]) => [
36+
new Map(projects.map((p) => [p.id, p])),
37+
new Map(areas.map((a) => [a.id, a])),
38+
] as const;
39+
40+
describe('getTaskAccentColor', () => {
41+
it('uses an explicitly chosen project color', () => {
42+
const [projects, areas] = maps([project({ color: '#f97316', areaId: 'a1' })], [area({ color: '#8b5cf6' })]);
43+
expect(getTaskAccentColor(task({ projectId: 'p1' }), projects, areas)).toBe('#f97316');
44+
});
45+
46+
it('falls through the never-changed default project color to the area color (#1124)', () => {
47+
const [projects, areas] = maps([project({ areaId: 'a1' })], [area({ color: '#8b5cf6' })]);
48+
expect(getTaskAccentColor(task({ projectId: 'p1' }), projects, areas)).toBe('#8b5cf6');
49+
});
50+
51+
it('uses the task area color when the task has no project', () => {
52+
const [projects, areas] = maps([], [area({ color: '#3b82f6' })]);
53+
expect(getTaskAccentColor(task({ areaId: 'a1' }), projects, areas)).toBe('#3b82f6');
54+
});
55+
56+
it('returns undefined when neither project nor area carries a real color', () => {
57+
const [projects, areas] = maps([project({ areaId: 'a1' })], [area({ color: DEFAULT_PROJECT_COLOR })]);
58+
expect(getTaskAccentColor(task({ projectId: 'p1' }), projects, areas)).toBeUndefined();
59+
expect(getTaskAccentColor(task({}), projects, areas)).toBeUndefined();
60+
});
61+
});

apps/desktop/src/lib/task-accent-color.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Area, Project, Task } from '@mindwtr/core';
1+
import { DEFAULT_PROJECT_COLOR, type Area, type Project, type Task } from '@mindwtr/core';
22

33
/**
44
* The identity color a task carries on the calendar and the timeline — project
@@ -13,7 +13,10 @@ export function getTaskAccentColor(
1313
areaById: Map<string, Area>,
1414
): string | undefined {
1515
const project = task.projectId ? projectById.get(task.projectId) : undefined;
16-
if (project?.color) return project.color;
16+
// Every project stores DEFAULT_PROJECT_COLOR until the user picks one; that
17+
// placeholder grey is "no identity", so it must not shadow the area color (#1124).
18+
if (project?.color && project.color !== DEFAULT_PROJECT_COLOR) return project.color;
1719
const areaId = project?.areaId ?? task.areaId;
18-
return (areaId ? areaById.get(areaId)?.color : undefined) || undefined;
20+
const areaColor = areaId ? areaById.get(areaId)?.color : undefined;
21+
return (areaColor !== DEFAULT_PROJECT_COLOR ? areaColor : undefined) || undefined;
1922
}

docs/release-notes/unreleased.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Changes collected after `v1.2.5` and before the next version tag.
3838
- Settings → About now links the official YouTube video tutorials (the Mindwtr App Demos playlist with the complete desktop and mobile walkthroughs). Desktop and mobile.
3939
- Desktop: the "go to Next" keybinding (`g n`, or Alt+N in the Emacs style) now opens the actual Next Actions list, with the full sort and group toolbar. It had always shown the Focus view instead, so the all-Next list was unreachable. (#1107)
4040
- Android: in the quick "Add task" sheet, tapping More no longer pushes the title input off the top of the screen behind the keyboard; the expanded options now scroll within the space the keyboard leaves while the input and Save buttons stay visible. (#1120)
41+
- Desktop calendar and Timeline: tasks in a project whose color was never changed from the default grey now take their area's color on the deadline chip bar, instead of showing the placeholder grey as if the project had no area. (#1124)
4142
- Mobile: the quick "Add task" sheet's More panel now starts with a Note field, so a longer thought can be captured without typing the /note: token; a typed field and a /note: token merge instead of one overwriting the other. (#1118)
4243
- Deleting a section now says up front that its tasks are kept and move to No Section, instead of a bare "are you sure". Desktop and mobile. (#1011)
4344
- Desktop Timeline: redesigned around a fixed name column — every task's title now sits in a sticky left column with its project, bars no longer carry floating labels, single-dated tasks draw as small dots on their day, and the card ends after its last row instead of stretching a gridded empty canvas. Feedback welcome on #1111.

0 commit comments

Comments
 (0)