@spunto/design-system 0.12.0 → 0.13.1
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 +8 -1
- package/package.json +1 -1
- package/src/components/projects/repo-list.tsx +22 -5
- package/src/components/projects/types.ts +7 -0
- package/src/components/workers/git-branch-chips.tsx +30 -7
- package/src/components/workers/index.ts +2 -2
- package/src/components/workers/types.ts +6 -0
- package/src/components/workers/worker-card.tsx +8 -2
package/README.md
CHANGED
|
@@ -120,7 +120,14 @@ panel are the same concept seen twice, so they share `/projects`.
|
|
|
120
120
|
differently: `WorkerStatusDot`/`WorkerStatusPill` (+`resolveWorkerStatus`,
|
|
121
121
|
`workerStatusConfig`), `SetupProgress` (+`setupProgress`, `phaseLabel`,
|
|
122
122
|
`setupTotalMs`), `StepIndicator`, `ResourceBars`, `GitBranchChips`/
|
|
123
|
-
`GitStatusSummary`, `TagChips` (+`tagColor`),
|
|
123
|
+
`GitStatusSummary`/`RequestedBranchChip`, `TagChips` (+`tagColor`),
|
|
124
|
+
`CreatorAvatar`.
|
|
125
|
+
- **What a worker is working on, in two tenses**: `gitStatus` is what it *did*
|
|
126
|
+
check out (a chip per repo) and `worker.branch` is what it was *asked* to
|
|
127
|
+
check out. The live status wins as soon as it exists; until then — during
|
|
128
|
+
setup, and on a stopped worker — the requested branch holds its place as a
|
|
129
|
+
lone chip (`RequestedBranchChip`), in the same shell so it reads as the same
|
|
130
|
+
kind of information.
|
|
124
131
|
- **Types are structural**, never the apps' OpenAPI types: the dashboard and
|
|
125
132
|
Spunto Lite model a worker differently, so `WorkerCardWorker` asks for the
|
|
126
133
|
minimum, everything optional but `id`, and an unknown state falls back to
|
package/package.json
CHANGED
|
@@ -130,10 +130,15 @@ export function RepoList({
|
|
|
130
130
|
return (
|
|
131
131
|
<div className={cn("@container/repos space-y-2", className)}>
|
|
132
132
|
{repos.length > 0 && (
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
// The header mirrors the ROW's flex rules rather than being a grid of
|
|
134
|
+
// its own — the rows stopped being a grid when they had to wrap on a
|
|
135
|
+
// phone, and a grid header over flex rows puts every label next to the
|
|
136
|
+
// wrong field. `size-8` spacer = the width of the row's icon button.
|
|
137
|
+
<div className="mb-1 hidden gap-2 px-1 text-xs text-muted-foreground @min-[34rem]/repos:flex">
|
|
138
|
+
<span className="min-w-0 flex-1">Repository</span>
|
|
139
|
+
<span className="min-w-0 flex-1">Workspace path</span>
|
|
140
|
+
<span className="min-w-0 flex-1 @min-[30rem]/repos:max-w-[9rem]">Branch</span>
|
|
141
|
+
<span className="size-8 shrink-0" />
|
|
137
142
|
</div>
|
|
138
143
|
)}
|
|
139
144
|
|
|
@@ -194,6 +199,17 @@ export function RepoList({
|
|
|
194
199
|
onChange={(e) => patch(repo.id, { workspacePath: e.target.value, workspacePathTouched: true })}
|
|
195
200
|
/>
|
|
196
201
|
|
|
202
|
+
<Input
|
|
203
|
+
placeholder="default"
|
|
204
|
+
aria-label="Branch"
|
|
205
|
+
title="Branch checked out when a worker clones this repo — empty for the remote's default branch"
|
|
206
|
+
// Narrower than the other two and last to get space: a branch name
|
|
207
|
+
// is short, and "default" is the answer most rows keep.
|
|
208
|
+
className="min-w-0 flex-1 font-mono text-xs @min-[30rem]/repos:max-w-[9rem]"
|
|
209
|
+
value={repo.branch ?? ""}
|
|
210
|
+
onChange={(e) => patch(repo.id, { branch: e.target.value })}
|
|
211
|
+
/>
|
|
212
|
+
|
|
197
213
|
<Button
|
|
198
214
|
type="button"
|
|
199
215
|
variant="ghost"
|
|
@@ -235,7 +251,8 @@ export function RepoList({
|
|
|
235
251
|
</div>
|
|
236
252
|
|
|
237
253
|
<p className="text-xs text-muted-foreground">
|
|
238
|
-
Cloned into <code>/workspace/<path></code> at worker startup
|
|
254
|
+
Cloned into <code>/workspace/<path></code> at worker startup, on the branch set here (empty = the
|
|
255
|
+
remote's default).{" "}
|
|
239
256
|
{connectUrl &&
|
|
240
257
|
(github?.connected ? (
|
|
241
258
|
<a href={connectUrl} className="underline underline-offset-2">
|
|
@@ -27,6 +27,13 @@ export interface ProjectRepo {
|
|
|
27
27
|
installationId?: number
|
|
28
28
|
/** Raw clone URL, `git` provider only. */
|
|
29
29
|
cloneUrl?: string
|
|
30
|
+
/**
|
|
31
|
+
* Branch checked out when a worker clones this repo. Empty/absent = the
|
|
32
|
+
* remote's default — which is why it's a plain optional string and not a
|
|
33
|
+
* required field with a magic "main" default: we don't know the remote's
|
|
34
|
+
* default, and guessing it wrong is worse than deferring to it.
|
|
35
|
+
*/
|
|
36
|
+
branch?: string
|
|
30
37
|
}
|
|
31
38
|
|
|
32
39
|
/** A devcontainer feature, as the form carries it. */
|
|
@@ -35,6 +35,14 @@ export function repoName(repo: GitRepoStatus): string {
|
|
|
35
35
|
return repo.name ?? repo.path.split("/").filter(Boolean).pop() ?? repo.path
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* `max-w-full` is what keeps a chip inside the card: without it a long
|
|
40
|
+
* "repo · branch" is a single unbreakable row that runs under the card's
|
|
41
|
+
* rounded edge and gets clipped.
|
|
42
|
+
*/
|
|
43
|
+
const CHIP =
|
|
44
|
+
"inline-flex min-w-0 max-w-full items-center gap-1 rounded-md border border-border bg-muted/40 px-2 py-0.5 font-mono text-[11px] text-muted-foreground"
|
|
45
|
+
|
|
38
46
|
/** One chip per checked-out repository, wrapping onto as many lines as needed. */
|
|
39
47
|
export function GitBranchChips({ repos, repoHref, className }: GitBranchChipsProps) {
|
|
40
48
|
if (!repos.length) return null
|
|
@@ -52,13 +60,7 @@ export function GitBranchChips({ repos, repoHref, className }: GitBranchChipsPro
|
|
|
52
60
|
key={repo.path}
|
|
53
61
|
{...(href ? { href, target: "_blank", rel: "noopener noreferrer" } : {})}
|
|
54
62
|
title={repo.path}
|
|
55
|
-
|
|
56
|
-
// long "repo · branch" is a single unbreakable row that runs under
|
|
57
|
-
// the card's rounded edge and gets clipped.
|
|
58
|
-
className={cn(
|
|
59
|
-
"inline-flex min-w-0 max-w-full items-center gap-1 rounded-md border border-border bg-muted/40 px-2 py-0.5 font-mono text-[11px] text-muted-foreground",
|
|
60
|
-
href && "transition-colors hover:border-border/80 hover:bg-muted/70"
|
|
61
|
-
)}
|
|
63
|
+
className={cn(CHIP, href && "transition-colors hover:border-border/80 hover:bg-muted/70")}
|
|
62
64
|
>
|
|
63
65
|
<span className="shrink-0 font-medium text-foreground/70">{repoName(repo)}</span>
|
|
64
66
|
<span className="mx-0.5 shrink-0 text-muted-foreground/40">·</span>
|
|
@@ -75,6 +77,27 @@ export function GitBranchChips({ repos, repoHref, className }: GitBranchChipsPro
|
|
|
75
77
|
)
|
|
76
78
|
}
|
|
77
79
|
|
|
80
|
+
export interface RequestedBranchChipProps {
|
|
81
|
+
branch: string
|
|
82
|
+
className?: string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The branch a worker was *asked* to check out, as a lone chip — no repo name,
|
|
87
|
+
* because at that point nothing is cloned yet and there is none to show. Same
|
|
88
|
+
* shell as the chips above on purpose: it's the placeholder they replace once
|
|
89
|
+
* the live status arrives, and a different-looking chip would read as a
|
|
90
|
+
* different kind of information.
|
|
91
|
+
*/
|
|
92
|
+
export function RequestedBranchChip({ branch, className }: RequestedBranchChipProps) {
|
|
93
|
+
return (
|
|
94
|
+
<span data-slot="requested-branch-chip" className={cn(CHIP, className)} title={`Requested branch: ${branch}`}>
|
|
95
|
+
<GitBranchIcon className="h-2.5 w-2.5 shrink-0" />
|
|
96
|
+
<span className="min-w-0 truncate">{branch}</span>
|
|
97
|
+
</span>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
78
101
|
/** Amber for local work not yet committed/pushed, muted for what's merely behind. */
|
|
79
102
|
function RepoCounters({ repo }: { repo: GitRepoStatus }) {
|
|
80
103
|
return (
|
|
@@ -18,8 +18,8 @@ export type { SetupProgressProps, StepState } from "./setup-progress"
|
|
|
18
18
|
export { ResourceBars } from "./resource-bars"
|
|
19
19
|
export type { ResourceBarsProps, WorkerStats } from "./resource-bars"
|
|
20
20
|
|
|
21
|
-
export { GitBranchChips, GitStatusSummary, repoName } from "./git-branch-chips"
|
|
22
|
-
export type { GitBranchChipsProps, GitRepoStatus, GitStatusSummaryProps } from "./git-branch-chips"
|
|
21
|
+
export { GitBranchChips, GitStatusSummary, RequestedBranchChip, repoName } from "./git-branch-chips"
|
|
22
|
+
export type { GitBranchChipsProps, GitRepoStatus, GitStatusSummaryProps, RequestedBranchChipProps } from "./git-branch-chips"
|
|
23
23
|
|
|
24
24
|
export { TagChips } from "./tag-chips"
|
|
25
25
|
export type { TagChipsProps } from "./tag-chips"
|
|
@@ -31,6 +31,12 @@ export interface WorkerCardWorker {
|
|
|
31
31
|
/** Docker-level state: `running` | `stopped` | `exited` | `created` | `not_found` | `error`. */
|
|
32
32
|
dockerState?: string | null
|
|
33
33
|
createdAt?: string | null
|
|
34
|
+
/**
|
|
35
|
+
* Branch asked for at creation — what the worker is *going to* check out. The
|
|
36
|
+
* live per-repo status (`gitStatus`) says what it *did* check out, and takes
|
|
37
|
+
* over as soon as it exists.
|
|
38
|
+
*/
|
|
39
|
+
branch?: string | null
|
|
34
40
|
projectVersion?: number | null
|
|
35
41
|
tags?: string[] | null
|
|
36
42
|
setupStatus?: WorkerSetupStatus | null
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
import { cn, formatDuration, formatRelativeTime } from "../../utils"
|
|
15
15
|
import { buttonVariants } from "../button-variants"
|
|
16
16
|
import { CreatorAvatar } from "./creator-avatar"
|
|
17
|
-
import { GitBranchChips, type GitRepoStatus } from "./git-branch-chips"
|
|
17
|
+
import { GitBranchChips, RequestedBranchChip, type GitRepoStatus } from "./git-branch-chips"
|
|
18
18
|
import { ResourceBars, type WorkerStats } from "./resource-bars"
|
|
19
19
|
import { SetupProgress, setupTotalMs } from "./setup-progress"
|
|
20
20
|
import { TagChips } from "./tag-chips"
|
|
@@ -209,10 +209,16 @@ export function WorkerCard({
|
|
|
209
209
|
</div>
|
|
210
210
|
)}
|
|
211
211
|
|
|
212
|
-
{repos.length > 0
|
|
212
|
+
{repos.length > 0 ? (
|
|
213
213
|
<div className="px-4 pb-3">
|
|
214
214
|
<GitBranchChips repos={repos} repoHref={repoHref} />
|
|
215
215
|
</div>
|
|
216
|
+
) : (
|
|
217
|
+
worker.branch && (
|
|
218
|
+
<div className="px-4 pb-3">
|
|
219
|
+
<RequestedBranchChip branch={worker.branch} />
|
|
220
|
+
</div>
|
|
221
|
+
)
|
|
216
222
|
)}
|
|
217
223
|
|
|
218
224
|
{settled && stats && (
|