tuiboard 0.7.1 → 0.7.3
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 +24 -0
- package/README.md +7 -6
- package/package.json +2 -2
- package/src/app.tsx +20 -8
- package/src/ui/Modal.tsx +7 -11
- package/src/ui/layout.ts +12 -0
- package/src/views/Dashboard.tsx +15 -12
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,28 @@ All notable changes to **tuiboard** are documented here.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.7.3] - 2026-06-02
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Opening a modal no longer shifts the whole dashboard up by a row. The Agenda's
|
|
12
|
+
tall scrollbox was inflating the main row one line past the terminal (flex
|
|
13
|
+
basis `auto` takes the content height); a modal in its place removed that
|
|
14
|
+
overflow, which read as a jump. The main row now grows purely from the
|
|
15
|
+
available space (`flex-basis: 0`), so the layout is steady whatever's on
|
|
16
|
+
screen. Modals also render in the Agenda's exact slot, so there's no
|
|
17
|
+
horizontal reflow either.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- Reclaimed a row: the board and agenda are one row taller, and the keyboard
|
|
21
|
+
cheat-sheet sits flush on the bottom line.
|
|
22
|
+
|
|
23
|
+
## [0.7.2] - 2026-06-02
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- Documentation: the intro and npm description now lead with the modular pitch
|
|
27
|
+
(a kanban with three optional panels you switch on or off) instead of a
|
|
28
|
+
bundled four-zone dashboard.
|
|
29
|
+
|
|
8
30
|
## [0.7.1] - 2026-06-02
|
|
9
31
|
|
|
10
32
|
### Changed
|
|
@@ -91,6 +113,8 @@ First public release on npm. This entry captures the full feature set at launch.
|
|
|
91
113
|
|
|
92
114
|
Built with [OpenTUI](https://opentui.com) + SolidJS on Bun.
|
|
93
115
|
|
|
116
|
+
[0.7.3]: https://github.com/NazzarenoGiannelli/tuiboard/releases/tag/v0.7.3
|
|
117
|
+
[0.7.2]: https://github.com/NazzarenoGiannelli/tuiboard/releases/tag/v0.7.2
|
|
94
118
|
[0.7.1]: https://github.com/NazzarenoGiannelli/tuiboard/releases/tag/v0.7.1
|
|
95
119
|
[0.7.0]: https://github.com/NazzarenoGiannelli/tuiboard/releases/tag/v0.7.0
|
|
96
120
|
[0.6.2]: https://github.com/NazzarenoGiannelli/tuiboard/releases/tag/v0.6.2
|
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 |
|
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.3",
|
|
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>",
|
package/src/app.tsx
CHANGED
|
@@ -115,23 +115,35 @@ function App() {
|
|
|
115
115
|
width: "100%",
|
|
116
116
|
height: "100%",
|
|
117
117
|
backgroundColor: T.bg,
|
|
118
|
-
padding:
|
|
118
|
+
// No bottom padding: the keyboard cheat-sheet sits flush on the last
|
|
119
|
+
// row, which gives the board + agenda one extra row of height. Safe
|
|
120
|
+
// thanks to the flexBasis:0 main row — the content just fills the space.
|
|
121
|
+
paddingTop: 1,
|
|
122
|
+
paddingLeft: 1,
|
|
123
|
+
paddingRight: 1,
|
|
124
|
+
paddingBottom: 0,
|
|
119
125
|
}}
|
|
120
126
|
>
|
|
121
127
|
<TopBar store={store} />
|
|
122
128
|
<box style={{ height: 1 }} />
|
|
123
129
|
{/*
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
130
|
+
The default Dashboard renders its modal inside the Agenda's slot, so the
|
|
131
|
+
layout stays put when a modal opens. The standalone `--view=` modes have
|
|
132
|
+
no Agenda slot, so they get the modal here as a right-hand panel.
|
|
133
|
+
(`view` is fixed at launch, never reactive.)
|
|
134
|
+
|
|
135
|
+
`flexBasis: 0` + `minHeight: 0` are load-bearing: without them the row's
|
|
136
|
+
flex-basis is `auto`, so the Agenda's tall scrollbox inflates the row to
|
|
137
|
+
its content height (1 row past the terminal). That overflow vanishes
|
|
138
|
+
when a modal (no scrollbox) takes the slot — which is exactly the 1-row
|
|
139
|
+
"shift" the whole bottom strip used to do. Basis 0 makes the row grow
|
|
140
|
+
purely from the available space, ignoring content, so it's stable.
|
|
129
141
|
*/}
|
|
130
|
-
<box style={{ flexDirection: "row", flexGrow: 1 }}>
|
|
142
|
+
<box style={{ flexDirection: "row", flexGrow: 1, flexBasis: 0, minHeight: 0 }}>
|
|
131
143
|
<box style={{ flexDirection: "column", flexGrow: 1 }}>
|
|
132
144
|
{rootViewFor(view, store)}
|
|
133
145
|
</box>
|
|
134
|
-
<ModalLayer store={store} />
|
|
146
|
+
{view ? <ModalLayer store={store} /> : null}
|
|
135
147
|
</box>
|
|
136
148
|
<BottomBar store={store} />
|
|
137
149
|
</box>
|
package/src/ui/Modal.tsx
CHANGED
|
@@ -20,13 +20,13 @@ import {
|
|
|
20
20
|
parseTimeBlockShortcut,
|
|
21
21
|
} from "~/store/parsers";
|
|
22
22
|
import { ATTR, T } from "~/ui/glyphs";
|
|
23
|
-
import {
|
|
23
|
+
import { AGENDA_WIDTH } from "~/ui/layout";
|
|
24
24
|
import type { TuiStore } from "~/store/index";
|
|
25
25
|
import type { PriorityLevel, TimeBlock } from "~/types";
|
|
26
26
|
|
|
27
27
|
/** The modal panel matches the Agenda's width so it can drop into the Agenda's
|
|
28
|
-
* slot (
|
|
29
|
-
const MODAL_WIDTH =
|
|
28
|
+
* slot (the Dashboard renders it there while a modal is open) with no reflow. */
|
|
29
|
+
const MODAL_WIDTH = AGENDA_WIDTH;
|
|
30
30
|
|
|
31
31
|
export function ModalLayer(props: { store: TuiStore }) {
|
|
32
32
|
const modal = createMemo(() => props.store.state.ui.modal);
|
|
@@ -69,16 +69,14 @@ function DialogShell(props: DialogShellProps) {
|
|
|
69
69
|
return (
|
|
70
70
|
<box
|
|
71
71
|
style={{
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
// the
|
|
72
|
+
// Byte-identical layout to the Agenda panel (TimelineView): same width,
|
|
73
|
+
// marginLeft, flexGrow, border and padding, so it occupies the Agenda's
|
|
74
|
+
// slot at the exact same size and the dashboard doesn't shift when a
|
|
75
|
+
// modal opens. The title rides in the top border like the columns/zones.
|
|
76
76
|
flexDirection: "column",
|
|
77
77
|
width: MODAL_WIDTH,
|
|
78
78
|
minWidth: MODAL_WIDTH,
|
|
79
79
|
flexGrow: 0,
|
|
80
|
-
flexShrink: 0,
|
|
81
|
-
alignSelf: "stretch",
|
|
82
80
|
marginLeft: 1,
|
|
83
81
|
backgroundColor: T.panelBgActive,
|
|
84
82
|
border: true,
|
|
@@ -86,8 +84,6 @@ function DialogShell(props: DialogShellProps) {
|
|
|
86
84
|
borderColor: T.borderActive,
|
|
87
85
|
paddingLeft: 1,
|
|
88
86
|
paddingRight: 1,
|
|
89
|
-
paddingTop: 1,
|
|
90
|
-
paddingBottom: 1,
|
|
91
87
|
}}
|
|
92
88
|
title={`┤ ${props.title} ├`}
|
|
93
89
|
titleAlignment="left"
|
package/src/ui/layout.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared dashboard layout constants. Kept in a leaf module so both the
|
|
3
|
+
* Dashboard and the Modal can import them without an import cycle (the modal
|
|
4
|
+
* panel matches the Agenda's width so it can drop into the Agenda's slot).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** Width (in cells) of the right-hand Agenda panel — and of the modal panel,
|
|
8
|
+
* which takes the Agenda's slot while a modal is open. */
|
|
9
|
+
export const AGENDA_WIDTH = 50;
|
|
10
|
+
|
|
11
|
+
/** Row height of the bottom Agents strip — enough for ~5 sessions. */
|
|
12
|
+
export const AGENTS_HEIGHT = 7;
|
package/src/views/Dashboard.tsx
CHANGED
|
@@ -25,19 +25,13 @@ import { AgentsBar } from "~/ui/AgentsBar";
|
|
|
25
25
|
import { BoardView } from "~/ui/BoardView";
|
|
26
26
|
import { TimelineView } from "~/ui/TimelineView";
|
|
27
27
|
import { PlannerPanel } from "~/ui/PlannerPanel";
|
|
28
|
+
import { ModalLayer } from "~/ui/Modal";
|
|
29
|
+
import { AGENDA_WIDTH, AGENTS_HEIGHT } from "~/ui/layout";
|
|
28
30
|
import { AgentsOnly } from "~/views/AgentsOnly";
|
|
29
31
|
import { BoardOnly } from "~/views/BoardOnly";
|
|
30
32
|
import { TimelineOnly } from "~/views/TimelineOnly";
|
|
31
33
|
import type { TuiStore } from "~/store/index";
|
|
32
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;
|
|
39
|
-
/** Row height for the bottom Agents strip — enough for ~5 sessions. */
|
|
40
|
-
const AGENTS_HEIGHT = 7;
|
|
41
35
|
|
|
42
36
|
export function Dashboard(props: { store: TuiStore }) {
|
|
43
37
|
const ui = () => props.store.state.ui;
|
|
@@ -100,10 +94,19 @@ function FourZoneLayout(props: { store: TuiStore }) {
|
|
|
100
94
|
<AgentsBar store={props.store} height={AGENTS_HEIGHT} />
|
|
101
95
|
</Show>
|
|
102
96
|
</box>
|
|
103
|
-
{/* Right column: Agenda
|
|
104
|
-
the
|
|
105
|
-
|
|
106
|
-
|
|
97
|
+
{/* Right column: the Agenda — or, while a modal is open, the modal panel
|
|
98
|
+
in the Agenda's exact slot (same parent, same width). Swapping them in
|
|
99
|
+
place keeps the whole layout and every height constant; nothing
|
|
100
|
+
shifts. The modal still appears here even if the Agenda is disabled. */}
|
|
101
|
+
<Show
|
|
102
|
+
when={ui().modal}
|
|
103
|
+
fallback={
|
|
104
|
+
<Show when={visible().timeline}>
|
|
105
|
+
<TimelineView store={props.store} width={AGENDA_WIDTH} />
|
|
106
|
+
</Show>
|
|
107
|
+
}
|
|
108
|
+
>
|
|
109
|
+
<ModalLayer store={props.store} />
|
|
107
110
|
</Show>
|
|
108
111
|
{/* ModalLayer rendered at App level so it can sit beside any view */}
|
|
109
112
|
</box>
|