tuiboard 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +106 -0
- package/README.md +9 -6
- package/package.json +3 -2
- package/src/app.tsx +5 -5
- package/src/ui/BoardView.tsx +26 -13
- package/src/ui/Modal.tsx +34 -42
- package/src/views/Dashboard.tsx +9 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to **tuiboard** are documented here.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.7.2] - 2026-06-02
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Documentation: the intro and npm description now lead with the modular pitch
|
|
12
|
+
(a kanban with three optional panels you switch on or off) instead of a
|
|
13
|
+
bundled four-zone dashboard.
|
|
14
|
+
|
|
15
|
+
## [0.7.1] - 2026-06-02
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Modals (new task, schedule, time block, assign, delete, detail, search, help)
|
|
19
|
+
now open in the Agenda's slot — an opaque panel of the same width — instead of
|
|
20
|
+
a side panel that pushed the dashboard left. Opening a modal no longer reflows
|
|
21
|
+
the board/planner; the Agenda returns when the modal closes.
|
|
22
|
+
- Modal titles now ride in the panel's top border (`┤ … ├`), matching the board
|
|
23
|
+
columns and the zones, instead of sitting as a body text line.
|
|
24
|
+
- A clipped board column keeps its task rows until it's scrolled down to less
|
|
25
|
+
than half visible (previously: blanked as soon as it was clipped at all), so a
|
|
26
|
+
column that's mostly on-screen stays useful.
|
|
27
|
+
|
|
28
|
+
## [0.7.0] - 2026-06-01
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
- **Configurable zones.** A `zones:` config block turns the planner, agenda, or
|
|
32
|
+
agents view off (`off`), starts it collapsed (`hidden`), or leaves it on
|
|
33
|
+
(`on`, the default; `true`/`false` alias `on`/`off`). The board is always on.
|
|
34
|
+
tuiboard can now be a pure kanban, kanban + calendar, kanban + agents, or any
|
|
35
|
+
mix. A disabled zone is never rendered, is skipped by `Shift-Tab`, has an
|
|
36
|
+
inert F-key, and **its background work never starts** — no calendar fetch and
|
|
37
|
+
no `~/.claude` reads when the agents zone is off.
|
|
38
|
+
- Documented zones in the README, the AI setup prompt, and `config.example.yaml`.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
- Renamed the internal "virtual" zone to **"planner"** throughout (code,
|
|
42
|
+
identifiers, comments, and the `VirtualPanel`/`virtual-panel` files) for
|
|
43
|
+
clarity. The visible "Today/Tomorrow" panel is unchanged.
|
|
44
|
+
- Reworked the responsive layout to combine three inputs — `enabled ∧ desired ∧
|
|
45
|
+
fits-width`. Auto-hide now only reports what fits; it never force-shows a
|
|
46
|
+
disabled or intentionally-hidden zone, and `F1`/`F2`/`F3` toggles persist
|
|
47
|
+
across terminal resizes.
|
|
48
|
+
|
|
49
|
+
## [0.6.2] - 2026-05-30
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
- Updated the hero screenshot to show the live calendar overlay (Google +
|
|
53
|
+
Microsoft 365 events side by side) and the aligned agent rows.
|
|
54
|
+
- Refreshed the README intro to mention the calendar overlay.
|
|
55
|
+
|
|
56
|
+
## [0.6.1] - 2026-05-30
|
|
57
|
+
|
|
58
|
+
### Added
|
|
59
|
+
- **Manual full-refresh key (`r`).** Reloads boards from disk, rescans agents,
|
|
60
|
+
and force-refetches the agenda calendar (bypassing the 30-minute cache) so
|
|
61
|
+
externally-edited events show without a restart.
|
|
62
|
+
|
|
63
|
+
### Changed
|
|
64
|
+
- Day-navigation keys (`[` / `]` / `\`) now work from any zone, not just when
|
|
65
|
+
the agenda is focused; pressing one also moves focus to the agenda.
|
|
66
|
+
- Added arrow keys and `r refresh` to the bottom cheat-sheet; the day-navigation
|
|
67
|
+
hint is now always visible in the agenda's resting state.
|
|
68
|
+
- Agent rows right-align the activity age in a fixed-width field so the end of
|
|
69
|
+
each working directory lines up across rows.
|
|
70
|
+
|
|
71
|
+
## [0.6.0] - 2026-05-30
|
|
72
|
+
|
|
73
|
+
First public release on npm. This entry captures the full feature set at launch.
|
|
74
|
+
|
|
75
|
+
### Added
|
|
76
|
+
- **Kanban board** over plain CommonMark files using the Obsidian Tasks-plugin
|
|
77
|
+
emoji vocabulary — no lock-in, the files stay yours. Multiple boards as tabs;
|
|
78
|
+
`##` headings become columns; `Done` and `Archive` columns are treated
|
|
79
|
+
specially. Quick-add syntax (`@assignee`, `#tag`, scheduling, time blocks,
|
|
80
|
+
priority), multi-select (`Space`), undo (`Ctrl-Z`), filters, search (`/`),
|
|
81
|
+
zoom (`z`), and atomic file round-trips with an external-edit watcher.
|
|
82
|
+
- **Planner** — a Today/Tomorrow panel aggregating everything scheduled across
|
|
83
|
+
all boards.
|
|
84
|
+
- **Agenda** — a 24-hour timeline with click-to-arm time-blocking, plus a
|
|
85
|
+
read-only **calendar overlay** for Google Calendar and Microsoft 365
|
|
86
|
+
(dependency-light, bring-your-own-credentials, all-day events skipped, each
|
|
87
|
+
calendar in its own color). Day-navigation with `[` / `]` / `\` pages tasks
|
|
88
|
+
and events across days.
|
|
89
|
+
- **`tuiboard calendar-setup`** — one-time OAuth for new users (Google browser
|
|
90
|
+
flow, Microsoft device-code flow); prints the exact `calendars:` block to add.
|
|
91
|
+
- **Live agents view** — reads local Claude Code sessions from `~/.claude` with
|
|
92
|
+
zero setup, showing status, branch, and last activity. `Enter` opens a session
|
|
93
|
+
in a terminal; the launch command is overridable via `resume_command`.
|
|
94
|
+
- **Keyboard-first with full mouse support**, a responsive multi-zone layout
|
|
95
|
+
that adapts to terminal width, standalone `--view=` modes, and the `tb` alias.
|
|
96
|
+
- Config resolution via `$TUIBOARD_CONFIG`, a project-local `.tuiboard/`, the
|
|
97
|
+
global `~/.config/tuiboard/`, or a cwd fallback scan.
|
|
98
|
+
|
|
99
|
+
Built with [OpenTUI](https://opentui.com) + SolidJS on Bun.
|
|
100
|
+
|
|
101
|
+
[0.7.2]: https://github.com/NazzarenoGiannelli/tuiboard/releases/tag/v0.7.2
|
|
102
|
+
[0.7.1]: https://github.com/NazzarenoGiannelli/tuiboard/releases/tag/v0.7.1
|
|
103
|
+
[0.7.0]: https://github.com/NazzarenoGiannelli/tuiboard/releases/tag/v0.7.0
|
|
104
|
+
[0.6.2]: https://github.com/NazzarenoGiannelli/tuiboard/releases/tag/v0.6.2
|
|
105
|
+
[0.6.1]: https://github.com/NazzarenoGiannelli/tuiboard/releases/tag/v0.6.1
|
|
106
|
+
[0.6.0]: https://github.com/NazzarenoGiannelli/tuiboard/releases/tag/v0.6.0
|
package/README.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# tuiboard
|
|
2
2
|
|
|
3
|
-
A terminal
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
A terminal **kanban** board on plain markdown files, with three optional panels
|
|
4
|
+
you switch on or off: a **Today/Tomorrow planner** across all your boards, a
|
|
5
|
+
**24-hour agenda** with a read-only Google / Microsoft 365 calendar overlay, and
|
|
6
|
+
a **live view of your Claude Code sessions**. Run it as a pure kanban, or any mix
|
|
7
|
+
of the four. The board is always on; the rest is opt-in (see [Zones](#zones)).
|
|
7
8
|
|
|
8
9
|
Built with [OpenTUI](https://opentui.com) + SolidJS on Bun. Cross-platform
|
|
9
10
|
(Linux, macOS, Windows). No vendor lock-in: boards are CommonMark with
|
|
@@ -269,11 +270,11 @@ are rebuilt only after an in-app mutation.
|
|
|
269
270
|
|
|
270
271
|
## Layouts
|
|
271
272
|
|
|
272
|
-
Launch `tuiboard` with no flag for the default
|
|
273
|
+
Launch `tuiboard` with no flag for the default dashboard (every enabled zone).
|
|
273
274
|
|
|
274
275
|
| Flag | View | Use case |
|
|
275
276
|
|---|---|---|
|
|
276
|
-
| (none) | **Dashboard** —
|
|
277
|
+
| (none) | **Dashboard** — every enabled zone | Default; your configured layout |
|
|
277
278
|
| `--view=board` | Kanban + planner panel only | Focus mode, or a single WezTerm pane |
|
|
278
279
|
| `--view=timeline` | Timeline fullscreen | Wall-mounted "what's now" |
|
|
279
280
|
| `--view=agents` | Agent view fullscreen | Cross-machine session monitor |
|
|
@@ -353,6 +354,8 @@ session (until the next terminal resize).
|
|
|
353
354
|
|
|
354
355
|
## Status
|
|
355
356
|
|
|
357
|
+
See [CHANGELOG.md](CHANGELOG.md) for the full release history.
|
|
358
|
+
|
|
356
359
|
- **v0.7** — configurable zones: turn the planner, agenda, or agents view off
|
|
357
360
|
(or start it collapsed) via the `zones:` config, so tuiboard can be a pure
|
|
358
361
|
kanban, kanban + calendar, or any mix.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tuiboard",
|
|
3
|
-
"version": "0.7.
|
|
4
|
-
"description": "Terminal
|
|
3
|
+
"version": "0.7.2",
|
|
4
|
+
"description": "Terminal kanban for markdown task boards, with optional Today/Tomorrow planner, 24h agenda + calendar overlay, and a live Claude Code agent view. Use only the panels you want.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Nazzareno Giannelli <nazzareno.giannelli@gmail.com>",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"bin/",
|
|
37
37
|
".tuiboard/config.example.yaml",
|
|
38
38
|
"README.md",
|
|
39
|
+
"CHANGELOG.md",
|
|
39
40
|
"LICENSE"
|
|
40
41
|
],
|
|
41
42
|
"scripts": {
|
package/src/app.tsx
CHANGED
|
@@ -121,11 +121,11 @@ function App() {
|
|
|
121
121
|
<TopBar store={store} />
|
|
122
122
|
<box style={{ height: 1 }} />
|
|
123
123
|
{/*
|
|
124
|
-
rootView
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
the whole row.
|
|
124
|
+
rootView + ModalLayer are flex-row siblings. The modal panel is exactly
|
|
125
|
+
the Agenda's width, and the Dashboard hides the Agenda while a modal is
|
|
126
|
+
open — so the modal drops into the Agenda's slot with zero reflow of the
|
|
127
|
+
left side (board / planner / agents). When no modal is open ModalLayer
|
|
128
|
+
renders nothing and rootView gets the whole row.
|
|
129
129
|
*/}
|
|
130
130
|
<box style={{ flexDirection: "row", flexGrow: 1 }}>
|
|
131
131
|
<box style={{ flexDirection: "column", flexGrow: 1 }}>
|
package/src/ui/BoardView.tsx
CHANGED
|
@@ -31,6 +31,13 @@ interface SizedBoxLike {
|
|
|
31
31
|
|
|
32
32
|
/** Fixed column width when not zoomed. Single source of truth for layout. */
|
|
33
33
|
const COL_WIDTH = 42;
|
|
34
|
+
/**
|
|
35
|
+
* Minimum fraction of a column that must be inside the viewport for its task
|
|
36
|
+
* rows to render. Above this, a column that's mostly on-screen keeps its tasks
|
|
37
|
+
* (the last one may be cut at the edge); below it — a thin sliver clipped at the
|
|
38
|
+
* edge — only the title shows as a "more columns →" hint.
|
|
39
|
+
*/
|
|
40
|
+
const MIN_TASKS_VISIBLE_FRACTION = 0.5;
|
|
34
41
|
/**
|
|
35
42
|
* Width of a collapsed column — one with no OPEN tasks (an all-done lane like
|
|
36
43
|
* "Done", or an empty column). It shows just the `✓ N` counter; zoom (`z`)
|
|
@@ -140,16 +147,22 @@ export function BoardView(props: BoardViewProps) {
|
|
|
140
147
|
});
|
|
141
148
|
|
|
142
149
|
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
150
|
+
* Should the column at rendered index `i` render its task rows? Yes unless
|
|
151
|
+
* it's clipped down to a thin sliver at the viewport edge (less than
|
|
152
|
+
* MIN_TASKS_VISIBLE_FRACTION on-screen) — then only its title shows as a
|
|
153
|
+
* "more columns →" hint. A mostly-visible column keeps its tasks even if the
|
|
154
|
+
* last one is cut at the edge. Defaults to true while the viewport width is
|
|
155
|
+
* still unknown (first paint) and in zoom.
|
|
146
156
|
*/
|
|
147
|
-
const
|
|
157
|
+
const columnTasksVisible = (i: number): boolean => {
|
|
148
158
|
const vw = viewportW();
|
|
149
159
|
if (vw <= 0 || ui().zoomed) return true;
|
|
150
160
|
const stride = COL_WIDTH + COL_GAP;
|
|
151
161
|
const start = i * stride;
|
|
152
|
-
|
|
162
|
+
const left = Math.max(start, scrollX());
|
|
163
|
+
const right = Math.min(start + COL_WIDTH, scrollX() + vw);
|
|
164
|
+
const visibleFraction = Math.max(0, right - left) / COL_WIDTH;
|
|
165
|
+
return visibleFraction >= MIN_TASKS_VISIBLE_FRACTION;
|
|
153
166
|
};
|
|
154
167
|
|
|
155
168
|
// Measure the viewport width once at mount, regardless of the active zone.
|
|
@@ -199,7 +212,7 @@ export function BoardView(props: BoardViewProps) {
|
|
|
199
212
|
columnIndex={originalIndex}
|
|
200
213
|
active={isActive()}
|
|
201
214
|
zoomed={ui().zoomed && isActive()}
|
|
202
|
-
|
|
215
|
+
tasksVisible={columnTasksVisible(i())}
|
|
203
216
|
boxId={columnId(props.board.filepath, originalIndex)}
|
|
204
217
|
/>
|
|
205
218
|
);
|
|
@@ -223,11 +236,11 @@ interface ColumnViewProps {
|
|
|
223
236
|
*/
|
|
224
237
|
zoomed: boolean;
|
|
225
238
|
/**
|
|
226
|
-
* False when the column is
|
|
227
|
-
*
|
|
228
|
-
*
|
|
239
|
+
* False when the column is clipped down to a thin sliver at the viewport
|
|
240
|
+
* edge. Its title still renders as a "more columns" hint, but the task rows
|
|
241
|
+
* are blanked. Mostly-visible columns keep their tasks.
|
|
229
242
|
*/
|
|
230
|
-
|
|
243
|
+
tasksVisible?: boolean;
|
|
231
244
|
/** Stable DOM-equivalent id used by `scrollChildIntoView`. */
|
|
232
245
|
boxId: string;
|
|
233
246
|
}
|
|
@@ -349,9 +362,9 @@ function ColumnView(props: ColumnViewProps) {
|
|
|
349
362
|
scrollbarOptions: { visible: false },
|
|
350
363
|
}}
|
|
351
364
|
>
|
|
352
|
-
{/* Blank the task rows when the column is
|
|
353
|
-
|
|
354
|
-
<Show when={props.
|
|
365
|
+
{/* Blank the task rows only when the column is a thin clipped sliver —
|
|
366
|
+
its title still shows as a "more columns" hint. */}
|
|
367
|
+
<Show when={props.tasksVisible !== false}>
|
|
355
368
|
{/*
|
|
356
369
|
Keyed on the task-list signature so a structural change (add/delete/
|
|
357
370
|
move) rebuilds the <For> fresh in the correct order, working around
|
package/src/ui/Modal.tsx
CHANGED
|
@@ -20,41 +20,21 @@ import {
|
|
|
20
20
|
parseTimeBlockShortcut,
|
|
21
21
|
} from "~/store/parsers";
|
|
22
22
|
import { ATTR, T } from "~/ui/glyphs";
|
|
23
|
+
import { TIMELINE_WIDTH } from "~/views/Dashboard";
|
|
23
24
|
import type { TuiStore } from "~/store/index";
|
|
24
25
|
import type { PriorityLevel, TimeBlock } from "~/types";
|
|
25
26
|
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
const MODAL_WIDTH =
|
|
27
|
+
/** The modal panel matches the Agenda's width so it can drop into the Agenda's
|
|
28
|
+
* slot (which the Dashboard vacates while a modal is open) with no reflow. */
|
|
29
|
+
const MODAL_WIDTH = TIMELINE_WIDTH;
|
|
29
30
|
|
|
30
31
|
export function ModalLayer(props: { store: TuiStore }) {
|
|
31
32
|
const modal = createMemo(() => props.store.state.ui.modal);
|
|
32
33
|
return (
|
|
33
34
|
<Show when={modal()}>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
width: MODAL_WIDTH,
|
|
38
|
-
minWidth: MODAL_WIDTH,
|
|
39
|
-
flexGrow: 0,
|
|
40
|
-
flexShrink: 0,
|
|
41
|
-
// Stretch to the parent's height so the modal panel matches
|
|
42
|
-
// the timeline / board zones it sits next to. Same contract as
|
|
43
|
-
// every other zone — fixed cross-axis size, full-height fill.
|
|
44
|
-
alignSelf: "stretch",
|
|
45
|
-
marginLeft: 1,
|
|
46
|
-
backgroundColor: T.panelBgActive,
|
|
47
|
-
border: true,
|
|
48
|
-
borderStyle: "rounded",
|
|
49
|
-
borderColor: T.borderActive,
|
|
50
|
-
paddingLeft: 1,
|
|
51
|
-
paddingRight: 1,
|
|
52
|
-
paddingTop: 1,
|
|
53
|
-
paddingBottom: 1,
|
|
54
|
-
}}
|
|
55
|
-
>
|
|
56
|
-
<ModalRouter store={props.store} modal={modal()!} />
|
|
57
|
-
</box>
|
|
35
|
+
{/* Each modal's DialogShell IS the panel box (border + title + slot
|
|
36
|
+
dimensions), so it drops into the Agenda's slot directly. */}
|
|
37
|
+
<ModalRouter store={props.store} modal={modal()!} />
|
|
58
38
|
</Show>
|
|
59
39
|
);
|
|
60
40
|
}
|
|
@@ -87,11 +67,31 @@ interface DialogShellProps {
|
|
|
87
67
|
function DialogShell(props: DialogShellProps) {
|
|
88
68
|
void props.width;
|
|
89
69
|
return (
|
|
90
|
-
<box
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
70
|
+
<box
|
|
71
|
+
style={{
|
|
72
|
+
// The modal panel: same width + marginLeft as the Agenda so it occupies
|
|
73
|
+
// the Agenda's slot (the Dashboard hides the Agenda while a modal is
|
|
74
|
+
// open) with no reflow. The title rides in the top border, exactly like
|
|
75
|
+
// the board columns and the other zones.
|
|
76
|
+
flexDirection: "column",
|
|
77
|
+
width: MODAL_WIDTH,
|
|
78
|
+
minWidth: MODAL_WIDTH,
|
|
79
|
+
flexGrow: 0,
|
|
80
|
+
flexShrink: 0,
|
|
81
|
+
alignSelf: "stretch",
|
|
82
|
+
marginLeft: 1,
|
|
83
|
+
backgroundColor: T.panelBgActive,
|
|
84
|
+
border: true,
|
|
85
|
+
borderStyle: "rounded",
|
|
86
|
+
borderColor: T.borderActive,
|
|
87
|
+
paddingLeft: 1,
|
|
88
|
+
paddingRight: 1,
|
|
89
|
+
paddingTop: 1,
|
|
90
|
+
paddingBottom: 1,
|
|
91
|
+
}}
|
|
92
|
+
title={`┤ ${props.title} ├`}
|
|
93
|
+
titleAlignment="left"
|
|
94
|
+
>
|
|
95
95
|
{props.children}
|
|
96
96
|
<Show when={props.hint}>
|
|
97
97
|
<text>
|
|
@@ -207,11 +207,7 @@ function ScheduleModal(props: { store: TuiStore; modal: Extract<NonNullable<TuiS
|
|
|
207
207
|
|
|
208
208
|
return (
|
|
209
209
|
<DialogShell
|
|
210
|
-
title={
|
|
211
|
-
markedCount > 1
|
|
212
|
-
? `Schedule ${markedCount} selected tasks`
|
|
213
|
-
: `Schedule: ${task?.displayTitle.slice(0, 50) ?? ""}`
|
|
214
|
-
}
|
|
210
|
+
title={markedCount > 1 ? `Schedule · ${markedCount} tasks` : "Schedule"}
|
|
215
211
|
hint="t = today · tm = tomorrow · +3 = in 3 days · lun = next Monday · 2026-06-15 · empty/-clear · Esc to cancel"
|
|
216
212
|
width={70}
|
|
217
213
|
>
|
|
@@ -256,11 +252,7 @@ function TimeBlockModal(props: { store: TuiStore; modal: Extract<NonNullable<Tui
|
|
|
256
252
|
|
|
257
253
|
return (
|
|
258
254
|
<DialogShell
|
|
259
|
-
title={
|
|
260
|
-
markedCount > 1
|
|
261
|
-
? `Time block ${markedCount} selected tasks`
|
|
262
|
-
: `Time block: ${task?.displayTitle.slice(0, 50) ?? ""}`
|
|
263
|
-
}
|
|
255
|
+
title={markedCount > 1 ? `Time block · ${markedCount} tasks` : "Time block"}
|
|
264
256
|
hint="n = now+30 · 9:00 · 9-11 · 09:30-10:45 · - to clear · Esc to cancel"
|
|
265
257
|
width={70}
|
|
266
258
|
>
|
package/src/views/Dashboard.tsx
CHANGED
|
@@ -30,8 +30,12 @@ import { BoardOnly } from "~/views/BoardOnly";
|
|
|
30
30
|
import { TimelineOnly } from "~/views/TimelineOnly";
|
|
31
31
|
import type { TuiStore } from "~/store/index";
|
|
32
32
|
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Width (in cells) for the right-column Agenda panel on a wide terminal. The
|
|
35
|
+
* modal panel matches this so it can drop into the Agenda's slot (see
|
|
36
|
+
* ModalLayer) without reflowing the rest of the dashboard.
|
|
37
|
+
*/
|
|
38
|
+
export const TIMELINE_WIDTH = 50;
|
|
35
39
|
/** Row height for the bottom Agents strip — enough for ~5 sessions. */
|
|
36
40
|
const AGENTS_HEIGHT = 7;
|
|
37
41
|
|
|
@@ -96,8 +100,9 @@ function FourZoneLayout(props: { store: TuiStore }) {
|
|
|
96
100
|
<AgentsBar store={props.store} height={AGENTS_HEIGHT} />
|
|
97
101
|
</Show>
|
|
98
102
|
</box>
|
|
99
|
-
{/* Right column:
|
|
100
|
-
|
|
103
|
+
{/* Right column: Agenda (full height). Hidden while a modal is open so
|
|
104
|
+
the modal panel takes its slot with no reflow. */}
|
|
105
|
+
<Show when={visible().timeline && !ui().modal}>
|
|
101
106
|
<TimelineView store={props.store} width={TIMELINE_WIDTH} />
|
|
102
107
|
</Show>
|
|
103
108
|
{/* ModalLayer rendered at App level so it can sit beside any view */}
|