Skip to content

Commit e640e87

Browse files
committed
cleans up pipelineDetails v2
1 parent 876fd02 commit e640e87

File tree

4 files changed

+140
-107
lines changed

4 files changed

+140
-107
lines changed

.cursorrules

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,30 @@ This is a React + TypeScript application for building and running Machine Learni
5555
- Common spacing/layout patterns → Suggest utility classes or component abstractions
5656
- Similar form field styling → Create form field components
5757

58+
### UI Primitives (Prefer Over Raw HTML)
59+
60+
**Always prefer our UI primitives over raw HTML elements:**
61+
62+
- **Layout**: Use `BlockStack` and `InlineStack` from `@/components/ui/layout` instead of `<div className="flex ...">`
63+
- `BlockStack` = vertical flex (`flex-col`)
64+
- `InlineStack` = horizontal flex (`flex-row`)
65+
- Both support `gap`, `align`, `blockAlign` props
66+
- Use `as` prop for semantic elements: `<BlockStack as="ul">`, `<InlineStack as="li">`
67+
68+
- **Typography**: Use `Text` from `@/components/ui/typography` instead of raw `<h1-h6>`, `<p>`, `<span>`, `<dt>`, `<dd>`
69+
- `<Text as="h3" size="md" weight="semibold">` instead of `<h3 className="text-md font-semibold">`
70+
- `<Text as="dt" weight="semibold">` instead of `<dt className="font-semibold">`
71+
- `<Text as="p" size="sm">` instead of `<p className="text-sm">`
72+
- Supports: `as`, `size`, `weight`, `tone`, `font` props
73+
74+
- **Buttons**: Use `Button` from `@/components/ui/button`
75+
- **Icons**: Use `Icon` from `@/components/ui/icon`
76+
77+
**When raw HTML is acceptable:**
78+
- Semantic elements not supported by primitives (e.g., `<dl>`, `<ul>`, `<ol>`, `<table>`)
79+
- Complex layouts where primitives don't fit
80+
- Performance-critical sections where abstraction overhead matters
81+
5882
### State Management
5983

6084
- Use Tanstack Query for server state
@@ -202,6 +226,7 @@ export const useContext = () => {
202226
- Don't create side effects in render functions
203227
- Don't use barrel exports
204228
- Don't modify componentSpec structure without express permission
229+
- Don't use raw HTML elements when UI primitives exist (use `Text`, `BlockStack`, `InlineStack`, etc.)
205230

206231
## Other rules
207232

src/components/Editor/PipelineDetails.tsx

Lines changed: 57 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { CopyText } from "@/components/shared/CopyText/CopyText";
77
import { Button } from "@/components/ui/button";
88
import { Icon } from "@/components/ui/icon";
99
import { BlockStack, InlineStack } from "@/components/ui/layout";
10+
import { Text } from "@/components/ui/typography";
1011
import useToastNotification from "@/hooks/useToastNotification";
1112
import { useComponentSpec } from "@/providers/ComponentSpecProvider";
1213
import { useContextPanel } from "@/providers/ContextPanelProvider";
@@ -144,85 +145,85 @@ const PipelineDetails = () => {
144145
/>
145146
</InlineStack>
146147

147-
{/* General Metadata */}
148-
<div className="flex flex-col gap-2 text-xs text-secondary-foreground mb-2">
149-
<div className="flex flex-wrap gap-6">
150-
{fileMeta.createdBy && (
151-
<div>
152-
<span className="font-semibold">Created by:</span>{" "}
153-
{fileMeta.createdBy}
154-
</div>
155-
)}
156-
</div>
157-
<div className="flex flex-wrap gap-x-6">
158-
{fileMeta.creationTime && (
159-
<div>
160-
<span className="font-semibold">Created at:</span>{" "}
161-
{new Date(fileMeta.creationTime).toLocaleString()}
162-
</div>
163-
)}
164-
{fileMeta.modificationTime && (
165-
<div>
166-
<span className="font-semibold">Last updated:</span>{" "}
167-
{new Date(fileMeta.modificationTime).toLocaleString()}
168-
</div>
169-
)}
170-
</div>
171-
</div>
148+
{(fileMeta.createdBy || fileMeta.creationTime || fileMeta.modificationTime) && (
149+
<BlockStack>
150+
<Text as="h3" size="md" weight="semibold" className="mb-1">Pipeline Info</Text>
151+
<dl className="flex flex-col gap-1 text-xs text-secondary-foreground">
152+
{fileMeta.createdBy && (
153+
<InlineStack as="div" gap="1" blockAlign="center">
154+
<Text as="dt" weight="semibold">Created by:</Text>
155+
<dd>{fileMeta.createdBy}</dd>
156+
</InlineStack>
157+
)}
158+
{fileMeta.creationTime && (
159+
<InlineStack as="div" gap="1" blockAlign="center">
160+
<Text as="dt" weight="semibold">Created at:</Text>
161+
<dd>{new Date(fileMeta.creationTime).toLocaleString()}</dd>
162+
</InlineStack>
163+
)}
164+
{fileMeta.modificationTime && (
165+
<InlineStack as="div" gap="1" blockAlign="center">
166+
<Text as="dt" weight="semibold">Last updated:</Text>
167+
<dd>{new Date(fileMeta.modificationTime).toLocaleString()}</dd>
168+
</InlineStack>
169+
)}
170+
</dl>
171+
</BlockStack>
172+
)}
172173

173174
{/* Description */}
174175
{componentSpec.description && (
175-
<div>
176-
<h3 className="text-md font-medium mb-1">Description</h3>
177-
<div className="text-sm whitespace-pre-line">
176+
<BlockStack>
177+
<Text as="h3" size="md" weight="semibold" className="mb-1">Description</Text>
178+
<Text as="p" size="sm" className="whitespace-pre-line">
178179
{componentSpec.description}
179-
</div>
180-
</div>
180+
</Text>
181+
</BlockStack>
181182
)}
182183

183184
{/* Component Digest */}
184185
{digest && (
185-
<div className="mb-2">
186-
<h3 className="text-md font-medium mb-1">Digest</h3>
186+
<BlockStack>
187+
<Text as="h3" size="md" weight="semibold" className="mb-1">Digest</Text>
187188
<Button
188189
className="bg-gray-100 border border-gray-300 rounded p-2 h-fit text-xs w-full text-left hover:bg-gray-200 active:bg-gray-300 transition cursor-pointer"
189190
onClick={handleDigestCopy}
190191
variant="ghost"
191192
>
192-
<span className="font-mono break-all w-full text-wrap">
193+
<Text as="span" font="mono" className="break-all w-full text-wrap">
193194
{digest}
194-
</span>
195+
</Text>
195196
</Button>
196-
</div>
197+
</BlockStack>
197198
)}
198199

199200
{/* Annotations */}
200201
{Object.keys(annotations).length > 0 && (
201-
<div>
202-
<h3 className="text-md font-medium mb-1">Annotations</h3>
202+
<BlockStack>
203+
<Text as="h3" size="md" weight="semibold" className="mb-1">Annotations</Text>
203204
<ul className="text-xs text-secondary-foreground">
204205
{Object.entries(annotations).map(([key, value]) => (
205206
<li key={key}>
206-
<span className="font-semibold">{key}:</span>{" "}
207-
<span className="break-all">{String(value)}</span>
207+
<Text as="span" weight="semibold">{key}:</Text>{" "}
208+
<Text as="span" className="break-all">{String(value)}</Text>
208209
</li>
209210
))}
210211
</ul>
211-
</div>
212+
</BlockStack>
212213
)}
213214

214215
{/* Artifacts (Inputs & Outputs) */}
215-
<div>
216-
<h3 className="text-md font-medium mb-1">Artifacts</h3>
217-
<div className="flex gap-4 flex-col">
218-
<div className="flex-1">
219-
<h4 className="text-sm font-semibold mb-1">Inputs</h4>
216+
<BlockStack>
217+
<Text as="h3" size="md" weight="semibold" className="mb-1">Artifacts</Text>
218+
<BlockStack gap="4">
219+
<BlockStack>
220+
<Text as="h4" size="sm" weight="semibold" className="mb-1">Inputs</Text>
220221
{componentSpec.inputs && componentSpec.inputs.length > 0 ? (
221222
<div className="flex flex-col">
222223
{componentSpec.inputs.map((input) => {
223224
return (
224225
<div
225-
className="flex flex-row justify-between even:bg-white odd:bg-gray-100 gap-1 px-2 py-0 rounded-xs items-center"
226+
className="flex flex-row justify-between even:bg-white odd:bg-gray-100 gap-1 px-2 py-1 rounded-xs items-center"
226227
key={input.name}
227228
>
228229
<div className="text-xs flex-1 truncate max-w-[200px]">
@@ -266,14 +267,14 @@ const PipelineDetails = () => {
266267
) : (
267268
<div className="text-xs text-muted-foreground">No inputs</div>
268269
)}
269-
</div>
270-
<div className="flex-1">
271-
<h4 className="text-sm font-semibold mb-1">Outputs</h4>
270+
</BlockStack>
271+
<BlockStack>
272+
<Text as="h4" size="sm" weight="semibold" className="mb-1">Outputs</Text>
272273
{componentSpec.outputs && componentSpec.outputs.length > 0 ? (
273274
<div className="flex flex-col">
274275
{componentSpec.outputs.map((output) => (
275276
<div
276-
className="flex flex-row justify-between even:bg-white odd:bg-gray-100 gap-1 px-2 py-0 rounded-xs items-center"
277+
className="flex flex-row justify-between even:bg-white odd:bg-gray-100 gap-1 px-2 py-1 rounded-xs items-center"
277278
key={output.name}
278279
>
279280
<div className="text-xs flex-1 truncate max-w-[200px]">
@@ -308,20 +309,20 @@ const PipelineDetails = () => {
308309
) : (
309310
<div className="text-xs text-muted-foreground">No outputs</div>
310311
)}
311-
</div>
312-
</div>
313-
</div>
312+
</BlockStack>
313+
</BlockStack>
314+
</BlockStack>
314315

315316
{/* Validations */}
316-
<div className="mt-2">
317-
<h3 className="text-md font-medium mb-1">Validations</h3>
317+
<BlockStack>
318+
<Text as="h3" size="md" weight="semibold" className="mb-1">Validations</Text>
318319
<PipelineValidationList
319320
isComponentTreeValid={isComponentTreeValid}
320321
groupedIssues={groupedIssues}
321322
totalIssueCount={globalValidationIssues.length}
322323
onIssueSelect={handleIssueClick}
323324
/>
324-
</div>
325+
</BlockStack>
325326
</BlockStack>
326327
);
327328
};

src/components/PipelineRun/RunDetails.tsx

Lines changed: 56 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ export const RunDetails = () => {
5252
if (error || !details || !state || !componentSpec) {
5353
return (
5454
<div className="flex flex-col gap-8 items-center justify-center h-full">
55-
<Frown className="w-12 h-12 text-gray-500" />
56-
<div className="text-gray-500">Error loading run details.</div>
55+
<Frown className="w-12 h-12 text-secondary-foreground" />
56+
<div className="text-secondary-foreground">Error loading run details.</div>
5757
</div>
5858
);
5959
}
@@ -62,7 +62,7 @@ export const RunDetails = () => {
6262
return (
6363
<div className="flex items-center justify-center h-full">
6464
<Spinner className="mr-2" />
65-
<p className="text-gray-500">Loading run details...</p>
65+
<p className="text-secondary-foreground">Loading run details...</p>
6666
</div>
6767
);
6868
}
@@ -106,75 +106,82 @@ export const RunDetails = () => {
106106
</InlineStack>
107107

108108
{metadata && (
109-
<div className="flex flex-col gap-2 text-xs text-secondary-foreground mb-2">
110-
<div className="flex flex-wrap gap-x-6">
109+
<BlockStack>
110+
<Text as="h3" size="md" weight="semibold" className="mb-1">Run Info</Text>
111+
<dl className="flex flex-col gap-1 text-xs text-secondary-foreground">
111112
{metadata.id && (
112-
<div>
113-
<span className="font-semibold">Run Id:</span> {metadata.id}
114-
</div>
113+
<InlineStack as="div" gap="1" blockAlign="center">
114+
<Text as="dt" weight="semibold" className="shrink-0">Run Id:</Text>
115+
<dd>
116+
<CopyText className="font-mono truncate max-w-[180px]">
117+
{metadata.id}
118+
</CopyText>
119+
</dd>
120+
</InlineStack>
115121
)}
116122
{metadata.root_execution_id && (
117-
<div>
118-
<span className="font-semibold">Execution Id:</span>{" "}
119-
{metadata.root_execution_id}
120-
</div>
123+
<InlineStack as="div" gap="1" blockAlign="center">
124+
<Text as="dt" weight="semibold" className="shrink-0">Execution Id:</Text>
125+
<dd>
126+
<CopyText className="font-mono truncate max-w-[180px]">
127+
{metadata.root_execution_id}
128+
</CopyText>
129+
</dd>
130+
</InlineStack>
121131
)}
122-
</div>
123-
<div className="flex flex-wrap gap-6">
124132
{metadata.created_by && (
125-
<div>
126-
<span className="font-semibold">Created by:</span>{" "}
127-
{metadata.created_by}
128-
</div>
133+
<InlineStack as="div" gap="1" blockAlign="center">
134+
<Text as="dt" weight="semibold">Created by:</Text>
135+
<dd>{metadata.created_by}</dd>
136+
</InlineStack>
129137
)}
130-
</div>
131-
<div className="flex flex-wrap gap-x-6">
132138
{metadata.created_at && (
133-
<div>
134-
<span className="font-semibold">Created at:</span>{" "}
135-
{new Date(metadata.created_at).toLocaleString()}
136-
</div>
139+
<InlineStack as="div" gap="1" blockAlign="center">
140+
<Text as="dt" weight="semibold">Created at:</Text>
141+
<dd>{new Date(metadata.created_at).toLocaleString()}</dd>
142+
</InlineStack>
137143
)}
138-
</div>
139-
</div>
144+
</dl>
145+
</BlockStack>
140146
)}
141147

142148
{componentSpec.description && (
143-
<div>
144-
<h3 className="text-md font-medium mb-1">Description</h3>
145-
<div className="text-sm text-gray-700 whitespace-pre-line">
149+
<BlockStack>
150+
<Text as="h3" size="md" weight="semibold" className="mb-1">Description</Text>
151+
<Text as="p" size="sm" className="whitespace-pre-line">
146152
{componentSpec.description}
147-
</div>
148-
</div>
153+
</Text>
154+
</BlockStack>
149155
)}
150156

151157
<BlockStack>
152-
<InlineStack gap="1" blockAlign="center">
153-
<Text size="md" weight="semibold">Status: {runStatus}</Text>
158+
<Text as="h3" size="md" weight="semibold" className="mb-1">Status</Text>
159+
<InlineStack gap="2" blockAlign="center" className="mb-1">
160+
<Text size="sm" weight="semibold">{runStatus}</Text>
154161
<StatusText statusCounts={statusCounts} />
155162
</InlineStack>
156163
<StatusBar statusCounts={statusCounts} />
157164
</BlockStack>
158165

159166
{Object.keys(annotations).length > 0 && (
160-
<div>
161-
<h3 className="text-md font-medium mb-1">Annotations</h3>
167+
<BlockStack>
168+
<Text as="h3" size="md" weight="semibold" className="mb-1">Annotations</Text>
162169
<ul className="text-xs text-secondary-foreground">
163170
{Object.entries(annotations).map(([key, value]) => (
164171
<li key={key}>
165-
<span className="font-semibold">{key}:</span>{" "}
166-
<span className="break-all">{String(value)}</span>
172+
<Text as="span" weight="semibold">{key}:</Text>{" "}
173+
<Text as="span" className="break-all">{String(value)}</Text>
167174
</li>
168175
))}
169176
</ul>
170-
</div>
177+
</BlockStack>
171178
)}
172179

173-
<div className="w-full">
174-
<h3 className="text-md font-medium mb-1">Artifacts</h3>
175-
<div className="flex gap-4 flex-col w-full">
176-
<div className="w-full">
177-
<h4 className="text-sm font-semibold mb-1">Inputs</h4>
180+
<BlockStack className="w-full">
181+
<Text as="h3" size="md" weight="semibold" className="mb-1">Artifacts</Text>
182+
<BlockStack gap="4" className="w-full">
183+
<BlockStack className="w-full">
184+
<Text as="h4" size="sm" weight="semibold" className="mb-1">Inputs</Text>
178185
{componentSpec.inputs && componentSpec.inputs.length > 0 ? (
179186
<div className="flex flex-col w-full">
180187
{componentSpec.inputs.map((input) => (
@@ -194,9 +201,9 @@ export const RunDetails = () => {
194201
) : (
195202
<div className="text-xs text-muted-foreground">No inputs</div>
196203
)}
197-
</div>
198-
<div className="w-full">
199-
<h4 className="text-sm font-semibold mb-1">Outputs</h4>
204+
</BlockStack>
205+
<BlockStack className="w-full">
206+
<Text as="h4" size="sm" weight="semibold" className="mb-1">Outputs</Text>
200207
{componentSpec.outputs && componentSpec.outputs.length > 0 ? (
201208
<div className="flex flex-col w-full">
202209
{componentSpec.outputs.map((output) => (
@@ -216,9 +223,9 @@ export const RunDetails = () => {
216223
) : (
217224
<div className="text-xs text-muted-foreground">No outputs</div>
218225
)}
219-
</div>
220-
</div>
221-
</div>
226+
</BlockStack>
227+
</BlockStack>
228+
</BlockStack>
222229
</BlockStack>
223230
);
224231
};

0 commit comments

Comments
 (0)