@gavin-hu/my-pi-agent 0.20.0 → 0.22.0
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/README.md +46 -30
- package/README.zh-CN.md +40 -25
- package/assets/screens/board.png +0 -0
- package/assets/screens/chrome.png +0 -0
- package/assets/screens/file-browse.png +0 -0
- package/assets/screens/plan-review.png +0 -0
- package/assets/screens/plan.png +0 -0
- package/docs/extensions/README.md +22 -23
- package/docs/extensions/board.md +397 -168
- package/docs/extensions/bytefly.md +234 -197
- package/docs/extensions/check.md +15 -17
- package/docs/extensions/context.md +35 -15
- package/docs/extensions/file-browse.md +57 -63
- package/docs/extensions/file-open.md +9 -11
- package/docs/extensions/file-read.md +12 -14
- package/docs/extensions/goal.md +15 -17
- package/docs/extensions/job.md +54 -42
- package/docs/extensions/memory.md +17 -19
- package/docs/extensions/plan.md +197 -140
- package/docs/extensions/question.md +16 -18
- package/docs/extensions/rewind.md +17 -19
- package/docs/extensions/serve.md +145 -0
- package/docs/extensions/session-bus.md +38 -16
- package/docs/extensions/subagent.md +23 -25
- package/docs/extensions/team.md +83 -44
- package/docs/extensions/todo.md +18 -18
- package/docs/extensions/watch.md +31 -31
- package/docs/extensions/web-access.md +2 -4
- package/docs/extensions/wechat.md +34 -35
- package/docs/extensions/worktree.md +56 -50
- package/extensions/board/commands.ts +79 -25
- package/extensions/board/format.ts +43 -24
- package/extensions/board/index.ts +17 -4
- package/extensions/board/input.ts +4 -9
- package/extensions/board/join.ts +5 -20
- package/extensions/board/lazy-page.ts +40 -0
- package/extensions/board/page.ts +65 -93
- package/extensions/board/result.ts +30 -39
- package/extensions/board/rows.ts +62 -25
- package/extensions/board/schema.ts +49 -11
- package/extensions/board/snapshot.ts +8 -6
- package/extensions/board/tone.ts +22 -0
- package/extensions/board/tools.ts +154 -55
- package/extensions/board/transport/router.ts +3 -5
- package/extensions/board/transport/server.ts +59 -28
- package/extensions/board/types.ts +36 -42
- package/extensions/board/view/card.ts +229 -0
- package/extensions/board/view/client.ts +35 -16
- package/extensions/board/view/dialog.ts +169 -6
- package/extensions/board/view/empty.ts +47 -0
- package/extensions/board/view/keys.ts +13 -2
- package/extensions/board/view/live.ts +90 -28
- package/extensions/board/view/names.ts +13 -4
- package/extensions/board/view/page.ts +38 -13
- package/extensions/board/view/render.ts +219 -277
- package/extensions/board/view/styles.ts +130 -32
- package/extensions/board/view/team.ts +297 -76
- package/extensions/bytefly/block/fallback.ts +1 -1
- package/extensions/bytefly/doctor/runtime.ts +5 -2
- package/extensions/bytefly/footer/collect/label.ts +60 -0
- package/extensions/bytefly/footer/collect/snapshot.ts +8 -1
- package/extensions/bytefly/footer/config.ts +7 -8
- package/extensions/bytefly/footer/register.ts +33 -4
- package/extensions/bytefly/footer/render/footer.ts +18 -4
- package/extensions/bytefly/footer/render/key.ts +46 -0
- package/extensions/bytefly/footer/render/layout.ts +13 -3
- package/extensions/bytefly/footer/render/lines.ts +10 -7
- package/extensions/bytefly/footer/render/segments.ts +41 -38
- package/extensions/bytefly/footer/render/status.ts +0 -11
- package/extensions/bytefly/footer/types.ts +7 -0
- package/extensions/bytefly/header/component.ts +4 -20
- package/extensions/bytefly/header/config.ts +1 -1
- package/extensions/bytefly/index.ts +32 -6
- package/extensions/bytefly/mode/editor.ts +115 -0
- package/extensions/bytefly/panel/commands.ts +210 -120
- package/extensions/bytefly/panel/format.ts +4 -4
- package/extensions/bytefly/panel/settings.ts +73 -6
- package/extensions/bytefly/panel/tui/keys.ts +2 -6
- package/extensions/bytefly/update/cache.ts +1 -1
- package/extensions/bytefly/update/register.ts +4 -4
- package/extensions/bytefly/working/config.ts +5 -7
- package/extensions/bytefly/working/format.ts +10 -13
- package/extensions/bytefly/working/register.ts +22 -27
- package/extensions/check/commands.ts +3 -2
- package/extensions/check/render.ts +10 -1
- package/extensions/check/{tui.ts → view/check-screens.ts} +14 -19
- package/extensions/context/commands.ts +2 -2
- package/extensions/context/{tui.ts → view/context-report.ts} +51 -19
- package/extensions/file-browse/config/config.ts +4 -19
- package/extensions/file-browse/index.ts +89 -79
- package/extensions/file-browse/live/live.ts +1 -1
- package/extensions/file-browse/transport/router.ts +12 -4
- package/extensions/file-browse/transport/server.ts +61 -28
- package/extensions/file-browse/view/chrome.ts +4 -4
- package/extensions/file-browse/view/client.ts +3 -1
- package/extensions/file-browse/view/html.ts +73 -40
- package/extensions/file-browse/view/live-client.ts +2 -2
- package/extensions/file-browse/view/markdown.ts +13 -14
- package/extensions/file-browse/view/palette.ts +2 -2
- package/extensions/file-browse/view/raw-html.ts +9 -9
- package/extensions/file-browse/view/tree.ts +1 -1
- package/extensions/file-browse/view/urls.ts +20 -6
- package/extensions/file-read/render.ts +4 -4
- package/extensions/goal/plan-route.ts +2 -2
- package/extensions/goal/tui.ts +12 -2
- package/extensions/job/child.ts +527 -0
- package/extensions/job/clock.ts +142 -0
- package/extensions/job/commands.ts +4 -2
- package/extensions/job/config.ts +8 -1
- package/extensions/job/format.ts +22 -1
- package/extensions/job/log-writer.ts +13 -2
- package/extensions/job/registry.ts +63 -7
- package/extensions/job/render.ts +34 -0
- package/extensions/job/runtime.ts +296 -655
- package/extensions/job/session.ts +132 -19
- package/extensions/job/store.ts +7 -7
- package/extensions/job/tools.ts +21 -9
- package/extensions/job/types.ts +47 -0
- package/extensions/job/{tui.ts → view/jobs-screen.ts} +19 -99
- package/extensions/job/waiters.ts +44 -1
- package/extensions/memory/commands.ts +4 -2
- package/extensions/memory/{tui.ts → view/memory-picker.ts} +12 -12
- package/extensions/plan/commands.ts +12 -9
- package/extensions/plan/feedback.ts +62 -16
- package/extensions/plan/format.ts +8 -2
- package/extensions/plan/git-bash.ts +115 -16
- package/extensions/plan/index.ts +58 -51
- package/extensions/plan/plan-index.ts +4 -2
- package/extensions/plan/plan-text.ts +114 -0
- package/extensions/plan/plans.ts +5 -54
- package/extensions/plan/policy.ts +8 -10
- package/extensions/plan/review-lazy.ts +85 -0
- package/extensions/plan/review.ts +2 -2
- package/extensions/plan/runtime.ts +61 -41
- package/extensions/plan/sections.ts +1 -1
- package/extensions/plan/steps.ts +3 -3
- package/extensions/plan/todos.ts +1 -1
- package/extensions/plan/tools/cancel.ts +27 -62
- package/extensions/plan/tools/enter.ts +55 -81
- package/extensions/plan/tools/exit.ts +221 -238
- package/extensions/plan/tools/refusal.ts +18 -0
- package/extensions/plan/tools/steps.ts +75 -92
- package/extensions/plan/tools/write.ts +77 -120
- package/extensions/plan/tools.ts +188 -30
- package/extensions/plan/tui.ts +5 -5
- package/extensions/plan/types.ts +48 -5
- package/extensions/plan/web-blocks.ts +76 -5
- package/extensions/plan/web-chrome.ts +4 -0
- package/extensions/plan/web-client.ts +102 -2
- package/extensions/plan/web-collab.ts +4 -4
- package/extensions/plan/web-comments.ts +39 -8
- package/extensions/plan/web-composer.ts +14 -3
- package/extensions/plan/web-keys.ts +149 -25
- package/extensions/plan/web-lazy.ts +53 -0
- package/extensions/plan/web-markdown.ts +10 -68
- package/extensions/plan/web-outline.ts +22 -2
- package/extensions/plan/web-page.ts +56 -86
- package/extensions/plan/web-payload.ts +188 -0
- package/extensions/plan/web-plan.ts +23 -13
- package/extensions/plan/web-router.ts +18 -9
- package/extensions/plan/web-settle.ts +14 -7
- package/extensions/plan/web-share-session.ts +24 -55
- package/extensions/plan/web-share.ts +19 -37
- package/extensions/plan/web-write.ts +112 -0
- package/extensions/plan/web.ts +67 -131
- package/extensions/question/tools.ts +6 -2
- package/extensions/question/{tui.ts → view/question-screen.ts} +11 -11
- package/extensions/rewind/commands/commands.ts +6 -3
- package/extensions/rewind/state/runtime.ts +1 -1
- package/extensions/rewind/{view/status.ts → status.ts} +4 -4
- package/extensions/rewind/view/review-tui.ts +4 -4
- package/extensions/serve/config.ts +39 -0
- package/extensions/serve/index.ts +85 -0
- package/extensions/serve/registry.ts +260 -0
- package/extensions/session-bus/commands.ts +11 -6
- package/extensions/session-bus/join-request.ts +17 -9
- package/extensions/session-bus/mail-watch.ts +26 -17
- package/extensions/session-bus/protocol.ts +15 -3
- package/extensions/session-bus/resolve.ts +5 -7
- package/extensions/session-bus/result.ts +1 -27
- package/extensions/session-bus/runtime.ts +40 -12
- package/extensions/session-bus/store.ts +101 -19
- package/extensions/session-bus/tools.ts +5 -4
- package/extensions/session-bus/types.ts +19 -0
- package/extensions/session-bus/{tui.ts → view/session-list.ts} +16 -16
- package/extensions/subagent/agents.ts +1 -1
- package/extensions/subagent/commands.ts +4 -2
- package/extensions/subagent/format.ts +15 -15
- package/extensions/subagent/index.ts +1 -1
- package/extensions/subagent/render.ts +3 -3
- package/extensions/subagent/{background-tui.ts → view/agents-board.ts} +11 -11
- package/extensions/team/commands.ts +24 -5
- package/extensions/team/dispatch.ts +18 -4
- package/extensions/team/format.ts +17 -2
- package/extensions/team/index.ts +9 -8
- package/extensions/team/schema.ts +6 -5
- package/extensions/team/tools.ts +107 -45
- package/extensions/team/types.ts +3 -2
- package/extensions/todo/commands.ts +4 -2
- package/extensions/todo/format.ts +11 -0
- package/extensions/todo/render.ts +57 -0
- package/extensions/todo/runtime.ts +1 -1
- package/extensions/todo/tools.ts +1 -1
- package/extensions/todo/{tui.ts → view/todo-screen.ts} +18 -90
- package/extensions/todo/widget.ts +47 -0
- package/extensions/watch/commands.ts +4 -2
- package/extensions/watch/format.ts +36 -7
- package/extensions/watch/render.ts +57 -0
- package/extensions/watch/runtime.ts +27 -22
- package/extensions/watch/tools.ts +4 -4
- package/extensions/watch/{tui.ts → view/watch-screen.ts} +18 -80
- package/extensions/web-access/fetch/tool.ts +12 -4
- package/extensions/wechat/commands/commands.ts +18 -14
- package/extensions/wechat/index.ts +72 -37
- package/extensions/wechat/state/credentials.ts +1 -1
- package/extensions/wechat/state/state.ts +1 -1
- package/extensions/wechat/text/status.ts +112 -0
- package/extensions/wechat/types.ts +2 -2
- package/extensions/wechat/view/status-screen.ts +4 -103
- package/extensions/worktree/commands.ts +11 -9
- package/extensions/worktree/enter.ts +2 -2
- package/extensions/worktree/exit.ts +2 -2
- package/extensions/worktree/index.ts +5 -5
- package/extensions/worktree/screen.ts +3 -3
- package/extensions/worktree/status.ts +2 -2
- package/extensions/worktree/tools.ts +113 -116
- package/lib/README.md +28 -13
- package/lib/board/actions.ts +111 -0
- package/lib/board/artifact.ts +149 -0
- package/lib/board/card.ts +163 -52
- package/lib/board/config.ts +58 -0
- package/lib/board/contract.ts +113 -0
- package/lib/board/join.ts +38 -0
- package/lib/board/lanes.ts +182 -0
- package/lib/board/lead.ts +130 -0
- package/lib/board/limits.ts +78 -0
- package/lib/board/links.ts +31 -10
- package/lib/board/page-pointer.ts +30 -5
- package/lib/board/read.ts +83 -0
- package/lib/board/reason.ts +102 -0
- package/lib/board/round-text.ts +68 -6
- package/lib/board/round.ts +31 -15
- package/lib/board/rules.ts +151 -307
- package/lib/board/seat.ts +35 -0
- package/lib/board/session.ts +199 -51
- package/lib/board/skipped.ts +22 -0
- package/lib/board/steps.ts +487 -0
- package/lib/board/store.ts +119 -36
- package/lib/board/tone.ts +92 -0
- package/lib/board/view.ts +81 -63
- package/lib/bus-request.ts +83 -0
- package/{extensions/watch → lib}/child.ts +40 -21
- package/lib/env.ts +65 -7
- package/lib/format.ts +13 -0
- package/lib/http/index.ts +17 -11
- package/lib/http/mount.ts +142 -0
- package/lib/http/port.ts +30 -0
- package/lib/http/serve.ts +170 -46
- package/lib/http/server.ts +3 -3
- package/lib/lazy.ts +45 -0
- package/lib/plan-entry.ts +46 -21
- package/lib/plans/paths.ts +82 -0
- package/lib/policy.ts +9 -6
- package/lib/report.ts +3 -2
- package/lib/requirements.ts +10 -10
- package/lib/session-label.ts +129 -7
- package/lib/session-roster.ts +43 -1
- package/lib/session-tool.ts +39 -22
- package/lib/stray-fields.ts +7 -2
- package/lib/tool-names.ts +5 -10
- package/lib/tui/README.md +29 -11
- package/lib/tui/chrome.ts +16 -15
- package/lib/tui/cursor.ts +18 -3
- package/lib/tui/glyphs.ts +11 -11
- package/lib/tui/render-cache.ts +29 -0
- package/lib/tui/tokens.ts +33 -2
- package/lib/tui/tool.ts +33 -4
- package/lib/web/README.md +21 -0
- package/lib/web/client-runtime.ts +27 -1
- package/lib/web/components.ts +5 -1
- package/lib/web/index.ts +1 -0
- package/lib/web/markdown.ts +83 -0
- package/lib/web/markup.ts +20 -2
- package/lib/web/runtime.ts +9 -10
- package/package.json +8 -2
- package/skills/init/SKILL.md +5 -5
- package/skills/next/SKILL.md +3 -5
- package/extensions/board/config.ts +0 -36
- package/extensions/board/seat.ts +0 -28
- package/lib/tui/index.ts +0 -34
- package/skills/project-docs/SKILL.md +0 -133
- package/skills/project-docs/references/audit.md +0 -131
- package/skills/project-docs/references/changelog.md +0 -105
- package/skills/project-docs/references/discovery.md +0 -127
- package/skills/project-docs/references/readme.md +0 -80
- package/skills/project-docs/references/release.md +0 -84
- package/skills/project-docs/references/roadmap.md +0 -93
- package/skills/project-docs/scripts/state.ts +0 -316
|
@@ -6,14 +6,58 @@
|
|
|
6
6
|
* follows the theme and `lib/web/web.test.ts`'s "draws every colour through a token"
|
|
7
7
|
* rule holds without an exception here. Colour is a role: a lane's dot, its head,
|
|
8
8
|
* and the reason line read `--muted`, `--accent`, `--danger`, and `--success`
|
|
9
|
-
* through `data-
|
|
9
|
+
* through `data-lane`, never a literal.
|
|
10
10
|
*
|
|
11
11
|
* The sheet is in three parts, in the order the page stacks: the toolbar, the
|
|
12
12
|
* board (lanes, cards, and the Team tables), then its dialogs.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
import { LANE_RULES, LANES } from "../../../lib/board/lanes.ts";
|
|
16
|
+
import { BOARD_TONES } from "../../../lib/board/tone.ts";
|
|
15
17
|
import { WEB_BASE_CSS, WEB_COMPONENTS_CSS, WEB_LAYOUT_CSS, WEB_THEME_CSS } from "../../../lib/web/index.ts";
|
|
16
18
|
|
|
19
|
+
/**
|
|
20
|
+
* A lane's colour, from the lane table: one role per lane, worn by the dot on its head and
|
|
21
|
+
* by the same dot in a card's dialog.
|
|
22
|
+
*
|
|
23
|
+
* Generated rather than written five times, so a lane added to `LANES` arrives with its
|
|
24
|
+
* colour and the two rules cannot drift from the table's `role`.
|
|
25
|
+
*/
|
|
26
|
+
const LANE_ROLE_CSS = LANES.flatMap((lane) => {
|
|
27
|
+
const role = LANE_RULES[lane].role;
|
|
28
|
+
return [
|
|
29
|
+
`.board-lane[data-lane="${lane}"] .board-lane__dot{background:var(--${role})}`,
|
|
30
|
+
`.board-dialog__state[data-lane="${lane}"]::before{background:var(--${role})}`,
|
|
31
|
+
];
|
|
32
|
+
}).join("\n");
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A reason line's colour, one rule per tone the tone table names.
|
|
36
|
+
*
|
|
37
|
+
* The card face picks a tone from the reason's kind; it never picks a class named after the
|
|
38
|
+
* kind, so a card owing a spot-check is not drawn with a rule that says "unplanned".
|
|
39
|
+
*/
|
|
40
|
+
const REASON_TONE_CSS = BOARD_TONES.map((tone) => `.board-card__reason--${tone}{color:var(--${tone})}`).join("\n");
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A decision row's edge, one rule per tone the table names.
|
|
44
|
+
*
|
|
45
|
+
* Generated from the same table the terminal reads, so `gone` — ranked above `idle` — wears
|
|
46
|
+
* the refusal colour by being classified, not by a rule somebody remembered to add.
|
|
47
|
+
*/
|
|
48
|
+
const DECISION_TONE_CSS = BOARD_TONES.map(
|
|
49
|
+
(tone) => `.board-team__decision[data-tone="${tone}"]{border-left-color:var(--${tone})}`,
|
|
50
|
+
).join("\n");
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The one tone whose sentence is coloured too.
|
|
54
|
+
*
|
|
55
|
+
* A danger row is a refusal or a loss, and that is the row's whole point; a warn row is
|
|
56
|
+
* somebody to ask, and colouring its sentence as well would spend the reader's attention on
|
|
57
|
+
* the words rather than on the edge that says "look here".
|
|
58
|
+
*/
|
|
59
|
+
const DECISION_WHY_CSS = `.board-team__decision[data-tone="danger"] .board-team__why{color:var(--danger)}`;
|
|
60
|
+
|
|
17
61
|
/** The shared shell, the components, and the board's own layout. */
|
|
18
62
|
export const BOARD_CSS = `${WEB_BASE_CSS}
|
|
19
63
|
${WEB_THEME_CSS}
|
|
@@ -31,12 +75,16 @@ ${WEB_COMPONENTS_CSS}
|
|
|
31
75
|
.board-picker{display:none;margin-bottom:var(--space-3)}
|
|
32
76
|
|
|
33
77
|
/* The main pane is this page's only child of the shell, so it grows to fill the
|
|
34
|
-
column and the footer stays at the bottom however short the board is.
|
|
35
|
-
|
|
78
|
+
column and the footer stays at the bottom however short the board is. Its top
|
|
79
|
+
padding moves to the panels: a sticky head pins to the scroll box's padding
|
|
80
|
+
edge, so a gutter above it is a strip a card scrolls through unheaded. */
|
|
81
|
+
.board-main{flex:1 1 auto;padding-top:0}
|
|
36
82
|
/* One panel per tab; the shell's main pane is the only scroll box. */
|
|
37
|
-
.board-panel{display:flex;flex-direction:column;min-width:0}
|
|
83
|
+
.board-panel{display:flex;flex-direction:column;min-width:0;padding-top:var(--space-5)}
|
|
38
84
|
.board-panel[hidden]{display:none}
|
|
39
85
|
.board-no-cards{max-width:32rem;margin:auto;padding:var(--space-8) var(--space-6)}
|
|
86
|
+
/* One way back out of a filter that matched nothing, under the sentence that says so. */
|
|
87
|
+
.board-no-cards .bf-btn{margin-top:var(--space-2)}
|
|
40
88
|
|
|
41
89
|
/* Lanes: trays of cards, each with a head that sticks while the pane scrolls. A lane is
|
|
42
90
|
sized by the work it holds rather than by its share of the row, so one holding nothing
|
|
@@ -50,44 +98,75 @@ ${WEB_COMPONENTS_CSS}
|
|
|
50
98
|
one — and the floor is the narrowest a tray is still a tray at. It is set on the two
|
|
51
99
|
states that draw one, so a rail keeps its own width, and both breakpoints below
|
|
52
100
|
replace the basis, so the floor only ever applies to the row it was chosen for:
|
|
53
|
-
|
|
54
|
-
.board-lane[data-empty="false"][data-folded="false"]{min-width:
|
|
101
|
+
five lanes at 1180px are 60rem, which is inside the row before the wrap. */
|
|
102
|
+
.board-lane[data-empty="false"][data-folded="false"]{min-width:12rem}
|
|
103
|
+
/* Except finished work: it is history, and a lane of five finished cards used to take
|
|
104
|
+
half the row while the one card still being worked sat on the floor and elided its
|
|
105
|
+
own title. A done lane draws as if it held three cards, however many it holds. */
|
|
106
|
+
.board-lane[data-lane="done"]{flex-grow:calc(1 + min(3, var(--lane-count)))}
|
|
55
107
|
/* The rail: a dot, a word, and a count — the fact that the lane is showing nothing, not a
|
|
56
108
|
tray. A lane is a rail when it holds no cards and when it is folded, because both say
|
|
57
109
|
the same thing: there is nothing here to read. */
|
|
58
110
|
.board-lane[data-empty="true"],.board-lane[data-folded="true"]{flex:0 0 8.5rem}
|
|
59
111
|
.board-lane__head{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:var(--space-2);margin:0 calc(-1 * var(--space-2)) var(--space-1);padding:var(--space-2) var(--space-2);background:var(--surface);border-bottom:1px solid var(--border);border-radius:var(--radius-lg) var(--radius-lg) 0 0;font:var(--fw-semibold) var(--fs-xs) var(--font-ui);letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
|
|
60
|
-
|
|
112
|
+
/* The fold control is the only thing in the head that acts, and a 16px line is a poor target:
|
|
113
|
+
the padding gives it 24px without growing the row it sits in. */
|
|
114
|
+
.board-lane__toggle{appearance:none;display:flex;align-items:center;gap:var(--space-2);border:0;background:none;padding:4px 0;margin:-4px 0;min-height:24px;font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit;cursor:pointer}
|
|
61
115
|
.board-lane__toggle:hover{color:var(--accent)}
|
|
62
116
|
.board-lane__toggle::after{content:"▾";margin-left:2px;font-size:var(--fs-sm);color:var(--muted)}
|
|
63
117
|
.board-lane__toggle:hover::after{color:var(--accent)}
|
|
64
118
|
.board-lane__toggle[aria-expanded="false"]::after{content:"▸"}
|
|
65
119
|
.board-lane__count{font-variant-numeric:tabular-nums;color:var(--muted);background:var(--canvas);border-radius:var(--radius-pill);padding:0 var(--space-2);font-size:var(--fs-xs);letter-spacing:0}
|
|
66
120
|
.board-lane__dot{width:var(--space-2);height:var(--space-2);border-radius:var(--radius-pill);background:var(--muted)}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
121
|
+
${LANE_ROLE_CSS}
|
|
122
|
+
${DECISION_TONE_CSS}
|
|
123
|
+
${DECISION_WHY_CSS}
|
|
70
124
|
.board-lane__list{display:flex;flex-direction:column;gap:var(--space-3);margin:0;padding:0;list-style:none}
|
|
71
|
-
.board-lane__empty{margin:0;font:var(--fs-sm) var(--font-ui);color:var(--
|
|
125
|
+
.board-lane__empty{margin:0;font:var(--fs-sm) var(--font-ui);color:var(--muted)}
|
|
72
126
|
|
|
73
127
|
/* A card: the title, then the facts a reader needs to act on it. Its lane says
|
|
74
128
|
which state it is in, so the card itself carries no second colour bar. */
|
|
75
|
-
.board-card{display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-3);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--canvas);transition:border-color var(--motion-fast) var(--motion-ease),transform var(--motion-fast) var(--motion-ease)}
|
|
129
|
+
.board-card{display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-3);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--canvas);cursor:pointer;transition:border-color var(--motion-fast) var(--motion-ease),transform var(--motion-fast) var(--motion-ease)}
|
|
76
130
|
.board-card:hover{border-color:var(--border-strong);transform:translateY(-1px)}
|
|
77
131
|
.board-card[hidden]{display:none}
|
|
78
132
|
.board-card__head{display:flex;align-items:baseline;gap:var(--space-2);margin:0;min-width:0}
|
|
79
133
|
.board-card__id{font:var(--fs-xs) var(--font-mono);color:var(--dim)}
|
|
80
|
-
.board-card__title{margin:0;padding:0;border:0;background:none;text-align:left;cursor:pointer;font:var(--fw-semibold) var(--fs-base)/var(--lh-snug) var(--font-ui);color:var(--text);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
|
134
|
+
.board-card__title{margin:0;padding:0;border:0;background:none;text-align:left;cursor:pointer;font:var(--fw-semibold) var(--fs-base)/var(--lh-snug) var(--font-ui);color:var(--text);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
|
|
81
135
|
.board-card__title:hover{color:var(--accent)}
|
|
82
136
|
/* Finished work recedes: it is history, and the live lanes should not compete with it. */
|
|
83
|
-
.board-card[data-
|
|
84
|
-
.board-card[data-
|
|
85
|
-
.board-card[data-
|
|
137
|
+
.board-card[data-lane="done"] .board-card__title{color:var(--muted)}
|
|
138
|
+
.board-card[data-lane="done"] .board-card__title:hover{color:var(--accent)}
|
|
139
|
+
.board-card[data-lane="done"] .bf-chip--accent{color:var(--muted);border-color:var(--border)}
|
|
86
140
|
.board-card__meta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2);margin:0;font:var(--fs-xs) var(--font-ui);color:var(--muted)}
|
|
87
|
-
|
|
141
|
+
/* How much history the card carries and how recent it is: a count and a stamp, in the
|
|
142
|
+
meta line's own voice, so a card with ten notes cannot look like one with none. */
|
|
143
|
+
.board-card__notes{display:inline-flex;align-items:baseline;gap:var(--space-1);font-variant-numeric:tabular-nums}
|
|
144
|
+
.board-card__paths{display:flex;flex-wrap:wrap;gap:var(--space-1) var(--space-2);margin:0;padding:0;list-style:none}
|
|
145
|
+
/* A chip is one line and nowrap by design, so an owner label or a path longer than the card
|
|
146
|
+
would spill past its border and across the lane beside it: clipped to the card instead,
|
|
147
|
+
with the whole of it on the hover title the renderer sets. The list item has to be the one
|
|
148
|
+
that shrinks, because a flex item's automatic minimum is its chip's width. */
|
|
149
|
+
.board-card__paths li{min-width:0;max-width:100%}
|
|
150
|
+
.board-card .bf-chip{display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis}
|
|
151
|
+
/* A path is something a reader types, so it wears the mono face the dialog's ladder uses. */
|
|
152
|
+
.board-card__paths .bf-chip{font-family:var(--font-mono)}
|
|
88
153
|
.board-card__reason{margin:0;font:var(--fs-sm)/var(--lh-snug) var(--font-ui);color:var(--muted);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
|
|
89
|
-
|
|
90
|
-
.
|
|
154
|
+
/* The tone rules come *after* the base rule, and that is load-bearing: a tone class is one
|
|
155
|
+
class and so is the base, so the later of two equal selectors wins. Generated before it,
|
|
156
|
+
every tone was inert and a blocked card's reason drew muted — the one thing this table
|
|
157
|
+
exists to stop. The pages suite pins the order, not just the rule's presence. */
|
|
158
|
+
${REASON_TONE_CSS}
|
|
159
|
+
|
|
160
|
+
/* The other side of a link: what leaving this card undone holds up. It is a cost and not a
|
|
161
|
+
verdict, so it stays in the card's own voice: warn already means "a reader has to decide",
|
|
162
|
+
and a card can hold others up while nothing about it needs deciding. */
|
|
163
|
+
.board-card__holds{margin:0;font:var(--fs-sm)/var(--lh-snug) var(--font-ui);color:var(--muted);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
|
|
164
|
+
/* Where the reader has been: j/k walks the drawn cards and wraps, so a lane walked and
|
|
165
|
+
come back to looked exactly like a lane arriving for the first time. A read card keeps
|
|
166
|
+
a quiet edge and the one the reader is on wears the accent one — after the hover rule,
|
|
167
|
+
so the mark outlives the pointer that made it. */
|
|
168
|
+
.board-card[data-visited="true"]{box-shadow:inset 3px 0 0 var(--border-strong)}
|
|
169
|
+
.board-card[data-current="true"]{border-color:var(--accent);box-shadow:inset 3px 0 0 var(--accent)}
|
|
91
170
|
|
|
92
171
|
/* The Team tab: a queue and a roster side by side, then one quiet strip. */
|
|
93
172
|
.board-team{display:grid;gap:var(--space-5);min-width:0}
|
|
@@ -99,19 +178,20 @@ ${WEB_COMPONENTS_CSS}
|
|
|
99
178
|
/* The queue: one row per card, its kind as an edge, its way out in the foot. */
|
|
100
179
|
.board-team__queue{display:flex;flex-direction:column;gap:var(--space-2);min-width:0}
|
|
101
180
|
/* The queue is the tallest thing here and it can be unbounded; capping it keeps the two
|
|
102
|
-
panels on one screen.
|
|
103
|
-
|
|
181
|
+
panels on one screen. The roster can be unbounded the same way — a board with a long
|
|
182
|
+
history names an owner per label that ever claimed a card — so it takes the same cap and
|
|
183
|
+
the same shade. Stacked below 1180px there is no second column to balance, and a nested
|
|
184
|
+
scroll on a phone is worse than the page's own. */
|
|
104
185
|
@media (min-width:1181px){
|
|
105
186
|
/* A row cut at the edge reads as a bug unless something says the list continues, and a
|
|
106
187
|
mac's scrollbars are hidden until it moves: an inset shade in the page's own colour
|
|
107
188
|
marks the edge without a literal. */
|
|
108
189
|
/* A floor, because a short window must not turn three rows into a scroll box. */
|
|
109
|
-
.board-team__queue{max-height:max(18rem,calc(100dvh - 16rem));overflow:auto;overscroll-behavior:contain;padding-right:var(--space-1);box-shadow:inset 0 calc(-1 * var(--space-6)) var(--space-6) calc(-1 * var(--space-6)) var(--canvas)}
|
|
190
|
+
.board-team__queue,.board-team__roster{max-height:max(18rem,calc(100dvh - 16rem));overflow:auto;overscroll-behavior:contain;padding-right:var(--space-1);box-shadow:inset 0 calc(-1 * var(--space-6)) var(--space-6) calc(-1 * var(--space-6)) var(--canvas)}
|
|
110
191
|
}
|
|
111
192
|
.board-team__decision{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"open foot" "why why";align-items:center;gap:var(--space-1) var(--space-3);padding:var(--space-2) var(--space-3);background:var(--raised);border:1px solid var(--border);border-left:3px solid var(--dim);border-radius:var(--radius-md);transition:border-color var(--motion-base) var(--motion-ease),transform var(--motion-base) var(--motion-ease)}
|
|
112
193
|
.board-team__decision:hover{border-color:var(--border-strong);transform:translateY(-1px)}
|
|
113
|
-
.
|
|
114
|
-
.board-team__decision[data-kind="idle"]{border-left-color:var(--warn)}
|
|
194
|
+
/* The edge's colour comes from the row's tone, spliced below from the board's tone table. */
|
|
115
195
|
/* Nobody holds it, so the edge is drawn but not filled: a shape, not a claim. */
|
|
116
196
|
.board-team__decision[data-kind="unassigned"]{border-left-style:dashed}
|
|
117
197
|
.board-team__open{grid-area:open;display:flex;align-items:baseline;gap:var(--space-2);appearance:none;border:0;background:none;padding:0;margin:0;text-align:left;cursor:pointer;color:var(--text);font:var(--fw-medium) var(--fs-md) var(--font-ui);min-width:0}
|
|
@@ -120,7 +200,6 @@ ${WEB_COMPONENTS_CSS}
|
|
|
120
200
|
.board-team__title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
|
|
121
201
|
/* Two lines, then a tooltip: the "why" is the reason the row is on this tab. */
|
|
122
202
|
.board-team__why{grid-area:why;margin:0;color:var(--muted);font:var(--fs-sm)/var(--lh-snug) var(--font-ui);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
|
|
123
|
-
.board-team__why--blocked{color:var(--danger)}
|
|
124
203
|
.board-team__foot{grid-area:foot;display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2)}
|
|
125
204
|
/* A row with no owner chip still puts its one action on the row's edge. */
|
|
126
205
|
.board-team__foot>.bf-btn:only-child{margin-left:auto}
|
|
@@ -128,6 +207,9 @@ ${WEB_COMPONENTS_CSS}
|
|
|
128
207
|
.board-team__roster{display:flex;flex-direction:column;gap:var(--space-1);margin:0;padding:0;list-style:none;min-width:0}
|
|
129
208
|
/* No row rule: the caption already delimits the list, and a second hairline beside it
|
|
130
209
|
was the same pen drawn twice. */
|
|
210
|
+
/* One row is one line: the name shrinks, the metrics take the rest, and a narrow column
|
|
211
|
+
wraps them under the name rather than clipping either. A row that always broke after the
|
|
212
|
+
name cost 56px, which is what made a roster of twenty a wall. */
|
|
131
213
|
.board-team__mate{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-1) var(--space-2);padding:var(--space-2) 0;min-width:0}
|
|
132
214
|
.board-team__dot{width:8px;height:8px;border-radius:var(--radius-pill);background:var(--muted);flex:0 0 auto;align-self:center}
|
|
133
215
|
.board-team__mate[data-state="live"] .board-team__dot{background:var(--success)}
|
|
@@ -136,14 +218,25 @@ ${WEB_COMPONENTS_CSS}
|
|
|
136
218
|
.board-team__mate[data-state="gone"] .board-team__dot{background:var(--danger)}
|
|
137
219
|
/* A record that is not there is a hollow ring, never a colour that claims it is. */
|
|
138
220
|
.board-team__mate[data-state="absent"] .board-team__dot,.board-team__mate[data-state="unknown"] .board-team__dot{background:transparent;box-shadow:inset 0 0 0 1px var(--border-strong)}
|
|
139
|
-
.board-team__name{font:var(--fw-medium) var(--fs-md) var(--font-ui);color:var(--text)}
|
|
140
|
-
.board-team__mets{flex:1 0
|
|
221
|
+
.board-team__name{font:var(--fw-medium) var(--fs-md) var(--font-ui);color:var(--text);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
222
|
+
.board-team__mets{flex:1 1 auto;min-width:0;margin:0;text-align:right;color:var(--muted);font:var(--fs-xs) var(--font-ui)}
|
|
141
223
|
.board-team__empty{margin:0;color:var(--muted);font:var(--fs-sm) var(--font-ui)}
|
|
224
|
+
/* The roster's one control: the owners the bus has no record of, counted in one row and
|
|
225
|
+
opened from it. Full width, because it stands for a group of rows rather than a row. */
|
|
226
|
+
.board-team__tail{display:flex;flex:1 1 100%;align-items:center;gap:var(--space-2);appearance:none;border:0;background:none;padding:0;margin:0;min-height:24px;cursor:pointer;text-align:left;color:var(--muted);font:var(--fs-md) var(--font-ui);text-decoration:underline dotted;text-underline-offset:3px}
|
|
227
|
+
.board-team__tail:hover{color:var(--text);text-decoration:underline}
|
|
228
|
+
/* The strip's ids past the sixth: one span, hidden whole, so the count that opens them
|
|
229
|
+
controls a single node. Its contents are the strip's own flex items, which is what gives
|
|
230
|
+
them the strip's gap and wrapping rather than jamming #7#8#9 together. */
|
|
231
|
+
.board-team__ids{display:contents}
|
|
232
|
+
/* The strip's count is its fold control: the number is what says how much is out of sight. */
|
|
233
|
+
.board-team__fold{appearance:none;border:0;background:none;padding:5px 8px;margin:-5px -8px;min-height:24px;cursor:pointer;color:var(--muted);font:var(--fs-sm) var(--font-ui);text-decoration:underline dotted;text-underline-offset:3px}
|
|
234
|
+
.board-team__fold:hover{color:var(--accent);text-decoration:underline}
|
|
142
235
|
/* Done stays quiet; its ids are buttons only because they open their card. */
|
|
143
236
|
.board-team__done{margin:0;font:var(--fs-sm) var(--font-ui);color:var(--muted);display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-2)}
|
|
144
237
|
/* An id in the Done strip is a button, so it wears the only affordance it has: a
|
|
145
238
|
dotted line, visible before the pointer arrives. */
|
|
146
|
-
.board-team__id{appearance:none;border:0;background:none;padding:
|
|
239
|
+
.board-team__id{appearance:none;border:0;background:none;padding:5px 8px;margin:-5px -8px;min-height:24px;cursor:pointer;font:var(--fs-sm) var(--font-mono);color:var(--muted);text-decoration:underline dotted;text-underline-offset:3px}
|
|
147
240
|
.board-team__id:hover{color:var(--accent);text-decoration:underline}
|
|
148
241
|
|
|
149
242
|
/* The card dialog: the record of one card, in two named sections. Nothing here scrolls on
|
|
@@ -184,12 +277,10 @@ ${WEB_COMPONENTS_CSS}
|
|
|
184
277
|
/* Who and when is the footnote of the note above it. */
|
|
185
278
|
.board-dialog__note-foot{display:flex;align-items:baseline;gap:var(--space-2);margin:0;max-width:68ch}
|
|
186
279
|
.board-dialog__note-by{font:var(--fw-medium) var(--fs-xs) var(--font-ui);color:var(--muted)}
|
|
187
|
-
.board-dialog__note-at{font:var(--fs-xs) var(--font-mono);color:var(--
|
|
280
|
+
.board-dialog__note-at{font:var(--fs-xs) var(--font-mono);color:var(--muted)}
|
|
188
281
|
.board-dialog__state{display:inline-flex;align-items:center;gap:var(--space-2);font:var(--fs-xs) var(--font-ui);letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
|
|
189
282
|
.board-dialog__state::before{content:"";width:var(--space-2);height:var(--space-2);border-radius:var(--radius-pill);background:var(--muted)}
|
|
190
|
-
|
|
191
|
-
.board-dialog__state[data-status="blocked"]::before{background:var(--danger)}
|
|
192
|
-
.board-dialog__state[data-status="done"]::before{background:var(--success)}
|
|
283
|
+
|
|
193
284
|
.board-skeleton{height:4.5rem;border:1px dashed var(--border);border-radius:var(--radius-md);background:var(--surface)}
|
|
194
285
|
|
|
195
286
|
@media (max-width:1180px){
|
|
@@ -214,6 +305,13 @@ ${WEB_COMPONENTS_CSS}
|
|
|
214
305
|
.board-filter{order:9;width:100%}
|
|
215
306
|
.board-team__foot{flex-wrap:wrap}
|
|
216
307
|
}
|
|
308
|
+
/* Five lane names do not fit a phone: the strip becomes wrapped pills rather than a
|
|
309
|
+
horizontal scroller that can hide the lane a reader is on. */
|
|
310
|
+
@media (max-width:420px){
|
|
311
|
+
.board-picker{flex-wrap:wrap;border:0;background:none;gap:var(--space-1)}
|
|
312
|
+
.board-picker .bf-segmented__item{border:1px solid var(--border);border-radius:var(--radius-pill);padding:5px 10px}
|
|
313
|
+
.board-picker .bf-segmented__item[aria-pressed="true"]{border-color:var(--accent)}
|
|
314
|
+
}
|
|
217
315
|
@media (prefers-reduced-motion: reduce){
|
|
218
316
|
.board-card,.board-team__decision{transition:none}
|
|
219
317
|
.board-card:hover,.board-team__decision:hover{transform:none}
|