Skip to content

Commit 8f2bd85

Browse files
committed
feat(mind map): offer the downward layout in the direction bar
Mind Elixir 5.15 added a fourth way to lay a map out — the root at the top with its branches hanging below (`direction: 3`, `initDown()`) — but left it out of its own toolbar, so nothing offered it. The direction bar carries it now, beside the three it already had. Its mark is the rightward one turned a quarter turn, which is what the layout itself is: Mind Elixir ships no mark for a direction its bar never showed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BuQw511c5ZdCHkvGzSwvyR
1 parent 6c86af1 commit 8f2bd85

5 files changed

Lines changed: 42 additions & 13 deletions

File tree

apps/client/src/translations/en/translation.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3775,7 +3775,8 @@
37753775
"exit-fullscreen": "Exit fullscreen",
37763776
"direction-left": "Branches to the left",
37773777
"direction-right": "Branches to the right",
3778-
"direction-side": "Branches to both sides"
3778+
"direction-side": "Branches to both sides",
3779+
"direction-down": "Branches downwards"
37793780
},
37803781
"llm": {
37813782
"disabled_placeholder": "AI features are turned off. Enable them to configure providers and MCP.",

apps/client/src/widgets/type_widgets/mind_map/MapToolbar.css

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
}
2323

2424
/*
25-
* The three marks a direction is chosen by, which are Mind Elixir's own (MIT, © 2019 DjZhou): each
25+
* The four marks a direction is chosen by, which are Mind Elixir's own (MIT, © 2019 DjZhou): each
2626
* draws the very layout it sets, and Trilium's icon set has nothing that says it. They are drawn as
2727
* a mask filled with the button's own color rather than as pictures, so that they take the color a
2828
* boxicon would — including the one a pressed or hovered button lends its icon.
2929
*
30-
* Sized in `em` against the font size the theme gives an icon button's mark, so that the three sit
31-
* at the size the four beside them do and follow that setting wherever it is changed.
30+
* Sized in `em` against the font size the theme gives an icon button's mark, so that the four sit
31+
* at the size the ones beside them do and follow that setting wherever it is changed.
3232
*/
3333
.mind-map-container .mind-map-direction-icon::before {
3434
content: "";
@@ -60,3 +60,10 @@
6060
-webkit-mask-image: url("./direction-side.svg");
6161
mask-image: url("./direction-side.svg");
6262
}
63+
64+
/* The layout Mind Elixir added last came without a mark of its own, its own bar never having offered
65+
it. Drawn here from the rightward one turned a quarter turn, which is what the layout itself is. */
66+
.mind-map-container .mind-map-direction-down::before {
67+
-webkit-mask-image: url("./direction-down.svg");
68+
mask-image: url("./direction-down.svg");
69+
}

apps/client/src/widgets/type_widgets/mind_map/MapToolbar.spec.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ function buildMind({ scaleVal = 1, direction = 1, isFocusMode = false } = {}) {
2727
});
2828

2929
// As the map does: it is laid out afresh, and says only that its branches have been drawn.
30-
const relayOut = (value: 0 | 1 | 2) => vi.fn(() => {
30+
const relayOut = (value: 0 | 1 | 2 | 3) => vi.fn(() => {
3131
mind.direction = value;
3232
fire("linkDiv");
3333
});
@@ -48,6 +48,7 @@ function buildMind({ scaleVal = 1, direction = 1, isFocusMode = false } = {}) {
4848
initLeft: relayOut(0),
4949
initRight: relayOut(1),
5050
initSide: relayOut(2),
51+
initDown: relayOut(3),
5152
// As the map does: it is laid out afresh, showing all it has again.
5253
cancelFocus: vi.fn(() => {
5354
mind.isFocusMode = false;
@@ -79,6 +80,7 @@ const FULLSCREEN = 4;
7980
const LEFT = 0;
8081
const RIGHT = 1;
8182
const SIDE = 2;
83+
const DOWN = 3;
8284

8385
/** Builds a bar and settles it, so that what it listens to is listened to before it is spoken to. */
8486
function renderBar(bar: ComponentChild) {
@@ -260,13 +262,16 @@ describe("MapToolbar", () => {
260262
});
261263

262264
describe("DirectionToolbar", () => {
263-
it("offers the three layouts the map's own bar did, each wearing its own mark", () => {
265+
// The three the map's own bar offered, and the downward one Mind Elixir added without ever
266+
// putting it in that bar.
267+
it("offers every layout the map can take, each wearing its own mark", () => {
264268
const container = renderDirections(buildMind());
265269

266270
expect(buttons(container).map((button) => button.className)).toEqual([
267271
expect.stringContaining("mind-map-direction-left"),
268272
expect.stringContaining("mind-map-direction-right"),
269-
expect.stringContaining("mind-map-direction-side")
273+
expect.stringContaining("mind-map-direction-side"),
274+
expect.stringContaining("mind-map-direction-down")
270275
]);
271276
});
272277

@@ -280,6 +285,9 @@ describe("DirectionToolbar", () => {
280285
press(container, SIDE);
281286
expect(mind.initSide).toHaveBeenCalled();
282287

288+
press(container, DOWN);
289+
expect(mind.initDown).toHaveBeenCalled();
290+
283291
press(container, RIGHT);
284292
expect(mind.initRight).toHaveBeenCalled();
285293
});
@@ -289,12 +297,17 @@ describe("DirectionToolbar", () => {
289297
const container = renderDirections(mind);
290298

291299
expect(buttons(container).map((button) => button.classList.contains("active")))
292-
.toEqual([ false, true, false ]);
300+
.toEqual([ false, true, false, false ]);
293301

294302
press(container, SIDE);
295303

296304
expect(buttons(container).map((button) => button.classList.contains("active")))
297-
.toEqual([ false, false, true ]);
305+
.toEqual([ false, false, true, false ]);
306+
307+
press(container, DOWN);
308+
309+
expect(buttons(container).map((button) => button.classList.contains("active")))
310+
.toEqual([ false, false, false, true ]);
298311
});
299312

300313
it("catches up with a map that took a direction from the content it was filled with", () => {
@@ -306,6 +319,6 @@ describe("DirectionToolbar", () => {
306319
act(() => mind.bus.fire("linkDiv"));
307320

308321
expect(buttons(container).map((button) => button.classList.contains("active")))
309-
.toEqual([ true, false, false ]);
322+
.toEqual([ true, false, false, false ]);
310323
});
311324
});

apps/client/src/widgets/type_widgets/mind_map/MapToolbar.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,9 @@ export default function MapToolbar({ mind }: MapToolbarProps) {
127127

128128
/**
129129
* The bar standing in the top corner opposite: which way the map's branches run from its root —
130-
* to the left of it, to the right of it, or to either side.
130+
* to the left of it, to the right of it, to either side, or below it.
131131
*
132-
* The three are a choice rather than three things to do, so the one the map is laid out by is shown
132+
* The four are a choice rather than four things to do, so the one the map is laid out by is shown
133133
* pressed. Their marks are Mind Elixir's own, kept because they draw the very thing they set and
134134
* nothing in Trilium's icon set says it (see MapToolbar.css).
135135
*/
@@ -153,7 +153,8 @@ export function DirectionToolbar({ mind }: MapToolbarProps) {
153153
}
154154

155155
/**
156-
* The ways a map is laid out, in the order Mind Elixir offered them: each with the value
156+
* The ways a map is laid out, in the order Mind Elixir offered them — the downward one last, being
157+
* the one it added last, and the only one its own bar never carried: each with the value
157158
* `mind.direction` reads as, the mark it wears, and the call that lays the map out that way.
158159
*
159160
* Named afresh on every render, which follows a change of locale.
@@ -177,6 +178,12 @@ function buildDirections() {
177178
icon: "mind-map-direction-side",
178179
label: t("mind-map.direction-side"),
179180
apply: (mind: MindElixirInstance) => mind.initSide()
181+
},
182+
{
183+
value: 3,
184+
icon: "mind-map-direction-down",
185+
label: t("mind-map.direction-down"),
186+
apply: (mind: MindElixirInstance) => mind.initDown()
180187
}
181188
];
182189
}
Lines changed: 1 addition & 0 deletions
Loading

0 commit comments

Comments
 (0)